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 - 2018, Intel Corporation. All rights reserved.<BR>
7 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
;
151 EFI_PCI_IO_PROTOCOL
*PciIo
;
154 if (RemainingDevicePath
!= NULL
) {
155 Node
= (EFI_DEV_PATH
*) RemainingDevicePath
;
157 // Check if RemainingDevicePath is the End of Device Path Node,
158 // if yes, go on checking other conditions
160 if (!IsDevicePathEnd (Node
)) {
162 // If RemainingDevicePath isn't the End of Device Path Node,
163 // check its validation
165 if (Node
->DevPath
.Type
!= MESSAGING_DEVICE_PATH
||
166 Node
->DevPath
.SubType
!= MSG_ATAPI_DP
||
167 DevicePathNodeLength(&Node
->DevPath
) != sizeof(ATAPI_DEVICE_PATH
)) {
168 return EFI_UNSUPPORTED
;
174 // Verify the Ide Controller Init Protocol, which installed by the
175 // IdeController module.
177 Status
= gBS
->OpenProtocol (
179 &gEfiIdeControllerInitProtocolGuid
,
181 This
->DriverBindingHandle
,
183 EFI_OPEN_PROTOCOL_BY_DRIVER
186 if (Status
== EFI_ALREADY_STARTED
) {
190 if (EFI_ERROR (Status
)) {
195 // Close the I/O Abstraction(s) used to perform the supported test
199 &gEfiIdeControllerInitProtocolGuid
,
200 This
->DriverBindingHandle
,
205 // Open the EFI Device Path protocol needed to perform the supported test
207 Status
= gBS
->OpenProtocol (
209 &gEfiDevicePathProtocolGuid
,
210 (VOID
**) &ParentDevicePath
,
211 This
->DriverBindingHandle
,
213 EFI_OPEN_PROTOCOL_BY_DRIVER
215 if (Status
== EFI_ALREADY_STARTED
) {
220 // Close protocol, don't use device path protocol in the Support() function
224 &gEfiDevicePathProtocolGuid
,
225 This
->DriverBindingHandle
,
230 // Get the EfiPciIoProtocol
232 Status
= gBS
->OpenProtocol (
234 &gEfiPciIoProtocolGuid
,
236 This
->DriverBindingHandle
,
238 EFI_OPEN_PROTOCOL_GET_PROTOCOL
241 if (EFI_ERROR (Status
)) {
246 // Now further check the PCI header: Base class (offset 0x0B) and
247 // Sub Class (offset 0x0A). This controller should be an IDE controller
249 Status
= PciIo
->Pci
.Read (
257 if (!EFI_ERROR (Status
)) {
259 // Examine if it is IDE mode by class code
261 if ((PciData
.Hdr
.ClassCode
[2] != PCI_CLASS_MASS_STORAGE
) || (PciData
.Hdr
.ClassCode
[1] != PCI_SUB_CLASS_IDE
)) {
262 Status
= EFI_UNSUPPORTED
;
264 Status
= EFI_SUCCESS
;
273 Start function of Driver binding protocol which start this driver on Controller
274 by detecting all disks and installing BlockIo protocol on them.
276 @param This Protocol instance pointer.
277 @param Controller Handle of device to bind driver to.
278 @param RemainingDevicePath produce all possible children.
280 @retval EFI_SUCCESS This driver is added to ControllerHandle.
281 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
282 @retval other This driver does not support this device.
287 IDEBusDriverBindingStart (
288 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
289 IN EFI_HANDLE Controller
,
290 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
294 EFI_STATUS SavedStatus
;
295 EFI_PCI_IO_PROTOCOL
*PciIo
;
296 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
299 UINT8 BeginningIdeChannel
;
302 UINT8 BeginningIdeDevice
;
304 IDE_BLK_IO_DEV
*IdeBlkIoDevice
[IdeMaxChannel
][IdeMaxDevice
];
305 IDE_BLK_IO_DEV
*IdeBlkIoDevicePtr
;
306 IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr
[IdeMaxChannel
];
307 ATA_TRANSFER_MODE TransferMode
;
308 ATA_DRIVE_PARMS DriveParameters
;
309 EFI_DEV_PATH NewNode
;
310 UINT8 ConfigurationOptions
;
311 UINT16 CommandBlockBaseAddr
;
312 UINT16 ControlBlockBaseAddr
;
314 IDE_BUS_DRIVER_PRIVATE_DATA
*IdeBusDriverPrivateData
;
318 // Local variables declaration for IdeControllerInit support
320 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
322 BOOLEAN ChannelEnabled
;
324 EFI_IDENTIFY_DATA IdentifyData
;
325 EFI_ATA_COLLECTIVE_MODE
*SupportedModes
;
327 IdeBusDriverPrivateData
= NULL
;
328 SupportedModes
= NULL
;
331 // Perform IdeBus initialization
333 Status
= gBS
->OpenProtocol (
335 &gEfiDevicePathProtocolGuid
,
336 (VOID
**) &ParentDevicePath
,
337 This
->DriverBindingHandle
,
339 EFI_OPEN_PROTOCOL_BY_DRIVER
341 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
346 // Now open the IDE_CONTROLLER_INIT protocol. Step7.1
348 Status
= gBS
->OpenProtocol (
350 &gEfiIdeControllerInitProtocolGuid
,
352 This
->DriverBindingHandle
,
354 EFI_OPEN_PROTOCOL_BY_DRIVER
358 // The following OpenProtocol function with _GET_PROTOCOL attribute and
359 // will not return EFI_ALREADY_STARTED, so save it for now
361 SavedStatus
= Status
;
363 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
364 DEBUG ((EFI_D_ERROR
, "Open Init, Status=%x", Status
));
366 // open protocol is not SUCCESS or not ALREADY_STARTED, error exit
372 // Save Enumall. Step7.2
374 EnumAll
= IdeInit
->EnumAll
;
377 // Consume PCI I/O protocol. Note that the OpenProtocol with _GET_PROTOCOL
378 // attribute will not return EFI_ALREADY_STARTED
380 Status
= gBS
->OpenProtocol (
382 &gEfiPciIoProtocolGuid
,
384 This
->DriverBindingHandle
,
386 EFI_OPEN_PROTOCOL_GET_PROTOCOL
388 if (EFI_ERROR (Status
)) {
389 DEBUG ((EFI_D_ERROR
, "Open PciIo, Status=%x", Status
));
394 // We must check EFI_ALREADY_STARTED because many ATAPI devices are removable
396 if (SavedStatus
!= EFI_ALREADY_STARTED
) {
397 IdeBusDriverPrivateData
= AllocatePool (sizeof (IDE_BUS_DRIVER_PRIVATE_DATA
));
398 if (IdeBusDriverPrivateData
== NULL
) {
399 Status
= EFI_OUT_OF_RESOURCES
;
403 ZeroMem (IdeBusDriverPrivateData
, sizeof (IDE_BUS_DRIVER_PRIVATE_DATA
));
404 Status
= gBS
->InstallMultipleProtocolInterfaces (
407 IdeBusDriverPrivateData
,
410 if (EFI_ERROR (Status
)) {
415 Status
= gBS
->OpenProtocol (
418 (VOID
**) &IdeBusDriverPrivateData
,
419 This
->DriverBindingHandle
,
421 EFI_OPEN_PROTOCOL_GET_PROTOCOL
423 if (EFI_ERROR (Status
)) {
424 IdeBusDriverPrivateData
= NULL
;
429 Status
= PciIo
->Attributes (
431 EfiPciIoAttributeOperationSupported
,
435 if (!EFI_ERROR (Status
)) {
436 Supports
&= (UINT64
)EFI_PCI_DEVICE_ENABLE
;
437 Status
= PciIo
->Attributes (
439 EfiPciIoAttributeOperationEnable
,
445 if (EFI_ERROR (Status
)) {
450 // Read the environment variable that contains the IDEBus Driver's
451 // Config options that were set by the Driver Configuration Protocol
453 DataSize
= sizeof (ConfigurationOptions
);
454 Status
= gRT
->GetVariable (
455 (CHAR16
*) L
"Configuration",
459 &ConfigurationOptions
461 if (EFI_ERROR (Status
)) {
462 ConfigurationOptions
= 0x0f;
465 if (EnumAll
|| RemainingDevicePath
== NULL
) {
467 // If IdeInit->EnumAll is TRUE or RemainingDevicePath is NULL,
468 // must enumerate all IDE devices anyway
470 BeginningIdeChannel
= IdePrimary
;
471 EndIdeChannel
= IdeSecondary
;
472 BeginningIdeDevice
= IdeMaster
;
473 EndIdeDevice
= IdeSlave
;
475 } else if (!IsDevicePathEnd (RemainingDevicePath
)) {
477 // If RemainingDevicePath isn't the End of Device Path Node,
478 // only scan the specified device by RemainingDevicePath
480 Node
= (EFI_DEV_PATH
*) RemainingDevicePath
;
481 BeginningIdeChannel
= Node
->Atapi
.PrimarySecondary
;
482 EndIdeChannel
= BeginningIdeChannel
;
483 BeginningIdeDevice
= Node
->Atapi
.SlaveMaster
;
484 EndIdeDevice
= BeginningIdeDevice
;
485 if (BeginningIdeChannel
>= IdeMaxChannel
|| EndIdeChannel
>= IdeMaxChannel
) {
486 Status
= EFI_INVALID_PARAMETER
;
489 if (BeginningIdeDevice
>= IdeMaxDevice
|| EndIdeDevice
>= IdeMaxDevice
) {
490 Status
= EFI_INVALID_PARAMETER
;
496 // If RemainingDevicePath is the End of Device Path Node,
497 // skip enumerate any device and return EFI_SUCESSS
499 BeginningIdeChannel
= IdeMaxChannel
;
500 EndIdeChannel
= IdeMaxChannel
- 1;
501 BeginningIdeDevice
= IdeMaxDevice
;
502 EndIdeDevice
= IdeMaxDevice
- 1;
506 // Obtain IDE IO port registers' base addresses
508 Status
= GetIdeRegistersBaseAddr (PciIo
, IdeRegsBaseAddr
);
509 if (EFI_ERROR (Status
)) {
514 // Report status code: begin IdeBus initialization
516 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
518 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_PC_RESET
),
523 // Strictly follow the enumeration based on IDE_CONTROLLER_INIT protocol
525 for (IdeChannel
= BeginningIdeChannel
; IdeChannel
<= EndIdeChannel
; IdeChannel
++) {
527 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelEnumeration
, IdeChannel
);
530 // now obtain channel information fron IdeControllerInit protocol. Step9
532 Status
= IdeInit
->GetChannelInfo (
538 if (EFI_ERROR (Status
)) {
539 DEBUG ((EFI_D_ERROR
, "[GetChannel, Status=%x]", Status
));
543 if (!ChannelEnabled
) {
547 EndIdeDevice
= (UINT8
) MIN ((MaxDevices
- 1), EndIdeDevice
);
548 ASSERT (EndIdeDevice
< IdeMaxDevice
);
550 // Now inform the IDE Controller Init Module. Sept10
552 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelReset
, IdeChannel
);
555 // No reset channel function implemented. Sept11
557 IdeInit
->NotifyPhase (IdeInit
, EfiIdeAfterChannelReset
, IdeChannel
);
562 IdeInit
->NotifyPhase (
564 EfiIdeBusBeforeDevicePresenceDetection
,
569 // Prepare to detect IDE device of this channel
571 InitializeIDEChannelData ();
574 // -- 1st inner loop --- Master/Slave ------------ Step14
576 for (IdeDevice
= BeginningIdeDevice
; IdeDevice
<= EndIdeDevice
; IdeDevice
++) {
578 // Check whether the configuration options allow this device
580 if ((ConfigurationOptions
& (1 << (IdeChannel
* 2 + IdeDevice
))) == 0) {
585 // The device has been scanned in another Start(), No need to scan it again
586 // for perf optimization.
588 if (IdeBusDriverPrivateData
->HaveScannedDevice
[IdeChannel
* 2 + IdeDevice
]) {
593 // create child handle for the detected device.
595 IdeBlkIoDevice
[IdeChannel
][IdeDevice
] = AllocatePool (sizeof (IDE_BLK_IO_DEV
));
596 if (IdeBlkIoDevice
[IdeChannel
][IdeDevice
] == NULL
) {
600 IdeBlkIoDevicePtr
= IdeBlkIoDevice
[IdeChannel
][IdeDevice
];
602 ZeroMem (IdeBlkIoDevicePtr
, sizeof (IDE_BLK_IO_DEV
));
604 IdeBlkIoDevicePtr
->Signature
= IDE_BLK_IO_DEV_SIGNATURE
;
605 IdeBlkIoDevicePtr
->Channel
= (EFI_IDE_CHANNEL
) IdeChannel
;
606 IdeBlkIoDevicePtr
->Device
= (EFI_IDE_DEVICE
) IdeDevice
;
609 // initialize Block IO interface's Media pointer
611 IdeBlkIoDevicePtr
->BlkIo
.Media
= &IdeBlkIoDevicePtr
->BlkMedia
;
614 // Initialize IDE IO port addresses, including Command Block registers
615 // and Control Block registers
617 IdeBlkIoDevicePtr
->IoPort
= AllocatePool (sizeof (IDE_BASE_REGISTERS
));
618 if (IdeBlkIoDevicePtr
->IoPort
== NULL
) {
622 ZeroMem (IdeBlkIoDevicePtr
->IoPort
, sizeof (IDE_BASE_REGISTERS
));
623 CommandBlockBaseAddr
= IdeRegsBaseAddr
[IdeChannel
].CommandBlockBaseAddr
;
624 ControlBlockBaseAddr
= IdeRegsBaseAddr
[IdeChannel
].ControlBlockBaseAddr
;
626 IdeBlkIoDevicePtr
->IoPort
->Data
= CommandBlockBaseAddr
;
627 (*(UINT16
*) &IdeBlkIoDevicePtr
->IoPort
->Reg1
) = (UINT16
) (CommandBlockBaseAddr
+ 0x01);
628 IdeBlkIoDevicePtr
->IoPort
->SectorCount
= (UINT16
) (CommandBlockBaseAddr
+ 0x02);
629 IdeBlkIoDevicePtr
->IoPort
->SectorNumber
= (UINT16
) (CommandBlockBaseAddr
+ 0x03);
630 IdeBlkIoDevicePtr
->IoPort
->CylinderLsb
= (UINT16
) (CommandBlockBaseAddr
+ 0x04);
631 IdeBlkIoDevicePtr
->IoPort
->CylinderMsb
= (UINT16
) (CommandBlockBaseAddr
+ 0x05);
632 IdeBlkIoDevicePtr
->IoPort
->Head
= (UINT16
) (CommandBlockBaseAddr
+ 0x06);
633 (*(UINT16
*) &IdeBlkIoDevicePtr
->IoPort
->Reg
) = (UINT16
) (CommandBlockBaseAddr
+ 0x07);
635 (*(UINT16
*) &IdeBlkIoDevicePtr
->IoPort
->Alt
) = ControlBlockBaseAddr
;
636 IdeBlkIoDevicePtr
->IoPort
->DriveAddress
= (UINT16
) (ControlBlockBaseAddr
+ 0x01);
638 IdeBlkIoDevicePtr
->IoPort
->MasterSlave
= (UINT16
) ((IdeDevice
== IdeMaster
) ? 1 : 0);
640 IdeBlkIoDevicePtr
->PciIo
= PciIo
;
641 IdeBlkIoDevicePtr
->IdeBusDriverPrivateData
= IdeBusDriverPrivateData
;
642 IdeBlkIoDevicePtr
->IoPort
->BusMasterBaseAddr
= IdeRegsBaseAddr
[IdeChannel
].BusMasterBaseAddr
;
645 // Report Status code: is about to detect IDE drive
647 REPORT_STATUS_CODE_EX (
649 (EFI_IO_BUS_ATA_ATAPI
| EFI_P_PC_PRESENCE_DETECT
),
658 // Discover device, now!
660 PERF_START (NULL
, "DiscoverIdeDevice", "IDE", 0);
661 Status
= DiscoverIdeDevice (IdeBlkIoDevicePtr
);
662 PERF_END (NULL
, "DiscoverIdeDevice", "IDE", 0);
664 IdeBusDriverPrivateData
->HaveScannedDevice
[IdeChannel
* 2 + IdeDevice
] = TRUE
;
665 IdeBusDriverPrivateData
->DeviceProcessed
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
667 if (!EFI_ERROR (Status
)) {
671 ZeroMem (&NewNode
, sizeof (NewNode
));
672 NewNode
.DevPath
.Type
= MESSAGING_DEVICE_PATH
;
673 NewNode
.DevPath
.SubType
= MSG_ATAPI_DP
;
674 SetDevicePathNodeLength (&NewNode
.DevPath
, sizeof (ATAPI_DEVICE_PATH
));
676 NewNode
.Atapi
.PrimarySecondary
= (UINT8
) IdeBlkIoDevicePtr
->Channel
;
677 NewNode
.Atapi
.SlaveMaster
= (UINT8
) IdeBlkIoDevicePtr
->Device
;
678 NewNode
.Atapi
.Lun
= IdeBlkIoDevicePtr
->Lun
;
679 IdeBlkIoDevicePtr
->DevicePath
= AppendDevicePathNode (
683 if (IdeBlkIoDevicePtr
->DevicePath
== NULL
) {
684 ReleaseIdeResources (IdeBlkIoDevicePtr
);
689 // Submit identify data to IDE controller init driver
691 CopyMem (&IdentifyData
, IdeBlkIoDevicePtr
->IdData
, sizeof (IdentifyData
));
692 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = TRUE
;
693 IdeInit
->SubmitData (IdeInit
, IdeChannel
, IdeDevice
, &IdentifyData
);
696 // Device detection failed
698 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
699 IdeInit
->SubmitData (IdeInit
, IdeChannel
, IdeDevice
, NULL
);
700 ReleaseIdeResources (IdeBlkIoDevicePtr
);
701 IdeBlkIoDevicePtr
= NULL
;
704 // end of 1st inner loop ---
708 // end of 1st outer loop =========
713 // = 2nd outer loop == Primary/Secondary =================
715 for (IdeChannel
= BeginningIdeChannel
; IdeChannel
<= EndIdeChannel
; IdeChannel
++) {
718 // -- 2nd inner loop --- Master/Slave --------
720 for (IdeDevice
= BeginningIdeDevice
; IdeDevice
<= EndIdeDevice
; IdeDevice
++) {
722 ASSERT (IdeChannel
* 2 + IdeDevice
< MAX_IDE_DEVICE
);
723 if (IdeBusDriverPrivateData
->DeviceProcessed
[IdeChannel
* 2 + IdeDevice
]) {
727 if (!IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
]) {
731 Status
= IdeInit
->CalculateMode (
737 if (EFI_ERROR (Status
)) {
738 DEBUG ((EFI_D_ERROR
, "[bStStp20S=%x]", Status
));
742 ASSERT (IdeChannel
< IdeMaxChannel
&& IdeDevice
< IdeMaxDevice
);
743 IdeBlkIoDevicePtr
= IdeBlkIoDevice
[IdeChannel
][IdeDevice
];
746 // Set best supported PIO mode on this IDE device
748 if (SupportedModes
->PioMode
.Mode
<= AtaPioMode2
) {
749 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_DEFAULT_PIO
;
751 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_FLOW_PIO
;
754 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->PioMode
.Mode
);
756 if (SupportedModes
->ExtModeCount
== 0){
757 Status
= SetDeviceTransferMode (IdeBlkIoDevicePtr
, &TransferMode
);
759 if (EFI_ERROR (Status
)) {
760 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
761 ReleaseIdeResources (IdeBlkIoDevicePtr
);
762 IdeBlkIoDevicePtr
= NULL
;
768 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
769 // be set together. Only one DMA mode can be set to a device. If setting
770 // DMA mode operation fails, we can continue moving on because we only use
771 // PIO mode at boot time. DMA modes are used by certain kind of OS booting
773 if (SupportedModes
->UdmaMode
.Valid
) {
775 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_UDMA
;
776 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->UdmaMode
.Mode
);
777 Status
= SetDeviceTransferMode (IdeBlkIoDevicePtr
, &TransferMode
);
779 if (EFI_ERROR (Status
)) {
780 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
781 ReleaseIdeResources (IdeBlkIoDevicePtr
);
782 IdeBlkIoDevicePtr
= NULL
;
788 IdeBlkIoDevicePtr
->UdmaMode
.Valid
= TRUE
;
789 IdeBlkIoDevicePtr
->UdmaMode
.Mode
= SupportedModes
->UdmaMode
.Mode
;
790 EnableInterrupt (IdeBlkIoDevicePtr
);
791 } else if (SupportedModes
->MultiWordDmaMode
.Valid
) {
793 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_MDMA
;
794 TransferMode
.ModeNumber
= (UINT8
) SupportedModes
->MultiWordDmaMode
.Mode
;
795 Status
= SetDeviceTransferMode (IdeBlkIoDevicePtr
, &TransferMode
);
797 if (EFI_ERROR (Status
)) {
798 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
799 ReleaseIdeResources (IdeBlkIoDevicePtr
);
800 IdeBlkIoDevicePtr
= NULL
;
804 EnableInterrupt (IdeBlkIoDevicePtr
);
807 // Init driver parameters
809 DriveParameters
.Sector
= (UINT8
) ((ATA5_IDENTIFY_DATA
*) IdeBlkIoDevicePtr
->IdData
)->sectors_per_track
;
810 DriveParameters
.Heads
= (UINT8
) (((ATA5_IDENTIFY_DATA
*) IdeBlkIoDevicePtr
->IdData
)->heads
- 1);
811 DriveParameters
.MultipleSector
= (UINT8
) IdeBlkIoDevicePtr
->IdData
->AtaData
.multi_sector_cmd_max_sct_cnt
;
813 // Set Parameters for the device:
815 // 2) Establish the block count for READ/WRITE MULTIPLE (EXT) command
817 if ((IdeBlkIoDevicePtr
->Type
== IdeHardDisk
) || (IdeBlkIoDevicePtr
->Type
== Ide48bitAddressingHardDisk
)) {
818 Status
= SetDriveParameters (IdeBlkIoDevicePtr
, &DriveParameters
);
822 // Record PIO mode used in private data
824 IdeBlkIoDevicePtr
->PioMode
= (ATA_PIO_MODE
) SupportedModes
->PioMode
.Mode
;
827 // Set IDE controller Timing Blocks in the PCI Configuration Space
829 IdeInit
->SetTiming (IdeInit
, IdeChannel
, IdeDevice
, SupportedModes
);
832 // Add Component Name for the IDE/ATAPI device that was discovered.
834 IdeBlkIoDevicePtr
->ControllerNameTable
= NULL
;
835 ADD_IDE_ATAPI_NAME (IdeBlkIoDevicePtr
);
837 Status
= gBS
->InstallMultipleProtocolInterfaces (
838 &IdeBlkIoDevicePtr
->Handle
,
839 &gEfiDevicePathProtocolGuid
,
840 IdeBlkIoDevicePtr
->DevicePath
,
841 &gEfiBlockIoProtocolGuid
,
842 &IdeBlkIoDevicePtr
->BlkIo
,
843 &gEfiDiskInfoProtocolGuid
,
844 &IdeBlkIoDevicePtr
->DiskInfo
,
848 if (EFI_ERROR (Status
)) {
849 ReleaseIdeResources (IdeBlkIoDevicePtr
);
854 &gEfiPciIoProtocolGuid
,
856 This
->DriverBindingHandle
,
857 IdeBlkIoDevicePtr
->Handle
,
858 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
861 IdeBusDriverPrivateData
->DeviceProcessed
[IdeChannel
* 2 + IdeDevice
] = TRUE
;
864 // Report status code: device eanbled!
866 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
868 (EFI_IO_BUS_ATA_ATAPI
| EFI_P_PC_ENABLE
),
869 IdeBlkIoDevicePtr
->DevicePath
873 // Create event to clear pending IDE interrupt
875 Status
= gBS
->CreateEventEx (
880 &gEfiEventExitBootServicesGuid
,
881 &IdeBlkIoDevicePtr
->ExitBootServiceEvent
885 // end of 2nd inner loop ----
889 // end of 2nd outer loop ==========
894 // All configurations done! Notify IdeController to do post initialization
895 // work such as saving IDE controller PCI settings for S3 resume
897 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBusPhaseMaximum
, 0);
899 if (SupportedModes
!= NULL
) {
900 FreePool (SupportedModes
);
903 PERF_START (NULL
, "Finish IDE detection", "IDE", 1);
904 PERF_END (NULL
, "Finish IDE detection", "IDE", 0);
911 // Report error code: controller error
913 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
914 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
915 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_EC_CONTROLLER_ERROR
),
921 &gEfiIdeControllerInitProtocolGuid
,
922 This
->DriverBindingHandle
,
926 gBS
->UninstallMultipleProtocolInterfaces (
929 IdeBusDriverPrivateData
,
933 if (IdeBusDriverPrivateData
!= NULL
) {
934 gBS
->FreePool (IdeBusDriverPrivateData
);
937 if (SupportedModes
!= NULL
) {
938 gBS
->FreePool (SupportedModes
);
943 &gEfiPciIoProtocolGuid
,
944 This
->DriverBindingHandle
,
950 &gEfiDevicePathProtocolGuid
,
951 This
->DriverBindingHandle
,
959 Stop function of Driver Binding Protocol which is to stop the driver on Controller Handle and all
960 child handle attached to the controller handle if there are.
962 @param This Protocol instance pointer.
963 @param Controller Handle of device to stop driver on
964 @param NumberOfChildren Not used
965 @param ChildHandleBuffer Not used
967 @retval EFI_SUCCESS This driver is removed DeviceHandle
968 @retval other This driver was not removed from this device
973 IDEBusDriverBindingStop (
974 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
975 IN EFI_HANDLE Controller
,
976 IN UINTN NumberOfChildren
,
977 IN EFI_HANDLE
*ChildHandleBuffer
981 EFI_PCI_IO_PROTOCOL
*PciIo
;
982 BOOLEAN AllChildrenStopped
;
984 IDE_BUS_DRIVER_PRIVATE_DATA
*IdeBusDriverPrivateData
;
987 IdeBusDriverPrivateData
= NULL
;
989 if (NumberOfChildren
== 0) {
991 Status
= gBS
->OpenProtocol (
993 &gEfiPciIoProtocolGuid
,
995 This
->DriverBindingHandle
,
997 EFI_OPEN_PROTOCOL_GET_PROTOCOL
999 if (!EFI_ERROR (Status
)) {
1000 Status
= PciIo
->Attributes (
1002 EfiPciIoAttributeOperationSupported
,
1006 if (!EFI_ERROR (Status
)) {
1007 Supports
&= (UINT64
)(EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO
| EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO
| EFI_PCI_DEVICE_ENABLE
);
1010 EfiPciIoAttributeOperationDisable
,
1020 (VOID
**) &IdeBusDriverPrivateData
,
1021 This
->DriverBindingHandle
,
1023 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1026 gBS
->UninstallMultipleProtocolInterfaces (
1029 IdeBusDriverPrivateData
,
1033 if (IdeBusDriverPrivateData
!= NULL
) {
1034 gBS
->FreePool (IdeBusDriverPrivateData
);
1037 // Close the bus driver
1039 gBS
->CloseProtocol (
1041 &gEfiIdeControllerInitProtocolGuid
,
1042 This
->DriverBindingHandle
,
1045 gBS
->CloseProtocol (
1047 &gEfiPciIoProtocolGuid
,
1048 This
->DriverBindingHandle
,
1051 gBS
->CloseProtocol (
1053 &gEfiDevicePathProtocolGuid
,
1054 This
->DriverBindingHandle
,
1061 AllChildrenStopped
= TRUE
;
1063 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1065 Status
= DeRegisterIdeDevice (This
, Controller
, ChildHandleBuffer
[Index
]);
1067 if (EFI_ERROR (Status
)) {
1068 AllChildrenStopped
= FALSE
;
1072 if (!AllChildrenStopped
) {
1073 return EFI_DEVICE_ERROR
;
1080 issue ATA or ATAPI command to reset a block IO device.
1081 @param This Block IO protocol instance pointer.
1082 @param ExtendedVerification If FALSE,for ATAPI device, driver will only invoke ATAPI reset method
1083 If TRUE, for ATAPI device, driver need invoke ATA reset method after
1084 invoke ATAPI reset method
1086 @retval EFI_DEVICE_ERROR When the device is neighther ATA device or ATAPI device.
1087 @retval EFI_SUCCESS The device reset successfully
1093 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1094 IN BOOLEAN ExtendedVerification
1097 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1101 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1103 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (This
);
1105 // Requery IDE IO resources in case of the switch of native and legacy modes
1107 ReassignIdeResources (IdeBlkIoDevice
);
1110 // for ATA device, using ATA reset method
1112 if (IdeBlkIoDevice
->Type
== IdeHardDisk
||
1113 IdeBlkIoDevice
->Type
== Ide48bitAddressingHardDisk
) {
1114 Status
= AtaSoftReset (IdeBlkIoDevice
);
1118 if (IdeBlkIoDevice
->Type
== IdeUnknown
) {
1119 Status
= EFI_DEVICE_ERROR
;
1124 // for ATAPI device, using ATAPI reset method
1126 Status
= AtapiSoftReset (IdeBlkIoDevice
);
1127 if (ExtendedVerification
) {
1128 Status
= AtaSoftReset (IdeBlkIoDevice
);
1132 gBS
->RestoreTPL (OldTpl
);
1137 Read data from a block IO device
1139 @param This Block IO protocol instance pointer.
1140 @param MediaId The media ID of the device
1141 @param Lba Starting LBA address to read data
1142 @param BufferSize The size of data to be read
1143 @param Buffer Caller supplied buffer to save data
1145 @retval EFI_DEVICE_ERROR unknown device type
1146 @retval other read data status.
1151 IDEBlkIoReadBlocks (
1152 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1155 IN UINTN BufferSize
,
1159 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1163 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1165 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (This
);
1168 // Requery IDE IO resources in case of the switch of native and legacy modes
1170 ReassignIdeResources (IdeBlkIoDevice
);
1173 // For ATA compatible device, use ATA read block's mechanism
1175 if (IdeBlkIoDevice
->Type
== IdeHardDisk
||
1176 IdeBlkIoDevice
->Type
== Ide48bitAddressingHardDisk
) {
1177 Status
= AtaBlkIoReadBlocks (
1187 if (IdeBlkIoDevice
->Type
== IdeUnknown
) {
1188 Status
= EFI_DEVICE_ERROR
;
1193 // for ATAPI device, using ATAPI read block's mechanism
1195 Status
= AtapiBlkIoReadBlocks (
1204 gBS
->RestoreTPL (OldTpl
);
1210 Write data to block io device.
1212 @param This Protocol instance pointer.
1213 @param MediaId The media ID of the device
1214 @param Lba Starting LBA address to write data
1215 @param BufferSize The size of data to be written
1216 @param Buffer Caller supplied buffer to save data
1218 @retval EFI_DEVICE_ERROR unknown device type
1219 @retval other write data status
1224 IDEBlkIoWriteBlocks (
1225 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1228 IN UINTN BufferSize
,
1232 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1236 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1238 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (This
);
1240 // Requery IDE IO resources in case of the switch of native and legacy modes
1242 ReassignIdeResources (IdeBlkIoDevice
);
1245 // for ATA device, using ATA write block's mechanism
1247 if (IdeBlkIoDevice
->Type
== IdeHardDisk
||
1248 IdeBlkIoDevice
->Type
== Ide48bitAddressingHardDisk
) {
1250 Status
= AtaBlkIoWriteBlocks (
1260 if (IdeBlkIoDevice
->Type
== IdeUnknown
) {
1261 Status
= EFI_DEVICE_ERROR
;
1266 // for ATAPI device, using ATAPI write block's mechanism
1268 Status
= AtapiBlkIoWriteBlocks (
1277 gBS
->RestoreTPL (OldTpl
);
1281 Flushes all modified data to a physical block devices
1283 @param This Indicates a pointer to the calling context which to sepcify a
1284 sepcific block device
1286 @retval EFI_SUCCESS Always return success.
1290 IDEBlkIoFlushBlocks (
1291 IN EFI_BLOCK_IO_PROTOCOL
*This
1301 This function is used by the IDE bus driver to get inquiry data.
1302 Data format of Identify data is defined by the Interface GUID.
1304 @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
1305 @param InquiryData Pointer to a buffer for the inquiry data.
1306 @param InquiryDataSize Pointer to the value for the inquiry data size.
1308 @retval EFI_SUCCESS The command was accepted without any errors.
1309 @retval EFI_NOT_FOUND Device does not support this data class
1310 @retval EFI_DEVICE_ERROR Error reading InquiryData from device
1311 @retval EFI_BUFFER_TOO_SMALL IntquiryDataSize not big enough
1316 IDEDiskInfoInquiry (
1317 IN EFI_DISK_INFO_PROTOCOL
*This
,
1318 IN OUT VOID
*InquiryData
,
1319 IN OUT UINT32
*InquiryDataSize
1322 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1324 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This
);
1326 if (*InquiryDataSize
< sizeof (ATAPI_INQUIRY_DATA
)) {
1327 *InquiryDataSize
= sizeof (ATAPI_INQUIRY_DATA
);
1328 return EFI_BUFFER_TOO_SMALL
;
1331 if (IdeBlkIoDevice
->InquiryData
== NULL
) {
1332 return EFI_NOT_FOUND
;
1335 gBS
->CopyMem (InquiryData
, IdeBlkIoDevice
->InquiryData
, sizeof (ATAPI_INQUIRY_DATA
));
1336 *InquiryDataSize
= sizeof (ATAPI_INQUIRY_DATA
);
1342 This function is used by the IDE bus driver to get identify data.
1343 Data format of Identify data is defined by the Interface GUID.
1345 @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
1346 @param IdentifyData Pointer to a buffer for the identify data.
1347 @param IdentifyDataSize Pointer to the value for the identify data size.
1349 @retval EFI_SUCCESS The command was accepted without any errors.
1350 @retval EFI_NOT_FOUND Device does not support this data class
1351 @retval EFI_DEVICE_ERROR Error reading IdentifyData from device
1352 @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough
1357 IDEDiskInfoIdentify (
1358 IN EFI_DISK_INFO_PROTOCOL
*This
,
1359 IN OUT VOID
*IdentifyData
,
1360 IN OUT UINT32
*IdentifyDataSize
1363 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1365 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This
);
1367 if (*IdentifyDataSize
< sizeof (EFI_IDENTIFY_DATA
)) {
1368 *IdentifyDataSize
= sizeof (EFI_IDENTIFY_DATA
);
1369 return EFI_BUFFER_TOO_SMALL
;
1372 if (IdeBlkIoDevice
->IdData
== NULL
) {
1373 return EFI_NOT_FOUND
;
1376 gBS
->CopyMem (IdentifyData
, IdeBlkIoDevice
->IdData
, sizeof (EFI_IDENTIFY_DATA
));
1377 *IdentifyDataSize
= sizeof (EFI_IDENTIFY_DATA
);
1383 This function is used by the IDE bus driver to get sense data.
1384 Data format of Sense data is defined by the Interface GUID.
1386 @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
1387 @param SenseData Pointer to the SenseData.
1388 @param SenseDataSize Size of SenseData in bytes.
1389 @param SenseDataNumber Pointer to the value for the identify data size.
1391 @retval EFI_SUCCESS The command was accepted without any errors.
1392 @retval EFI_NOT_FOUND Device does not support this data class
1393 @retval EFI_DEVICE_ERROR Error reading InquiryData from device
1394 @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough
1399 IDEDiskInfoSenseData (
1400 IN EFI_DISK_INFO_PROTOCOL
*This
,
1401 IN OUT VOID
*SenseData
,
1402 IN OUT UINT32
*SenseDataSize
,
1403 OUT UINT8
*SenseDataNumber
1406 return EFI_NOT_FOUND
;
1410 This function is used by the IDE bus driver to get controller information.
1412 @param This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
1413 @param IdeChannel Pointer to the Ide Channel number. Primary or secondary.
1414 @param IdeDevice Pointer to the Ide Device number. Master or slave.
1416 @retval EFI_SUCCESS IdeChannel and IdeDevice are valid
1417 @retval EFI_UNSUPPORTED This is not an IDE device
1422 IDEDiskInfoWhichIde (
1423 IN EFI_DISK_INFO_PROTOCOL
*This
,
1424 OUT UINT32
*IdeChannel
,
1425 OUT UINT32
*IdeDevice
1428 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1430 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This
);
1431 *IdeChannel
= IdeBlkIoDevice
->Channel
;
1432 *IdeDevice
= IdeBlkIoDevice
->Device
;
1438 The is an event(generally the event is exitBootService event) call back function.
1439 Clear pending IDE interrupt before OS loader/kernel take control of the IDE device.
1441 @param Event Pointer to this event
1442 @param Context Event handler private data
1453 UINT64 IoPortForBmis
;
1454 UINT8 RegisterValue
;
1455 IDE_BLK_IO_DEV
*IdeDev
;
1460 IdeDev
= (IDE_BLK_IO_DEV
*) Context
;
1463 // Obtain IDE IO port registers' base addresses
1465 Status
= ReassignIdeResources (IdeDev
);
1466 if (EFI_ERROR (Status
)) {
1471 // Check whether interrupt is pending
1475 // Reset IDE device to force it de-assert interrupt pin
1476 // Note: this will reset all devices on this IDE channel
1478 Status
= AtaSoftReset (IdeDev
);
1479 if (EFI_ERROR (Status
)) {
1484 // Get base address of IDE Bus Master Status Regsiter
1486 if (IdePrimary
== IdeDev
->Channel
) {
1487 IoPortForBmis
= IdeDev
->IoPort
->BusMasterBaseAddr
+ BMISP_OFFSET
;
1489 if (IdeSecondary
== IdeDev
->Channel
) {
1490 IoPortForBmis
= IdeDev
->IoPort
->BusMasterBaseAddr
+ BMISS_OFFSET
;
1496 // Read BMIS register and clear ERROR and INTR bit
1498 IdeDev
->PciIo
->Io
.Read (
1501 EFI_PCI_IO_PASS_THROUGH_BAR
,
1507 RegisterValue
|= (BMIS_INTERRUPT
| BMIS_ERROR
);
1509 IdeDev
->PciIo
->Io
.Write (
1512 EFI_PCI_IO_PASS_THROUGH_BAR
,
1519 // Select the other device on this channel to ensure this device to release the interrupt pin
1521 if (IdeDev
->Device
== 0) {
1522 RegisterValue
= (1 << 4) | 0xe0;
1524 RegisterValue
= (0 << 4) | 0xe0;
1528 IdeDev
->IoPort
->Head
,
1535 The user Entry Point for module IdeBus. The user code starts with this function.
1537 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1538 @param[in] SystemTable A pointer to the EFI System Table.
1540 @retval EFI_SUCCESS The entry point is executed successfully.
1541 @retval other Some error occurs when executing this entry point.
1547 IN EFI_HANDLE ImageHandle
,
1548 IN EFI_SYSTEM_TABLE
*SystemTable
1554 // Install driver model protocol(s).
1556 Status
= EfiLibInstallAllDriverProtocols2 (
1559 &gIDEBusDriverBinding
,
1561 &gIDEBusComponentName
,
1562 &gIDEBusComponentName2
,
1565 &gIDEBusDriverDiagnostics
,
1566 &gIDEBusDriverDiagnostics2
1568 ASSERT_EFI_ERROR (Status
);