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