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