]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBus.c
change TokenSpaceGuid to the package Token Space Guid
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / IsaBusDxe / IsaBus.c
CommitLineData
f8cd287b 1/**@file\r
c3902377 2\r
3 Discovers all the ISA Controllers and their resources by using the ISA PnP \r
4 Protocol, produces an instance of the ISA I/O Protocol for every ISA \r
5 Controller found, loads and initializes all ISA Device Drivers, matches ISA\r
6 Device Drivers with their respective ISA Controllers in a deterministic \r
7 manner, and informs a ISA Device Driver when it is to start managing an ISA\r
8 Controller. \r
f8cd287b 9 \r
10Copyright (c) 2006 - 2007, Intel Corporation.<BR>\r
11All rights reserved. This program and the accompanying materials\r
12are licensed and made available under the terms and conditions of the BSD License\r
13which accompanies this distribution. The full text of the license may be found at\r
14http://opensource.org/licenses/bsd-license.php\r
15\r
16THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
17WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
c3902377 18\r
f8cd287b 19**/\r
c3902377 20\r
c3902377 21\r
22#include "InternalIsaBus.h"\r
23\r
24//\r
25// ISA Bus Driver Global Variables\r
26//\r
27EFI_DRIVER_BINDING_PROTOCOL gIsaBusControllerDriver = {\r
28 IsaBusControllerDriverSupported,\r
29 IsaBusControllerDriverStart,\r
30 IsaBusControllerDriverStop,\r
31 0xa,\r
32 NULL,\r
33 NULL\r
34};\r
35\r
c55fa8cc 36/**\r
37 The user Entry Point for module IsaBus. The user code starts with this function.\r
38\r
39 @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
40 @param[in] SystemTable A pointer to the EFI System Table.\r
41 \r
42 @retval EFI_SUCCESS The entry point is executed successfully.\r
43 @retval other Some error occurs when executing this entry point.\r
44\r
45**/\r
46EFI_STATUS\r
47EFIAPI\r
48InitializeIsaBus(\r
49 IN EFI_HANDLE ImageHandle,\r
50 IN EFI_SYSTEM_TABLE *SystemTable\r
51 )\r
52{\r
53 EFI_STATUS Status;\r
54\r
55 //\r
56 // Install driver model protocol(s).\r
57 //\r
58 Status = EfiLibInstallAllDriverProtocols (\r
59 ImageHandle,\r
60 SystemTable,\r
61 &gIsaBusControllerDriver,\r
62 ImageHandle,\r
63 &gIsaBusComponentName,\r
64 NULL,\r
65 NULL\r
66 );\r
67 ASSERT_EFI_ERROR (Status);\r
68\r
69\r
70 return Status;\r
71}\r
72\r
73\r
c3902377 74EFI_STATUS\r
75EFIAPI\r
76IsaBusControllerDriverSupported (\r
77 IN EFI_DRIVER_BINDING_PROTOCOL * This,\r
78 IN EFI_HANDLE Controller,\r
79 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL\r
80 )\r
81/*++\r
82\r
83 Routine Description:\r
84 \r
85 This function checks to see if a controller can be managed by the ISA Bus \r
86 Driver. This is done by checking to see if the controller supports the \r
87 EFI_PCI_IO_PROTOCOL protocol, and then looking at the PCI Configuration \r
88 Header to see if the device is a PCI to ISA bridge. The class code of \r
89 PCI to ISA bridge: Base class 06h, Sub class 01h Interface 00h \r
90 \r
91 Arguments:\r
92 \r
93 This - The EFI_DRIVER_BINDING_PROTOCOL instance.\r
94 Controller - The handle of the device to check.\r
95 RemainingDevicePath - A pointer to the remaining portion of a device path.\r
96\r
97 Returns:\r
98 \r
99 EFI_SUCCESS - The device is supported by this driver.\r
100 EFI_UNSUPPORTED - The device is not supported by this driver.\r
101\r
102--*/\r
103{\r
104 EFI_STATUS Status;\r
105 EFI_ISA_ACPI_PROTOCOL *IsaAcpi;\r
106\r
107 //\r
108 // If RemainingDevicePath is not NULL, it should verify that the first device\r
109 // path node in RemainingDevicePath is an ACPI Device path node\r
110 //\r
111 if (RemainingDevicePath != NULL) {\r
112 if (RemainingDevicePath->Type != ACPI_DEVICE_PATH) {\r
113 return EFI_UNSUPPORTED;\r
114 } else if (RemainingDevicePath->SubType == ACPI_DP) {\r
115 if (DevicePathNodeLength (RemainingDevicePath) != sizeof (ACPI_HID_DEVICE_PATH)) {\r
116 return EFI_UNSUPPORTED;\r
117 }\r
118 } else if (RemainingDevicePath->SubType == ACPI_EXTENDED_DP) {\r
119 if (DevicePathNodeLength (RemainingDevicePath) != sizeof (ACPI_EXTENDED_HID_DEVICE_PATH)) {\r
120 return EFI_UNSUPPORTED;\r
121 }\r
122 } else {\r
123 return EFI_UNSUPPORTED;\r
124 }\r
125 }\r
126 //\r
127 // Test the existence of DEVICE_PATH protocol\r
128 //\r
129 Status = gBS->OpenProtocol (\r
130 Controller,\r
131 &gEfiDevicePathProtocolGuid,\r
132 NULL,\r
133 This->DriverBindingHandle,\r
134 Controller,\r
135 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
136 );\r
137 if (EFI_ERROR (Status)) {\r
138 return Status;\r
139 }\r
140 //\r
141 // Get the Isa Acpi protocol\r
142 //\r
143 Status = gBS->OpenProtocol (\r
144 Controller,\r
145 &gEfiIsaAcpiProtocolGuid,\r
146 (VOID **) &IsaAcpi,\r
147 This->DriverBindingHandle,\r
148 Controller,\r
149 EFI_OPEN_PROTOCOL_BY_DRIVER\r
150 );\r
151 if (Status == EFI_ALREADY_STARTED) {\r
152 return EFI_SUCCESS;\r
153 }\r
154\r
155 if (EFI_ERROR (Status)) {\r
156 return Status;\r
157 }\r
158\r
159 gBS->CloseProtocol (\r
160 Controller,\r
161 &gEfiIsaAcpiProtocolGuid,\r
162 This->DriverBindingHandle,\r
163 Controller\r
164 );\r
165\r
166 return Status;\r
167}\r
168\r
169EFI_STATUS\r
170EFIAPI\r
171IsaBusControllerDriverStart (\r
172 IN EFI_DRIVER_BINDING_PROTOCOL * This,\r
173 IN EFI_HANDLE Controller,\r
174 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL\r
175 )\r
176/*++\r
177\r
178 Routine Description:\r
179 \r
180 This function tells the ISA Bus Driver to start managing a PCI to ISA \r
181 Bridge controller. \r
182 \r
183 Arguments:\r
184 \r
185 This - The EFI_DRIVER_BINDING_PROTOCOL instance.\r
186 Controller - A handle to the device being started. \r
187 RemainingDevicePath - A pointer to the remaining portion of a device path.\r
188\r
189 Returns:\r
190 \r
191 EFI_SUCCESS - The device was started.\r
192 EFI_UNSUPPORTED - The device is not supported.\r
193 EFI_DEVICE_ERROR - The device could not be started due to a device error.\r
194 EFI_ALREADY_STARTED - The device has already been started.\r
195 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.\r
196 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of \r
197 resources.\r
198 \r
199--*/\r
200{\r
201 EFI_STATUS Status;\r
202 EFI_PCI_IO_PROTOCOL *PciIo;\r
203 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
204 EFI_ISA_ACPI_PROTOCOL *IsaAcpi;\r
205 EFI_ISA_ACPI_DEVICE_ID *IsaDevice;\r
206 EFI_ISA_ACPI_RESOURCE_LIST *ResourceList;\r
207 EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenMemoryTest;\r
208\r
209 //\r
210 // Local variables declaration for StatusCode reporting\r
211 //\r
212 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA AllocFailExtendedData;\r
213 EFI_DEVICE_PATH_PROTOCOL *DevicePathData;\r
214\r
c3902377 215 //\r
216 // Initialize status code structure\r
217 //\r
218 AllocFailExtendedData.DataHeader.HeaderSize = sizeof (EFI_STATUS_CODE_DATA);\r
219 AllocFailExtendedData.DataHeader.Size = sizeof (EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA) - sizeof (EFI_STATUS_CODE_DATA);\r
220 CopyMem (\r
221 &AllocFailExtendedData.DataHeader.Type,\r
222 &gEfiStatusCodeSpecificDataGuid,\r
223 sizeof (EFI_GUID)\r
224 );\r
225\r
226 //\r
227 // Open Device Path Protocol\r
228 //\r
229 Status = gBS->OpenProtocol (\r
230 Controller,\r
231 &gEfiDevicePathProtocolGuid,\r
232 (VOID **) &ParentDevicePath,\r
233 This->DriverBindingHandle,\r
234 Controller,\r
235 EFI_OPEN_PROTOCOL_BY_DRIVER\r
236 );\r
237 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
238 return Status;\r
239 }\r
240 //\r
241 // Open Pci IO Protocol\r
242 //\r
243 Status = gBS->OpenProtocol (\r
244 Controller,\r
245 &gEfiPciIoProtocolGuid,\r
246 (VOID **) &PciIo,\r
247 This->DriverBindingHandle,\r
248 Controller,\r
249 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
250 );\r
251 if (EFI_ERROR (Status)) {\r
252 //\r
253 // Close opened protocol\r
254 //\r
255 gBS->CloseProtocol (\r
256 Controller,\r
257 &gEfiDevicePathProtocolGuid,\r
258 This->DriverBindingHandle,\r
259 Controller\r
260 );\r
261 return Status;\r
262 }\r
263 //\r
264 // Open ISA Acpi Protocol\r
265 //\r
266 Status = gBS->OpenProtocol (\r
267 Controller,\r
268 &gEfiIsaAcpiProtocolGuid,\r
269 (VOID **) &IsaAcpi,\r
270 This->DriverBindingHandle,\r
271 Controller,\r
272 EFI_OPEN_PROTOCOL_BY_DRIVER\r
273 );\r
274 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
275 //\r
276 // Close opened protocol\r
277 //\r
278 gBS->CloseProtocol (\r
279 Controller,\r
280 &gEfiDevicePathProtocolGuid,\r
281 This->DriverBindingHandle,\r
282 Controller\r
283 );\r
284 gBS->CloseProtocol (\r
285 Controller,\r
286 &gEfiPciIoProtocolGuid,\r
287 This->DriverBindingHandle,\r
288 Controller\r
289 );\r
290 return Status;\r
291 }\r
292 //\r
293 // The IsaBus driver will use memory below 16M, which is not tested yet,\r
294 // so call CompatibleRangeTest to test them. Since memory below 1M should\r
295 // be reserved to CSM, and 15M~16M might be reserved for Isa hole, test 1M\r
296 // ~15M here\r
297 //\r
298 Status = gBS->LocateProtocol (\r
299 &gEfiGenericMemTestProtocolGuid,\r
300 NULL,\r
301 (VOID **) &GenMemoryTest\r
302 );\r
303\r
304 if (!EFI_ERROR (Status)) {\r
305 Status = GenMemoryTest->CompatibleRangeTest (\r
306 GenMemoryTest,\r
307 0x100000,\r
308 0xE00000\r
309 );\r
310 }\r
311 //\r
312 // Report Status Code here since we will initialize the host controller\r
313 //\r
314 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
315 EFI_PROGRESS_CODE,\r
316 (EFI_IO_BUS_LPC | EFI_IOB_PC_INIT),\r
317 ParentDevicePath\r
318 );\r
319\r
320 //\r
321 // first init ISA interface\r
322 //\r
323 IsaAcpi->InterfaceInit (IsaAcpi);\r
324\r
325 //\r
326 // Report Status Code here since we will enable the host controller\r
327 //\r
328 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
329 EFI_PROGRESS_CODE,\r
330 (EFI_IO_BUS_LPC | EFI_IOB_PC_ENABLE),\r
331 ParentDevicePath\r
332 );\r
333\r
334 //\r
335 // Create each ISA device handle in this ISA bus\r
336 //\r
337 IsaDevice = NULL;\r
338 do {\r
339 Status = IsaAcpi->DeviceEnumerate (IsaAcpi, &IsaDevice);\r
340 if (EFI_ERROR (Status)) {\r
341 break;\r
342 }\r
343 //\r
344 // Get current resource of this ISA device\r
345 //\r
346 ResourceList = NULL;\r
347 Status = IsaAcpi->GetCurResource (IsaAcpi, IsaDevice, &ResourceList);\r
348 if (EFI_ERROR (Status)) {\r
349 continue;\r
350 }\r
351\r
352 //\r
353 // Create handle for this ISA device\r
354 //\r
355 Status = IsaCreateDevice (\r
356 This,\r
357 Controller,\r
358 PciIo,\r
359 ParentDevicePath,\r
360 ResourceList,\r
361 &DevicePathData\r
362 //&AllocFailExtendedData.DevicePath\r
363 );\r
364\r
365 if (EFI_ERROR (Status)) {\r
366 continue;\r
367 }\r
368 //\r
369 // Initialize ISA device\r
370 //\r
371 IsaAcpi->InitDevice (IsaAcpi, IsaDevice);\r
372\r
373 //\r
374 // Set resources for this ISA device\r
375 //\r
376 Status = IsaAcpi->SetResource (IsaAcpi, IsaDevice, ResourceList);\r
377\r
378 //\r
379 // Report Status Code here when failed to resource conflicts\r
380 //\r
381 if (EFI_ERROR (Status) && (Status != EFI_UNSUPPORTED)) {\r
382 //\r
383 // It's hard to tell which resource conflicts\r
384 //\r
385 AllocFailExtendedData.Bar = 0;\r
386 AllocFailExtendedData.ReqRes = NULL;\r
387 AllocFailExtendedData.AllocRes = NULL;\r
388 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
389 EFI_ERROR_CODE,\r
390 (EFI_IO_BUS_LPC | EFI_IOB_EC_RESOURCE_CONFLICT),\r
391 DevicePathData\r
392 );\r
393\r
394 }\r
395 //\r
396 // Set power for this ISA device\r
397 //\r
398 IsaAcpi->SetPower (IsaAcpi, IsaDevice, TRUE);\r
399\r
400 //\r
401 // Enable this ISA device\r
402 //\r
403 IsaAcpi->EnableDevice (IsaAcpi, IsaDevice, TRUE);\r
404\r
405 } while (TRUE);\r
406\r
c3902377 407 return EFI_SUCCESS;\r
408}\r
409\r
410EFI_STATUS\r
411EFIAPI\r
412IsaBusControllerDriverStop (\r
413 IN EFI_DRIVER_BINDING_PROTOCOL * This,\r
414 IN EFI_HANDLE Controller,\r
415 IN UINTN NumberOfChildren,\r
416 IN EFI_HANDLE * ChildHandleBuffer OPTIONAL\r
417 )\r
418/*++\r
419\r
420 Routine Description:\r
421 \r
422 This function tells the ISA Bus Driver to stop managing a PCI to ISA \r
423 Bridge controller. \r
424 \r
425 Arguments:\r
426 \r
427 This - The EFI_DRIVER_BINDING_PROTOCOL instance.\r
428 Controller - A handle to the device being stopped.\r
429 NumberOfChindren - The number of child device handles in ChildHandleBuffer.\r
430 ChildHandleBuffer - An array of child handles to be freed.\r
431\r
432 \r
433 Returns:\r
434 \r
435 EFI_SUCCESS - The device was stopped.\r
436 EFI_DEVICE_ERROR - The device could not be stopped due to a device error.\r
437 EFI_NOT_STARTED - The device has not been started.\r
438 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.\r
439 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of \r
440 resources.\r
441\r
442--*/\r
443{\r
444 EFI_STATUS Status;\r
445 UINTN Index;\r
446 BOOLEAN AllChildrenStopped;\r
447 ISA_IO_DEVICE *IsaIoDevice;\r
448 EFI_ISA_IO_PROTOCOL *IsaIo;\r
449\r
450 if (NumberOfChildren == 0) {\r
451 //\r
452 // Close the bus driver\r
453 //\r
454 Status = gBS->CloseProtocol (\r
455 Controller,\r
456 &gEfiPciIoProtocolGuid,\r
457 This->DriverBindingHandle,\r
458 Controller\r
459 );\r
460 if (EFI_ERROR (Status)) {\r
461 return Status;\r
462 }\r
463\r
464 Status = gBS->CloseProtocol (\r
465 Controller,\r
466 &gEfiDevicePathProtocolGuid,\r
467 This->DriverBindingHandle,\r
468 Controller\r
469 );\r
470 if (EFI_ERROR (Status)) {\r
471 return Status;\r
472 }\r
473\r
474 Status = gBS->CloseProtocol (\r
475 Controller,\r
476 &gEfiIsaAcpiProtocolGuid,\r
477 This->DriverBindingHandle,\r
478 Controller\r
479 );\r
480 if (EFI_ERROR (Status)) {\r
481 return Status;\r
482 }\r
483\r
484 return EFI_SUCCESS;\r
485 }\r
486 //\r
487 // Complete all outstanding transactions to Controller.\r
488 // Don't allow any new transaction to Controller to be started.\r
489 //\r
490 //\r
491 // Stop all the children\r
492 // Find all the ISA devices that were discovered on this PCI to ISA Bridge\r
493 // with the Start() function.\r
494 //\r
495 AllChildrenStopped = TRUE;\r
496\r
497 for (Index = 0; Index < NumberOfChildren; Index++) {\r
498\r
499 Status = gBS->OpenProtocol (\r
500 ChildHandleBuffer[Index],\r
501 &gEfiIsaIoProtocolGuid,\r
502 (VOID **) &IsaIo,\r
503 This->DriverBindingHandle,\r
504 Controller,\r
505 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
506 );\r
507 if (!EFI_ERROR (Status)) {\r
508\r
509 IsaIoDevice = ISA_IO_DEVICE_FROM_ISA_IO_THIS (IsaIo);\r
510\r
511 Status = gBS->UninstallMultipleProtocolInterfaces (\r
512 ChildHandleBuffer[Index],\r
513 &gEfiDevicePathProtocolGuid,\r
514 IsaIoDevice->DevicePath,\r
515 &gEfiIsaIoProtocolGuid,\r
516 &IsaIoDevice->IsaIo,\r
517 NULL\r
518 );\r
519\r
520 if (!EFI_ERROR (Status)) {\r
521 //\r
522 // Close the child handle\r
523 //\r
524 Status = gBS->CloseProtocol (\r
525 Controller,\r
526 &gEfiPciIoProtocolGuid,\r
527 This->DriverBindingHandle,\r
528 ChildHandleBuffer[Index]\r
529 );\r
530\r
531 gBS->FreePool (IsaIoDevice->DevicePath);\r
532 gBS->FreePool (IsaIoDevice);\r
533 }\r
534 }\r
535\r
536 if (EFI_ERROR (Status)) {\r
537 AllChildrenStopped = FALSE;\r
538 }\r
539 }\r
540\r
541 if (!AllChildrenStopped) {\r
542 return EFI_DEVICE_ERROR;\r
543 }\r
544\r
545 return EFI_SUCCESS;\r
546}\r
547//\r
548// Internal Function\r
549//\r
550EFI_STATUS\r
551IsaCreateDevice (\r
552 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
553 IN EFI_HANDLE Controller,\r
554 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
555 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
556 IN EFI_ISA_ACPI_RESOURCE_LIST *IsaDeviceResourceList,\r
557 OUT EFI_DEVICE_PATH_PROTOCOL **ChildDevicePath\r
558 )\r
559/*++\r
560\r
561 Routine Description:\r
562 \r
563 Create ISA device found by IsaPnpProtocol \r
564\r
565 Arguments:\r
566 \r
567 This - The EFI_DRIVER_BINDING_PROTOCOL instance.\r
568 Controller - The handle of ISA bus controller(PCI to ISA bridge)\r
569 PciIo - The Pointer to the PCI protocol \r
570 ParentDevicePath - Device path of the ISA bus controller\r
571 IsaDeviceResourceList - The resource list of the ISA device\r
572 ChildDevicePath - The pointer to the child device.\r
573\r
574 Returns:\r
575 \r
576 EFI_SUCCESS - Create the child device.\r
577 EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of \r
578 resources.\r
579 EFI_DEVICE_ERROR - Can not create child device.\r
580 \r
581--*/\r
582{\r
583 EFI_STATUS Status;\r
584 ISA_IO_DEVICE *IsaIoDevice;\r
585 EFI_DEV_PATH Node;\r
586\r
587 //\r
588 // Initialize the PCI_IO_DEVICE structure\r
589 //\r
590 IsaIoDevice = AllocateZeroPool (sizeof (ISA_IO_DEVICE));\r
591 if (IsaIoDevice == NULL) {\r
592 return EFI_OUT_OF_RESOURCES;\r
593 }\r
594\r
595 IsaIoDevice->Signature = ISA_IO_DEVICE_SIGNATURE;\r
596 IsaIoDevice->Handle = NULL;\r
597 IsaIoDevice->PciIo = PciIo;\r
598\r
599 //\r
600 // Initialize the ISA I/O instance structure\r
601 //\r
602 Status = InitializeIsaIoInstance (IsaIoDevice, IsaDeviceResourceList);\r
603 if (EFI_ERROR (Status)) {\r
604 gBS->FreePool (IsaIoDevice);\r
605 return Status;\r
606 }\r
607 //\r
608 // Build the child device path\r
609 //\r
610 Node.DevPath.Type = ACPI_DEVICE_PATH;\r
611 Node.DevPath.SubType = ACPI_DP;\r
612 SetDevicePathNodeLength (&Node.DevPath, sizeof (ACPI_HID_DEVICE_PATH));\r
613 Node.Acpi.HID = IsaDeviceResourceList->Device.HID;\r
614 Node.Acpi.UID = IsaDeviceResourceList->Device.UID;\r
615\r
616 IsaIoDevice->DevicePath = AppendDevicePathNode (\r
617 ParentDevicePath,\r
618 &Node.DevPath\r
619 );\r
620\r
621 if (IsaIoDevice->DevicePath == NULL) {\r
622 Status = EFI_DEVICE_ERROR;\r
623 goto Done;\r
624 }\r
625\r
626 *ChildDevicePath = IsaIoDevice->DevicePath;\r
627\r
628 //\r
629 // Create a child handle and attach the DevicePath,\r
630 // PCI I/O, and Controller State\r
631 //\r
632 Status = gBS->InstallMultipleProtocolInterfaces (\r
633 &IsaIoDevice->Handle,\r
634 &gEfiDevicePathProtocolGuid,\r
635 IsaIoDevice->DevicePath,\r
636 &gEfiIsaIoProtocolGuid,\r
637 &IsaIoDevice->IsaIo,\r
638 NULL\r
639 );\r
640 if (EFI_ERROR (Status)) {\r
641 goto Done;\r
642 }\r
643\r
644 Status = gBS->OpenProtocol (\r
645 Controller,\r
646 &gEfiPciIoProtocolGuid,\r
647 (VOID **) &PciIo,\r
648 This->DriverBindingHandle,\r
649 IsaIoDevice->Handle,\r
650 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
651 );\r
652 if (EFI_ERROR (Status)) {\r
653 gBS->UninstallMultipleProtocolInterfaces (\r
654 IsaIoDevice->Handle,\r
655 &gEfiDevicePathProtocolGuid,\r
656 IsaIoDevice->DevicePath,\r
657 &gEfiIsaIoProtocolGuid,\r
658 &IsaIoDevice->IsaIo,\r
659 NULL\r
660 );\r
661 }\r
662\r
663Done:\r
664\r
665 if (EFI_ERROR (Status)) {\r
666 if (IsaIoDevice->DevicePath != NULL) {\r
667 gBS->FreePool (IsaIoDevice->DevicePath);\r
668 }\r
669\r
670 gBS->FreePool (IsaIoDevice);\r
671 }\r
672\r
673 return Status;\r
674}\r