1 /** @file
2   Collect Sio information from Native EFI Drivers.
3   Sio is floppy, parallel, serial, ... hardware
4 
5 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
6 
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions
9 of the BSD License which accompanies this distribution.  The
10 full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
12 
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT 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 **/
29 EFI_STATUS
LegacyBiosBuildSioData(IN LEGACY_BIOS_INSTANCE * Private)30 LegacyBiosBuildSioData (
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