2 This file implement UEFI driver for IDE Bus which includes device identification,
3 Child device(Disk, CDROM, etc) enumeration and child handler installation, and
6 Copyright (c) 2006 - 2009, Intel Corporation
7 All rights reserved. This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 @par Revision Reference:
16 This module is modified from DXE\IDE module for Ide Contriller Init support
22 #define PCI_CLASS_MASS_STORAGE 0x01
23 #define PCI_SUB_CLASS_IDE 0x01
27 // IDE Bus Driver Binding Protocol Instance
29 EFI_DRIVER_BINDING_PROTOCOL gIDEBusDriverBinding
= {
30 IDEBusDriverBindingSupported
,
31 IDEBusDriverBindingStart
,
32 IDEBusDriverBindingStop
,
38 Deregister an IDE device and free resources
40 @param This Protocol instance pointer.
41 @param Controller Ide device handle
42 @param Handle Handle of device to deregister driver on
44 @retval EFI_SUCCESS Deregiter a specific IDE device successfully
50 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
51 IN EFI_HANDLE Controller
,
56 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
57 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
58 EFI_PCI_IO_PROTOCOL
*PciIo
;
61 Status
= gBS
->OpenProtocol (
63 &gEfiBlockIoProtocolGuid
,
65 This
->DriverBindingHandle
,
67 EFI_OPEN_PROTOCOL_GET_PROTOCOL
69 if (EFI_ERROR (Status
)) {
73 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo
);
76 // Report Status code: Device disabled
78 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
80 (EFI_IO_BUS_ATA_ATAPI
| EFI_P_PC_DISABLE
),
81 IdeBlkIoDevice
->DevicePath
85 // Close the child handle
87 Status
= gBS
->CloseProtocol (
89 &gEfiPciIoProtocolGuid
,
90 This
->DriverBindingHandle
,
94 Status
= gBS
->UninstallMultipleProtocolInterfaces (
96 &gEfiDevicePathProtocolGuid
,
97 IdeBlkIoDevice
->DevicePath
,
98 &gEfiBlockIoProtocolGuid
,
99 &IdeBlkIoDevice
->BlkIo
,
100 &gEfiDiskInfoProtocolGuid
,
101 &IdeBlkIoDevice
->DiskInfo
,
105 if (EFI_ERROR (Status
)) {
108 &gEfiPciIoProtocolGuid
,
110 This
->DriverBindingHandle
,
112 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
118 // Release allocated resources
120 Index
= IdeBlkIoDevice
->Channel
* 2 + IdeBlkIoDevice
->Device
;
121 if (Index
< MAX_IDE_DEVICE
) {
122 IdeBlkIoDevice
->IdeBusDriverPrivateData
->HaveScannedDevice
[Index
] = FALSE
;
124 ReleaseIdeResources (IdeBlkIoDevice
);
129 Supported function of Driver Binding protocol for this driver.
131 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
132 @param ControllerHandle The handle of the controller to test.
133 @param RemainingDevicePath A pointer to the remaining portion of a device path.
135 @retval EFI_SUCCESS Driver loaded.
136 @retval other Driver not loaded.
141 IDEBusDriverBindingSupported (
142 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
143 IN EFI_HANDLE Controller
,
144 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
148 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
150 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
152 if (RemainingDevicePath
!= NULL
) {
153 Node
= (EFI_DEV_PATH
*) RemainingDevicePath
;
155 // Check if RemainingDevicePath is the End of Device Path Node,
156 // if yes, go on checking other conditions
158 if (!IsDevicePathEnd (Node
)) {
160 // If RemainingDevicePath isn't the End of Device Path Node,
161 // check its validation
163 if (Node
->DevPath
.Type
!= MESSAGING_DEVICE_PATH
||
164 Node
->DevPath
.SubType
!= MSG_ATAPI_DP
||
165 DevicePathNodeLength(&Node
->DevPath
) != sizeof(ATAPI_DEVICE_PATH
)) {
166 return EFI_UNSUPPORTED
;
172 // Verify the Ide Controller Init Protocol, which installed by the
173 // IdeController module.
174 // Note 1: PciIo protocol has been opened BY_DRIVER by ide_init, so We can't
175 // open BY_DRIVER here) That's why we don't check pciio protocol
176 // Note 2: ide_init driver check ide controller's pci config space, so we dont
177 // check here any more to save code size
179 Status
= gBS
->OpenProtocol (
181 &gEfiIdeControllerInitProtocolGuid
,
183 This
->DriverBindingHandle
,
185 EFI_OPEN_PROTOCOL_BY_DRIVER
188 if (Status
== EFI_ALREADY_STARTED
) {
192 if (EFI_ERROR (Status
)) {
197 // Close the I/O Abstraction(s) used to perform the supported test
201 &gEfiIdeControllerInitProtocolGuid
,
202 This
->DriverBindingHandle
,
207 // Open the EFI Device Path protocol needed to perform the supported test
209 Status
= gBS
->OpenProtocol (
211 &gEfiDevicePathProtocolGuid
,
212 (VOID
**) &ParentDevicePath
,
213 This
->DriverBindingHandle
,
215 EFI_OPEN_PROTOCOL_BY_DRIVER
217 if (Status
== EFI_ALREADY_STARTED
) {
222 // Close protocol, don't use device path protocol in the Support() function
226 &gEfiDevicePathProtocolGuid
,
227 This
->DriverBindingHandle
,
236 Start function of Driver binding protocol which start this driver on Controller
237 by detecting all disks and installing BlockIo protocol on them.
239 @param This Protocol instance pointer.
240 @param Controller Handle of device to bind driver to.
241 @param RemainingDevicePath produce all possible children.
243 @retval EFI_SUCCESS This driver is added to ControllerHandle.
244 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
245 @retval other This driver does not support this device.
250 IDEBusDriverBindingStart (
251 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
252 IN EFI_HANDLE Controller
,
253 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
257 EFI_STATUS SavedStatus
;
258 EFI_PCI_IO_PROTOCOL
*PciIo
;
259 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
262 UINT8 BeginningIdeChannel
;
265 UINT8 BeginningIdeDevice
;
267 IDE_BLK_IO_DEV
*IdeBlkIoDevice
[IdeMaxChannel
][IdeMaxDevice
];
268 IDE_BLK_IO_DEV
*IdeBlkIoDevicePtr
;
269 IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr
[IdeMaxChannel
];
270 ATA_TRANSFER_MODE TransferMode
;
271 ATA_DRIVE_PARMS DriveParameters
;
272 EFI_DEV_PATH NewNode
;
273 UINT8 ConfigurationOptions
;
274 UINT16 CommandBlockBaseAddr
;
275 UINT16 ControlBlockBaseAddr
;
277 IDE_BUS_DRIVER_PRIVATE_DATA
*IdeBusDriverPrivateData
;
281 // Local variables declaration for IdeControllerInit support
283 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
285 BOOLEAN ChannelEnabled
;
287 EFI_IDENTIFY_DATA IdentifyData
;
288 EFI_ATA_COLLECTIVE_MODE
*SupportedModes
;
290 IdeBusDriverPrivateData
= NULL
;
291 SupportedModes
= NULL
;
294 // Perform IdeBus initialization
296 Status
= gBS
->OpenProtocol (
298 &gEfiDevicePathProtocolGuid
,
299 (VOID
**) &ParentDevicePath
,
300 This
->DriverBindingHandle
,
302 EFI_OPEN_PROTOCOL_BY_DRIVER
304 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
309 // Now open the IDE_CONTROLLER_INIT protocol. Step7.1
311 Status
= gBS
->OpenProtocol (
313 &gEfiIdeControllerInitProtocolGuid
,
315 This
->DriverBindingHandle
,
317 EFI_OPEN_PROTOCOL_BY_DRIVER
321 // The following OpenProtocol function with _GET_PROTOCOL attribute and
322 // will not return EFI_ALREADY_STARTED, so save it for now
324 SavedStatus
= Status
;
326 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
327 DEBUG ((EFI_D_ERROR
, "Open Init, Status=%x", Status
));
329 // open protocol is not SUCCESS or not ALREADY_STARTED, error exit
335 // Save Enumall. Step7.2
337 EnumAll
= IdeInit
->EnumAll
;
340 // Consume PCI I/O protocol. Note that the OpenProtocol with _GET_PROTOCOL
341 // attribute will not return EFI_ALREADY_STARTED
343 Status
= gBS
->OpenProtocol (
345 &gEfiPciIoProtocolGuid
,
347 This
->DriverBindingHandle
,
349 EFI_OPEN_PROTOCOL_GET_PROTOCOL
351 if (EFI_ERROR (Status
)) {
352 DEBUG ((EFI_D_ERROR
, "Open PciIo, Status=%x", Status
));
357 // We must check EFI_ALREADY_STARTED because many ATAPI devices are removable
359 if (SavedStatus
!= EFI_ALREADY_STARTED
) {
360 IdeBusDriverPrivateData
= AllocatePool (sizeof (IDE_BUS_DRIVER_PRIVATE_DATA
));
361 if (IdeBusDriverPrivateData
== NULL
) {
362 Status
= EFI_OUT_OF_RESOURCES
;
366 ZeroMem (IdeBusDriverPrivateData
, sizeof (IDE_BUS_DRIVER_PRIVATE_DATA
));
367 Status
= gBS
->InstallMultipleProtocolInterfaces (
370 IdeBusDriverPrivateData
,
373 if (EFI_ERROR (Status
)) {
378 Status
= gBS
->OpenProtocol (
381 (VOID
**) &IdeBusDriverPrivateData
,
382 This
->DriverBindingHandle
,
384 EFI_OPEN_PROTOCOL_GET_PROTOCOL
386 if (EFI_ERROR (Status
)) {
387 IdeBusDriverPrivateData
= NULL
;
392 Status
= PciIo
->Attributes (
394 EfiPciIoAttributeOperationSupported
,
398 if (!EFI_ERROR (Status
)) {
399 Supports
&= EFI_PCI_DEVICE_ENABLE
;
400 Status
= PciIo
->Attributes (
402 EfiPciIoAttributeOperationEnable
,
408 if (EFI_ERROR (Status
)) {
413 // Read the environment variable that contains the IDEBus Driver's
414 // Config options that were set by the Driver Configuration Protocol
416 DataSize
= sizeof (ConfigurationOptions
);
417 Status
= gRT
->GetVariable (
418 (CHAR16
*) L
"Configuration",
422 &ConfigurationOptions
424 if (EFI_ERROR (Status
)) {
425 ConfigurationOptions
= 0x0f;
428 if (EnumAll
|| RemainingDevicePath
== NULL
) {
430 // If IdeInit->EnumAll is TRUE or RemainingDevicePath is NULL,
431 // must enumerate all IDE devices anyway
433 BeginningIdeChannel
= IdePrimary
;
434 EndIdeChannel
= IdeSecondary
;
435 BeginningIdeDevice
= IdeMaster
;
436 EndIdeDevice
= IdeSlave
;
438 } else if (!IsDevicePathEnd (RemainingDevicePath
)) {
440 // If RemainingDevicePath isn't the End of Device Path Node,
441 // only scan the specified device by RemainingDevicePath
443 Node
= (EFI_DEV_PATH
*) RemainingDevicePath
;
444 BeginningIdeChannel
= Node
->Atapi
.PrimarySecondary
;
445 EndIdeChannel
= BeginningIdeChannel
;
446 BeginningIdeDevice
= Node
->Atapi
.SlaveMaster
;
447 EndIdeDevice
= BeginningIdeDevice
;
448 if (BeginningIdeChannel
>= IdeMaxChannel
|| EndIdeChannel
>= IdeMaxChannel
) {
449 Status
= EFI_INVALID_PARAMETER
;
452 if (BeginningIdeDevice
>= IdeMaxDevice
|| EndIdeDevice
>= IdeMaxDevice
) {
453 Status
= EFI_INVALID_PARAMETER
;
459 // If RemainingDevicePath is the End of Device Path Node,
460 // skip enumerate any device and return EFI_SUCESSS
462 BeginningIdeChannel
= IdeMaxChannel
;
463 EndIdeChannel
= IdeMaxChannel
- 1;
464 BeginningIdeDevice
= IdeMaxDevice
;
465 EndIdeDevice
= IdeMaxDevice
- 1;
469 // Obtain IDE IO port registers' base addresses
471 Status
= GetIdeRegistersBaseAddr (PciIo
, IdeRegsBaseAddr
);
472 if (EFI_ERROR (Status
)) {
477 // Report status code: begin IdeBus initialization
479 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
481 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_PC_RESET
),
486 // Strictly follow the enumeration based on IDE_CONTROLLER_INIT protocol
488 for (IdeChannel
= BeginningIdeChannel
; IdeChannel
<= EndIdeChannel
; IdeChannel
++) {
490 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelEnumeration
, IdeChannel
);
493 // now obtain channel information fron IdeControllerInit protocol. Step9
495 Status
= IdeInit
->GetChannelInfo (
501 if (EFI_ERROR (Status
)) {
502 DEBUG ((EFI_D_ERROR
, "[GetChannel, Status=%x]", Status
));
506 if (!ChannelEnabled
) {
510 EndIdeDevice
= (UINT8
) MIN ((MaxDevices
- 1), EndIdeDevice
);
511 ASSERT (EndIdeDevice
< IdeMaxDevice
);
513 // Now inform the IDE Controller Init Module. Sept10
515 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelReset
, IdeChannel
);
518 // No reset channel function implemented. Sept11
520 IdeInit
->NotifyPhase (IdeInit
, EfiIdeAfterChannelReset
, IdeChannel
);
525 IdeInit
->NotifyPhase (
527 EfiIdeBusBeforeDevicePresenceDetection
,
532 // Prepare to detect IDE device of this channel
534 InitializeIDEChannelData ();
537 // -- 1st inner loop --- Master/Slave ------------ Step14
539 for (IdeDevice
= BeginningIdeDevice
; IdeDevice
<= EndIdeDevice
; IdeDevice
++) {
541 // Check whether the configuration options allow this device
543 if ((ConfigurationOptions
& (1 << (IdeChannel
* 2 + IdeDevice
))) == 0) {
548 // The device has been scanned in another Start(), No need to scan it again
549 // for perf optimization.
551 if (IdeBusDriverPrivateData
->HaveScannedDevice
[IdeChannel
* 2 + IdeDevice
]) {
556 // create child handle for the detected device.
558 IdeBlkIoDevice
[IdeChannel
][IdeDevice
] = AllocatePool (sizeof (IDE_BLK_IO_DEV
));
559 if (IdeBlkIoDevice
[IdeChannel
][IdeDevice
] == NULL
) {
563 IdeBlkIoDevicePtr
= IdeBlkIoDevice
[IdeChannel
][IdeDevice
];
565 ZeroMem (IdeBlkIoDevicePtr
, sizeof (IDE_BLK_IO_DEV
));
567 IdeBlkIoDevicePtr
->Signature
= IDE_BLK_IO_DEV_SIGNATURE
;
568 IdeBlkIoDevicePtr
->Channel
= (EFI_IDE_CHANNEL
) IdeChannel
;
569 IdeBlkIoDevicePtr
->Device
= (EFI_IDE_DEVICE
) IdeDevice
;
572 // initialize Block IO interface's Media pointer
574 IdeBlkIoDevicePtr
->BlkIo
.Media
= &IdeBlkIoDevicePtr
->BlkMedia
;
577 // Initialize IDE IO port addresses, including Command Block registers
578 // and Control Block registers
580 IdeBlkIoDevicePtr
->IoPort
= AllocatePool (sizeof (IDE_BASE_REGISTERS
));
581 if (IdeBlkIoDevicePtr
->IoPort
== NULL
) {
585 ZeroMem (IdeBlkIoDevicePtr
->IoPort
, sizeof (IDE_BASE_REGISTERS
));
586 CommandBlockBaseAddr
= IdeRegsBaseAddr
[IdeChannel
].CommandBlockBaseAddr
;
587 ControlBlockBaseAddr
= IdeRegsBaseAddr
[IdeChannel
].ControlBlockBaseAddr
;
589 IdeBlkIoDevicePtr
->IoPort
->Data
= CommandBlockBaseAddr
;
590 (*(UINT16
*) &IdeBlkIoDevicePtr
->IoPort
->Reg1
) = (UINT16
) (CommandBlockBaseAddr
+ 0x01);
591 IdeBlkIoDevicePtr
->IoPort
->SectorCount
= (UINT16
) (CommandBlockBaseAddr
+ 0x02);
592 IdeBlkIoDevicePtr
->IoPort
->SectorNumber
= (UINT16
) (CommandBlockBaseAddr
+ 0x03);
593 IdeBlkIoDevicePtr
->IoPort
->CylinderLsb
= (UINT16
) (CommandBlockBaseAddr
+ 0x04);
594 IdeBlkIoDevicePtr
->IoPort
->CylinderMsb
= (UINT16
) (CommandBlockBaseAddr
+ 0x05);
595 IdeBlkIoDevicePtr
->IoPort
->Head
= (UINT16
) (CommandBlockBaseAddr
+ 0x06);
596 (*(UINT16
*) &IdeBlkIoDevicePtr
->IoPort
->Reg
) = (UINT16
) (CommandBlockBaseAddr
+ 0x07);
598 (*(UINT16
*) &IdeBlkIoDevicePtr
->IoPort
->Alt
) = ControlBlockBaseAddr
;
599 IdeBlkIoDevicePtr
->IoPort
->DriveAddress
= (UINT16
) (ControlBlockBaseAddr
+ 0x01);
601 IdeBlkIoDevicePtr
->IoPort
->MasterSlave
= (UINT16
) ((IdeDevice
== IdeMaster
) ? 1 : 0);
603 IdeBlkIoDevicePtr
->PciIo
= PciIo
;
604 IdeBlkIoDevicePtr
->IdeBusDriverPrivateData
= IdeBusDriverPrivateData
;
605 IdeBlkIoDevicePtr
->IoPort
->BusMasterBaseAddr
= IdeRegsBaseAddr
[IdeChannel
].BusMasterBaseAddr
;
608 // Report Status code: is about to detect IDE drive
610 REPORT_STATUS_CODE_EX (
612 (EFI_IO_BUS_ATA_ATAPI
| EFI_P_PC_PRESENCE_DETECT
),
621 // Discover device, now!
623 PERF_START (NULL
, "DiscoverIdeDevice", "IDE", 0);
624 Status
= DiscoverIdeDevice (IdeBlkIoDevicePtr
);
625 PERF_END (NULL
, "DiscoverIdeDevice", "IDE", 0);
627 IdeBusDriverPrivateData
->HaveScannedDevice
[IdeChannel
* 2 + IdeDevice
] = TRUE
;
628 IdeBusDriverPrivateData
->DeviceProcessed
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
630 if (!EFI_ERROR (Status
)) {
634 ZeroMem (&NewNode
, sizeof (NewNode
));
635 NewNode
.DevPath
.Type
= MESSAGING_DEVICE_PATH
;
636 NewNode
.DevPath
.SubType
= MSG_ATAPI_DP
;
637 SetDevicePathNodeLength (&NewNode
.DevPath
, sizeof (ATAPI_DEVICE_PATH
));
639 NewNode
.Atapi
.PrimarySecondary
= (UINT8
) IdeBlkIoDevicePtr
->Channel
;
640 NewNode
.Atapi
.SlaveMaster
= (UINT8
) IdeBlkIoDevicePtr
->Device
;
641 NewNode
.Atapi
.Lun
= IdeBlkIoDevicePtr
->Lun
;
642 IdeBlkIoDevicePtr
->DevicePath
= AppendDevicePathNode (
646 if (IdeBlkIoDevicePtr
->DevicePath
== NULL
) {
647 ReleaseIdeResources (IdeBlkIoDevicePtr
);
652 // Submit identify data to IDE controller init driver
654 CopyMem (&IdentifyData
, IdeBlkIoDevicePtr
->IdData
, sizeof (IdentifyData
));
655 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = TRUE
;
656 IdeInit
->SubmitData (IdeInit
, IdeChannel
, IdeDevice
, &IdentifyData
);
659 // Device detection failed
661 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
662 IdeInit
->SubmitData (IdeInit
, IdeChannel
, IdeDevice
, NULL
);
663 ReleaseIdeResources (IdeBlkIoDevicePtr
);
664 IdeBlkIoDevicePtr
= NULL
;
667 // end of 1st inner loop ---
671 // end of 1st outer loop =========
676 // = 2nd outer loop == Primary/Secondary =================
678 for (IdeChannel
= BeginningIdeChannel
; IdeChannel
<= EndIdeChannel
; IdeChannel
++) {
681 // -- 2nd inner loop --- Master/Slave --------
683 for (IdeDevice
= BeginningIdeDevice
; IdeDevice
<= EndIdeDevice
; IdeDevice
++) {
685 if (IdeBusDriverPrivateData
->DeviceProcessed
[IdeChannel
* 2 + IdeDevice
]) {
689 if (!IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
]) {
693 Status
= IdeInit
->CalculateMode (
699 if (EFI_ERROR (Status
)) {
700 DEBUG ((EFI_D_ERROR
, "[bStStp20S=%x]", Status
));
704 IdeBlkIoDevicePtr
= IdeBlkIoDevice
[IdeChannel
][IdeDevice
];
707 // Set best supported PIO mode on this IDE device
709 if (SupportedModes
->PioMode
.Mode
<= AtaPioMode2
) {
710 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_DEFAULT_PIO
;
712 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_FLOW_PIO
;
715 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->PioMode
.Mode
);
717 if (SupportedModes
->ExtModeCount
== 0){
718 Status
= SetDeviceTransferMode (IdeBlkIoDevicePtr
, &TransferMode
);
720 if (EFI_ERROR (Status
)) {
721 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
722 ReleaseIdeResources (IdeBlkIoDevicePtr
);
723 IdeBlkIoDevicePtr
= NULL
;
729 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
730 // be set together. Only one DMA mode can be set to a device. If setting
731 // DMA mode operation fails, we can continue moving on because we only use
732 // PIO mode at boot time. DMA modes are used by certain kind of OS booting
734 if (SupportedModes
->UdmaMode
.Valid
) {
736 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_UDMA
;
737 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->UdmaMode
.Mode
);
738 Status
= SetDeviceTransferMode (IdeBlkIoDevicePtr
, &TransferMode
);
740 if (EFI_ERROR (Status
)) {
741 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
742 ReleaseIdeResources (IdeBlkIoDevicePtr
);
743 IdeBlkIoDevicePtr
= NULL
;
749 IdeBlkIoDevicePtr
->UdmaMode
.Valid
= TRUE
;
750 IdeBlkIoDevicePtr
->UdmaMode
.Mode
= SupportedModes
->UdmaMode
.Mode
;
751 EnableInterrupt (IdeBlkIoDevicePtr
);
752 } else if (SupportedModes
->MultiWordDmaMode
.Valid
) {
754 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_MDMA
;
755 TransferMode
.ModeNumber
= (UINT8
) SupportedModes
->MultiWordDmaMode
.Mode
;
756 Status
= SetDeviceTransferMode (IdeBlkIoDevicePtr
, &TransferMode
);
758 if (EFI_ERROR (Status
)) {
759 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
760 ReleaseIdeResources (IdeBlkIoDevicePtr
);
761 IdeBlkIoDevicePtr
= NULL
;
765 EnableInterrupt (IdeBlkIoDevicePtr
);
768 // Init driver parameters
770 DriveParameters
.Sector
= (UINT8
) IdeBlkIoDevicePtr
->IdData
->AtaData
.sectors_per_track
;
771 DriveParameters
.Heads
= (UINT8
) (IdeBlkIoDevicePtr
->IdData
->AtaData
.heads
- 1);
772 DriveParameters
.MultipleSector
= (UINT8
) IdeBlkIoDevicePtr
->IdData
->AtaData
.multi_sector_cmd_max_sct_cnt
;
774 // Set Parameters for the device:
776 // 2) Establish the block count for READ/WRITE MULTIPLE (EXT) command
778 if ((IdeBlkIoDevicePtr
->Type
== IdeHardDisk
) || (IdeBlkIoDevicePtr
->Type
== Ide48bitAddressingHardDisk
)) {
779 Status
= SetDriveParameters (IdeBlkIoDevicePtr
, &DriveParameters
);
783 // Record PIO mode used in private data
785 IdeBlkIoDevicePtr
->PioMode
= (ATA_PIO_MODE
) SupportedModes
->PioMode
.Mode
;
788 // Set IDE controller Timing Blocks in the PCI Configuration Space
790 IdeInit
->SetTiming (IdeInit
, IdeChannel
, IdeDevice
, SupportedModes
);
793 // Add Component Name for the IDE/ATAPI device that was discovered.
795 IdeBlkIoDevicePtr
->ControllerNameTable
= NULL
;
796 ADD_IDE_ATAPI_NAME (IdeBlkIoDevicePtr
);
798 Status
= gBS
->InstallMultipleProtocolInterfaces (
799 &IdeBlkIoDevicePtr
->Handle
,
800 &gEfiDevicePathProtocolGuid
,
801 IdeBlkIoDevicePtr
->DevicePath
,
802 &gEfiBlockIoProtocolGuid
,
803 &IdeBlkIoDevicePtr
->BlkIo
,
804 &gEfiDiskInfoProtocolGuid
,
805 &IdeBlkIoDevicePtr
->DiskInfo
,
809 if (EFI_ERROR (Status
)) {
810 ReleaseIdeResources (IdeBlkIoDevicePtr
);
815 &gEfiPciIoProtocolGuid
,
817 This
->DriverBindingHandle
,
818 IdeBlkIoDevicePtr
->Handle
,
819 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
822 IdeBusDriverPrivateData
->DeviceProcessed
[IdeChannel
* 2 + IdeDevice
] = TRUE
;
825 // Report status code: device eanbled!
827 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
829 (EFI_IO_BUS_ATA_ATAPI
| EFI_P_PC_ENABLE
),
830 IdeBlkIoDevicePtr
->DevicePath
834 // Create event to clear pending IDE interrupt
836 Status
= gBS
->CreateEventEx (
841 &gEfiEventExitBootServicesGuid
,
842 &IdeBlkIoDevicePtr
->ExitBootServiceEvent
846 // end of 2nd inner loop ----
850 // end of 2nd outer loop ==========
855 // All configurations done! Notify IdeController to do post initialization
856 // work such as saving IDE controller PCI settings for S3 resume
858 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBusPhaseMaximum
, 0);
860 if (SupportedModes
!= NULL
) {
861 FreePool (SupportedModes
);
864 PERF_START (NULL
, "Finish IDE detection", "IDE", 1);
865 PERF_END (NULL
, "Finish IDE detection", "IDE", 0);
872 // Report error code: controller error
874 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
875 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
876 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_EC_CONTROLLER_ERROR
),
882 &gEfiIdeControllerInitProtocolGuid
,
883 This
->DriverBindingHandle
,
887 gBS
->UninstallMultipleProtocolInterfaces (
890 IdeBusDriverPrivateData
,
894 if (IdeBusDriverPrivateData
!= NULL
) {
895 gBS
->FreePool (IdeBusDriverPrivateData
);
898 if (SupportedModes
!= NULL
) {
899 gBS
->FreePool (SupportedModes
);
904 &gEfiPciIoProtocolGuid
,
905 This
->DriverBindingHandle
,
911 &gEfiDevicePathProtocolGuid
,
912 This
->DriverBindingHandle
,
920 Stop function of Driver Binding Protocol which is to stop the driver on Controller Handle and all
921 child handle attached to the controller handle if there are.
923 @param This Protocol instance pointer.
924 @param Controller Handle of device to stop driver on
925 @param NumberOfChildren Not used
926 @param ChildHandleBuffer Not used
928 @retval EFI_SUCCESS This driver is removed DeviceHandle
929 @retval other This driver was not removed from this device
934 IDEBusDriverBindingStop (
935 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
936 IN EFI_HANDLE Controller
,
937 IN UINTN NumberOfChildren
,
938 IN EFI_HANDLE
*ChildHandleBuffer
942 EFI_PCI_IO_PROTOCOL
*PciIo
;
943 BOOLEAN AllChildrenStopped
;
945 IDE_BUS_DRIVER_PRIVATE_DATA
*IdeBusDriverPrivateData
;
948 IdeBusDriverPrivateData
= NULL
;
950 if (NumberOfChildren
== 0) {
952 Status
= gBS
->OpenProtocol (
954 &gEfiPciIoProtocolGuid
,
956 This
->DriverBindingHandle
,
958 EFI_OPEN_PROTOCOL_GET_PROTOCOL
960 if (!EFI_ERROR (Status
)) {
961 Status
= PciIo
->Attributes (
963 EfiPciIoAttributeOperationSupported
,
967 if (!EFI_ERROR (Status
)) {
968 Supports
&= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO
| EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO
| EFI_PCI_DEVICE_ENABLE
;
971 EfiPciIoAttributeOperationDisable
,
981 (VOID
**) &IdeBusDriverPrivateData
,
982 This
->DriverBindingHandle
,
984 EFI_OPEN_PROTOCOL_GET_PROTOCOL
987 gBS
->UninstallMultipleProtocolInterfaces (
990 IdeBusDriverPrivateData
,
994 if (IdeBusDriverPrivateData
!= NULL
) {
995 gBS
->FreePool (IdeBusDriverPrivateData
);
998 // Close the bus driver
1000 gBS
->CloseProtocol (
1002 &gEfiIdeControllerInitProtocolGuid
,
1003 This
->DriverBindingHandle
,
1006 gBS
->CloseProtocol (
1008 &gEfiPciIoProtocolGuid
,
1009 This
->DriverBindingHandle
,
1012 gBS
->CloseProtocol (
1014 &gEfiDevicePathProtocolGuid
,
1015 This
->DriverBindingHandle
,
1022 AllChildrenStopped
= TRUE
;
1024 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1026 Status
= DeRegisterIdeDevice (This
, Controller
, ChildHandleBuffer
[Index
]);
1028 if (EFI_ERROR (Status
)) {
1029 AllChildrenStopped
= FALSE
;
1033 if (!AllChildrenStopped
) {
1034 return EFI_DEVICE_ERROR
;
1041 issue ATA or ATAPI command to reset a block IO device.
1042 @param This Block IO protocol instance pointer.
1043 @param ExtendedVerification If FALSE,for ATAPI device, driver will only invoke ATAPI reset method
1044 If TRUE, for ATAPI device, driver need invoke ATA reset method after
1045 invoke ATAPI reset method
1047 @retval EFI_DEVICE_ERROR When the device is neighther ATA device or ATAPI device.
1048 @retval EFI_SUCCESS The device reset successfully
1054 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1055 IN BOOLEAN ExtendedVerification
1058 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1062 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1064 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (This
);
1066 // Requery IDE IO resources in case of the switch of native and legacy modes
1068 ReassignIdeResources (IdeBlkIoDevice
);
1071 // for ATA device, using ATA reset method
1073 if (IdeBlkIoDevice
->Type
== IdeHardDisk
||
1074 IdeBlkIoDevice
->Type
== Ide48bitAddressingHardDisk
) {
1075 Status
= AtaSoftReset (IdeBlkIoDevice
);
1079 if (IdeBlkIoDevice
->Type
== IdeUnknown
) {
1080 Status
= EFI_DEVICE_ERROR
;
1085 // for ATAPI device, using ATAPI reset method
1087 Status
= AtapiSoftReset (IdeBlkIoDevice
);
1088 if (ExtendedVerification
) {
1089 Status
= AtaSoftReset (IdeBlkIoDevice
);
1093 gBS
->RestoreTPL (OldTpl
);
1098 Read data from a block IO device
1100 @param This Block IO protocol instance pointer.
1101 @param MediaId The media ID of the device
1102 @param Lba Starting LBA address to read data
1103 @param BufferSize The size of data to be read
1104 @param Buffer Caller supplied buffer to save data
1106 @retval EFI_DEVICE_ERROR unknown device type
1107 @retval other read data status.
1112 IDEBlkIoReadBlocks (
1113 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1116 IN UINTN BufferSize
,
1120 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1124 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1126 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (This
);
1129 // Requery IDE IO resources in case of the switch of native and legacy modes
1131 ReassignIdeResources (IdeBlkIoDevice
);
1134 // For ATA compatible device, use ATA read block's mechanism
1136 if (IdeBlkIoDevice
->Type
== IdeHardDisk
||
1137 IdeBlkIoDevice
->Type
== Ide48bitAddressingHardDisk
) {
1138 Status
= AtaBlkIoReadBlocks (
1148 if (IdeBlkIoDevice
->Type
== IdeUnknown
) {
1149 Status
= EFI_DEVICE_ERROR
;
1154 // for ATAPI device, using ATAPI read block's mechanism
1156 Status
= AtapiBlkIoReadBlocks (
1165 gBS
->RestoreTPL (OldTpl
);
1171 Write data to block io device.
1173 @param This Protocol instance pointer.
1174 @param MediaId The media ID of the device
1175 @param Lba Starting LBA address to write data
1176 @param BufferSize The size of data to be written
1177 @param Buffer Caller supplied buffer to save data
1179 @retval EFI_DEVICE_ERROR unknown device type
1180 @retval other write data status
1185 IDEBlkIoWriteBlocks (
1186 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1189 IN UINTN BufferSize
,
1193 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1197 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1199 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (This
);
1201 // Requery IDE IO resources in case of the switch of native and legacy modes
1203 ReassignIdeResources (IdeBlkIoDevice
);
1206 // for ATA device, using ATA write block's mechanism
1208 if (IdeBlkIoDevice
->Type
== IdeHardDisk
||
1209 IdeBlkIoDevice
->Type
== Ide48bitAddressingHardDisk
) {
1211 Status
= AtaBlkIoWriteBlocks (
1221 if (IdeBlkIoDevice
->Type
== IdeUnknown
) {
1222 Status
= EFI_DEVICE_ERROR
;
1227 // for ATAPI device, using ATAPI write block's mechanism
1229 Status
= AtapiBlkIoWriteBlocks (
1238 gBS
->RestoreTPL (OldTpl
);
1242 Flushes all modified data to a physical block devices
1244 @param This Indicates a pointer to the calling context which to sepcify a
1245 sepcific block device
1247 @retval EFI_SUCCESS Always return success.
1251 IDEBlkIoFlushBlocks (
1252 IN EFI_BLOCK_IO_PROTOCOL
*This
1262 This function is used by the IDE bus driver to get inquiry data.
1263 Data format of Identify data is defined by the Interface GUID.
1265 @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
1266 @param InquiryData Pointer to a buffer for the inquiry data.
1267 @param InquiryDataSize Pointer to the value for the inquiry data size.
1269 @retval EFI_SUCCESS The command was accepted without any errors.
1270 @retval EFI_NOT_FOUND Device does not support this data class
1271 @retval EFI_DEVICE_ERROR Error reading InquiryData from device
1272 @retval EFI_BUFFER_TOO_SMALL IntquiryDataSize not big enough
1277 IDEDiskInfoInquiry (
1278 IN EFI_DISK_INFO_PROTOCOL
*This
,
1279 IN OUT VOID
*InquiryData
,
1280 IN OUT UINT32
*InquiryDataSize
1283 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1285 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This
);
1287 if (*InquiryDataSize
< sizeof (ATAPI_INQUIRY_DATA
)) {
1288 *InquiryDataSize
= sizeof (ATAPI_INQUIRY_DATA
);
1289 return EFI_BUFFER_TOO_SMALL
;
1292 if (IdeBlkIoDevice
->InquiryData
== NULL
) {
1293 return EFI_NOT_FOUND
;
1296 gBS
->CopyMem (InquiryData
, IdeBlkIoDevice
->InquiryData
, sizeof (ATAPI_INQUIRY_DATA
));
1297 *InquiryDataSize
= sizeof (ATAPI_INQUIRY_DATA
);
1303 This function is used by the IDE bus driver to get identify data.
1304 Data format of Identify data is defined by the Interface GUID.
1306 @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
1307 @param IdentifyData Pointer to a buffer for the identify data.
1308 @param IdentifyDataSize Pointer to the value for the identify data size.
1310 @retval EFI_SUCCESS The command was accepted without any errors.
1311 @retval EFI_NOT_FOUND Device does not support this data class
1312 @retval EFI_DEVICE_ERROR Error reading IdentifyData from device
1313 @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough
1318 IDEDiskInfoIdentify (
1319 IN EFI_DISK_INFO_PROTOCOL
*This
,
1320 IN OUT VOID
*IdentifyData
,
1321 IN OUT UINT32
*IdentifyDataSize
1324 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1326 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This
);
1328 if (*IdentifyDataSize
< sizeof (EFI_IDENTIFY_DATA
)) {
1329 *IdentifyDataSize
= sizeof (EFI_IDENTIFY_DATA
);
1330 return EFI_BUFFER_TOO_SMALL
;
1333 if (IdeBlkIoDevice
->IdData
== NULL
) {
1334 return EFI_NOT_FOUND
;
1337 gBS
->CopyMem (IdentifyData
, IdeBlkIoDevice
->IdData
, sizeof (EFI_IDENTIFY_DATA
));
1338 *IdentifyDataSize
= sizeof (EFI_IDENTIFY_DATA
);
1344 This function is used by the IDE bus driver to get sense data.
1345 Data format of Sense data is defined by the Interface GUID.
1347 @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
1348 @param SenseData Pointer to the SenseData.
1349 @param SenseDataSize Size of SenseData in bytes.
1350 @param SenseDataNumber Pointer to the value for the identify data size.
1352 @retval EFI_SUCCESS The command was accepted without any errors.
1353 @retval EFI_NOT_FOUND Device does not support this data class
1354 @retval EFI_DEVICE_ERROR Error reading InquiryData from device
1355 @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough
1360 IDEDiskInfoSenseData (
1361 IN EFI_DISK_INFO_PROTOCOL
*This
,
1362 IN OUT VOID
*SenseData
,
1363 IN OUT UINT32
*SenseDataSize
,
1364 OUT UINT8
*SenseDataNumber
1367 return EFI_NOT_FOUND
;
1371 This function is used by the IDE bus driver to get controller information.
1373 @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
1374 @param IdeChannel Pointer to the Ide Channel number. Primary or secondary.
1375 @param IdeDevice Pointer to the Ide Device number. Master or slave.
1377 @retval EFI_SUCCESS IdeChannel and IdeDevice are valid
1378 @retval EFI_UNSUPPORTED This is not an IDE device
1383 IDEDiskInfoWhichIde (
1384 IN EFI_DISK_INFO_PROTOCOL
*This
,
1385 OUT UINT32
*IdeChannel
,
1386 OUT UINT32
*IdeDevice
1389 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1391 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This
);
1392 *IdeChannel
= IdeBlkIoDevice
->Channel
;
1393 *IdeDevice
= IdeBlkIoDevice
->Device
;
1399 The is an event(generally the event is exitBootService event) call back function.
1400 Clear pending IDE interrupt before OS loader/kernel take control of the IDE device.
1402 @param Event Pointer to this event
1403 @param Context Event hanlder private data
1414 UINT64 IoPortForBmis
;
1415 UINT8 RegisterValue
;
1416 IDE_BLK_IO_DEV
*IdeDev
;
1421 IdeDev
= (IDE_BLK_IO_DEV
*) Context
;
1424 // Obtain IDE IO port registers' base addresses
1426 Status
= ReassignIdeResources (IdeDev
);
1427 if (EFI_ERROR (Status
)) {
1432 // Check whether interrupt is pending
1436 // Reset IDE device to force it de-assert interrupt pin
1437 // Note: this will reset all devices on this IDE channel
1439 AtaSoftReset (IdeDev
);
1440 if (EFI_ERROR (Status
)) {
1445 // Get base address of IDE Bus Master Status Regsiter
1447 if (IdePrimary
== IdeDev
->Channel
) {
1448 IoPortForBmis
= IdeDev
->IoPort
->BusMasterBaseAddr
+ BMISP_OFFSET
;
1450 if (IdeSecondary
== IdeDev
->Channel
) {
1451 IoPortForBmis
= IdeDev
->IoPort
->BusMasterBaseAddr
+ BMISS_OFFSET
;
1457 // Read BMIS register and clear ERROR and INTR bit
1459 IdeDev
->PciIo
->Io
.Read (
1462 EFI_PCI_IO_PASS_THROUGH_BAR
,
1468 RegisterValue
|= (BMIS_INTERRUPT
| BMIS_ERROR
);
1470 IdeDev
->PciIo
->Io
.Write (
1473 EFI_PCI_IO_PASS_THROUGH_BAR
,
1480 // Select the other device on this channel to ensure this device to release the interrupt pin
1482 if (IdeDev
->Device
== 0) {
1483 RegisterValue
= (1 << 4) | 0xe0;
1485 RegisterValue
= (0 << 4) | 0xe0;
1489 IdeDev
->IoPort
->Head
,
1496 The user Entry Point for module IdeBus. The user code starts with this function.
1498 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1499 @param[in] SystemTable A pointer to the EFI System Table.
1501 @retval EFI_SUCCESS The entry point is executed successfully.
1502 @retval other Some error occurs when executing this entry point.
1508 IN EFI_HANDLE ImageHandle
,
1509 IN EFI_SYSTEM_TABLE
*SystemTable
1515 // Install driver model protocol(s).
1517 Status
= EfiLibInstallAllDriverProtocols2 (
1520 &gIDEBusDriverBinding
,
1522 &gIDEBusComponentName
,
1523 &gIDEBusComponentName2
,
1526 &gIDEBusDriverDiagnostics
,
1527 &gIDEBusDriverDiagnostics2
1529 ASSERT_EFI_ERROR (Status
);