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 - 2008, 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
;
154 if (Node
->DevPath
.Type
!= MESSAGING_DEVICE_PATH
||
155 Node
->DevPath
.SubType
!= MSG_ATAPI_DP
||
156 DevicePathNodeLength(&Node
->DevPath
) != sizeof(ATAPI_DEVICE_PATH
)) {
157 return EFI_UNSUPPORTED
;
162 // Open the IO Abstraction(s) needed to perform the supported test
164 Status
= gBS
->OpenProtocol (
166 &gEfiDevicePathProtocolGuid
,
167 (VOID
**) &ParentDevicePath
,
168 This
->DriverBindingHandle
,
170 EFI_OPEN_PROTOCOL_BY_DRIVER
172 if (Status
== EFI_ALREADY_STARTED
) {
176 if (EFI_ERROR (Status
)) {
181 // Close protocol, don't use device path protocol in the .Support() function
185 &gEfiDevicePathProtocolGuid
,
186 This
->DriverBindingHandle
,
191 // Verify the Ide Controller Init Protocol, which installed by the
192 // IdeController module.
193 // Note 1: PciIo protocol has been opened BY_DRIVER by ide_init, so We can't
194 // open BY_DRIVER here) That's why we don't check pciio protocol
195 // Note 2: ide_init driver check ide controller's pci config space, so we dont
196 // check here any more to save code size
198 Status
= gBS
->OpenProtocol (
200 &gEfiIdeControllerInitProtocolGuid
,
202 This
->DriverBindingHandle
,
204 EFI_OPEN_PROTOCOL_BY_DRIVER
207 if (Status
== EFI_ALREADY_STARTED
) {
212 // If protocols were opened normally, closed it
216 &gEfiIdeControllerInitProtocolGuid
,
217 This
->DriverBindingHandle
,
226 Start function of Driver binding protocol which start this driver on Controller
227 by detecting all disks and installing BlockIo protocol on them.
229 @param This Protocol instance pointer.
230 @param Controller Handle of device to bind driver to.
231 @param RemainingDevicePath produce all possible children.
233 @retval EFI_SUCCESS This driver is added to ControllerHandle.
234 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
235 @retval other This driver does not support this device.
240 IDEBusDriverBindingStart (
241 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
242 IN EFI_HANDLE Controller
,
243 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
247 EFI_STATUS SavedStatus
;
248 EFI_PCI_IO_PROTOCOL
*PciIo
;
249 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
252 UINT8 BeginningIdeChannel
;
255 UINT8 BeginningIdeDevice
;
257 IDE_BLK_IO_DEV
*IdeBlkIoDevice
[IdeMaxChannel
][IdeMaxDevice
];
258 IDE_BLK_IO_DEV
*IdeBlkIoDevicePtr
;
259 IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr
[IdeMaxChannel
];
260 ATA_TRANSFER_MODE TransferMode
;
261 ATA_DRIVE_PARMS DriveParameters
;
262 EFI_DEV_PATH NewNode
;
263 UINT8 ConfigurationOptions
;
264 UINT16 CommandBlockBaseAddr
;
265 UINT16 ControlBlockBaseAddr
;
267 IDE_BUS_DRIVER_PRIVATE_DATA
*IdeBusDriverPrivateData
;
271 // Local variables declaration for IdeControllerInit support
273 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
275 BOOLEAN ChannelEnabled
;
277 EFI_IDENTIFY_DATA IdentifyData
;
278 EFI_ATA_COLLECTIVE_MODE
*SupportedModes
;
280 IdeBusDriverPrivateData
= NULL
;
281 SupportedModes
= NULL
;
284 // Perform IdeBus initialization
286 Status
= gBS
->OpenProtocol (
288 &gEfiDevicePathProtocolGuid
,
289 (VOID
**) &ParentDevicePath
,
290 This
->DriverBindingHandle
,
292 EFI_OPEN_PROTOCOL_BY_DRIVER
294 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
299 // Now open the IDE_CONTROLLER_INIT protocol. Step7.1
301 Status
= gBS
->OpenProtocol (
303 &gEfiIdeControllerInitProtocolGuid
,
305 This
->DriverBindingHandle
,
307 EFI_OPEN_PROTOCOL_BY_DRIVER
311 // The following OpenProtocol function with _GET_PROTOCOL attribute and
312 // will not return EFI_ALREADY_STARTED, so save it for now
314 SavedStatus
= Status
;
316 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
317 DEBUG ((EFI_D_ERROR
, "Open Init, Status=%x", Status
));
319 // open protocol is not SUCCESS or not ALREADY_STARTED, error exit
325 // Save Enumall. Step7.2
327 EnumAll
= IdeInit
->EnumAll
;
330 // Consume PCI I/O protocol. Note that the OpenProtocol with _GET_PROTOCOL
331 // attribute will not return EFI_ALREADY_STARTED
333 Status
= gBS
->OpenProtocol (
335 &gEfiPciIoProtocolGuid
,
337 This
->DriverBindingHandle
,
339 EFI_OPEN_PROTOCOL_GET_PROTOCOL
341 if (EFI_ERROR (Status
)) {
342 DEBUG ((EFI_D_ERROR
, "Open PciIo, Status=%x", Status
));
347 // We must check EFI_ALREADY_STARTED because many ATAPI devices are removable
349 if (SavedStatus
!= EFI_ALREADY_STARTED
) {
350 IdeBusDriverPrivateData
= AllocatePool (sizeof (IDE_BUS_DRIVER_PRIVATE_DATA
));
351 if (IdeBusDriverPrivateData
== NULL
) {
352 Status
= EFI_OUT_OF_RESOURCES
;
356 ZeroMem (IdeBusDriverPrivateData
, sizeof (IDE_BUS_DRIVER_PRIVATE_DATA
));
357 Status
= gBS
->InstallMultipleProtocolInterfaces (
360 IdeBusDriverPrivateData
,
363 if (EFI_ERROR (Status
)) {
368 Status
= gBS
->OpenProtocol (
371 (VOID
**) &IdeBusDriverPrivateData
,
372 This
->DriverBindingHandle
,
374 EFI_OPEN_PROTOCOL_GET_PROTOCOL
376 if (EFI_ERROR (Status
)) {
377 IdeBusDriverPrivateData
= NULL
;
382 Status
= PciIo
->Attributes (
384 EfiPciIoAttributeOperationSupported
,
388 if (!EFI_ERROR (Status
)) {
389 Supports
&= EFI_PCI_DEVICE_ENABLE
;
390 Status
= PciIo
->Attributes (
392 EfiPciIoAttributeOperationEnable
,
398 if (EFI_ERROR (Status
)) {
403 // Read the environment variable that contains the IDEBus Driver's
404 // Config options that were set by the Driver Configuration Protocol
406 DataSize
= sizeof (ConfigurationOptions
);
407 Status
= gRT
->GetVariable (
408 (CHAR16
*) L
"Configuration",
412 &ConfigurationOptions
414 if (EFI_ERROR (Status
)) {
415 ConfigurationOptions
= 0x0f;
420 // If IdeInit->EnumAll is TRUE, must enumerate all IDE device anyway
422 BeginningIdeChannel
= IdePrimary
;
423 EndIdeChannel
= IdeSecondary
;
424 BeginningIdeDevice
= IdeMaster
;
425 EndIdeDevice
= IdeSlave
;
426 } else if (RemainingDevicePath
== NULL
) {
428 // RemainingDevicePath is NULL, scan IDE bus for each device;
430 BeginningIdeChannel
= IdePrimary
;
431 EndIdeChannel
= IdeSecondary
;
432 BeginningIdeDevice
= IdeMaster
;
434 // default, may be redefined by IdeInit
436 EndIdeDevice
= IdeSlave
;
439 // RemainingDevicePath is not NULL, only scan the specified device.
441 Node
= (EFI_DEV_PATH
*) RemainingDevicePath
;
442 BeginningIdeChannel
= Node
->Atapi
.PrimarySecondary
;
443 EndIdeChannel
= BeginningIdeChannel
;
444 BeginningIdeDevice
= Node
->Atapi
.SlaveMaster
;
445 EndIdeDevice
= BeginningIdeDevice
;
446 if (BeginningIdeChannel
>= IdeMaxChannel
|| EndIdeChannel
>= IdeMaxChannel
) {
447 Status
= EFI_INVALID_PARAMETER
;
450 if (BeginningIdeDevice
>= IdeMaxDevice
|| EndIdeDevice
>= IdeMaxDevice
) {
451 Status
= EFI_INVALID_PARAMETER
;
457 // Obtain IDE IO port registers' base addresses
459 Status
= GetIdeRegistersBaseAddr (PciIo
, IdeRegsBaseAddr
);
460 if (EFI_ERROR (Status
)) {
465 // Report status code: begin IdeBus initialization
467 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
469 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_PC_RESET
),
474 // Strictly follow the enumeration based on IDE_CONTROLLER_INIT protocol
476 for (IdeChannel
= BeginningIdeChannel
; IdeChannel
<= EndIdeChannel
; IdeChannel
++) {
478 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelEnumeration
, IdeChannel
);
481 // now obtain channel information fron IdeControllerInit protocol. Step9
483 Status
= IdeInit
->GetChannelInfo (
489 if (EFI_ERROR (Status
)) {
490 DEBUG ((EFI_D_ERROR
, "[GetChannel, Status=%x]", Status
));
494 if (!ChannelEnabled
) {
498 EndIdeDevice
= (UINT8
) MIN ((MaxDevices
- 1), EndIdeDevice
);
499 ASSERT (EndIdeDevice
< IdeMaxDevice
);
501 // Now inform the IDE Controller Init Module. Sept10
503 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelReset
, IdeChannel
);
506 // No reset channel function implemented. Sept11
508 IdeInit
->NotifyPhase (IdeInit
, EfiIdeAfterChannelReset
, IdeChannel
);
513 IdeInit
->NotifyPhase (
515 EfiIdeBusBeforeDevicePresenceDetection
,
520 // Prepare to detect IDE device of this channel
522 InitializeIDEChannelData ();
525 // -- 1st inner loop --- Master/Slave ------------ Step14
527 for (IdeDevice
= BeginningIdeDevice
; IdeDevice
<= EndIdeDevice
; IdeDevice
++) {
529 // Check whether the configuration options allow this device
531 if ((ConfigurationOptions
& (1 << (IdeChannel
* 2 + IdeDevice
))) == 0) {
536 // The device has been scanned in another Start(), No need to scan it again
537 // for perf optimization.
539 if (IdeBusDriverPrivateData
->HaveScannedDevice
[IdeChannel
* 2 + IdeDevice
]) {
544 // create child handle for the detected device.
546 IdeBlkIoDevice
[IdeChannel
][IdeDevice
] = AllocatePool (sizeof (IDE_BLK_IO_DEV
));
547 if (IdeBlkIoDevice
[IdeChannel
][IdeDevice
] == NULL
) {
551 IdeBlkIoDevicePtr
= IdeBlkIoDevice
[IdeChannel
][IdeDevice
];
553 ZeroMem (IdeBlkIoDevicePtr
, sizeof (IDE_BLK_IO_DEV
));
555 IdeBlkIoDevicePtr
->Signature
= IDE_BLK_IO_DEV_SIGNATURE
;
556 IdeBlkIoDevicePtr
->Channel
= (EFI_IDE_CHANNEL
) IdeChannel
;
557 IdeBlkIoDevicePtr
->Device
= (EFI_IDE_DEVICE
) IdeDevice
;
560 // initialize Block IO interface's Media pointer
562 IdeBlkIoDevicePtr
->BlkIo
.Media
= &IdeBlkIoDevicePtr
->BlkMedia
;
565 // Initialize IDE IO port addresses, including Command Block registers
566 // and Control Block registers
568 IdeBlkIoDevicePtr
->IoPort
= AllocatePool (sizeof (IDE_BASE_REGISTERS
));
569 if (IdeBlkIoDevicePtr
->IoPort
== NULL
) {
573 ZeroMem (IdeBlkIoDevicePtr
->IoPort
, sizeof (IDE_BASE_REGISTERS
));
574 CommandBlockBaseAddr
= IdeRegsBaseAddr
[IdeChannel
].CommandBlockBaseAddr
;
575 ControlBlockBaseAddr
= IdeRegsBaseAddr
[IdeChannel
].ControlBlockBaseAddr
;
577 IdeBlkIoDevicePtr
->IoPort
->Data
= CommandBlockBaseAddr
;
578 (*(UINT16
*) &IdeBlkIoDevicePtr
->IoPort
->Reg1
) = (UINT16
) (CommandBlockBaseAddr
+ 0x01);
579 IdeBlkIoDevicePtr
->IoPort
->SectorCount
= (UINT16
) (CommandBlockBaseAddr
+ 0x02);
580 IdeBlkIoDevicePtr
->IoPort
->SectorNumber
= (UINT16
) (CommandBlockBaseAddr
+ 0x03);
581 IdeBlkIoDevicePtr
->IoPort
->CylinderLsb
= (UINT16
) (CommandBlockBaseAddr
+ 0x04);
582 IdeBlkIoDevicePtr
->IoPort
->CylinderMsb
= (UINT16
) (CommandBlockBaseAddr
+ 0x05);
583 IdeBlkIoDevicePtr
->IoPort
->Head
= (UINT16
) (CommandBlockBaseAddr
+ 0x06);
584 (*(UINT16
*) &IdeBlkIoDevicePtr
->IoPort
->Reg
) = (UINT16
) (CommandBlockBaseAddr
+ 0x07);
586 (*(UINT16
*) &IdeBlkIoDevicePtr
->IoPort
->Alt
) = ControlBlockBaseAddr
;
587 IdeBlkIoDevicePtr
->IoPort
->DriveAddress
= (UINT16
) (ControlBlockBaseAddr
+ 0x01);
589 IdeBlkIoDevicePtr
->IoPort
->MasterSlave
= (UINT16
) ((IdeDevice
== IdeMaster
) ? 1 : 0);
591 IdeBlkIoDevicePtr
->PciIo
= PciIo
;
592 IdeBlkIoDevicePtr
->IdeBusDriverPrivateData
= IdeBusDriverPrivateData
;
593 IdeBlkIoDevicePtr
->IoPort
->BusMasterBaseAddr
= IdeRegsBaseAddr
[IdeChannel
].BusMasterBaseAddr
;
596 // Report Status code: is about to detect IDE drive
598 REPORT_STATUS_CODE_EX (
600 (EFI_IO_BUS_ATA_ATAPI
| EFI_P_PC_PRESENCE_DETECT
),
609 // Discover device, now!
611 PERF_START (0, "DiscoverIdeDevice", "IDE", 0);
612 Status
= DiscoverIdeDevice (IdeBlkIoDevicePtr
);
613 PERF_END (0, "DiscoverIdeDevice", "IDE", 0);
615 IdeBusDriverPrivateData
->HaveScannedDevice
[IdeChannel
* 2 + IdeDevice
] = TRUE
;
616 IdeBusDriverPrivateData
->DeviceProcessed
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
618 if (!EFI_ERROR (Status
)) {
622 ZeroMem (&NewNode
, sizeof (NewNode
));
623 NewNode
.DevPath
.Type
= MESSAGING_DEVICE_PATH
;
624 NewNode
.DevPath
.SubType
= MSG_ATAPI_DP
;
625 SetDevicePathNodeLength (&NewNode
.DevPath
, sizeof (ATAPI_DEVICE_PATH
));
627 NewNode
.Atapi
.PrimarySecondary
= (UINT8
) IdeBlkIoDevicePtr
->Channel
;
628 NewNode
.Atapi
.SlaveMaster
= (UINT8
) IdeBlkIoDevicePtr
->Device
;
629 NewNode
.Atapi
.Lun
= IdeBlkIoDevicePtr
->Lun
;
630 IdeBlkIoDevicePtr
->DevicePath
= AppendDevicePathNode (
634 if (IdeBlkIoDevicePtr
->DevicePath
== NULL
) {
635 ReleaseIdeResources (IdeBlkIoDevicePtr
);
640 // Submit identify data to IDE controller init driver
642 CopyMem (&IdentifyData
, IdeBlkIoDevicePtr
->IdData
, sizeof (IdentifyData
));
643 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = TRUE
;
644 IdeInit
->SubmitData (IdeInit
, IdeChannel
, IdeDevice
, &IdentifyData
);
647 // Device detection failed
649 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
650 IdeInit
->SubmitData (IdeInit
, IdeChannel
, IdeDevice
, NULL
);
651 ReleaseIdeResources (IdeBlkIoDevicePtr
);
652 IdeBlkIoDevicePtr
= NULL
;
655 // end of 1st inner loop ---
659 // end of 1st outer loop =========
664 // = 2nd outer loop == Primary/Secondary =================
666 for (IdeChannel
= BeginningIdeChannel
; IdeChannel
<= EndIdeChannel
; IdeChannel
++) {
669 // -- 2nd inner loop --- Master/Slave --------
671 for (IdeDevice
= BeginningIdeDevice
; IdeDevice
<= EndIdeDevice
; IdeDevice
++) {
673 if (IdeBusDriverPrivateData
->DeviceProcessed
[IdeChannel
* 2 + IdeDevice
]) {
677 if (!IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
]) {
681 Status
= IdeInit
->CalculateMode (
687 if (EFI_ERROR (Status
)) {
688 DEBUG ((EFI_D_ERROR
, "[bStStp20S=%x]", Status
));
692 IdeBlkIoDevicePtr
= IdeBlkIoDevice
[IdeChannel
][IdeDevice
];
695 // Set best supported PIO mode on this IDE device
697 if (SupportedModes
->PioMode
.Mode
<= AtaPioMode2
) {
698 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_DEFAULT_PIO
;
700 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_FLOW_PIO
;
703 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->PioMode
.Mode
);
705 if (SupportedModes
->ExtModeCount
== 0){
706 Status
= SetDeviceTransferMode (IdeBlkIoDevicePtr
, &TransferMode
);
708 if (EFI_ERROR (Status
)) {
709 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
710 ReleaseIdeResources (IdeBlkIoDevicePtr
);
711 IdeBlkIoDevicePtr
= NULL
;
717 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
718 // be set together. Only one DMA mode can be set to a device. If setting
719 // DMA mode operation fails, we can continue moving on because we only use
720 // PIO mode at boot time. DMA modes are used by certain kind of OS booting
722 if (SupportedModes
->UdmaMode
.Valid
) {
724 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_UDMA
;
725 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->UdmaMode
.Mode
);
726 Status
= SetDeviceTransferMode (IdeBlkIoDevicePtr
, &TransferMode
);
728 if (EFI_ERROR (Status
)) {
729 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
730 ReleaseIdeResources (IdeBlkIoDevicePtr
);
731 IdeBlkIoDevicePtr
= NULL
;
737 IdeBlkIoDevicePtr
->UdmaMode
.Valid
= TRUE
;
738 IdeBlkIoDevicePtr
->UdmaMode
.Mode
= SupportedModes
->UdmaMode
.Mode
;
739 EnableInterrupt (IdeBlkIoDevicePtr
);
740 } else if (SupportedModes
->MultiWordDmaMode
.Valid
) {
742 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_MDMA
;
743 TransferMode
.ModeNumber
= (UINT8
) SupportedModes
->MultiWordDmaMode
.Mode
;
744 Status
= SetDeviceTransferMode (IdeBlkIoDevicePtr
, &TransferMode
);
746 if (EFI_ERROR (Status
)) {
747 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
748 ReleaseIdeResources (IdeBlkIoDevicePtr
);
749 IdeBlkIoDevicePtr
= NULL
;
753 EnableInterrupt (IdeBlkIoDevicePtr
);
756 // Init driver parameters
758 DriveParameters
.Sector
= (UINT8
) IdeBlkIoDevicePtr
->IdData
->AtaData
.sectors_per_track
;
759 DriveParameters
.Heads
= (UINT8
) (IdeBlkIoDevicePtr
->IdData
->AtaData
.heads
- 1);
760 DriveParameters
.MultipleSector
= (UINT8
) IdeBlkIoDevicePtr
->IdData
->AtaData
.multi_sector_cmd_max_sct_cnt
;
762 // Set Parameters for the device:
764 // 2) Establish the block count for READ/WRITE MULTIPLE (EXT) command
766 if ((IdeBlkIoDevicePtr
->Type
== IdeHardDisk
) || (IdeBlkIoDevicePtr
->Type
== Ide48bitAddressingHardDisk
)) {
767 Status
= SetDriveParameters (IdeBlkIoDevicePtr
, &DriveParameters
);
771 // Record PIO mode used in private data
773 IdeBlkIoDevicePtr
->PioMode
= (ATA_PIO_MODE
) SupportedModes
->PioMode
.Mode
;
776 // Set IDE controller Timing Blocks in the PCI Configuration Space
778 IdeInit
->SetTiming (IdeInit
, IdeChannel
, IdeDevice
, SupportedModes
);
781 // Add Component Name for the IDE/ATAPI device that was discovered.
783 IdeBlkIoDevicePtr
->ControllerNameTable
= NULL
;
784 ADD_IDE_ATAPI_NAME (IdeBlkIoDevicePtr
);
786 Status
= gBS
->InstallMultipleProtocolInterfaces (
787 &IdeBlkIoDevicePtr
->Handle
,
788 &gEfiDevicePathProtocolGuid
,
789 IdeBlkIoDevicePtr
->DevicePath
,
790 &gEfiBlockIoProtocolGuid
,
791 &IdeBlkIoDevicePtr
->BlkIo
,
792 &gEfiDiskInfoProtocolGuid
,
793 &IdeBlkIoDevicePtr
->DiskInfo
,
797 if (EFI_ERROR (Status
)) {
798 ReleaseIdeResources (IdeBlkIoDevicePtr
);
803 &gEfiPciIoProtocolGuid
,
805 This
->DriverBindingHandle
,
806 IdeBlkIoDevicePtr
->Handle
,
807 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
810 IdeBusDriverPrivateData
->DeviceProcessed
[IdeChannel
* 2 + IdeDevice
] = TRUE
;
813 // Report status code: device eanbled!
815 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
817 (EFI_IO_BUS_ATA_ATAPI
| EFI_P_PC_ENABLE
),
818 IdeBlkIoDevicePtr
->DevicePath
822 // Create event to clear pending IDE interrupt
824 Status
= gBS
->CreateEventEx (
829 &gEfiEventExitBootServicesGuid
,
830 &IdeBlkIoDevicePtr
->ExitBootServiceEvent
834 // end of 2nd inner loop ----
838 // end of 2nd outer loop ==========
843 // All configurations done! Notify IdeController to do post initialization
844 // work such as saving IDE controller PCI settings for S3 resume
846 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBusPhaseMaximum
, 0);
848 if (SupportedModes
!= NULL
) {
849 gBS
->FreePool (SupportedModes
);
852 PERF_START (0, "Finish IDE detection", "IDE", 1);
853 PERF_END (0, "Finish IDE detection", "IDE", 0);
860 // Report error code: controller error
862 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
863 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
864 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_EC_CONTROLLER_ERROR
),
870 &gEfiIdeControllerInitProtocolGuid
,
871 This
->DriverBindingHandle
,
875 gBS
->UninstallMultipleProtocolInterfaces (
878 IdeBusDriverPrivateData
,
882 if (IdeBusDriverPrivateData
!= NULL
) {
883 gBS
->FreePool (IdeBusDriverPrivateData
);
886 if (SupportedModes
!= NULL
) {
887 gBS
->FreePool (SupportedModes
);
892 &gEfiPciIoProtocolGuid
,
893 This
->DriverBindingHandle
,
899 &gEfiDevicePathProtocolGuid
,
900 This
->DriverBindingHandle
,
908 Stop function of Driver Binding Protocol which is to stop the driver on Controller Handle and all
909 child handle attached to the controller handle if there are.
911 @param This Protocol instance pointer.
912 @param Controller Handle of device to stop driver on
913 @param NumberOfChildren Not used
914 @param ChildHandleBuffer Not used
916 @retval EFI_SUCCESS This driver is removed DeviceHandle
917 @retval other This driver was not removed from this device
922 IDEBusDriverBindingStop (
923 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
924 IN EFI_HANDLE Controller
,
925 IN UINTN NumberOfChildren
,
926 IN EFI_HANDLE
*ChildHandleBuffer
930 EFI_PCI_IO_PROTOCOL
*PciIo
;
931 BOOLEAN AllChildrenStopped
;
933 IDE_BUS_DRIVER_PRIVATE_DATA
*IdeBusDriverPrivateData
;
936 IdeBusDriverPrivateData
= NULL
;
938 if (NumberOfChildren
== 0) {
940 Status
= gBS
->OpenProtocol (
942 &gEfiPciIoProtocolGuid
,
944 This
->DriverBindingHandle
,
946 EFI_OPEN_PROTOCOL_GET_PROTOCOL
948 if (!EFI_ERROR (Status
)) {
949 Status
= PciIo
->Attributes (
951 EfiPciIoAttributeOperationSupported
,
955 if (!EFI_ERROR (Status
)) {
956 Supports
&= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO
| EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO
| EFI_PCI_DEVICE_ENABLE
;
959 EfiPciIoAttributeOperationDisable
,
969 (VOID
**) &IdeBusDriverPrivateData
,
970 This
->DriverBindingHandle
,
972 EFI_OPEN_PROTOCOL_GET_PROTOCOL
975 gBS
->UninstallMultipleProtocolInterfaces (
978 IdeBusDriverPrivateData
,
982 if (IdeBusDriverPrivateData
!= NULL
) {
983 gBS
->FreePool (IdeBusDriverPrivateData
);
986 // Close the bus driver
990 &gEfiIdeControllerInitProtocolGuid
,
991 This
->DriverBindingHandle
,
996 &gEfiPciIoProtocolGuid
,
997 This
->DriverBindingHandle
,
1000 gBS
->CloseProtocol (
1002 &gEfiDevicePathProtocolGuid
,
1003 This
->DriverBindingHandle
,
1010 AllChildrenStopped
= TRUE
;
1012 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1014 Status
= DeRegisterIdeDevice (This
, Controller
, ChildHandleBuffer
[Index
]);
1016 if (EFI_ERROR (Status
)) {
1017 AllChildrenStopped
= FALSE
;
1021 if (!AllChildrenStopped
) {
1022 return EFI_DEVICE_ERROR
;
1029 issue ATA or ATAPI command to reset a block IO device.
1030 @param This Block IO protocol instance pointer.
1031 @param ExtendedVerification If FALSE,for ATAPI device, driver will only invoke ATAPI reset method
1032 If TRUE, for ATAPI device, driver need invoke ATA reset method after
1033 invoke ATAPI reset method
1035 @retval EFI_DEVICE_ERROR When the device is neighther ATA device or ATAPI device.
1036 @retval EFI_SUCCESS The device reset successfully
1042 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1043 IN BOOLEAN ExtendedVerification
1046 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1050 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1052 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (This
);
1054 // Requery IDE IO resources in case of the switch of native and legacy modes
1056 ReassignIdeResources (IdeBlkIoDevice
);
1059 // for ATA device, using ATA reset method
1061 if (IdeBlkIoDevice
->Type
== IdeHardDisk
||
1062 IdeBlkIoDevice
->Type
== Ide48bitAddressingHardDisk
) {
1063 Status
= AtaSoftReset (IdeBlkIoDevice
);
1067 if (IdeBlkIoDevice
->Type
== IdeUnknown
) {
1068 Status
= EFI_DEVICE_ERROR
;
1073 // for ATAPI device, using ATAPI reset method
1075 Status
= AtapiSoftReset (IdeBlkIoDevice
);
1076 if (ExtendedVerification
) {
1077 Status
= AtaSoftReset (IdeBlkIoDevice
);
1081 gBS
->RestoreTPL (OldTpl
);
1086 Read data from a block IO device
1088 @param This Block IO protocol instance pointer.
1089 @param MediaId The media ID of the device
1090 @param Lba Starting LBA address to read data
1091 @param BufferSize The size of data to be read
1092 @param Buffer Caller supplied buffer to save data
1094 @retval EFI_DEVICE_ERROR unknown device type
1095 @retval other read data status.
1100 IDEBlkIoReadBlocks (
1101 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1104 IN UINTN BufferSize
,
1108 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1112 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1114 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (This
);
1117 // Requery IDE IO resources in case of the switch of native and legacy modes
1119 ReassignIdeResources (IdeBlkIoDevice
);
1122 // For ATA compatible device, use ATA read block's mechanism
1124 if (IdeBlkIoDevice
->Type
== IdeHardDisk
||
1125 IdeBlkIoDevice
->Type
== Ide48bitAddressingHardDisk
) {
1126 Status
= AtaBlkIoReadBlocks (
1136 if (IdeBlkIoDevice
->Type
== IdeUnknown
) {
1137 Status
= EFI_DEVICE_ERROR
;
1142 // for ATAPI device, using ATAPI read block's mechanism
1144 Status
= AtapiBlkIoReadBlocks (
1153 gBS
->RestoreTPL (OldTpl
);
1159 Write data to block io device.
1161 @param This Protocol instance pointer.
1162 @param MediaId The media ID of the device
1163 @param Lba Starting LBA address to write data
1164 @param BufferSize The size of data to be written
1165 @param Buffer Caller supplied buffer to save data
1167 @retval EFI_DEVICE_ERROR unknown device type
1168 @retval other write data status
1173 IDEBlkIoWriteBlocks (
1174 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1177 IN UINTN BufferSize
,
1181 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1185 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1187 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (This
);
1189 // Requery IDE IO resources in case of the switch of native and legacy modes
1191 ReassignIdeResources (IdeBlkIoDevice
);
1194 // for ATA device, using ATA write block's mechanism
1196 if (IdeBlkIoDevice
->Type
== IdeHardDisk
||
1197 IdeBlkIoDevice
->Type
== Ide48bitAddressingHardDisk
) {
1199 Status
= AtaBlkIoWriteBlocks (
1209 if (IdeBlkIoDevice
->Type
== IdeUnknown
) {
1210 Status
= EFI_DEVICE_ERROR
;
1215 // for ATAPI device, using ATAPI write block's mechanism
1217 Status
= AtapiBlkIoWriteBlocks (
1226 gBS
->RestoreTPL (OldTpl
);
1230 Flushes all modified data to a physical block devices
1232 @param This Indicates a pointer to the calling context which to sepcify a
1233 sepcific block device
1235 @retval EFI_SUCCESS Always return success.
1239 IDEBlkIoFlushBlocks (
1240 IN EFI_BLOCK_IO_PROTOCOL
*This
1250 Return the results of the Inquiry command to a drive in InquiryData.
1251 Data format of Inquiry data is defined by the Interface GUID.
1253 @param This Protocol Instance pointer.
1254 @param InquiryData Results of Inquiry command to device
1255 @param InquiryDataSize Size of InquiryData in bytes.
1257 @retval EFI_SUCCESS InquiryData valid
1258 @retval EFI_NOT_FOUND Device does not support this data class
1259 @retval EFI_DEVICE_ERROR Error reading InquiryData from device
1260 @retval EFI_BUFFER_TOO_SMALL IntquiryDataSize not big enough
1265 IDEDiskInfoInquiry (
1266 IN EFI_DISK_INFO_PROTOCOL
*This
,
1267 IN OUT VOID
*InquiryData
,
1268 IN OUT UINT32
*InquiryDataSize
1271 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1273 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This
);
1275 if (*InquiryDataSize
< sizeof (ATAPI_INQUIRY_DATA
)) {
1276 *InquiryDataSize
= sizeof (ATAPI_INQUIRY_DATA
);
1277 return EFI_BUFFER_TOO_SMALL
;
1280 if (IdeBlkIoDevice
->InquiryData
== NULL
) {
1281 return EFI_NOT_FOUND
;
1284 gBS
->CopyMem (InquiryData
, IdeBlkIoDevice
->InquiryData
, sizeof (ATAPI_INQUIRY_DATA
));
1285 *InquiryDataSize
= sizeof (ATAPI_INQUIRY_DATA
);
1291 Return the results of the Identify command to a drive in IdentifyData.
1292 Data format of Identify data is defined by the Interface GUID.
1294 @param This Protocol instance pointer.
1295 @param IdentifyData Results of Identify command to device
1296 @param IdentifyDataSize Size of IdentifyData in bytes.
1298 @retval EFI_SUCCESS IdentifyData valid
1299 @retval EFI_NOT_FOUND Device does not support this data class
1300 @retval EFI_DEVICE_ERROR Error reading IdentifyData from device
1301 @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough
1306 IDEDiskInfoIdentify (
1307 IN EFI_DISK_INFO_PROTOCOL
*This
,
1308 IN OUT VOID
*IdentifyData
,
1309 IN OUT UINT32
*IdentifyDataSize
1312 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1314 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This
);
1316 if (*IdentifyDataSize
< sizeof (EFI_IDENTIFY_DATA
)) {
1317 *IdentifyDataSize
= sizeof (EFI_IDENTIFY_DATA
);
1318 return EFI_BUFFER_TOO_SMALL
;
1321 if (IdeBlkIoDevice
->IdData
== NULL
) {
1322 return EFI_NOT_FOUND
;
1325 gBS
->CopyMem (IdentifyData
, IdeBlkIoDevice
->IdData
, sizeof (EFI_IDENTIFY_DATA
));
1326 *IdentifyDataSize
= sizeof (EFI_IDENTIFY_DATA
);
1332 Return the results of the Request Sense command to a drive in SenseData.
1333 Data format of Sense data is defined by the Interface GUID.
1335 @param This Protocol instance pointer.
1336 @param SenseData Results of Request Sense command to device
1337 @param SenseDataSize Size of SenseData in bytes.
1338 @param SenseDataNumber Type of SenseData
1340 @retval EFI_SUCCESS InquiryData valid
1341 @retval EFI_NOT_FOUND Device does not support this data class
1342 @retval EFI_DEVICE_ERROR Error reading InquiryData from device
1343 @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough
1348 IDEDiskInfoSenseData (
1349 IN EFI_DISK_INFO_PROTOCOL
*This
,
1350 IN OUT VOID
*SenseData
,
1351 IN OUT UINT32
*SenseDataSize
,
1352 OUT UINT8
*SenseDataNumber
1355 return EFI_NOT_FOUND
;
1359 Return the results of the Request Sense command to a drive in SenseData.
1360 Data format of Sense data is defined by the Interface GUID.
1362 @param This Protocol instance pointer.
1363 @param IdeChannel Primary or Secondary
1364 @param IdeDevice Master or Slave
1366 @retval EFI_SUCCESS IdeChannel and IdeDevice are valid
1367 @retval EFI_UNSUPPORTED This is not an IDE device
1372 IDEDiskInfoWhichIde (
1373 IN EFI_DISK_INFO_PROTOCOL
*This
,
1374 OUT UINT32
*IdeChannel
,
1375 OUT UINT32
*IdeDevice
1378 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1380 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This
);
1381 *IdeChannel
= IdeBlkIoDevice
->Channel
;
1382 *IdeDevice
= IdeBlkIoDevice
->Device
;
1388 The is an event(generally the event is exitBootService event) call back function.
1389 Clear pending IDE interrupt before OS loader/kernel take control of the IDE device.
1391 @param Event Pointer to this event
1392 @param Context Event hanlder private data
1403 UINT64 IoPortForBmis
;
1404 UINT8 RegisterValue
;
1405 IDE_BLK_IO_DEV
*IdeDev
;
1410 IdeDev
= (IDE_BLK_IO_DEV
*) Context
;
1413 // Obtain IDE IO port registers' base addresses
1415 Status
= ReassignIdeResources (IdeDev
);
1416 if (EFI_ERROR (Status
)) {
1421 // Check whether interrupt is pending
1425 // Reset IDE device to force it de-assert interrupt pin
1426 // Note: this will reset all devices on this IDE channel
1428 AtaSoftReset (IdeDev
);
1429 if (EFI_ERROR (Status
)) {
1434 // Get base address of IDE Bus Master Status Regsiter
1436 if (IdePrimary
== IdeDev
->Channel
) {
1437 IoPortForBmis
= IdeDev
->IoPort
->BusMasterBaseAddr
+ BMISP_OFFSET
;
1439 if (IdeSecondary
== IdeDev
->Channel
) {
1440 IoPortForBmis
= IdeDev
->IoPort
->BusMasterBaseAddr
+ BMISS_OFFSET
;
1446 // Read BMIS register and clear ERROR and INTR bit
1448 IdeDev
->PciIo
->Io
.Read (
1451 EFI_PCI_IO_PASS_THROUGH_BAR
,
1457 RegisterValue
|= (BMIS_INTERRUPT
| BMIS_ERROR
);
1459 IdeDev
->PciIo
->Io
.Write (
1462 EFI_PCI_IO_PASS_THROUGH_BAR
,
1469 // Select the other device on this channel to ensure this device to release the interrupt pin
1471 if (IdeDev
->Device
== 0) {
1472 RegisterValue
= (1 << 4) | 0xe0;
1474 RegisterValue
= (0 << 4) | 0xe0;
1478 IdeDev
->IoPort
->Head
,
1485 The user Entry Point for module IdeBus. The user code starts with this function.
1487 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1488 @param[in] SystemTable A pointer to the EFI System Table.
1490 @retval EFI_SUCCESS The entry point is executed successfully.
1491 @retval other Some error occurs when executing this entry point.
1497 IN EFI_HANDLE ImageHandle
,
1498 IN EFI_SYSTEM_TABLE
*SystemTable
1504 // Install driver model protocol(s).
1506 Status
= EfiLibInstallAllDriverProtocols2 (
1509 &gIDEBusDriverBinding
,
1511 &gIDEBusComponentName
,
1512 &gIDEBusComponentName2
,
1515 &gIDEBusDriverDiagnostics
,
1516 &gIDEBusDriverDiagnostics2
1518 ASSERT_EFI_ERROR (Status
);