2 Copyright (c) 2006 - 2008, Intel Corporation
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
;
188 // Local variables declaration for IdeControllerInit support
190 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
192 BOOLEAN ChannelEnabled
;
194 EFI_IDENTIFY_DATA IdentifyData
;
195 EFI_ATA_COLLECTIVE_MODE
*SupportedModes
;
197 IdeBusDriverPrivateData
= NULL
;
198 SupportedModes
= NULL
;
201 // Perform IdeBus initialization
203 Status
= gBS
->OpenProtocol (
205 &gEfiDevicePathProtocolGuid
,
206 (VOID
**) &ParentDevicePath
,
207 This
->DriverBindingHandle
,
209 EFI_OPEN_PROTOCOL_BY_DRIVER
211 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
216 // Now open the IDE_CONTROLLER_INIT protocol. Step7.1
218 Status
= gBS
->OpenProtocol (
220 &gEfiIdeControllerInitProtocolGuid
,
222 This
->DriverBindingHandle
,
224 EFI_OPEN_PROTOCOL_BY_DRIVER
228 // The following OpenProtocol function with _GET_PROTOCOL attribute and
229 // will not return EFI_ALREADY_STARTED, so save it for now
231 SavedStatus
= Status
;
233 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
234 DEBUG ((EFI_D_ERROR
, "Open Init, Status=%x", Status
));
236 // open protocol is not SUCCESS or not ALREADY_STARTED, error exit
242 // Save Enumall. Step7.2
244 EnumAll
= IdeInit
->EnumAll
;
247 // Consume PCI I/O protocol. Note that the OpenProtocol with _GET_PROTOCOL
248 // attribute will not return EFI_ALREADY_STARTED
250 Status
= gBS
->OpenProtocol (
252 &gEfiPciIoProtocolGuid
,
254 This
->DriverBindingHandle
,
256 EFI_OPEN_PROTOCOL_GET_PROTOCOL
258 if (EFI_ERROR (Status
)) {
259 DEBUG ((EFI_D_ERROR
, "Open PciIo, Status=%x", Status
));
264 // We must check EFI_ALREADY_STARTED because many ATAPI devices are removable
266 if (SavedStatus
!= EFI_ALREADY_STARTED
) {
267 IdeBusDriverPrivateData
= AllocatePool (sizeof (IDE_BUS_DRIVER_PRIVATE_DATA
));
268 if (IdeBusDriverPrivateData
== NULL
) {
269 Status
= EFI_OUT_OF_RESOURCES
;
273 ZeroMem (IdeBusDriverPrivateData
, sizeof (IDE_BUS_DRIVER_PRIVATE_DATA
));
274 Status
= gBS
->InstallMultipleProtocolInterfaces (
277 IdeBusDriverPrivateData
,
280 if (EFI_ERROR (Status
)) {
285 Status
= gBS
->OpenProtocol (
288 (VOID
**) &IdeBusDriverPrivateData
,
289 This
->DriverBindingHandle
,
291 EFI_OPEN_PROTOCOL_GET_PROTOCOL
293 if (EFI_ERROR (Status
)) {
294 IdeBusDriverPrivateData
= NULL
;
299 Status
= PciIo
->Attributes (
301 EfiPciIoAttributeOperationSupported
,
305 if (!EFI_ERROR (Status
)) {
306 Supports
&= EFI_PCI_DEVICE_ENABLE
;
307 Status
= PciIo
->Attributes (
309 EfiPciIoAttributeOperationEnable
,
315 if (EFI_ERROR (Status
)) {
320 // Read the environment variable that contains the IDEBus Driver's
321 // Config options that were set by the Driver Configuration Protocol
323 DataSize
= sizeof (ConfigurationOptions
);
324 Status
= gRT
->GetVariable (
325 (CHAR16
*) L
"Configuration",
329 &ConfigurationOptions
331 if (EFI_ERROR (Status
)) {
332 ConfigurationOptions
= 0x0f;
337 // If IdeInit->EnumAll is TRUE, must enumerate all IDE device anyway
339 BeginningIdeChannel
= IdePrimary
;
340 EndIdeChannel
= IdeSecondary
;
341 BeginningIdeDevice
= IdeMaster
;
342 EndIdeDevice
= IdeSlave
;
343 } else if (RemainingDevicePath
== NULL
) {
345 // RemainingDevicePath is NULL, scan IDE bus for each device;
347 BeginningIdeChannel
= IdePrimary
;
348 EndIdeChannel
= IdeSecondary
;
349 BeginningIdeDevice
= IdeMaster
;
351 // default, may be redefined by IdeInit
353 EndIdeDevice
= IdeSlave
;
356 // RemainingDevicePath is not NULL, only scan the specified device.
358 Node
= (EFI_DEV_PATH
*) RemainingDevicePath
;
359 BeginningIdeChannel
= Node
->Atapi
.PrimarySecondary
;
360 EndIdeChannel
= BeginningIdeChannel
;
361 BeginningIdeDevice
= Node
->Atapi
.SlaveMaster
;
362 EndIdeDevice
= BeginningIdeDevice
;
366 // Obtain IDE IO port registers' base addresses
368 Status
= GetIdeRegistersBaseAddr (PciIo
, IdeRegsBaseAddr
);
369 if (EFI_ERROR (Status
)) {
374 // Report status code: begin IdeBus initialization
376 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
378 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_PC_RESET
),
383 // Strictly follow the enumeration based on IDE_CONTROLLER_INIT protocol
385 for (IdeChannel
= BeginningIdeChannel
; IdeChannel
<= EndIdeChannel
; IdeChannel
++) {
387 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelEnumeration
, IdeChannel
);
390 // now obtain channel information fron IdeControllerInit protocol. Step9
392 Status
= IdeInit
->GetChannelInfo (
398 if (EFI_ERROR (Status
)) {
399 DEBUG ((EFI_D_ERROR
, "[GetChannel, Status=%x]", Status
));
403 if (!ChannelEnabled
) {
407 EndIdeDevice
= (UINT8
) MIN ((MaxDevices
- 1), EndIdeDevice
);
410 // Now inform the IDE Controller Init Module. Sept10
412 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelReset
, IdeChannel
);
415 // No reset channel function implemented. Sept11
417 IdeInit
->NotifyPhase (IdeInit
, EfiIdeAfterChannelReset
, IdeChannel
);
422 IdeInit
->NotifyPhase (
424 EfiIdeBusBeforeDevicePresenceDetection
,
429 // Prepare to detect IDE device of this channel
431 InitializeIDEChannelData ();
434 // -- 1st inner loop --- Master/Slave ------------ Step14
436 for (IdeDevice
= BeginningIdeDevice
; IdeDevice
<= EndIdeDevice
; IdeDevice
++) {
438 // Check whether the configuration options allow this device
440 if (!(ConfigurationOptions
& (1 << (IdeChannel
* 2 + IdeDevice
)))) {
445 // The device has been scanned in another Start(), No need to scan it again
446 // for perf optimization.
448 if (IdeBusDriverPrivateData
->HaveScannedDevice
[IdeChannel
* 2 + IdeDevice
]) {
453 // create child handle for the detected device.
455 IdeBlkIoDevice
[IdeChannel
][IdeDevice
] = AllocatePool (sizeof (IDE_BLK_IO_DEV
));
456 if (IdeBlkIoDevice
[IdeChannel
][IdeDevice
] == NULL
) {
460 IdeBlkIoDevicePtr
= IdeBlkIoDevice
[IdeChannel
][IdeDevice
];
462 ZeroMem (IdeBlkIoDevicePtr
, sizeof (IDE_BLK_IO_DEV
));
464 IdeBlkIoDevicePtr
->Signature
= IDE_BLK_IO_DEV_SIGNATURE
;
465 IdeBlkIoDevicePtr
->Channel
= (EFI_IDE_CHANNEL
) IdeChannel
;
466 IdeBlkIoDevicePtr
->Device
= (EFI_IDE_DEVICE
) IdeDevice
;
469 // initialize Block IO interface's Media pointer
471 IdeBlkIoDevicePtr
->BlkIo
.Media
= &IdeBlkIoDevicePtr
->BlkMedia
;
474 // Initialize IDE IO port addresses, including Command Block registers
475 // and Control Block registers
477 IdeBlkIoDevicePtr
->IoPort
= AllocatePool (sizeof (IDE_BASE_REGISTERS
));
478 if (IdeBlkIoDevicePtr
->IoPort
== NULL
) {
482 ZeroMem (IdeBlkIoDevicePtr
->IoPort
, sizeof (IDE_BASE_REGISTERS
));
483 CommandBlockBaseAddr
= IdeRegsBaseAddr
[IdeChannel
].CommandBlockBaseAddr
;
484 ControlBlockBaseAddr
= IdeRegsBaseAddr
[IdeChannel
].ControlBlockBaseAddr
;
486 IdeBlkIoDevicePtr
->IoPort
->Data
= CommandBlockBaseAddr
;
487 (*(UINT16
*) &IdeBlkIoDevicePtr
->IoPort
->Reg1
) = (UINT16
) (CommandBlockBaseAddr
+ 0x01);
488 IdeBlkIoDevicePtr
->IoPort
->SectorCount
= (UINT16
) (CommandBlockBaseAddr
+ 0x02);
489 IdeBlkIoDevicePtr
->IoPort
->SectorNumber
= (UINT16
) (CommandBlockBaseAddr
+ 0x03);
490 IdeBlkIoDevicePtr
->IoPort
->CylinderLsb
= (UINT16
) (CommandBlockBaseAddr
+ 0x04);
491 IdeBlkIoDevicePtr
->IoPort
->CylinderMsb
= (UINT16
) (CommandBlockBaseAddr
+ 0x05);
492 IdeBlkIoDevicePtr
->IoPort
->Head
= (UINT16
) (CommandBlockBaseAddr
+ 0x06);
493 (*(UINT16
*) &IdeBlkIoDevicePtr
->IoPort
->Reg
) = (UINT16
) (CommandBlockBaseAddr
+ 0x07);
495 (*(UINT16
*) &IdeBlkIoDevicePtr
->IoPort
->Alt
) = ControlBlockBaseAddr
;
496 IdeBlkIoDevicePtr
->IoPort
->DriveAddress
= (UINT16
) (ControlBlockBaseAddr
+ 0x01);
498 IdeBlkIoDevicePtr
->IoPort
->MasterSlave
= (UINT16
) ((IdeDevice
== IdeMaster
) ? 1 : 0);
500 IdeBlkIoDevicePtr
->PciIo
= PciIo
;
501 IdeBlkIoDevicePtr
->IdeBusDriverPrivateData
= IdeBusDriverPrivateData
;
502 IdeBlkIoDevicePtr
->IoPort
->BusMasterBaseAddr
= IdeRegsBaseAddr
[IdeChannel
].BusMasterBaseAddr
;
505 // Report Status code: is about to detect IDE drive
507 REPORT_STATUS_CODE_EX (
509 (EFI_IO_BUS_ATA_ATAPI
| EFI_P_PC_PRESENCE_DETECT
),
518 // Discover device, now!
520 PERF_START (0, "DiscoverIdeDevice", "IDE", 0);
521 Status
= DiscoverIdeDevice (IdeBlkIoDevicePtr
);
522 PERF_END (0, "DiscoverIdeDevice", "IDE", 0);
524 IdeBusDriverPrivateData
->HaveScannedDevice
[IdeChannel
* 2 + IdeDevice
] = TRUE
;
525 IdeBusDriverPrivateData
->DeviceProcessed
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
527 if (!EFI_ERROR (Status
)) {
531 ZeroMem (&NewNode
, sizeof (NewNode
));
532 NewNode
.DevPath
.Type
= MESSAGING_DEVICE_PATH
;
533 NewNode
.DevPath
.SubType
= MSG_ATAPI_DP
;
534 SetDevicePathNodeLength (&NewNode
.DevPath
, sizeof (ATAPI_DEVICE_PATH
));
536 NewNode
.Atapi
.PrimarySecondary
= (UINT8
) IdeBlkIoDevicePtr
->Channel
;
537 NewNode
.Atapi
.SlaveMaster
= (UINT8
) IdeBlkIoDevicePtr
->Device
;
538 NewNode
.Atapi
.Lun
= IdeBlkIoDevicePtr
->Lun
;
539 IdeBlkIoDevicePtr
->DevicePath
= AppendDevicePathNode (
543 if (IdeBlkIoDevicePtr
->DevicePath
== NULL
) {
544 ReleaseIdeResources (IdeBlkIoDevicePtr
);
549 // Submit identify data to IDE controller init driver
551 CopyMem (&IdentifyData
, IdeBlkIoDevicePtr
->pIdData
, sizeof (IdentifyData
));
552 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = TRUE
;
553 IdeInit
->SubmitData (IdeInit
, IdeChannel
, IdeDevice
, &IdentifyData
);
556 // Device detection failed
558 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
559 IdeInit
->SubmitData (IdeInit
, IdeChannel
, IdeDevice
, NULL
);
560 ReleaseIdeResources (IdeBlkIoDevicePtr
);
561 IdeBlkIoDevicePtr
= NULL
;
564 // end of 1st inner loop ---
568 // end of 1st outer loop =========
573 // = 2nd outer loop == Primary/Secondary =================
575 for (IdeChannel
= BeginningIdeChannel
; IdeChannel
<= EndIdeChannel
; IdeChannel
++) {
578 // -- 2nd inner loop --- Master/Slave --------
580 for (IdeDevice
= BeginningIdeDevice
; IdeDevice
<= EndIdeDevice
; IdeDevice
++) {
582 if (IdeBusDriverPrivateData
->DeviceProcessed
[IdeChannel
* 2 + IdeDevice
]) {
586 if (!IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
]) {
590 Status
= IdeInit
->CalculateMode (
596 if (EFI_ERROR (Status
)) {
597 DEBUG ((EFI_D_ERROR
, "[bStStp20S=%x]", Status
));
601 IdeBlkIoDevicePtr
= IdeBlkIoDevice
[IdeChannel
][IdeDevice
];
604 // Set best supported PIO mode on this IDE device
606 if (SupportedModes
->PioMode
.Mode
<= ATA_PIO_MODE_2
) {
607 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_DEFAULT_PIO
;
609 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_FLOW_PIO
;
612 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->PioMode
.Mode
);
614 if (SupportedModes
->ExtModeCount
== 0){
615 Status
= SetDeviceTransferMode (IdeBlkIoDevicePtr
, &TransferMode
);
617 if (EFI_ERROR (Status
)) {
618 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
619 ReleaseIdeResources (IdeBlkIoDevicePtr
);
620 IdeBlkIoDevicePtr
= NULL
;
626 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
627 // be set together. Only one DMA mode can be set to a device. If setting
628 // DMA mode operation fails, we can continue moving on because we only use
629 // PIO mode at boot time. DMA modes are used by certain kind of OS booting
631 if (SupportedModes
->UdmaMode
.Valid
) {
633 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_UDMA
;
634 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->UdmaMode
.Mode
);
635 Status
= SetDeviceTransferMode (IdeBlkIoDevicePtr
, &TransferMode
);
637 if (EFI_ERROR (Status
)) {
638 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
639 ReleaseIdeResources (IdeBlkIoDevicePtr
);
640 IdeBlkIoDevicePtr
= NULL
;
646 IdeBlkIoDevicePtr
->UdmaMode
.Valid
= TRUE
;
647 IdeBlkIoDevicePtr
->UdmaMode
.Mode
= SupportedModes
->UdmaMode
.Mode
;
648 EnableInterrupt (IdeBlkIoDevicePtr
);
649 } else if (SupportedModes
->MultiWordDmaMode
.Valid
) {
651 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_MDMA
;
652 TransferMode
.ModeNumber
= (UINT8
) SupportedModes
->MultiWordDmaMode
.Mode
;
653 Status
= SetDeviceTransferMode (IdeBlkIoDevicePtr
, &TransferMode
);
655 if (EFI_ERROR (Status
)) {
656 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
657 ReleaseIdeResources (IdeBlkIoDevicePtr
);
658 IdeBlkIoDevicePtr
= NULL
;
662 EnableInterrupt (IdeBlkIoDevicePtr
);
665 // Init driver parameters
667 DriveParameters
.Sector
= (UINT8
) IdeBlkIoDevicePtr
->pIdData
->AtaData
.sectors_per_track
;
668 DriveParameters
.Heads
= (UINT8
) (IdeBlkIoDevicePtr
->pIdData
->AtaData
.heads
- 1);
669 DriveParameters
.MultipleSector
= (UINT8
) IdeBlkIoDevicePtr
->pIdData
->AtaData
.multi_sector_cmd_max_sct_cnt
;
671 // Set Parameters for the device:
673 // 2) Establish the block count for READ/WRITE MULTIPLE (EXT) command
675 if ((IdeBlkIoDevicePtr
->Type
== IdeHardDisk
) || (IdeBlkIoDevicePtr
->Type
== Ide48bitAddressingHardDisk
)) {
676 Status
= SetDriveParameters (IdeBlkIoDevicePtr
, &DriveParameters
);
680 // Record PIO mode used in private data
682 IdeBlkIoDevicePtr
->PioMode
= (ATA_PIO_MODE
) SupportedModes
->PioMode
.Mode
;
685 // Set IDE controller Timing Blocks in the PCI Configuration Space
687 IdeInit
->SetTiming (IdeInit
, IdeChannel
, IdeDevice
, SupportedModes
);
690 // Add Component Name for the IDE/ATAPI device that was discovered.
692 IdeBlkIoDevicePtr
->ControllerNameTable
= NULL
;
693 ADD_NAME (IdeBlkIoDevicePtr
);
695 Status
= gBS
->InstallMultipleProtocolInterfaces (
696 &IdeBlkIoDevicePtr
->Handle
,
697 &gEfiDevicePathProtocolGuid
,
698 IdeBlkIoDevicePtr
->DevicePath
,
699 &gEfiBlockIoProtocolGuid
,
700 &IdeBlkIoDevicePtr
->BlkIo
,
701 &gEfiDiskInfoProtocolGuid
,
702 &IdeBlkIoDevicePtr
->DiskInfo
,
706 if (EFI_ERROR (Status
)) {
707 ReleaseIdeResources (IdeBlkIoDevicePtr
);
712 &gEfiPciIoProtocolGuid
,
714 This
->DriverBindingHandle
,
715 IdeBlkIoDevicePtr
->Handle
,
716 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
719 IdeBusDriverPrivateData
->DeviceProcessed
[IdeChannel
* 2 + IdeDevice
] = TRUE
;
722 // Report status code: device eanbled!
724 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
726 (EFI_IO_BUS_ATA_ATAPI
| EFI_P_PC_ENABLE
),
727 IdeBlkIoDevicePtr
->DevicePath
731 // Create event to clear pending IDE interrupt
733 Status
= gBS
->CreateEvent (
734 EVT_SIGNAL_EXIT_BOOT_SERVICES
,
738 &IdeBlkIoDevicePtr
->ExitBootServiceEvent
742 // end of 2nd inner loop ----
746 // end of 2nd outer loop ==========
751 // All configurations done! Notify IdeController to do post initialization
752 // work such as saving IDE controller PCI settings for S3 resume
754 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBusPhaseMaximum
, 0);
756 if (SupportedModes
!= NULL
) {
757 gBS
->FreePool (SupportedModes
);
760 PERF_START (0, "Finish IDE detection", "IDE", 1);
761 PERF_END (0, "Finish IDE detection", "IDE", 0);
768 // Report error code: controller error
770 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
771 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
772 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_EC_CONTROLLER_ERROR
),
778 &gEfiIdeControllerInitProtocolGuid
,
779 This
->DriverBindingHandle
,
783 gBS
->UninstallMultipleProtocolInterfaces (
786 IdeBusDriverPrivateData
,
790 if (IdeBusDriverPrivateData
!= NULL
) {
791 gBS
->FreePool (IdeBusDriverPrivateData
);
794 if (SupportedModes
!= NULL
) {
795 gBS
->FreePool (SupportedModes
);
800 &gEfiPciIoProtocolGuid
,
801 This
->DriverBindingHandle
,
807 &gEfiDevicePathProtocolGuid
,
808 This
->DriverBindingHandle
,
817 // ***********************************************************************************
818 // IDEBusDriverBindingStop
819 // ***********************************************************************************
822 Stop this driver on Controller Handle.
824 @param This Protocol instance pointer.
825 @param DeviceHandle Handle of device to stop driver on
826 @param NumberOfChildren Not used
827 @param ChildHandleBuffer Not used
829 @retval EFI_SUCCESS This driver is removed DeviceHandle
830 @retval other This driver was not removed from this device
835 IDEBusDriverBindingStop (
836 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
837 IN EFI_HANDLE Controller
,
838 IN UINTN NumberOfChildren
,
839 IN EFI_HANDLE
*ChildHandleBuffer
841 // TODO: Controller - add argument and description to function comment
842 // TODO: EFI_DEVICE_ERROR - add return value to function comment
845 EFI_PCI_IO_PROTOCOL
*PciIo
;
846 BOOLEAN AllChildrenStopped
;
848 IDE_BUS_DRIVER_PRIVATE_DATA
*IdeBusDriverPrivateData
;
851 IdeBusDriverPrivateData
= NULL
;
853 if (NumberOfChildren
== 0) {
855 Status
= gBS
->OpenProtocol (
857 &gEfiPciIoProtocolGuid
,
859 This
->DriverBindingHandle
,
861 EFI_OPEN_PROTOCOL_GET_PROTOCOL
863 if (!EFI_ERROR (Status
)) {
864 Status
= PciIo
->Attributes (
866 EfiPciIoAttributeOperationSupported
,
870 if (!EFI_ERROR (Status
)) {
871 Supports
&= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO
| EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO
| EFI_PCI_DEVICE_ENABLE
;
874 EfiPciIoAttributeOperationDisable
,
884 (VOID
**) &IdeBusDriverPrivateData
,
885 This
->DriverBindingHandle
,
887 EFI_OPEN_PROTOCOL_GET_PROTOCOL
890 gBS
->UninstallMultipleProtocolInterfaces (
893 IdeBusDriverPrivateData
,
897 if (IdeBusDriverPrivateData
!= NULL
) {
898 gBS
->FreePool (IdeBusDriverPrivateData
);
901 // Close the bus driver
905 &gEfiIdeControllerInitProtocolGuid
,
906 This
->DriverBindingHandle
,
911 &gEfiPciIoProtocolGuid
,
912 This
->DriverBindingHandle
,
917 &gEfiDevicePathProtocolGuid
,
918 This
->DriverBindingHandle
,
925 AllChildrenStopped
= TRUE
;
927 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
929 Status
= DeRegisterIdeDevice (This
, Controller
, ChildHandleBuffer
[Index
]);
931 if (EFI_ERROR (Status
)) {
932 AllChildrenStopped
= FALSE
;
936 if (!AllChildrenStopped
) {
937 return EFI_DEVICE_ERROR
;
944 // ***********************************************************************************
945 // DeRegisterIdeDevice
946 // ***********************************************************************************
949 Deregister an IDE device and free resources
951 @param This Protocol instance pointer.
952 @param Controller Ide device handle
953 @param Handle Handle of device to deregister driver on
959 DeRegisterIdeDevice (
960 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
961 IN EFI_HANDLE Controller
,
964 // TODO: EFI_SUCCESS - add return value to function comment
967 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
968 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
969 EFI_PCI_IO_PROTOCOL
*PciIo
;
972 Status
= gBS
->OpenProtocol (
974 &gEfiBlockIoProtocolGuid
,
976 This
->DriverBindingHandle
,
978 EFI_OPEN_PROTOCOL_GET_PROTOCOL
980 if (EFI_ERROR (Status
)) {
984 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo
);
987 // Report Status code: Device disabled
989 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
991 (EFI_IO_BUS_ATA_ATAPI
| EFI_P_PC_DISABLE
),
992 IdeBlkIoDevice
->DevicePath
996 // Close the child handle
998 Status
= gBS
->CloseProtocol (
1000 &gEfiPciIoProtocolGuid
,
1001 This
->DriverBindingHandle
,
1005 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1007 &gEfiDevicePathProtocolGuid
,
1008 IdeBlkIoDevice
->DevicePath
,
1009 &gEfiBlockIoProtocolGuid
,
1010 &IdeBlkIoDevice
->BlkIo
,
1011 &gEfiDiskInfoProtocolGuid
,
1012 &IdeBlkIoDevice
->DiskInfo
,
1016 if (EFI_ERROR (Status
)) {
1019 &gEfiPciIoProtocolGuid
,
1021 This
->DriverBindingHandle
,
1023 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1029 // Release allocated resources
1031 Index
= IdeBlkIoDevice
->Channel
* 2 + IdeBlkIoDevice
->Device
;
1032 IdeBlkIoDevice
->IdeBusDriverPrivateData
->HaveScannedDevice
[Index
] = FALSE
;
1034 ReleaseIdeResources (IdeBlkIoDevice
);
1040 // ***********************************************************************************
1042 // ***********************************************************************************
1045 TODO: This - add argument and description to function comment
1046 TODO: ExtendedVerification - add argument and description to function comment
1047 TODO: EFI_DEVICE_ERROR - add return value to function comment
1053 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1054 IN BOOLEAN ExtendedVerification
1057 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1061 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1063 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (This
);
1065 // Requery IDE IO resources in case of the switch of native and legacy modes
1067 ReassignIdeResources (IdeBlkIoDevice
);
1070 // for ATA device, using ATA reset method
1072 if (IdeBlkIoDevice
->Type
== IdeHardDisk
||
1073 IdeBlkIoDevice
->Type
== Ide48bitAddressingHardDisk
) {
1074 Status
= AtaSoftReset (IdeBlkIoDevice
);
1078 if (IdeBlkIoDevice
->Type
== IdeUnknown
) {
1079 Status
= EFI_DEVICE_ERROR
;
1084 // for ATAPI device, using ATAPI reset method
1086 Status
= AtapiSoftReset (IdeBlkIoDevice
);
1087 if (ExtendedVerification
) {
1088 Status
= AtaSoftReset (IdeBlkIoDevice
);
1092 gBS
->RestoreTPL (OldTpl
);
1097 Read data from block io device
1099 @param This Protocol instance pointer.
1100 @param MediaId The media ID of the device
1101 @param LBA Starting LBA address to read data
1102 @param BufferSize The size of data to be read
1103 @param Buffer Caller supplied buffer to save data
1105 @return read data status
1110 IDEBlkIoReadBlocks (
1111 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1114 IN UINTN BufferSize
,
1117 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1119 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1123 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1125 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (This
);
1128 // Requery IDE IO resources in case of the switch of native and legacy modes
1130 ReassignIdeResources (IdeBlkIoDevice
);
1133 // For ATA compatible device, use ATA read block's mechanism
1135 if (IdeBlkIoDevice
->Type
== IdeHardDisk
||
1136 IdeBlkIoDevice
->Type
== Ide48bitAddressingHardDisk
) {
1137 Status
= AtaBlkIoReadBlocks (
1147 if (IdeBlkIoDevice
->Type
== IdeUnknown
) {
1148 Status
= EFI_DEVICE_ERROR
;
1153 // for ATAPI device, using ATAPI read block's mechanism
1155 Status
= AtapiBlkIoReadBlocks (
1164 gBS
->RestoreTPL (OldTpl
);
1170 Write data to block io device
1172 @param This Protocol instance pointer.
1173 @param MediaId The media ID of the device
1174 @param LBA Starting LBA address to write data
1175 @param BufferSize The size of data to be written
1176 @param Buffer Caller supplied buffer to save data
1178 @return write data status
1183 IDEBlkIoWriteBlocks (
1184 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1187 IN UINTN BufferSize
,
1190 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1192 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1196 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1198 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (This
);
1200 // Requery IDE IO resources in case of the switch of native and legacy modes
1202 ReassignIdeResources (IdeBlkIoDevice
);
1205 // for ATA device, using ATA write block's mechanism
1207 if (IdeBlkIoDevice
->Type
== IdeHardDisk
||
1208 IdeBlkIoDevice
->Type
== Ide48bitAddressingHardDisk
) {
1210 Status
= AtaBlkIoWriteBlocks (
1220 if (IdeBlkIoDevice
->Type
== IdeUnknown
) {
1221 Status
= EFI_DEVICE_ERROR
;
1226 // for ATAPI device, using ATAPI write block's mechanism
1228 Status
= AtapiBlkIoWriteBlocks (
1237 gBS
->RestoreTPL (OldTpl
);
1242 // ***********************************************************************************
1243 // IDEBlkIoFlushBlocks
1244 // ***********************************************************************************
1247 TODO: This - add argument and description to function comment
1248 TODO: EFI_SUCCESS - add return value to function comment
1252 IDEBlkIoFlushBlocks (
1253 IN EFI_BLOCK_IO_PROTOCOL
*This
1263 Return the results of the Inquiry command to a drive in InquiryData.
1264 Data format of Inquiry data is defined by the Interface GUID.
1266 @param This Protocol instance pointer.
1267 @param InquiryData Results of Inquiry command to device
1268 @param InquiryDataSize Size of InquiryData in bytes.
1270 @retval EFI_SUCCESS InquiryData valid
1271 @retval EFI_NOT_FOUND Device does not support this data class
1272 @retval EFI_DEVICE_ERROR Error reading InquiryData from device
1273 @retval EFI_BUFFER_TOO_SMALL IntquiryDataSize not big enough
1278 IDEDiskInfoInquiry (
1279 IN EFI_DISK_INFO_PROTOCOL
*This
,
1280 IN OUT VOID
*InquiryData
,
1281 IN OUT UINT32
*InquiryDataSize
1284 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1286 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This
);
1288 if (*InquiryDataSize
< sizeof (ATAPI_INQUIRY_DATA
)) {
1289 *InquiryDataSize
= sizeof (ATAPI_INQUIRY_DATA
);
1290 return EFI_BUFFER_TOO_SMALL
;
1293 if (IdeBlkIoDevice
->pInquiryData
== NULL
) {
1294 return EFI_NOT_FOUND
;
1297 gBS
->CopyMem (InquiryData
, IdeBlkIoDevice
->pInquiryData
, sizeof (ATAPI_INQUIRY_DATA
));
1298 *InquiryDataSize
= sizeof (ATAPI_INQUIRY_DATA
);
1304 Return the results of the Identify command to a drive in IdentifyData.
1305 Data format of Identify data is defined by the Interface GUID.
1307 @param This Protocol instance pointer.
1308 @param IdentifyData Results of Identify command to device
1309 @param IdentifyDataSize Size of IdentifyData in bytes.
1311 @retval EFI_SUCCESS IdentifyData valid
1312 @retval EFI_NOT_FOUND Device does not support this data class
1313 @retval EFI_DEVICE_ERROR Error reading IdentifyData from device
1314 @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough
1319 IDEDiskInfoIdentify (
1320 IN EFI_DISK_INFO_PROTOCOL
*This
,
1321 IN OUT VOID
*IdentifyData
,
1322 IN OUT UINT32
*IdentifyDataSize
1325 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1327 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This
);
1329 if (*IdentifyDataSize
< sizeof (EFI_IDENTIFY_DATA
)) {
1330 *IdentifyDataSize
= sizeof (EFI_IDENTIFY_DATA
);
1331 return EFI_BUFFER_TOO_SMALL
;
1334 if (IdeBlkIoDevice
->pIdData
== NULL
) {
1335 return EFI_NOT_FOUND
;
1338 gBS
->CopyMem (IdentifyData
, IdeBlkIoDevice
->pIdData
, sizeof (EFI_IDENTIFY_DATA
));
1339 *IdentifyDataSize
= sizeof (EFI_IDENTIFY_DATA
);
1345 Return the results of the Request Sense command to a drive in SenseData.
1346 Data format of Sense data is defined by the Interface GUID.
1348 @param This Protocol instance pointer.
1349 @param SenseData Results of Request Sense command to device
1350 @param SenseDataSize Size of SenseData in bytes.
1351 @param SenseDataNumber Type of SenseData
1353 @retval EFI_SUCCESS InquiryData valid
1354 @retval EFI_NOT_FOUND Device does not support this data class
1355 @retval EFI_DEVICE_ERROR Error reading InquiryData from device
1356 @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough
1361 IDEDiskInfoSenseData (
1362 IN EFI_DISK_INFO_PROTOCOL
*This
,
1363 IN OUT VOID
*SenseData
,
1364 IN OUT UINT32
*SenseDataSize
,
1365 OUT UINT8
*SenseDataNumber
1368 return EFI_NOT_FOUND
;
1372 Return the results of the Request Sense command to a drive in SenseData.
1373 Data format of Sense data is defined by the Interface GUID.
1375 @param This Protocol instance pointer.
1376 @param IdeChannel Primary or Secondary
1377 @param IdeDevice Master or Slave
1379 @retval EFI_SUCCESS IdeChannel and IdeDevice are valid
1380 @retval EFI_UNSUPPORTED This is not an IDE device
1385 IDEDiskInfoWhichIde (
1386 IN EFI_DISK_INFO_PROTOCOL
*This
,
1387 OUT UINT32
*IdeChannel
,
1388 OUT UINT32
*IdeDevice
1391 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1393 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This
);
1394 *IdeChannel
= IdeBlkIoDevice
->Channel
;
1395 *IdeDevice
= IdeBlkIoDevice
->Device
;
1401 The user Entry Point for module IdeBus. The user code starts with this function.
1403 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1404 @param[in] SystemTable A pointer to the EFI System Table.
1406 @retval EFI_SUCCESS The entry point is executed successfully.
1407 @retval other Some error occurs when executing this entry point.
1413 IN EFI_HANDLE ImageHandle
,
1414 IN EFI_SYSTEM_TABLE
*SystemTable
1420 // Install driver model protocol(s).
1422 Status
= EfiLibInstallAllDriverProtocols2 (
1425 &gIDEBusDriverBinding
,
1427 &gIDEBusComponentName
,
1428 &gIDEBusComponentName2
,
1430 &gIDEBusDriverDiagnostics
,
1431 &gIDEBusDriverDiagnostics2
1433 ASSERT_EFI_ERROR (Status
);