2 Copyright (c) 2006, 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 // Clsoe 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
;
185 IDE_BUS_DRIVER_PRIVATE_DATA
*IdeBusDriverPrivateData
;
188 // Local variables declaration for IdeControllerInit support
190 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
192 BOOLEAN ChannelEnabled
;
195 EFI_IDENTIFY_DATA IdentifyData
;
196 EFI_ATA_COLLECTIVE_MODE
*SupportedModes
;
198 IdeBusDriverPrivateData
= NULL
;
199 SupportedModes
= NULL
;
202 // Perform IdeBus initialization
204 Status
= gBS
->OpenProtocol (
206 &gEfiDevicePathProtocolGuid
,
207 (VOID
**) &ParentDevicePath
,
208 This
->DriverBindingHandle
,
210 EFI_OPEN_PROTOCOL_BY_DRIVER
212 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
217 // Now open the IDE_CONTROLLER_INIT protocol. Step7.1
219 Status
= gBS
->OpenProtocol (
221 &gEfiIdeControllerInitProtocolGuid
,
223 This
->DriverBindingHandle
,
225 EFI_OPEN_PROTOCOL_BY_DRIVER
229 // The following OpenProtocol function with _GET_PROTOCOL attribute and
230 // will not return EFI_ALREADY_STARTED, so save it for now
232 SavedStatus
= Status
;
234 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
235 DEBUG ((EFI_D_ERROR
, "Open Init, Status=%x", Status
));
237 // open protocol is not SUCCESS or not ALREADY_STARTED, error exit
243 // Save Enumall and ChannelCount. Step7.2
245 EnumAll
= IdeInit
->EnumAll
;
246 ChannelCount
= IdeInit
->ChannelCount
;
249 // Consume PCI I/O protocol. Note that the OpenProtocol with _GET_PROTOCOL
250 // attribute will not return EFI_ALREADY_STARTED
252 Status
= gBS
->OpenProtocol (
254 &gEfiPciIoProtocolGuid
,
256 This
->DriverBindingHandle
,
258 EFI_OPEN_PROTOCOL_GET_PROTOCOL
260 if (EFI_ERROR (Status
)) {
261 DEBUG ((EFI_D_ERROR
, "Open PciIo, Status=%x", Status
));
266 // We must check EFI_ALREADY_STARTED because many ATAPI devices are removable
268 if (SavedStatus
!= EFI_ALREADY_STARTED
) {
269 IdeBusDriverPrivateData
= AllocatePool (sizeof (IDE_BUS_DRIVER_PRIVATE_DATA
));
270 if (IdeBusDriverPrivateData
== NULL
) {
271 Status
= EFI_OUT_OF_RESOURCES
;
275 ZeroMem (IdeBusDriverPrivateData
, sizeof (IDE_BUS_DRIVER_PRIVATE_DATA
));
276 Status
= gBS
->InstallMultipleProtocolInterfaces (
279 IdeBusDriverPrivateData
,
282 if (EFI_ERROR (Status
)) {
287 Status
= gBS
->OpenProtocol (
290 (VOID
**) &IdeBusDriverPrivateData
,
291 This
->DriverBindingHandle
,
293 EFI_OPEN_PROTOCOL_GET_PROTOCOL
295 if (EFI_ERROR (Status
)) {
296 IdeBusDriverPrivateData
= NULL
;
301 Status
= PciIo
->Attributes (
303 EfiPciIoAttributeOperationEnable
,
304 EFI_PCI_DEVICE_ENABLE
,
307 if (EFI_ERROR (Status
)) {
312 // Read the environment variable that contains the IDEBus Driver's
313 // Config options that were set by the Driver Configuration Protocol
315 DataSize
= sizeof (ConfigurationOptions
);
316 Status
= gRT
->GetVariable (
317 (CHAR16
*) L
"Configuration",
321 &ConfigurationOptions
323 if (EFI_ERROR (Status
)) {
324 ConfigurationOptions
= 0x0f;
329 // If IdeInit->EnumAll is TRUE, must enumerate all IDE device anyway
331 BeginningIdeChannel
= IdePrimary
;
332 EndIdeChannel
= IdeSecondary
;
333 BeginningIdeDevice
= IdeMaster
;
334 EndIdeDevice
= IdeSlave
;
335 } else if (RemainingDevicePath
== NULL
) {
337 // RemainingDevicePath is NULL, scan IDE bus for each device;
339 BeginningIdeChannel
= IdePrimary
;
340 EndIdeChannel
= IdeSecondary
;
341 BeginningIdeDevice
= IdeMaster
;
343 // default, may be redefined by IdeInit
345 EndIdeDevice
= IdeSlave
;
348 // RemainingDevicePath is not NULL, only scan the specified device.
350 Node
= (EFI_DEV_PATH
*) RemainingDevicePath
;
351 BeginningIdeChannel
= Node
->Atapi
.PrimarySecondary
;
352 EndIdeChannel
= BeginningIdeChannel
;
353 BeginningIdeDevice
= Node
->Atapi
.SlaveMaster
;
354 EndIdeDevice
= BeginningIdeDevice
;
358 // Obtain IDE IO port registers' base addresses
360 Status
= GetIdeRegistersBaseAddr (PciIo
, IdeRegsBaseAddr
);
361 if (EFI_ERROR (Status
)) {
366 // Report status code: begin IdeBus initialization
368 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
370 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_PC_RESET
),
375 // Strictly follow the enumeration based on IDE_CONTROLLER_INIT protocol
377 for (IdeChannel
= BeginningIdeChannel
; IdeChannel
<= EndIdeChannel
; IdeChannel
++) {
379 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelEnumeration
, IdeChannel
);
382 // now obtain channel information fron IdeControllerInit protocol. Step9
384 Status
= IdeInit
->GetChannelInfo (
390 if (EFI_ERROR (Status
)) {
391 DEBUG ((EFI_D_ERROR
, "[GetChannel, Status=%x]", Status
));
395 if (!ChannelEnabled
) {
399 EndIdeDevice
= (UINT8
) EFI_MIN ((MaxDevices
- 1), EndIdeDevice
);
402 // Now inform the IDE Controller Init Module. Sept10
404 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelReset
, IdeChannel
);
407 // No reset channel function implemented. Sept11
409 IdeInit
->NotifyPhase (IdeInit
, EfiIdeAfterChannelReset
, IdeChannel
);
414 IdeInit
->NotifyPhase (
416 EfiIdeBusBeforeDevicePresenceDetection
,
421 // Prepare to detect IDE device of this channel
423 InitializeIDEChannelData ();
426 // -- 1st inner loop --- Master/Slave ------------ Step14
428 for (IdeDevice
= BeginningIdeDevice
; IdeDevice
<= EndIdeDevice
; IdeDevice
++) {
430 // Check whether the configuration options allow this device
432 if (!(ConfigurationOptions
& (1 << (IdeChannel
* 2 + IdeDevice
)))) {
437 // The device has been scanned in another Start(), No need to scan it again
438 // for perf optimization.
440 if (IdeBusDriverPrivateData
->HaveScannedDevice
[IdeChannel
* 2 + IdeDevice
]) {
445 // create child handle for the detected device.
447 IdeBlkIoDevice
[IdeChannel
][IdeDevice
] = AllocatePool (sizeof (IDE_BLK_IO_DEV
));
448 if (IdeBlkIoDevice
[IdeChannel
][IdeDevice
] == NULL
) {
452 IdeBlkIoDevicePtr
= IdeBlkIoDevice
[IdeChannel
][IdeDevice
];
454 ZeroMem (IdeBlkIoDevicePtr
, sizeof (IDE_BLK_IO_DEV
));
456 IdeBlkIoDevicePtr
->Signature
= IDE_BLK_IO_DEV_SIGNATURE
;
457 IdeBlkIoDevicePtr
->Channel
= IdeChannel
;
458 IdeBlkIoDevicePtr
->Device
= IdeDevice
;
461 // initialize Block IO interface's Media pointer
463 IdeBlkIoDevicePtr
->BlkIo
.Media
= &IdeBlkIoDevicePtr
->BlkMedia
;
466 // Initialize IDE IO port addresses, including Command Block registers
467 // and Control Block registers
469 IdeBlkIoDevicePtr
->IoPort
= AllocatePool (sizeof (IDE_BASE_REGISTERS
));
470 if (IdeBlkIoDevicePtr
->IoPort
== NULL
) {
474 ZeroMem (IdeBlkIoDevicePtr
->IoPort
, sizeof (IDE_BASE_REGISTERS
));
475 CommandBlockBaseAddr
= IdeRegsBaseAddr
[IdeChannel
].CommandBlockBaseAddr
;
476 ControlBlockBaseAddr
= IdeRegsBaseAddr
[IdeChannel
].ControlBlockBaseAddr
;
478 IdeBlkIoDevicePtr
->IoPort
->Data
= CommandBlockBaseAddr
;
479 (*(UINT16
*) &IdeBlkIoDevicePtr
->IoPort
->Reg1
) = (UINT16
) (CommandBlockBaseAddr
+ 0x01);
480 IdeBlkIoDevicePtr
->IoPort
->SectorCount
= (UINT16
) (CommandBlockBaseAddr
+ 0x02);
481 IdeBlkIoDevicePtr
->IoPort
->SectorNumber
= (UINT16
) (CommandBlockBaseAddr
+ 0x03);
482 IdeBlkIoDevicePtr
->IoPort
->CylinderLsb
= (UINT16
) (CommandBlockBaseAddr
+ 0x04);
483 IdeBlkIoDevicePtr
->IoPort
->CylinderMsb
= (UINT16
) (CommandBlockBaseAddr
+ 0x05);
484 IdeBlkIoDevicePtr
->IoPort
->Head
= (UINT16
) (CommandBlockBaseAddr
+ 0x06);
485 (*(UINT16
*) &IdeBlkIoDevicePtr
->IoPort
->Reg
) = (UINT16
) (CommandBlockBaseAddr
+ 0x07);
487 (*(UINT16
*) &IdeBlkIoDevicePtr
->IoPort
->Alt
) = ControlBlockBaseAddr
;
488 IdeBlkIoDevicePtr
->IoPort
->DriveAddress
= (UINT16
) (ControlBlockBaseAddr
+ 0x01);
490 IdeBlkIoDevicePtr
->IoPort
->MasterSlave
= (UINT16
) ((IdeDevice
== IdeMaster
) ? 1 : 0);
492 IdeBlkIoDevicePtr
->PciIo
= PciIo
;
493 IdeBlkIoDevicePtr
->IdeBusDriverPrivateData
= IdeBusDriverPrivateData
;
494 IdeBlkIoDevicePtr
->IoPort
->BusMasterBaseAddr
= IdeRegsBaseAddr
[IdeChannel
].BusMasterBaseAddr
;
497 // Report Status code: is about to detect IDE drive
499 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
501 (EFI_IO_BUS_ATA_ATAPI
| EFI_P_PC_PRESENCE_DETECT
),
502 IdeBlkIoDevicePtr
->DevicePath
506 // Discover device, now!
508 PERF_START (0, "DiscoverIdeDevice", "IDE", 0);
509 Status
= DiscoverIdeDevice (IdeBlkIoDevicePtr
);
510 PERF_END (0, "DiscoverIdeDevice", "IDE", 0);
512 IdeBusDriverPrivateData
->HaveScannedDevice
[IdeChannel
* 2 + IdeDevice
] = TRUE
;
513 IdeBusDriverPrivateData
->DeviceProcessed
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
515 if (!EFI_ERROR (Status
)) {
519 ZeroMem (&NewNode
, sizeof (NewNode
));
520 NewNode
.DevPath
.Type
= MESSAGING_DEVICE_PATH
;
521 NewNode
.DevPath
.SubType
= MSG_ATAPI_DP
;
522 SetDevicePathNodeLength (&NewNode
.DevPath
, sizeof (ATAPI_DEVICE_PATH
));
524 NewNode
.Atapi
.PrimarySecondary
= (UINT8
) IdeBlkIoDevicePtr
->Channel
;
525 NewNode
.Atapi
.SlaveMaster
= (UINT8
) IdeBlkIoDevicePtr
->Device
;
526 NewNode
.Atapi
.Lun
= IdeBlkIoDevicePtr
->Lun
;
527 IdeBlkIoDevicePtr
->DevicePath
= AppendDevicePathNode (
531 if (IdeBlkIoDevicePtr
->DevicePath
== NULL
) {
532 ReleaseIdeResources (IdeBlkIoDevicePtr
);
537 // Submit identify data to IDE controller init driver
539 CopyMem (&IdentifyData
, IdeBlkIoDevicePtr
->pIdData
, sizeof (IdentifyData
));
540 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = TRUE
;
541 IdeInit
->SubmitData (IdeInit
, IdeChannel
, IdeDevice
, &IdentifyData
);
544 // Device detection failed
546 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
547 IdeInit
->SubmitData (IdeInit
, IdeChannel
, IdeDevice
, NULL
);
548 ReleaseIdeResources (IdeBlkIoDevicePtr
);
549 IdeBlkIoDevicePtr
= NULL
;
552 // end of 1st inner loop ---
556 // end of 1st outer loop =========
561 // = 2nd outer loop == Primary/Secondary =================
563 for (IdeChannel
= BeginningIdeChannel
; IdeChannel
<= EndIdeChannel
; IdeChannel
++) {
566 // -- 2nd inner loop --- Master/Slave --------
568 for (IdeDevice
= BeginningIdeDevice
; IdeDevice
<= EndIdeDevice
; IdeDevice
++) {
570 if (IdeBusDriverPrivateData
->DeviceProcessed
[IdeChannel
* 2 + IdeDevice
]) {
574 if (!IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
]) {
578 Status
= IdeInit
->CalculateMode (
584 if (EFI_ERROR (Status
)) {
585 DEBUG ((EFI_D_ERROR
, "[bStStp20S=%x]", Status
));
589 IdeBlkIoDevicePtr
= IdeBlkIoDevice
[IdeChannel
][IdeDevice
];
592 // Set best supported PIO mode on this IDE device
594 if (SupportedModes
->PioMode
.Mode
<= ATA_PIO_MODE_2
) {
595 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_DEFAULT_PIO
;
597 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_FLOW_PIO
;
600 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->PioMode
.Mode
);
602 if (SupportedModes
->ExtModeCount
== 0){
603 Status
= SetDeviceTransferMode (IdeBlkIoDevicePtr
, &TransferMode
);
605 if (EFI_ERROR (Status
)) {
606 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
607 ReleaseIdeResources (IdeBlkIoDevicePtr
);
608 IdeBlkIoDevicePtr
= NULL
;
614 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
615 // be set together. Only one DMA mode can be set to a device. If setting
616 // DMA mode operation fails, we can continue moving on because we only use
617 // PIO mode at boot time. DMA modes are used by certain kind of OS booting
619 if (SupportedModes
->UdmaMode
.Valid
) {
621 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_UDMA
;
622 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->UdmaMode
.Mode
);
623 Status
= SetDeviceTransferMode (IdeBlkIoDevicePtr
, &TransferMode
);
625 if (EFI_ERROR (Status
)) {
626 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
627 ReleaseIdeResources (IdeBlkIoDevicePtr
);
628 IdeBlkIoDevicePtr
= NULL
;
632 EnableInterrupt (IdeBlkIoDevicePtr
);
633 } else if (SupportedModes
->MultiWordDmaMode
.Valid
) {
635 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_MDMA
;
636 TransferMode
.ModeNumber
= (UINT8
) SupportedModes
->MultiWordDmaMode
.Mode
;
637 Status
= SetDeviceTransferMode (IdeBlkIoDevicePtr
, &TransferMode
);
639 if (EFI_ERROR (Status
)) {
640 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
641 ReleaseIdeResources (IdeBlkIoDevicePtr
);
642 IdeBlkIoDevicePtr
= NULL
;
646 EnableInterrupt (IdeBlkIoDevicePtr
);
649 // Init driver parameters
651 DriveParameters
.Sector
= (UINT8
) IdeBlkIoDevicePtr
->pIdData
->AtaData
.sectors_per_track
;
652 DriveParameters
.Heads
= (UINT8
) (IdeBlkIoDevicePtr
->pIdData
->AtaData
.heads
- 1);
653 DriveParameters
.MultipleSector
= (UINT8
) IdeBlkIoDevicePtr
->pIdData
->AtaData
.multi_sector_cmd_max_sct_cnt
;
655 // Set Parameters for the device:
657 // 2) Establish the block count for READ/WRITE MULTIPLE (EXT) command
659 if ((IdeBlkIoDevicePtr
->Type
== IdeHardDisk
) || (IdeBlkIoDevicePtr
->Type
== Ide48bitAddressingHardDisk
)) {
660 Status
= SetDriveParameters (IdeBlkIoDevicePtr
, &DriveParameters
);
664 // Record PIO mode used in private data
666 IdeBlkIoDevicePtr
->PioMode
= SupportedModes
->PioMode
.Mode
;
669 // Set IDE controller Timing Blocks in the PCI Configuration Space
671 IdeInit
->SetTiming (IdeInit
, IdeChannel
, IdeDevice
, SupportedModes
);
674 // Add Component Name for the IDE/ATAPI device that was discovered.
676 IdeBlkIoDevicePtr
->ControllerNameTable
= NULL
;
677 ADD_NAME (IdeBlkIoDevicePtr
);
679 Status
= gBS
->InstallMultipleProtocolInterfaces (
680 &IdeBlkIoDevicePtr
->Handle
,
681 &gEfiDevicePathProtocolGuid
,
682 IdeBlkIoDevicePtr
->DevicePath
,
683 &gEfiBlockIoProtocolGuid
,
684 &IdeBlkIoDevicePtr
->BlkIo
,
685 &gEfiDiskInfoProtocolGuid
,
686 &IdeBlkIoDevicePtr
->DiskInfo
,
690 if (EFI_ERROR (Status
)) {
691 ReleaseIdeResources (IdeBlkIoDevicePtr
);
696 &gEfiPciIoProtocolGuid
,
698 This
->DriverBindingHandle
,
699 IdeBlkIoDevicePtr
->Handle
,
700 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
703 IdeBusDriverPrivateData
->DeviceProcessed
[IdeChannel
* 2 + IdeDevice
] = TRUE
;
706 // Report status code: device eanbled!
708 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
710 (EFI_IO_BUS_ATA_ATAPI
| EFI_P_PC_ENABLE
),
711 IdeBlkIoDevicePtr
->DevicePath
715 // Create event to clear pending IDE interrupt
717 Status
= gBS
->CreateEvent (
718 EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES
,
722 &IdeBlkIoDevicePtr
->ExitBootServiceEvent
726 // end of 2nd inner loop ----
730 // end of 2nd outer loop ==========
735 // All configurations done! Notify IdeController to do post initialization
736 // work such as saving IDE controller PCI settings for S3 resume
738 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBusPhaseMaximum
, 0);
740 if (SupportedModes
!= NULL
) {
741 gBS
->FreePool (SupportedModes
);
744 PERF_START (0, "Finish IDE detection", "IDE", 1);
745 PERF_END (0, "Finish IDE detection", "IDE", 0);
752 // Report error code: controller error
754 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
755 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
756 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_EC_CONTROLLER_ERROR
),
762 &gEfiIdeControllerInitProtocolGuid
,
763 This
->DriverBindingHandle
,
767 gBS
->UninstallMultipleProtocolInterfaces (
770 IdeBusDriverPrivateData
,
774 if (IdeBusDriverPrivateData
!= NULL
) {
775 gBS
->FreePool (IdeBusDriverPrivateData
);
778 if (SupportedModes
!= NULL
) {
779 gBS
->FreePool (SupportedModes
);
784 &gEfiPciIoProtocolGuid
,
785 This
->DriverBindingHandle
,
791 &gEfiDevicePathProtocolGuid
,
792 This
->DriverBindingHandle
,
801 // ***********************************************************************************
802 // IDEBusDriverBindingStop
803 // ***********************************************************************************
806 Stop this driver on Controller Handle.
808 @param This Protocol instance pointer.
809 @param DeviceHandle Handle of device to stop driver on
810 @param NumberOfChildren Not used
811 @param ChildHandleBuffer Not used
813 @retval EFI_SUCCESS This driver is removed DeviceHandle
814 @retval other This driver was not removed from this device
819 IDEBusDriverBindingStop (
820 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
821 IN EFI_HANDLE Controller
,
822 IN UINTN NumberOfChildren
,
823 IN EFI_HANDLE
*ChildHandleBuffer
825 // TODO: Controller - add argument and description to function comment
826 // TODO: EFI_DEVICE_ERROR - add return value to function comment
829 EFI_PCI_IO_PROTOCOL
*PciIo
;
830 BOOLEAN AllChildrenStopped
;
832 IDE_BUS_DRIVER_PRIVATE_DATA
*IdeBusDriverPrivateData
;
834 IdeBusDriverPrivateData
= NULL
;
836 if (NumberOfChildren
== 0) {
838 Status
= gBS
->OpenProtocol (
840 &gEfiPciIoProtocolGuid
,
842 This
->DriverBindingHandle
,
844 EFI_OPEN_PROTOCOL_GET_PROTOCOL
846 if (!EFI_ERROR (Status
)) {
849 EfiPciIoAttributeOperationDisable
,
850 EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO
| EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO
| EFI_PCI_DEVICE_ENABLE
,
858 (VOID
**) &IdeBusDriverPrivateData
,
859 This
->DriverBindingHandle
,
861 EFI_OPEN_PROTOCOL_GET_PROTOCOL
864 gBS
->UninstallMultipleProtocolInterfaces (
867 IdeBusDriverPrivateData
,
871 if (IdeBusDriverPrivateData
!= NULL
) {
872 gBS
->FreePool (IdeBusDriverPrivateData
);
875 // Close the bus driver
879 &gEfiIdeControllerInitProtocolGuid
,
880 This
->DriverBindingHandle
,
885 &gEfiPciIoProtocolGuid
,
886 This
->DriverBindingHandle
,
891 &gEfiDevicePathProtocolGuid
,
892 This
->DriverBindingHandle
,
899 AllChildrenStopped
= TRUE
;
901 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
903 Status
= DeRegisterIdeDevice (This
, Controller
, ChildHandleBuffer
[Index
]);
905 if (EFI_ERROR (Status
)) {
906 AllChildrenStopped
= FALSE
;
910 if (!AllChildrenStopped
) {
911 return EFI_DEVICE_ERROR
;
918 // ***********************************************************************************
919 // DeRegisterIdeDevice
920 // ***********************************************************************************
923 Deregister an IDE device and free resources
925 @param This Protocol instance pointer.
926 @param Controller Ide device handle
927 @param Handle Handle of device to deregister driver on
933 DeRegisterIdeDevice (
934 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
935 IN EFI_HANDLE Controller
,
938 // TODO: EFI_SUCCESS - add return value to function comment
941 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
942 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
943 EFI_PCI_IO_PROTOCOL
*PciIo
;
946 Status
= gBS
->OpenProtocol (
948 &gEfiBlockIoProtocolGuid
,
950 This
->DriverBindingHandle
,
952 EFI_OPEN_PROTOCOL_GET_PROTOCOL
954 if (EFI_ERROR (Status
)) {
958 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo
);
961 // Report Status code: Device disabled
963 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
965 (EFI_IO_BUS_ATA_ATAPI
| EFI_P_PC_DISABLE
),
966 IdeBlkIoDevice
->DevicePath
970 // Close the child handle
972 Status
= gBS
->CloseProtocol (
974 &gEfiPciIoProtocolGuid
,
975 This
->DriverBindingHandle
,
979 Status
= gBS
->UninstallMultipleProtocolInterfaces (
981 &gEfiDevicePathProtocolGuid
,
982 IdeBlkIoDevice
->DevicePath
,
983 &gEfiBlockIoProtocolGuid
,
984 &IdeBlkIoDevice
->BlkIo
,
985 &gEfiDiskInfoProtocolGuid
,
986 &IdeBlkIoDevice
->DiskInfo
,
990 if (EFI_ERROR (Status
)) {
993 &gEfiPciIoProtocolGuid
,
995 This
->DriverBindingHandle
,
997 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1003 // Release allocated resources
1005 Index
= IdeBlkIoDevice
->Channel
* 2 + IdeBlkIoDevice
->Device
;
1006 IdeBlkIoDevice
->IdeBusDriverPrivateData
->HaveScannedDevice
[Index
] = FALSE
;
1008 ReleaseIdeResources (IdeBlkIoDevice
);
1014 // ***********************************************************************************
1016 // ***********************************************************************************
1019 TODO: This - add argument and description to function comment
1020 TODO: ExtendedVerification - add argument and description to function comment
1021 TODO: EFI_DEVICE_ERROR - add return value to function comment
1027 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1028 IN BOOLEAN ExtendedVerification
1031 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1034 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (This
);
1036 // Requery IDE IO resources in case of the switch of native and legacy modes
1038 ReassignIdeResources (IdeBlkIoDevice
);
1041 // for ATA device, using ATA reset method
1043 if (IdeBlkIoDevice
->Type
== IdeHardDisk
||
1044 IdeBlkIoDevice
->Type
== Ide48bitAddressingHardDisk
) {
1045 return AtaSoftReset (IdeBlkIoDevice
);
1048 if (IdeBlkIoDevice
->Type
== IdeUnknown
) {
1049 return EFI_DEVICE_ERROR
;
1053 // for ATAPI device, using ATAPI reset method
1055 Status
= AtapiSoftReset (IdeBlkIoDevice
);
1056 if (ExtendedVerification
) {
1057 Status
= AtaSoftReset (IdeBlkIoDevice
);
1064 Read data from block io device
1066 @param This Protocol instance pointer.
1067 @param MediaId The media ID of the device
1068 @param LBA Starting LBA address to read data
1069 @param BufferSize The size of data to be read
1070 @param Buffer Caller supplied buffer to save data
1072 @return read data status
1077 IDEBlkIoReadBlocks (
1078 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1081 IN UINTN BufferSize
,
1084 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1086 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1088 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (This
);
1091 // Requery IDE IO resources in case of the switch of native and legacy modes
1093 ReassignIdeResources (IdeBlkIoDevice
);
1096 // For ATA compatible device, use ATA read block's mechanism
1098 if (IdeBlkIoDevice
->Type
== IdeHardDisk
||
1099 IdeBlkIoDevice
->Type
== Ide48bitAddressingHardDisk
) {
1100 return AtaBlkIoReadBlocks (
1109 if (IdeBlkIoDevice
->Type
== IdeUnknown
) {
1110 return EFI_DEVICE_ERROR
;
1114 // for ATAPI device, using ATAPI read block's mechanism
1116 return AtapiBlkIoReadBlocks (
1127 Write data to block io device
1129 @param This Protocol instance pointer.
1130 @param MediaId The media ID of the device
1131 @param LBA Starting LBA address to write data
1132 @param BufferSize The size of data to be written
1133 @param Buffer Caller supplied buffer to save data
1135 @return write data status
1140 IDEBlkIoWriteBlocks (
1141 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1144 IN UINTN BufferSize
,
1147 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1149 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1151 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (This
);
1153 // Requery IDE IO resources in case of the switch of native and legacy modes
1155 ReassignIdeResources (IdeBlkIoDevice
);
1158 // for ATA device, using ATA write block's mechanism
1160 if (IdeBlkIoDevice
->Type
== IdeHardDisk
||
1161 IdeBlkIoDevice
->Type
== Ide48bitAddressingHardDisk
) {
1163 return AtaBlkIoWriteBlocks (
1172 if (IdeBlkIoDevice
->Type
== IdeUnknown
) {
1173 return EFI_DEVICE_ERROR
;
1177 // for ATAPI device, using ATAPI write block's mechanism
1179 return AtapiBlkIoWriteBlocks (
1189 // ***********************************************************************************
1190 // IDEBlkIoFlushBlocks
1191 // ***********************************************************************************
1194 TODO: This - add argument and description to function comment
1195 TODO: EFI_SUCCESS - add return value to function comment
1199 IDEBlkIoFlushBlocks (
1200 IN EFI_BLOCK_IO_PROTOCOL
*This
1210 Return the results of the Inquiry command to a drive in InquiryData.
1211 Data format of Inquiry data is defined by the Interface GUID.
1213 @param This Protocol instance pointer.
1214 @param InquiryData Results of Inquiry command to device
1215 @param InquiryDataSize Size of InquiryData in bytes.
1217 @retval EFI_SUCCESS InquiryData valid
1218 @retval EFI_NOT_FOUND Device does not support this data class
1219 @retval EFI_DEVICE_ERROR Error reading InquiryData from device
1220 @retval EFI_BUFFER_TOO_SMALL IntquiryDataSize not big enough
1225 IDEDiskInfoInquiry (
1226 IN EFI_DISK_INFO_PROTOCOL
*This
,
1227 IN OUT VOID
*InquiryData
,
1228 IN OUT UINT32
*InquiryDataSize
1231 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1233 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This
);
1235 if (*InquiryDataSize
< sizeof (INQUIRY_DATA
)) {
1236 *InquiryDataSize
= sizeof (INQUIRY_DATA
);
1237 return EFI_BUFFER_TOO_SMALL
;
1240 if (IdeBlkIoDevice
->pInquiryData
== NULL
) {
1241 return EFI_NOT_FOUND
;
1244 gBS
->CopyMem (InquiryData
, IdeBlkIoDevice
->pInquiryData
, sizeof (INQUIRY_DATA
));
1245 *InquiryDataSize
= sizeof (INQUIRY_DATA
);
1251 Return the results of the Identify command to a drive in IdentifyData.
1252 Data format of Identify data is defined by the Interface GUID.
1254 @param This Protocol instance pointer.
1255 @param IdentifyData Results of Identify command to device
1256 @param IdentifyDataSize Size of IdentifyData in bytes.
1258 @retval EFI_SUCCESS IdentifyData valid
1259 @retval EFI_NOT_FOUND Device does not support this data class
1260 @retval EFI_DEVICE_ERROR Error reading IdentifyData from device
1261 @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough
1266 IDEDiskInfoIdentify (
1267 IN EFI_DISK_INFO_PROTOCOL
*This
,
1268 IN OUT VOID
*IdentifyData
,
1269 IN OUT UINT32
*IdentifyDataSize
1272 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1274 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This
);
1276 if (*IdentifyDataSize
< sizeof (EFI_IDENTIFY_DATA
)) {
1277 *IdentifyDataSize
= sizeof (EFI_IDENTIFY_DATA
);
1278 return EFI_BUFFER_TOO_SMALL
;
1281 if (IdeBlkIoDevice
->pIdData
== NULL
) {
1282 return EFI_NOT_FOUND
;
1285 gBS
->CopyMem (IdentifyData
, IdeBlkIoDevice
->pIdData
, sizeof (EFI_IDENTIFY_DATA
));
1286 *IdentifyDataSize
= sizeof (EFI_IDENTIFY_DATA
);
1292 Return the results of the Request Sense command to a drive in SenseData.
1293 Data format of Sense data is defined by the Interface GUID.
1295 @param This Protocol instance pointer.
1296 @param SenseData Results of Request Sense command to device
1297 @param SenseDataSize Size of SenseData in bytes.
1298 @param SenseDataNumber Type of SenseData
1300 @retval EFI_SUCCESS InquiryData valid
1301 @retval EFI_NOT_FOUND Device does not support this data class
1302 @retval EFI_DEVICE_ERROR Error reading InquiryData from device
1303 @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough
1308 IDEDiskInfoSenseData (
1309 IN EFI_DISK_INFO_PROTOCOL
*This
,
1310 IN OUT VOID
*SenseData
,
1311 IN OUT UINT32
*SenseDataSize
,
1312 OUT UINT8
*SenseDataNumber
1315 return EFI_NOT_FOUND
;
1319 Return the results of the Request Sense command to a drive in SenseData.
1320 Data format of Sense data is defined by the Interface GUID.
1322 @param This Protocol instance pointer.
1323 @param IdeChannel Primary or Secondary
1324 @param IdeDevice Master or Slave
1326 @retval EFI_SUCCESS IdeChannel and IdeDevice are valid
1327 @retval EFI_UNSUPPORTED This is not an IDE device
1332 IDEDiskInfoWhichIde (
1333 IN EFI_DISK_INFO_PROTOCOL
*This
,
1334 OUT UINT32
*IdeChannel
,
1335 OUT UINT32
*IdeDevice
1338 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1340 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This
);
1341 *IdeChannel
= IdeBlkIoDevice
->Channel
;
1342 *IdeDevice
= IdeBlkIoDevice
->Device
;