1/** @file
2  Collect Sio information from Native EFI Drivers.
3  Sio is floppy, parallel, serial, ... hardware
4
5Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
6
7This program and the accompanying materials
8are licensed and made available under the terms and conditions
9of the BSD License which accompanies this distribution.  The
10full text of the license may be found at
11http://opensource.org/licenses/bsd-license.php
12
13THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15
16**/
17
18#include "LegacyBiosInterface.h"
19
20
21/**
22  Collect EFI Info about legacy devices.
23
24  @param  Private      Legacy BIOS Instance data
25
26  @retval EFI_SUCCESS  It should always work.
27
28**/
29EFI_STATUS
30LegacyBiosBuildSioData (
31  IN  LEGACY_BIOS_INSTANCE      *Private
32  )
33{
34  EFI_STATUS                          Status;
35  DEVICE_PRODUCER_DATA_HEADER         *SioPtr;
36  DEVICE_PRODUCER_SERIAL              *Sio1Ptr;
37  DEVICE_PRODUCER_PARALLEL            *Sio2Ptr;
38  DEVICE_PRODUCER_FLOPPY              *Sio3Ptr;
39  EFI_HANDLE                          IsaBusController;
40  UINTN                               HandleCount;
41  EFI_HANDLE                          *HandleBuffer;
42  UINTN                               Index;
43  UINTN                               ResourceIndex;
44  UINTN                               ChildIndex;
45  EFI_ISA_IO_PROTOCOL                 *IsaIo;
46  EFI_ISA_ACPI_RESOURCE_LIST          *ResourceList;
47  EFI_ISA_ACPI_RESOURCE               *IoResource;
48  EFI_ISA_ACPI_RESOURCE               *DmaResource;
49  EFI_ISA_ACPI_RESOURCE               *InterruptResource;
50  UINTN                               EntryCount;
51  EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
52  EFI_BLOCK_IO_PROTOCOL               *BlockIo;
53
54  //
55  // Get the pointer to the SIO data structure
56  //
57  SioPtr = &Private->IntThunk->EfiToLegacy16BootTable.SioData;
58
59  //
60  // Zero the data in the SIO data structure
61  //
62  gBS->SetMem (SioPtr, sizeof (DEVICE_PRODUCER_DATA_HEADER), 0);
63
64  //
65  // Find the ISA Bus Controller used for legacy
66  //
67  Status = Private->LegacyBiosPlatform->GetPlatformHandle (
68                                          Private->LegacyBiosPlatform,
69                                          EfiGetPlatformIsaBusHandle,
70                                          0,
71                                          &HandleBuffer,
72                                          &HandleCount,
73                                          NULL
74                                          );
75  IsaBusController = HandleBuffer[0];
76  if (!EFI_ERROR (Status)) {
77    //
78    // Force ISA Bus Controller to produce all ISA devices
79    //
80    gBS->ConnectController (IsaBusController, NULL, NULL, TRUE);
81  }
82  //
83  // Get the list of ISA controllers in the system
84  //
85  Status = gBS->LocateHandleBuffer (
86                  ByProtocol,
87                  &gEfiIsaIoProtocolGuid,
88                  NULL,
89                  &HandleCount,
90                  &HandleBuffer
91                  );
92  if (EFI_ERROR (Status)) {
93    return EFI_SUCCESS;
94  }
95  //
96  // Collect legacy information from each of the ISA controllers in the system
97  //
98  for (Index = 0; Index < HandleCount; Index++) {
99
100    Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiIsaIoProtocolGuid, (VOID **) &IsaIo);
101    if (EFI_ERROR (Status)) {
102      continue;
103    }
104
105    ResourceList = IsaIo->ResourceList;
106
107    if (ResourceList == NULL) {
108      continue;
109    }
110    //
111    // Collect the resource types neededto fill in the SIO data structure
112    //
113    IoResource        = NULL;
114    DmaResource       = NULL;
115    InterruptResource = NULL;
116    for (ResourceIndex = 0;
117         ResourceList->ResourceItem[ResourceIndex].Type != EfiIsaAcpiResourceEndOfList;
118         ResourceIndex++
119        ) {
120      switch (ResourceList->ResourceItem[ResourceIndex].Type) {
121      case EfiIsaAcpiResourceIo:
122        IoResource = &ResourceList->ResourceItem[ResourceIndex];
123        break;
124
125      case EfiIsaAcpiResourceMemory:
126        break;
127
128      case EfiIsaAcpiResourceDma:
129        DmaResource = &ResourceList->ResourceItem[ResourceIndex];
130        break;
131
132      case EfiIsaAcpiResourceInterrupt:
133        InterruptResource = &ResourceList->ResourceItem[ResourceIndex];
134        break;
135
136      default:
137        break;
138      }
139    }
140    //
141    // See if this is an ISA serial port
142    //
143    // Ignore DMA resource since it is always returned NULL
144    //
145    if (ResourceList->Device.HID == EISA_PNP_ID (0x500) || ResourceList->Device.HID == EISA_PNP_ID (0x501)) {
146
147      if (ResourceList->Device.UID <= 3 &&
148          IoResource != NULL &&
149          InterruptResource != NULL
150          ) {
151        //
152        // Get the handle of the child device that has opened the ISA I/O Protocol
153        //
154        Status = gBS->OpenProtocolInformation (
155                        HandleBuffer[Index],
156                        &gEfiIsaIoProtocolGuid,
157                        &OpenInfoBuffer,
158                        &EntryCount
159                        );
160        if (EFI_ERROR (Status)) {
161          continue;
162        }
163        //
164        // We want resource for legacy even if no 32-bit driver installed
165        //
166        for (ChildIndex = 0; ChildIndex < EntryCount; ChildIndex++) {
167          Sio1Ptr           = &SioPtr->Serial[ResourceList->Device.UID];
168          Sio1Ptr->Address  = (UINT16) IoResource->StartRange;
169          Sio1Ptr->Irq      = (UINT8) InterruptResource->StartRange;
170          Sio1Ptr->Mode     = DEVICE_SERIAL_MODE_NORMAL | DEVICE_SERIAL_MODE_DUPLEX_HALF;
171        }
172
173        FreePool (OpenInfoBuffer);
174      }
175    }
176    //
177    // See if this is an ISA parallel port
178    //
179    // Ignore DMA resource since it is always returned NULL, port
180    // only used in output mode.
181    //
182    if (ResourceList->Device.HID == EISA_PNP_ID (0x400) || ResourceList->Device.HID == EISA_PNP_ID (0x401)) {
183      if (ResourceList->Device.UID <= 2 &&
184          IoResource != NULL &&
185          InterruptResource != NULL &&
186          DmaResource != NULL
187          ) {
188        Sio2Ptr           = &SioPtr->Parallel[ResourceList->Device.UID];
189        Sio2Ptr->Address  = (UINT16) IoResource->StartRange;
190        Sio2Ptr->Irq      = (UINT8) InterruptResource->StartRange;
191        Sio2Ptr->Dma      = (UINT8) DmaResource->StartRange;
192        Sio2Ptr->Mode     = DEVICE_PARALLEL_MODE_MODE_OUTPUT_ONLY;
193      }
194    }
195    //
196    // See if this is an ISA floppy controller
197    //
198    if (ResourceList->Device.HID == EISA_PNP_ID (0x604)) {
199      if (IoResource != NULL && InterruptResource != NULL && DmaResource != NULL) {
200        Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);
201        if (!EFI_ERROR (Status)) {
202          Sio3Ptr           = &SioPtr->Floppy;
203          Sio3Ptr->Address  = (UINT16) IoResource->StartRange;
204          Sio3Ptr->Irq      = (UINT8) InterruptResource->StartRange;
205          Sio3Ptr->Dma      = (UINT8) DmaResource->StartRange;
206          Sio3Ptr->NumberOfFloppy++;
207        }
208      }
209    }
210    //
211    // See if this is a mouse
212    // Always set mouse found so USB hot plug will work
213    //
214    // Ignore lower byte of HID. Pnp0fxx is any type of mouse.
215    //
216    //    Hid = ResourceList->Device.HID & 0xff00ffff;
217    //    PnpId = EISA_PNP_ID(0x0f00);
218    //    if (Hid == PnpId) {
219    //      if (ResourceList->Device.UID == 1) {
220    //        Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSimplePointerProtocolGuid, &SimplePointer);
221    //      if (!EFI_ERROR (Status)) {
222    //
223    SioPtr->MousePresent = 0x01;
224    //
225    //        }
226    //      }
227    //    }
228    //
229  }
230
231  FreePool (HandleBuffer);
232
233  return EFI_SUCCESS;
234}
235