2 Copyright (c) 2006 - 2007 Intel Corporation. <BR>
3 All rights reserved. This program and the accompanying materials
4 are licensed and made available under the terms and conditions of the BSD License
5 which accompanies this distribution. The full text of the license may be found at
6 http://opensource.org/licenses/bsd-license.php
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 @par Revision Reference:
12 This module is modified from DXE\IDE module for Ide Contriller Init support
18 #define PCI_CLASS_MASS_STORAGE 0x01
19 #define PCI_SUB_CLASS_IDE 0x01
23 // IDE Bus Driver Binding Protocol Instance
25 EFI_DRIVER_BINDING_PROTOCOL gIDEBusDriverBinding
= {
26 IDEBusDriverBindingSupported
,
27 IDEBusDriverBindingStart
,
28 IDEBusDriverBindingStop
,
35 // ***********************************************************************************
36 // IDEBusDriverBindingSupported
37 // ***********************************************************************************
40 Register Driver Binding protocol for this driver.
42 @param[in] This -- A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
43 @param[in] ControllerHandle -- The handle of the controller to test.
44 @param[in] RemainingDevicePath -- A pointer to the remaining portion of a device path.
46 @retval EFI_SUCCESS Driver loaded.
47 @retval other Driver not loaded.
52 IDEBusDriverBindingSupported (
53 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
54 IN EFI_HANDLE Controller
,
55 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
57 // TODO: Controller - add argument and description to function comment
58 // TODO: EFI_UNSUPPORTED - add return value to function comment
61 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
63 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
65 if (RemainingDevicePath
!= NULL
) {
66 Node
= (EFI_DEV_PATH
*) RemainingDevicePath
;
67 if (Node
->DevPath
.Type
!= MESSAGING_DEVICE_PATH
||
68 Node
->DevPath
.SubType
!= MSG_ATAPI_DP
||
69 DevicePathNodeLength(&Node
->DevPath
) != sizeof(ATAPI_DEVICE_PATH
)) {
70 return EFI_UNSUPPORTED
;
75 // Open the IO Abstraction(s) needed to perform the supported test
77 Status
= gBS
->OpenProtocol (
79 &gEfiDevicePathProtocolGuid
,
80 (VOID
**) &ParentDevicePath
,
81 This
->DriverBindingHandle
,
83 EFI_OPEN_PROTOCOL_BY_DRIVER
85 if (Status
== EFI_ALREADY_STARTED
) {
89 if (EFI_ERROR (Status
)) {
94 // Close protocol, don't use device path protocol in the .Support() function
98 &gEfiDevicePathProtocolGuid
,
99 This
->DriverBindingHandle
,
104 // Verify the Ide Controller Init Protocol, which installed by the
105 // IdeController module.
106 // Note 1: PciIo protocol has been opened BY_DRIVER by ide_init, so We can't
107 // open BY_DRIVER here) That's why we don't check pciio protocol
108 // Note 2: ide_init driver check ide controller's pci config space, so we dont
109 // check here any more to save code size
111 Status
= gBS
->OpenProtocol (
113 &gEfiIdeControllerInitProtocolGuid
,
115 This
->DriverBindingHandle
,
117 EFI_OPEN_PROTOCOL_BY_DRIVER
120 if (Status
== EFI_ALREADY_STARTED
) {
125 // If protocols were opened normally, closed it
129 &gEfiIdeControllerInitProtocolGuid
,
130 This
->DriverBindingHandle
,
138 // ***********************************************************************************
139 // IDEBusDriverBindingStart
140 // ***********************************************************************************
143 Start this driver on Controller by detecting all disks and installing
144 BlockIo protocol on them.
146 @param This Protocol instance pointer.
147 @param Controller Handle of device to bind driver to.
148 @param RemainingDevicePath Not used, always produce all possible children.
150 @retval EFI_SUCCESS This driver is added to ControllerHandle.
151 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
152 @retval other This driver does not support this device.
157 IDEBusDriverBindingStart (
158 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
159 IN EFI_HANDLE Controller
,
160 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
164 EFI_STATUS SavedStatus
;
165 EFI_PCI_IO_PROTOCOL
*PciIo
;
166 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
169 UINT8 BeginningIdeChannel
;
172 UINT8 BeginningIdeDevice
;
174 IDE_BLK_IO_DEV
*IdeBlkIoDevice
[IdeMaxChannel
][IdeMaxDevice
];
175 IDE_BLK_IO_DEV
*IdeBlkIoDevicePtr
;
176 IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr
[IdeMaxChannel
];
177 ATA_TRANSFER_MODE TransferMode
;
178 ATA_DRIVE_PARMS DriveParameters
;
179 EFI_DEV_PATH NewNode
;
180 UINT8 ConfigurationOptions
;
181 UINT16 CommandBlockBaseAddr
;
182 UINT16 ControlBlockBaseAddr
;
184 IDE_BUS_DRIVER_PRIVATE_DATA
*IdeBusDriverPrivateData
;
187 // Local variables declaration for IdeControllerInit support
189 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
191 BOOLEAN ChannelEnabled
;
193 EFI_IDENTIFY_DATA IdentifyData
;
194 EFI_ATA_COLLECTIVE_MODE
*SupportedModes
;
196 IdeBusDriverPrivateData
= NULL
;
197 SupportedModes
= NULL
;
200 // Perform IdeBus initialization
202 Status
= gBS
->OpenProtocol (
204 &gEfiDevicePathProtocolGuid
,
205 (VOID
**) &ParentDevicePath
,
206 This
->DriverBindingHandle
,
208 EFI_OPEN_PROTOCOL_BY_DRIVER
210 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
215 // Now open the IDE_CONTROLLER_INIT protocol. Step7.1
217 Status
= gBS
->OpenProtocol (
219 &gEfiIdeControllerInitProtocolGuid
,
221 This
->DriverBindingHandle
,
223 EFI_OPEN_PROTOCOL_BY_DRIVER
227 // The following OpenProtocol function with _GET_PROTOCOL attribute and
228 // will not return EFI_ALREADY_STARTED, so save it for now
230 SavedStatus
= Status
;
232 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
233 DEBUG ((EFI_D_ERROR
, "Open Init, Status=%x", Status
));
235 // open protocol is not SUCCESS or not ALREADY_STARTED, error exit
241 // Save Enumall. Step7.2
243 EnumAll
= IdeInit
->EnumAll
;
246 // Consume PCI I/O protocol. Note that the OpenProtocol with _GET_PROTOCOL
247 // attribute will not return EFI_ALREADY_STARTED
249 Status
= gBS
->OpenProtocol (
251 &gEfiPciIoProtocolGuid
,
253 This
->DriverBindingHandle
,
255 EFI_OPEN_PROTOCOL_GET_PROTOCOL
257 if (EFI_ERROR (Status
)) {
258 DEBUG ((EFI_D_ERROR
, "Open PciIo, Status=%x", Status
));
263 // We must check EFI_ALREADY_STARTED because many ATAPI devices are removable
265 if (SavedStatus
!= EFI_ALREADY_STARTED
) {
266 IdeBusDriverPrivateData
= AllocatePool (sizeof (IDE_BUS_DRIVER_PRIVATE_DATA
));
267 if (IdeBusDriverPrivateData
== NULL
) {
268 Status
= EFI_OUT_OF_RESOURCES
;
272 ZeroMem (IdeBusDriverPrivateData
, sizeof (IDE_BUS_DRIVER_PRIVATE_DATA
));
273 Status
= gBS
->InstallMultipleProtocolInterfaces (
276 IdeBusDriverPrivateData
,
279 if (EFI_ERROR (Status
)) {
284 Status
= gBS
->OpenProtocol (
287 (VOID
**) &IdeBusDriverPrivateData
,
288 This
->DriverBindingHandle
,
290 EFI_OPEN_PROTOCOL_GET_PROTOCOL
292 if (EFI_ERROR (Status
)) {
293 IdeBusDriverPrivateData
= NULL
;
298 Status
= PciIo
->Attributes (
300 EfiPciIoAttributeOperationEnable
,
301 EFI_PCI_DEVICE_ENABLE
,
304 if (EFI_ERROR (Status
)) {
309 // Read the environment variable that contains the IDEBus Driver's
310 // Config options that were set by the Driver Configuration Protocol
312 DataSize
= sizeof (ConfigurationOptions
);
313 Status
= gRT
->GetVariable (
314 (CHAR16
*) L
"Configuration",
318 &ConfigurationOptions
320 if (EFI_ERROR (Status
)) {
321 ConfigurationOptions
= 0x0f;
326 // If IdeInit->EnumAll is TRUE, must enumerate all IDE device anyway
328 BeginningIdeChannel
= IdePrimary
;
329 EndIdeChannel
= IdeSecondary
;
330 BeginningIdeDevice
= IdeMaster
;
331 EndIdeDevice
= IdeSlave
;
332 } else if (RemainingDevicePath
== NULL
) {
334 // RemainingDevicePath is NULL, scan IDE bus for each device;
336 BeginningIdeChannel
= IdePrimary
;
337 EndIdeChannel
= IdeSecondary
;
338 BeginningIdeDevice
= IdeMaster
;
340 // default, may be redefined by IdeInit
342 EndIdeDevice
= IdeSlave
;
345 // RemainingDevicePath is not NULL, only scan the specified device.
347 Node
= (EFI_DEV_PATH
*) RemainingDevicePath
;
348 BeginningIdeChannel
= Node
->Atapi
.PrimarySecondary
;
349 EndIdeChannel
= BeginningIdeChannel
;
350 BeginningIdeDevice
= Node
->Atapi
.SlaveMaster
;
351 EndIdeDevice
= BeginningIdeDevice
;
355 // Obtain IDE IO port registers' base addresses
357 Status
= GetIdeRegistersBaseAddr (PciIo
, IdeRegsBaseAddr
);
358 if (EFI_ERROR (Status
)) {
363 // Report status code: begin IdeBus initialization
365 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
367 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_PC_RESET
),
372 // Strictly follow the enumeration based on IDE_CONTROLLER_INIT protocol
374 for (IdeChannel
= BeginningIdeChannel
; IdeChannel
<= EndIdeChannel
; IdeChannel
++) {
376 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelEnumeration
, IdeChannel
);
379 // now obtain channel information fron IdeControllerInit protocol. Step9
381 Status
= IdeInit
->GetChannelInfo (
387 if (EFI_ERROR (Status
)) {
388 DEBUG ((EFI_D_ERROR
, "[GetChannel, Status=%x]", Status
));
392 if (!ChannelEnabled
) {
396 EndIdeDevice
= (UINT8
) EFI_MIN ((MaxDevices
- 1), EndIdeDevice
);
399 // Now inform the IDE Controller Init Module. Sept10
401 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelReset
, IdeChannel
);
404 // No reset channel function implemented. Sept11
406 IdeInit
->NotifyPhase (IdeInit
, EfiIdeAfterChannelReset
, IdeChannel
);
411 IdeInit
->NotifyPhase (
413 EfiIdeBusBeforeDevicePresenceDetection
,
418 // Prepare to detect IDE device of this channel
420 InitializeIDEChannelData ();
423 // -- 1st inner loop --- Master/Slave ------------ Step14
425 for (IdeDevice
= BeginningIdeDevice
; IdeDevice
<= EndIdeDevice
; IdeDevice
++) {
427 // Check whether the configuration options allow this device
429 if (!(ConfigurationOptions
& (1 << (IdeChannel
* 2 + IdeDevice
)))) {
434 // The device has been scanned in another Start(), No need to scan it again
435 // for perf optimization.
437 if (IdeBusDriverPrivateData
->HaveScannedDevice
[IdeChannel
* 2 + IdeDevice
]) {
442 // create child handle for the detected device.
444 IdeBlkIoDevice
[IdeChannel
][IdeDevice
] = AllocatePool (sizeof (IDE_BLK_IO_DEV
));
445 if (IdeBlkIoDevice
[IdeChannel
][IdeDevice
] == NULL
) {
449 IdeBlkIoDevicePtr
= IdeBlkIoDevice
[IdeChannel
][IdeDevice
];
451 ZeroMem (IdeBlkIoDevicePtr
, sizeof (IDE_BLK_IO_DEV
));
453 IdeBlkIoDevicePtr
->Signature
= IDE_BLK_IO_DEV_SIGNATURE
;
454 IdeBlkIoDevicePtr
->Channel
= (EFI_IDE_CHANNEL
) IdeChannel
;
455 IdeBlkIoDevicePtr
->Device
= (EFI_IDE_DEVICE
) IdeDevice
;
458 // initialize Block IO interface's Media pointer
460 IdeBlkIoDevicePtr
->BlkIo
.Media
= &IdeBlkIoDevicePtr
->BlkMedia
;
463 // Initialize IDE IO port addresses, including Command Block registers
464 // and Control Block registers
466 IdeBlkIoDevicePtr
->IoPort
= AllocatePool (sizeof (IDE_BASE_REGISTERS
));
467 if (IdeBlkIoDevicePtr
->IoPort
== NULL
) {
471 ZeroMem (IdeBlkIoDevicePtr
->IoPort
, sizeof (IDE_BASE_REGISTERS
));
472 CommandBlockBaseAddr
= IdeRegsBaseAddr
[IdeChannel
].CommandBlockBaseAddr
;
473 ControlBlockBaseAddr
= IdeRegsBaseAddr
[IdeChannel
].ControlBlockBaseAddr
;
475 IdeBlkIoDevicePtr
->IoPort
->Data
= CommandBlockBaseAddr
;
476 (*(UINT16
*) &IdeBlkIoDevicePtr
->IoPort
->Reg1
) = (UINT16
) (CommandBlockBaseAddr
+ 0x01);
477 IdeBlkIoDevicePtr
->IoPort
->SectorCount
= (UINT16
) (CommandBlockBaseAddr
+ 0x02);
478 IdeBlkIoDevicePtr
->IoPort
->SectorNumber
= (UINT16
) (CommandBlockBaseAddr
+ 0x03);
479 IdeBlkIoDevicePtr
->IoPort
->CylinderLsb
= (UINT16
) (CommandBlockBaseAddr
+ 0x04);
480 IdeBlkIoDevicePtr
->IoPort
->CylinderMsb
= (UINT16
) (CommandBlockBaseAddr
+ 0x05);
481 IdeBlkIoDevicePtr
->IoPort
->Head
= (UINT16
) (CommandBlockBaseAddr
+ 0x06);
482 (*(UINT16
*) &IdeBlkIoDevicePtr
->IoPort
->Reg
) = (UINT16
) (CommandBlockBaseAddr
+ 0x07);
484 (*(UINT16
*) &IdeBlkIoDevicePtr
->IoPort
->Alt
) = ControlBlockBaseAddr
;
485 IdeBlkIoDevicePtr
->IoPort
->DriveAddress
= (UINT16
) (ControlBlockBaseAddr
+ 0x01);
487 IdeBlkIoDevicePtr
->IoPort
->MasterSlave
= (UINT16
) ((IdeDevice
== IdeMaster
) ? 1 : 0);
489 IdeBlkIoDevicePtr
->PciIo
= PciIo
;
490 IdeBlkIoDevicePtr
->IdeBusDriverPrivateData
= IdeBusDriverPrivateData
;
491 IdeBlkIoDevicePtr
->IoPort
->BusMasterBaseAddr
= IdeRegsBaseAddr
[IdeChannel
].BusMasterBaseAddr
;
494 // Report Status code: is about to detect IDE drive
496 REPORT_STATUS_CODE_EX (
498 (EFI_IO_BUS_ATA_ATAPI
| EFI_P_PC_PRESENCE_DETECT
),
507 // Discover device, now!
509 PERF_START (0, "DiscoverIdeDevice", "IDE", 0);
510 Status
= DiscoverIdeDevice (IdeBlkIoDevicePtr
);
511 PERF_END (0, "DiscoverIdeDevice", "IDE", 0);
513 IdeBusDriverPrivateData
->HaveScannedDevice
[IdeChannel
* 2 + IdeDevice
] = TRUE
;
514 IdeBusDriverPrivateData
->DeviceProcessed
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
516 if (!EFI_ERROR (Status
)) {
520 ZeroMem (&NewNode
, sizeof (NewNode
));
521 NewNode
.DevPath
.Type
= MESSAGING_DEVICE_PATH
;
522 NewNode
.DevPath
.SubType
= MSG_ATAPI_DP
;
523 SetDevicePathNodeLength (&NewNode
.DevPath
, sizeof (ATAPI_DEVICE_PATH
));
525 NewNode
.Atapi
.PrimarySecondary
= (UINT8
) IdeBlkIoDevicePtr
->Channel
;
526 NewNode
.Atapi
.SlaveMaster
= (UINT8
) IdeBlkIoDevicePtr
->Device
;
527 NewNode
.Atapi
.Lun
= IdeBlkIoDevicePtr
->Lun
;
528 IdeBlkIoDevicePtr
->DevicePath
= AppendDevicePathNode (
532 if (IdeBlkIoDevicePtr
->DevicePath
== NULL
) {
533 ReleaseIdeResources (IdeBlkIoDevicePtr
);
538 // Submit identify data to IDE controller init driver
540 CopyMem (&IdentifyData
, IdeBlkIoDevicePtr
->pIdData
, sizeof (IdentifyData
));
541 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = TRUE
;
542 IdeInit
->SubmitData (IdeInit
, IdeChannel
, IdeDevice
, &IdentifyData
);
545 // Device detection failed
547 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
548 IdeInit
->SubmitData (IdeInit
, IdeChannel
, IdeDevice
, NULL
);
549 ReleaseIdeResources (IdeBlkIoDevicePtr
);
550 IdeBlkIoDevicePtr
= NULL
;
553 // end of 1st inner loop ---
557 // end of 1st outer loop =========
562 // = 2nd outer loop == Primary/Secondary =================
564 for (IdeChannel
= BeginningIdeChannel
; IdeChannel
<= EndIdeChannel
; IdeChannel
++) {
567 // -- 2nd inner loop --- Master/Slave --------
569 for (IdeDevice
= BeginningIdeDevice
; IdeDevice
<= EndIdeDevice
; IdeDevice
++) {
571 if (IdeBusDriverPrivateData
->DeviceProcessed
[IdeChannel
* 2 + IdeDevice
]) {
575 if (!IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
]) {
579 Status
= IdeInit
->CalculateMode (
585 if (EFI_ERROR (Status
)) {
586 DEBUG ((EFI_D_ERROR
, "[bStStp20S=%x]", Status
));
590 IdeBlkIoDevicePtr
= IdeBlkIoDevice
[IdeChannel
][IdeDevice
];
593 // Set best supported PIO mode on this IDE device
595 if (SupportedModes
->PioMode
.Mode
<= ATA_PIO_MODE_2
) {
596 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_DEFAULT_PIO
;
598 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_FLOW_PIO
;
601 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->PioMode
.Mode
);
603 if (SupportedModes
->ExtModeCount
== 0){
604 Status
= SetDeviceTransferMode (IdeBlkIoDevicePtr
, &TransferMode
);
606 if (EFI_ERROR (Status
)) {
607 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
608 ReleaseIdeResources (IdeBlkIoDevicePtr
);
609 IdeBlkIoDevicePtr
= NULL
;
615 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
616 // be set together. Only one DMA mode can be set to a device. If setting
617 // DMA mode operation fails, we can continue moving on because we only use
618 // PIO mode at boot time. DMA modes are used by certain kind of OS booting
620 if (SupportedModes
->UdmaMode
.Valid
) {
622 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_UDMA
;
623 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->UdmaMode
.Mode
);
624 Status
= SetDeviceTransferMode (IdeBlkIoDevicePtr
, &TransferMode
);
626 if (EFI_ERROR (Status
)) {
627 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
628 ReleaseIdeResources (IdeBlkIoDevicePtr
);
629 IdeBlkIoDevicePtr
= NULL
;
635 IdeBlkIoDevicePtr
->UdmaMode
.Valid
= TRUE
;
636 IdeBlkIoDevicePtr
->UdmaMode
.Mode
= SupportedModes
->UdmaMode
.Mode
;
637 EnableInterrupt (IdeBlkIoDevicePtr
);
638 } else if (SupportedModes
->MultiWordDmaMode
.Valid
) {
640 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_MDMA
;
641 TransferMode
.ModeNumber
= (UINT8
) SupportedModes
->MultiWordDmaMode
.Mode
;
642 Status
= SetDeviceTransferMode (IdeBlkIoDevicePtr
, &TransferMode
);
644 if (EFI_ERROR (Status
)) {
645 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
646 ReleaseIdeResources (IdeBlkIoDevicePtr
);
647 IdeBlkIoDevicePtr
= NULL
;
651 EnableInterrupt (IdeBlkIoDevicePtr
);
654 // Init driver parameters
656 DriveParameters
.Sector
= (UINT8
) IdeBlkIoDevicePtr
->pIdData
->AtaData
.sectors_per_track
;
657 DriveParameters
.Heads
= (UINT8
) (IdeBlkIoDevicePtr
->pIdData
->AtaData
.heads
- 1);
658 DriveParameters
.MultipleSector
= (UINT8
) IdeBlkIoDevicePtr
->pIdData
->AtaData
.multi_sector_cmd_max_sct_cnt
;
660 // Set Parameters for the device:
662 // 2) Establish the block count for READ/WRITE MULTIPLE (EXT) command
664 if ((IdeBlkIoDevicePtr
->Type
== IdeHardDisk
) || (IdeBlkIoDevicePtr
->Type
== Ide48bitAddressingHardDisk
)) {
665 Status
= SetDriveParameters (IdeBlkIoDevicePtr
, &DriveParameters
);
669 // Record PIO mode used in private data
671 IdeBlkIoDevicePtr
->PioMode
= (ATA_PIO_MODE
) SupportedModes
->PioMode
.Mode
;
674 // Set IDE controller Timing Blocks in the PCI Configuration Space
676 IdeInit
->SetTiming (IdeInit
, IdeChannel
, IdeDevice
, SupportedModes
);
679 // Add Component Name for the IDE/ATAPI device that was discovered.
681 IdeBlkIoDevicePtr
->ControllerNameTable
= NULL
;
682 ADD_NAME (IdeBlkIoDevicePtr
);
684 Status
= gBS
->InstallMultipleProtocolInterfaces (
685 &IdeBlkIoDevicePtr
->Handle
,
686 &gEfiDevicePathProtocolGuid
,
687 IdeBlkIoDevicePtr
->DevicePath
,
688 &gEfiBlockIoProtocolGuid
,
689 &IdeBlkIoDevicePtr
->BlkIo
,
690 &gEfiDiskInfoProtocolGuid
,
691 &IdeBlkIoDevicePtr
->DiskInfo
,
695 if (EFI_ERROR (Status
)) {
696 ReleaseIdeResources (IdeBlkIoDevicePtr
);
701 &gEfiPciIoProtocolGuid
,
703 This
->DriverBindingHandle
,
704 IdeBlkIoDevicePtr
->Handle
,
705 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
708 IdeBusDriverPrivateData
->DeviceProcessed
[IdeChannel
* 2 + IdeDevice
] = TRUE
;
711 // Report status code: device eanbled!
713 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
715 (EFI_IO_BUS_ATA_ATAPI
| EFI_P_PC_ENABLE
),
716 IdeBlkIoDevicePtr
->DevicePath
720 // Create event to clear pending IDE interrupt
722 Status
= gBS
->CreateEvent (
723 EVT_SIGNAL_EXIT_BOOT_SERVICES
,
727 &IdeBlkIoDevicePtr
->ExitBootServiceEvent
731 // end of 2nd inner loop ----
735 // end of 2nd outer loop ==========
740 // All configurations done! Notify IdeController to do post initialization
741 // work such as saving IDE controller PCI settings for S3 resume
743 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBusPhaseMaximum
, 0);
745 if (SupportedModes
!= NULL
) {
746 gBS
->FreePool (SupportedModes
);
749 PERF_START (0, "Finish IDE detection", "IDE", 1);
750 PERF_END (0, "Finish IDE detection", "IDE", 0);
757 // Report error code: controller error
759 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
760 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
761 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_EC_CONTROLLER_ERROR
),
767 &gEfiIdeControllerInitProtocolGuid
,
768 This
->DriverBindingHandle
,
772 gBS
->UninstallMultipleProtocolInterfaces (
775 IdeBusDriverPrivateData
,
779 if (IdeBusDriverPrivateData
!= NULL
) {
780 gBS
->FreePool (IdeBusDriverPrivateData
);
783 if (SupportedModes
!= NULL
) {
784 gBS
->FreePool (SupportedModes
);
789 &gEfiPciIoProtocolGuid
,
790 This
->DriverBindingHandle
,
796 &gEfiDevicePathProtocolGuid
,
797 This
->DriverBindingHandle
,
806 // ***********************************************************************************
807 // IDEBusDriverBindingStop
808 // ***********************************************************************************
811 Stop this driver on Controller Handle.
813 @param This Protocol instance pointer.
814 @param DeviceHandle Handle of device to stop driver on
815 @param NumberOfChildren Not used
816 @param ChildHandleBuffer Not used
818 @retval EFI_SUCCESS This driver is removed DeviceHandle
819 @retval other This driver was not removed from this device
824 IDEBusDriverBindingStop (
825 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
826 IN EFI_HANDLE Controller
,
827 IN UINTN NumberOfChildren
,
828 IN EFI_HANDLE
*ChildHandleBuffer
830 // TODO: Controller - add argument and description to function comment
831 // TODO: EFI_DEVICE_ERROR - add return value to function comment
834 EFI_PCI_IO_PROTOCOL
*PciIo
;
835 BOOLEAN AllChildrenStopped
;
837 IDE_BUS_DRIVER_PRIVATE_DATA
*IdeBusDriverPrivateData
;
839 IdeBusDriverPrivateData
= NULL
;
841 if (NumberOfChildren
== 0) {
843 Status
= gBS
->OpenProtocol (
845 &gEfiPciIoProtocolGuid
,
847 This
->DriverBindingHandle
,
849 EFI_OPEN_PROTOCOL_GET_PROTOCOL
851 if (!EFI_ERROR (Status
)) {
854 EfiPciIoAttributeOperationDisable
,
855 EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO
| EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO
| EFI_PCI_DEVICE_ENABLE
,
863 (VOID
**) &IdeBusDriverPrivateData
,
864 This
->DriverBindingHandle
,
866 EFI_OPEN_PROTOCOL_GET_PROTOCOL
869 gBS
->UninstallMultipleProtocolInterfaces (
872 IdeBusDriverPrivateData
,
876 if (IdeBusDriverPrivateData
!= NULL
) {
877 gBS
->FreePool (IdeBusDriverPrivateData
);
880 // Close the bus driver
884 &gEfiIdeControllerInitProtocolGuid
,
885 This
->DriverBindingHandle
,
890 &gEfiPciIoProtocolGuid
,
891 This
->DriverBindingHandle
,
896 &gEfiDevicePathProtocolGuid
,
897 This
->DriverBindingHandle
,
904 AllChildrenStopped
= TRUE
;
906 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
908 Status
= DeRegisterIdeDevice (This
, Controller
, ChildHandleBuffer
[Index
]);
910 if (EFI_ERROR (Status
)) {
911 AllChildrenStopped
= FALSE
;
915 if (!AllChildrenStopped
) {
916 return EFI_DEVICE_ERROR
;
923 // ***********************************************************************************
924 // DeRegisterIdeDevice
925 // ***********************************************************************************
928 Deregister an IDE device and free resources
930 @param This Protocol instance pointer.
931 @param Controller Ide device handle
932 @param Handle Handle of device to deregister driver on
938 DeRegisterIdeDevice (
939 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
940 IN EFI_HANDLE Controller
,
943 // TODO: EFI_SUCCESS - add return value to function comment
946 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
947 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
948 EFI_PCI_IO_PROTOCOL
*PciIo
;
951 Status
= gBS
->OpenProtocol (
953 &gEfiBlockIoProtocolGuid
,
955 This
->DriverBindingHandle
,
957 EFI_OPEN_PROTOCOL_GET_PROTOCOL
959 if (EFI_ERROR (Status
)) {
963 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo
);
966 // Report Status code: Device disabled
968 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
970 (EFI_IO_BUS_ATA_ATAPI
| EFI_P_PC_DISABLE
),
971 IdeBlkIoDevice
->DevicePath
975 // Close the child handle
977 Status
= gBS
->CloseProtocol (
979 &gEfiPciIoProtocolGuid
,
980 This
->DriverBindingHandle
,
984 Status
= gBS
->UninstallMultipleProtocolInterfaces (
986 &gEfiDevicePathProtocolGuid
,
987 IdeBlkIoDevice
->DevicePath
,
988 &gEfiBlockIoProtocolGuid
,
989 &IdeBlkIoDevice
->BlkIo
,
990 &gEfiDiskInfoProtocolGuid
,
991 &IdeBlkIoDevice
->DiskInfo
,
995 if (EFI_ERROR (Status
)) {
998 &gEfiPciIoProtocolGuid
,
1000 This
->DriverBindingHandle
,
1002 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1008 // Release allocated resources
1010 Index
= IdeBlkIoDevice
->Channel
* 2 + IdeBlkIoDevice
->Device
;
1011 IdeBlkIoDevice
->IdeBusDriverPrivateData
->HaveScannedDevice
[Index
] = FALSE
;
1013 ReleaseIdeResources (IdeBlkIoDevice
);
1019 // ***********************************************************************************
1021 // ***********************************************************************************
1024 TODO: This - add argument and description to function comment
1025 TODO: ExtendedVerification - add argument and description to function comment
1026 TODO: EFI_DEVICE_ERROR - add return value to function comment
1032 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1033 IN BOOLEAN ExtendedVerification
1036 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1040 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1042 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (This
);
1044 // Requery IDE IO resources in case of the switch of native and legacy modes
1046 ReassignIdeResources (IdeBlkIoDevice
);
1049 // for ATA device, using ATA reset method
1051 if (IdeBlkIoDevice
->Type
== IdeHardDisk
||
1052 IdeBlkIoDevice
->Type
== Ide48bitAddressingHardDisk
) {
1053 Status
= AtaSoftReset (IdeBlkIoDevice
);
1057 if (IdeBlkIoDevice
->Type
== IdeUnknown
) {
1058 Status
= EFI_DEVICE_ERROR
;
1063 // for ATAPI device, using ATAPI reset method
1065 Status
= AtapiSoftReset (IdeBlkIoDevice
);
1066 if (ExtendedVerification
) {
1067 Status
= AtaSoftReset (IdeBlkIoDevice
);
1071 gBS
->RestoreTPL (OldTpl
);
1076 Read data from block io device
1078 @param This Protocol instance pointer.
1079 @param MediaId The media ID of the device
1080 @param LBA Starting LBA address to read data
1081 @param BufferSize The size of data to be read
1082 @param Buffer Caller supplied buffer to save data
1084 @return read data status
1089 IDEBlkIoReadBlocks (
1090 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1093 IN UINTN BufferSize
,
1096 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1098 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1102 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1104 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (This
);
1107 // Requery IDE IO resources in case of the switch of native and legacy modes
1109 ReassignIdeResources (IdeBlkIoDevice
);
1112 // For ATA compatible device, use ATA read block's mechanism
1114 if (IdeBlkIoDevice
->Type
== IdeHardDisk
||
1115 IdeBlkIoDevice
->Type
== Ide48bitAddressingHardDisk
) {
1116 Status
= AtaBlkIoReadBlocks (
1126 if (IdeBlkIoDevice
->Type
== IdeUnknown
) {
1127 Status
= EFI_DEVICE_ERROR
;
1132 // for ATAPI device, using ATAPI read block's mechanism
1134 Status
= AtapiBlkIoReadBlocks (
1143 gBS
->RestoreTPL (OldTpl
);
1149 Write data to block io device
1151 @param This Protocol instance pointer.
1152 @param MediaId The media ID of the device
1153 @param LBA Starting LBA address to write data
1154 @param BufferSize The size of data to be written
1155 @param Buffer Caller supplied buffer to save data
1157 @return write data status
1162 IDEBlkIoWriteBlocks (
1163 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1166 IN UINTN BufferSize
,
1169 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1171 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1175 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1177 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (This
);
1179 // Requery IDE IO resources in case of the switch of native and legacy modes
1181 ReassignIdeResources (IdeBlkIoDevice
);
1184 // for ATA device, using ATA write block's mechanism
1186 if (IdeBlkIoDevice
->Type
== IdeHardDisk
||
1187 IdeBlkIoDevice
->Type
== Ide48bitAddressingHardDisk
) {
1189 Status
= AtaBlkIoWriteBlocks (
1199 if (IdeBlkIoDevice
->Type
== IdeUnknown
) {
1200 Status
= EFI_DEVICE_ERROR
;
1205 // for ATAPI device, using ATAPI write block's mechanism
1207 Status
= AtapiBlkIoWriteBlocks (
1216 gBS
->RestoreTPL (OldTpl
);
1221 // ***********************************************************************************
1222 // IDEBlkIoFlushBlocks
1223 // ***********************************************************************************
1226 TODO: This - add argument and description to function comment
1227 TODO: EFI_SUCCESS - add return value to function comment
1231 IDEBlkIoFlushBlocks (
1232 IN EFI_BLOCK_IO_PROTOCOL
*This
1242 Return the results of the Inquiry command to a drive in InquiryData.
1243 Data format of Inquiry data is defined by the Interface GUID.
1245 @param This Protocol instance pointer.
1246 @param InquiryData Results of Inquiry command to device
1247 @param InquiryDataSize Size of InquiryData in bytes.
1249 @retval EFI_SUCCESS InquiryData valid
1250 @retval EFI_NOT_FOUND Device does not support this data class
1251 @retval EFI_DEVICE_ERROR Error reading InquiryData from device
1252 @retval EFI_BUFFER_TOO_SMALL IntquiryDataSize not big enough
1257 IDEDiskInfoInquiry (
1258 IN EFI_DISK_INFO_PROTOCOL
*This
,
1259 IN OUT VOID
*InquiryData
,
1260 IN OUT UINT32
*InquiryDataSize
1263 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1265 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This
);
1267 if (*InquiryDataSize
< sizeof (INQUIRY_DATA
)) {
1268 *InquiryDataSize
= sizeof (INQUIRY_DATA
);
1269 return EFI_BUFFER_TOO_SMALL
;
1272 if (IdeBlkIoDevice
->pInquiryData
== NULL
) {
1273 return EFI_NOT_FOUND
;
1276 gBS
->CopyMem (InquiryData
, IdeBlkIoDevice
->pInquiryData
, sizeof (INQUIRY_DATA
));
1277 *InquiryDataSize
= sizeof (INQUIRY_DATA
);
1283 Return the results of the Identify command to a drive in IdentifyData.
1284 Data format of Identify data is defined by the Interface GUID.
1286 @param This Protocol instance pointer.
1287 @param IdentifyData Results of Identify command to device
1288 @param IdentifyDataSize Size of IdentifyData in bytes.
1290 @retval EFI_SUCCESS IdentifyData valid
1291 @retval EFI_NOT_FOUND Device does not support this data class
1292 @retval EFI_DEVICE_ERROR Error reading IdentifyData from device
1293 @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough
1298 IDEDiskInfoIdentify (
1299 IN EFI_DISK_INFO_PROTOCOL
*This
,
1300 IN OUT VOID
*IdentifyData
,
1301 IN OUT UINT32
*IdentifyDataSize
1304 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1306 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This
);
1308 if (*IdentifyDataSize
< sizeof (EFI_IDENTIFY_DATA
)) {
1309 *IdentifyDataSize
= sizeof (EFI_IDENTIFY_DATA
);
1310 return EFI_BUFFER_TOO_SMALL
;
1313 if (IdeBlkIoDevice
->pIdData
== NULL
) {
1314 return EFI_NOT_FOUND
;
1317 gBS
->CopyMem (IdentifyData
, IdeBlkIoDevice
->pIdData
, sizeof (EFI_IDENTIFY_DATA
));
1318 *IdentifyDataSize
= sizeof (EFI_IDENTIFY_DATA
);
1324 Return the results of the Request Sense command to a drive in SenseData.
1325 Data format of Sense data is defined by the Interface GUID.
1327 @param This Protocol instance pointer.
1328 @param SenseData Results of Request Sense command to device
1329 @param SenseDataSize Size of SenseData in bytes.
1330 @param SenseDataNumber Type of SenseData
1332 @retval EFI_SUCCESS InquiryData valid
1333 @retval EFI_NOT_FOUND Device does not support this data class
1334 @retval EFI_DEVICE_ERROR Error reading InquiryData from device
1335 @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough
1340 IDEDiskInfoSenseData (
1341 IN EFI_DISK_INFO_PROTOCOL
*This
,
1342 IN OUT VOID
*SenseData
,
1343 IN OUT UINT32
*SenseDataSize
,
1344 OUT UINT8
*SenseDataNumber
1347 return EFI_NOT_FOUND
;
1351 Return the results of the Request Sense command to a drive in SenseData.
1352 Data format of Sense data is defined by the Interface GUID.
1354 @param This Protocol instance pointer.
1355 @param IdeChannel Primary or Secondary
1356 @param IdeDevice Master or Slave
1358 @retval EFI_SUCCESS IdeChannel and IdeDevice are valid
1359 @retval EFI_UNSUPPORTED This is not an IDE device
1364 IDEDiskInfoWhichIde (
1365 IN EFI_DISK_INFO_PROTOCOL
*This
,
1366 OUT UINT32
*IdeChannel
,
1367 OUT UINT32
*IdeDevice
1370 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1372 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This
);
1373 *IdeChannel
= IdeBlkIoDevice
->Channel
;
1374 *IdeDevice
= IdeBlkIoDevice
->Device
;
1380 The user Entry Point for module IdeBus. The user code starts with this function.
1382 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1383 @param[in] SystemTable A pointer to the EFI System Table.
1385 @retval EFI_SUCCESS The entry point is executed successfully.
1386 @retval other Some error occurs when executing this entry point.
1392 IN EFI_HANDLE ImageHandle
,
1393 IN EFI_SYSTEM_TABLE
*SystemTable
1399 // Install driver model protocol(s).
1401 Status
= EfiLibInstallAllDriverProtocols (
1404 &gIDEBusDriverBinding
,
1406 &gIDEBusComponentName
,
1410 ASSERT_EFI_ERROR (Status
);