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
;
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
;
633 EnableInterrupt (IdeBlkIoDevicePtr
);
634 } else if (SupportedModes
->MultiWordDmaMode
.Valid
) {
636 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_MDMA
;
637 TransferMode
.ModeNumber
= (UINT8
) SupportedModes
->MultiWordDmaMode
.Mode
;
638 Status
= SetDeviceTransferMode (IdeBlkIoDevicePtr
, &TransferMode
);
640 if (EFI_ERROR (Status
)) {
641 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
642 ReleaseIdeResources (IdeBlkIoDevicePtr
);
643 IdeBlkIoDevicePtr
= NULL
;
647 EnableInterrupt (IdeBlkIoDevicePtr
);
650 // Init driver parameters
652 DriveParameters
.Sector
= (UINT8
) IdeBlkIoDevicePtr
->pIdData
->AtaData
.sectors_per_track
;
653 DriveParameters
.Heads
= (UINT8
) (IdeBlkIoDevicePtr
->pIdData
->AtaData
.heads
- 1);
654 DriveParameters
.MultipleSector
= (UINT8
) IdeBlkIoDevicePtr
->pIdData
->AtaData
.multi_sector_cmd_max_sct_cnt
;
656 // Set Parameters for the device:
658 // 2) Establish the block count for READ/WRITE MULTIPLE (EXT) command
660 if ((IdeBlkIoDevicePtr
->Type
== IdeHardDisk
) || (IdeBlkIoDevicePtr
->Type
== Ide48bitAddressingHardDisk
)) {
661 Status
= SetDriveParameters (IdeBlkIoDevicePtr
, &DriveParameters
);
665 // Record PIO mode used in private data
667 IdeBlkIoDevicePtr
->PioMode
= (ATA_PIO_MODE
) SupportedModes
->PioMode
.Mode
;
670 // Set IDE controller Timing Blocks in the PCI Configuration Space
672 IdeInit
->SetTiming (IdeInit
, IdeChannel
, IdeDevice
, SupportedModes
);
675 // Add Component Name for the IDE/ATAPI device that was discovered.
677 IdeBlkIoDevicePtr
->ControllerNameTable
= NULL
;
678 ADD_NAME (IdeBlkIoDevicePtr
);
680 Status
= gBS
->InstallMultipleProtocolInterfaces (
681 &IdeBlkIoDevicePtr
->Handle
,
682 &gEfiDevicePathProtocolGuid
,
683 IdeBlkIoDevicePtr
->DevicePath
,
684 &gEfiBlockIoProtocolGuid
,
685 &IdeBlkIoDevicePtr
->BlkIo
,
686 &gEfiDiskInfoProtocolGuid
,
687 &IdeBlkIoDevicePtr
->DiskInfo
,
691 if (EFI_ERROR (Status
)) {
692 ReleaseIdeResources (IdeBlkIoDevicePtr
);
697 &gEfiPciIoProtocolGuid
,
699 This
->DriverBindingHandle
,
700 IdeBlkIoDevicePtr
->Handle
,
701 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
704 IdeBusDriverPrivateData
->DeviceProcessed
[IdeChannel
* 2 + IdeDevice
] = TRUE
;
707 // Report status code: device eanbled!
709 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
711 (EFI_IO_BUS_ATA_ATAPI
| EFI_P_PC_ENABLE
),
712 IdeBlkIoDevicePtr
->DevicePath
716 // Create event to clear pending IDE interrupt
718 Status
= gBS
->CreateEvent (
719 EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES
,
723 &IdeBlkIoDevicePtr
->ExitBootServiceEvent
727 // end of 2nd inner loop ----
731 // end of 2nd outer loop ==========
736 // All configurations done! Notify IdeController to do post initialization
737 // work such as saving IDE controller PCI settings for S3 resume
739 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBusPhaseMaximum
, 0);
741 if (SupportedModes
!= NULL
) {
742 gBS
->FreePool (SupportedModes
);
745 PERF_START (0, "Finish IDE detection", "IDE", 1);
746 PERF_END (0, "Finish IDE detection", "IDE", 0);
753 // Report error code: controller error
755 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
756 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
757 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_EC_CONTROLLER_ERROR
),
763 &gEfiIdeControllerInitProtocolGuid
,
764 This
->DriverBindingHandle
,
768 gBS
->UninstallMultipleProtocolInterfaces (
771 IdeBusDriverPrivateData
,
775 if (IdeBusDriverPrivateData
!= NULL
) {
776 gBS
->FreePool (IdeBusDriverPrivateData
);
779 if (SupportedModes
!= NULL
) {
780 gBS
->FreePool (SupportedModes
);
785 &gEfiPciIoProtocolGuid
,
786 This
->DriverBindingHandle
,
792 &gEfiDevicePathProtocolGuid
,
793 This
->DriverBindingHandle
,
802 // ***********************************************************************************
803 // IDEBusDriverBindingStop
804 // ***********************************************************************************
807 Stop this driver on Controller Handle.
809 @param This Protocol instance pointer.
810 @param DeviceHandle Handle of device to stop driver on
811 @param NumberOfChildren Not used
812 @param ChildHandleBuffer Not used
814 @retval EFI_SUCCESS This driver is removed DeviceHandle
815 @retval other This driver was not removed from this device
820 IDEBusDriverBindingStop (
821 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
822 IN EFI_HANDLE Controller
,
823 IN UINTN NumberOfChildren
,
824 IN EFI_HANDLE
*ChildHandleBuffer
826 // TODO: Controller - add argument and description to function comment
827 // TODO: EFI_DEVICE_ERROR - add return value to function comment
830 EFI_PCI_IO_PROTOCOL
*PciIo
;
831 BOOLEAN AllChildrenStopped
;
833 IDE_BUS_DRIVER_PRIVATE_DATA
*IdeBusDriverPrivateData
;
835 IdeBusDriverPrivateData
= NULL
;
837 if (NumberOfChildren
== 0) {
839 Status
= gBS
->OpenProtocol (
841 &gEfiPciIoProtocolGuid
,
843 This
->DriverBindingHandle
,
845 EFI_OPEN_PROTOCOL_GET_PROTOCOL
847 if (!EFI_ERROR (Status
)) {
850 EfiPciIoAttributeOperationDisable
,
851 EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO
| EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO
| EFI_PCI_DEVICE_ENABLE
,
859 (VOID
**) &IdeBusDriverPrivateData
,
860 This
->DriverBindingHandle
,
862 EFI_OPEN_PROTOCOL_GET_PROTOCOL
865 gBS
->UninstallMultipleProtocolInterfaces (
868 IdeBusDriverPrivateData
,
872 if (IdeBusDriverPrivateData
!= NULL
) {
873 gBS
->FreePool (IdeBusDriverPrivateData
);
876 // Close the bus driver
880 &gEfiIdeControllerInitProtocolGuid
,
881 This
->DriverBindingHandle
,
886 &gEfiPciIoProtocolGuid
,
887 This
->DriverBindingHandle
,
892 &gEfiDevicePathProtocolGuid
,
893 This
->DriverBindingHandle
,
900 AllChildrenStopped
= TRUE
;
902 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
904 Status
= DeRegisterIdeDevice (This
, Controller
, ChildHandleBuffer
[Index
]);
906 if (EFI_ERROR (Status
)) {
907 AllChildrenStopped
= FALSE
;
911 if (!AllChildrenStopped
) {
912 return EFI_DEVICE_ERROR
;
919 // ***********************************************************************************
920 // DeRegisterIdeDevice
921 // ***********************************************************************************
924 Deregister an IDE device and free resources
926 @param This Protocol instance pointer.
927 @param Controller Ide device handle
928 @param Handle Handle of device to deregister driver on
934 DeRegisterIdeDevice (
935 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
936 IN EFI_HANDLE Controller
,
939 // TODO: EFI_SUCCESS - add return value to function comment
942 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
943 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
944 EFI_PCI_IO_PROTOCOL
*PciIo
;
947 Status
= gBS
->OpenProtocol (
949 &gEfiBlockIoProtocolGuid
,
951 This
->DriverBindingHandle
,
953 EFI_OPEN_PROTOCOL_GET_PROTOCOL
955 if (EFI_ERROR (Status
)) {
959 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo
);
962 // Report Status code: Device disabled
964 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
966 (EFI_IO_BUS_ATA_ATAPI
| EFI_P_PC_DISABLE
),
967 IdeBlkIoDevice
->DevicePath
971 // Close the child handle
973 Status
= gBS
->CloseProtocol (
975 &gEfiPciIoProtocolGuid
,
976 This
->DriverBindingHandle
,
980 Status
= gBS
->UninstallMultipleProtocolInterfaces (
982 &gEfiDevicePathProtocolGuid
,
983 IdeBlkIoDevice
->DevicePath
,
984 &gEfiBlockIoProtocolGuid
,
985 &IdeBlkIoDevice
->BlkIo
,
986 &gEfiDiskInfoProtocolGuid
,
987 &IdeBlkIoDevice
->DiskInfo
,
991 if (EFI_ERROR (Status
)) {
994 &gEfiPciIoProtocolGuid
,
996 This
->DriverBindingHandle
,
998 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1004 // Release allocated resources
1006 Index
= IdeBlkIoDevice
->Channel
* 2 + IdeBlkIoDevice
->Device
;
1007 IdeBlkIoDevice
->IdeBusDriverPrivateData
->HaveScannedDevice
[Index
] = FALSE
;
1009 ReleaseIdeResources (IdeBlkIoDevice
);
1015 // ***********************************************************************************
1017 // ***********************************************************************************
1020 TODO: This - add argument and description to function comment
1021 TODO: ExtendedVerification - add argument and description to function comment
1022 TODO: EFI_DEVICE_ERROR - add return value to function comment
1028 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1029 IN BOOLEAN ExtendedVerification
1032 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1035 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (This
);
1037 // Requery IDE IO resources in case of the switch of native and legacy modes
1039 ReassignIdeResources (IdeBlkIoDevice
);
1042 // for ATA device, using ATA reset method
1044 if (IdeBlkIoDevice
->Type
== IdeHardDisk
||
1045 IdeBlkIoDevice
->Type
== Ide48bitAddressingHardDisk
) {
1046 return AtaSoftReset (IdeBlkIoDevice
);
1049 if (IdeBlkIoDevice
->Type
== IdeUnknown
) {
1050 return EFI_DEVICE_ERROR
;
1054 // for ATAPI device, using ATAPI reset method
1056 Status
= AtapiSoftReset (IdeBlkIoDevice
);
1057 if (ExtendedVerification
) {
1058 Status
= AtaSoftReset (IdeBlkIoDevice
);
1065 Read data from block io device
1067 @param This Protocol instance pointer.
1068 @param MediaId The media ID of the device
1069 @param LBA Starting LBA address to read data
1070 @param BufferSize The size of data to be read
1071 @param Buffer Caller supplied buffer to save data
1073 @return read data status
1078 IDEBlkIoReadBlocks (
1079 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1082 IN UINTN BufferSize
,
1085 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1087 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1089 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (This
);
1092 // Requery IDE IO resources in case of the switch of native and legacy modes
1094 ReassignIdeResources (IdeBlkIoDevice
);
1097 // For ATA compatible device, use ATA read block's mechanism
1099 if (IdeBlkIoDevice
->Type
== IdeHardDisk
||
1100 IdeBlkIoDevice
->Type
== Ide48bitAddressingHardDisk
) {
1101 return AtaBlkIoReadBlocks (
1110 if (IdeBlkIoDevice
->Type
== IdeUnknown
) {
1111 return EFI_DEVICE_ERROR
;
1115 // for ATAPI device, using ATAPI read block's mechanism
1117 return AtapiBlkIoReadBlocks (
1128 Write data to block io device
1130 @param This Protocol instance pointer.
1131 @param MediaId The media ID of the device
1132 @param LBA Starting LBA address to write data
1133 @param BufferSize The size of data to be written
1134 @param Buffer Caller supplied buffer to save data
1136 @return write data status
1141 IDEBlkIoWriteBlocks (
1142 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1145 IN UINTN BufferSize
,
1148 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1150 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1152 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (This
);
1154 // Requery IDE IO resources in case of the switch of native and legacy modes
1156 ReassignIdeResources (IdeBlkIoDevice
);
1159 // for ATA device, using ATA write block's mechanism
1161 if (IdeBlkIoDevice
->Type
== IdeHardDisk
||
1162 IdeBlkIoDevice
->Type
== Ide48bitAddressingHardDisk
) {
1164 return AtaBlkIoWriteBlocks (
1173 if (IdeBlkIoDevice
->Type
== IdeUnknown
) {
1174 return EFI_DEVICE_ERROR
;
1178 // for ATAPI device, using ATAPI write block's mechanism
1180 return AtapiBlkIoWriteBlocks (
1190 // ***********************************************************************************
1191 // IDEBlkIoFlushBlocks
1192 // ***********************************************************************************
1195 TODO: This - add argument and description to function comment
1196 TODO: EFI_SUCCESS - add return value to function comment
1200 IDEBlkIoFlushBlocks (
1201 IN EFI_BLOCK_IO_PROTOCOL
*This
1211 Return the results of the Inquiry command to a drive in InquiryData.
1212 Data format of Inquiry data is defined by the Interface GUID.
1214 @param This Protocol instance pointer.
1215 @param InquiryData Results of Inquiry command to device
1216 @param InquiryDataSize Size of InquiryData in bytes.
1218 @retval EFI_SUCCESS InquiryData valid
1219 @retval EFI_NOT_FOUND Device does not support this data class
1220 @retval EFI_DEVICE_ERROR Error reading InquiryData from device
1221 @retval EFI_BUFFER_TOO_SMALL IntquiryDataSize not big enough
1226 IDEDiskInfoInquiry (
1227 IN EFI_DISK_INFO_PROTOCOL
*This
,
1228 IN OUT VOID
*InquiryData
,
1229 IN OUT UINT32
*InquiryDataSize
1232 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1234 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This
);
1236 if (*InquiryDataSize
< sizeof (INQUIRY_DATA
)) {
1237 *InquiryDataSize
= sizeof (INQUIRY_DATA
);
1238 return EFI_BUFFER_TOO_SMALL
;
1241 if (IdeBlkIoDevice
->pInquiryData
== NULL
) {
1242 return EFI_NOT_FOUND
;
1245 gBS
->CopyMem (InquiryData
, IdeBlkIoDevice
->pInquiryData
, sizeof (INQUIRY_DATA
));
1246 *InquiryDataSize
= sizeof (INQUIRY_DATA
);
1252 Return the results of the Identify command to a drive in IdentifyData.
1253 Data format of Identify data is defined by the Interface GUID.
1255 @param This Protocol instance pointer.
1256 @param IdentifyData Results of Identify command to device
1257 @param IdentifyDataSize Size of IdentifyData in bytes.
1259 @retval EFI_SUCCESS IdentifyData valid
1260 @retval EFI_NOT_FOUND Device does not support this data class
1261 @retval EFI_DEVICE_ERROR Error reading IdentifyData from device
1262 @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough
1267 IDEDiskInfoIdentify (
1268 IN EFI_DISK_INFO_PROTOCOL
*This
,
1269 IN OUT VOID
*IdentifyData
,
1270 IN OUT UINT32
*IdentifyDataSize
1273 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1275 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This
);
1277 if (*IdentifyDataSize
< sizeof (EFI_IDENTIFY_DATA
)) {
1278 *IdentifyDataSize
= sizeof (EFI_IDENTIFY_DATA
);
1279 return EFI_BUFFER_TOO_SMALL
;
1282 if (IdeBlkIoDevice
->pIdData
== NULL
) {
1283 return EFI_NOT_FOUND
;
1286 gBS
->CopyMem (IdentifyData
, IdeBlkIoDevice
->pIdData
, sizeof (EFI_IDENTIFY_DATA
));
1287 *IdentifyDataSize
= sizeof (EFI_IDENTIFY_DATA
);
1293 Return the results of the Request Sense command to a drive in SenseData.
1294 Data format of Sense data is defined by the Interface GUID.
1296 @param This Protocol instance pointer.
1297 @param SenseData Results of Request Sense command to device
1298 @param SenseDataSize Size of SenseData in bytes.
1299 @param SenseDataNumber Type of SenseData
1301 @retval EFI_SUCCESS InquiryData valid
1302 @retval EFI_NOT_FOUND Device does not support this data class
1303 @retval EFI_DEVICE_ERROR Error reading InquiryData from device
1304 @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough
1309 IDEDiskInfoSenseData (
1310 IN EFI_DISK_INFO_PROTOCOL
*This
,
1311 IN OUT VOID
*SenseData
,
1312 IN OUT UINT32
*SenseDataSize
,
1313 OUT UINT8
*SenseDataNumber
1316 return EFI_NOT_FOUND
;
1320 Return the results of the Request Sense command to a drive in SenseData.
1321 Data format of Sense data is defined by the Interface GUID.
1323 @param This Protocol instance pointer.
1324 @param IdeChannel Primary or Secondary
1325 @param IdeDevice Master or Slave
1327 @retval EFI_SUCCESS IdeChannel and IdeDevice are valid
1328 @retval EFI_UNSUPPORTED This is not an IDE device
1333 IDEDiskInfoWhichIde (
1334 IN EFI_DISK_INFO_PROTOCOL
*This
,
1335 OUT UINT32
*IdeChannel
,
1336 OUT UINT32
*IdeDevice
1339 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1341 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This
);
1342 *IdeChannel
= IdeBlkIoDevice
->Channel
;
1343 *IdeDevice
= IdeBlkIoDevice
->Device
;