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