3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 This module is modified from DXE\IDE module for Ide Contriller Init support
26 #define PCI_CLASS_MASS_STORAGE 0x01
27 #define PCI_SUB_CLASS_IDE 0x01
31 // IDE Bus Driver Binding Protocol Instance
33 EFI_DRIVER_BINDING_PROTOCOL gIDEBusDriverBinding
= {
34 IDEBusDriverBindingSupported
,
35 IDEBusDriverBindingStart
,
36 IDEBusDriverBindingStop
,
43 // ***********************************************************************************
44 // IDEBusDriverBindingSupported
45 // ***********************************************************************************
49 IDEBusDriverBindingSupported (
50 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
51 IN EFI_HANDLE Controller
,
52 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
57 Register Driver Binding protocol for this driver.
60 This -- A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
61 ControllerHandle -- The handle of the controller to test.
62 RemainingDevicePath -- A pointer to the remaining portion of a device path.
65 EFI_SUCCESS - Driver loaded.
66 other - Driver not loaded.
68 // TODO: Controller - add argument and description to function comment
69 // TODO: EFI_UNSUPPORTED - add return value to function comment
72 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
74 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
76 if (RemainingDevicePath
!= NULL
) {
77 Node
= (EFI_DEV_PATH
*) RemainingDevicePath
;
78 if (Node
->DevPath
.Type
!= MESSAGING_DEVICE_PATH
||
79 Node
->DevPath
.SubType
!= MSG_ATAPI_DP
||
80 DevicePathNodeLength(&Node
->DevPath
) != sizeof(ATAPI_DEVICE_PATH
)) {
81 return EFI_UNSUPPORTED
;
86 // Open the IO Abstraction(s) needed to perform the supported test
88 Status
= gBS
->OpenProtocol (
90 &gEfiDevicePathProtocolGuid
,
91 (VOID
**) &ParentDevicePath
,
92 This
->DriverBindingHandle
,
94 EFI_OPEN_PROTOCOL_BY_DRIVER
96 if (Status
== EFI_ALREADY_STARTED
) {
100 if (EFI_ERROR (Status
)) {
105 // Clsoe protocol, don't use device path protocol in the .Support() function
109 &gEfiDevicePathProtocolGuid
,
110 This
->DriverBindingHandle
,
115 // Verify the Ide Controller Init Protocol, which installed by the
116 // IdeController module.
117 // Note 1: PciIo protocol has been opened BY_DRIVER by ide_init, so We can't
118 // open BY_DRIVER here) That's why we don't check pciio protocol
119 // Note 2: ide_init driver check ide controller's pci config space, so we dont
120 // check here any more to save code size
122 Status
= gBS
->OpenProtocol (
124 &gEfiIdeControllerInitProtocolGuid
,
126 This
->DriverBindingHandle
,
128 EFI_OPEN_PROTOCOL_BY_DRIVER
131 if (Status
== EFI_ALREADY_STARTED
) {
136 // If protocols were opened normally, closed it
140 &gEfiIdeControllerInitProtocolGuid
,
141 This
->DriverBindingHandle
,
149 // ***********************************************************************************
150 // IDEBusDriverBindingStart
151 // ***********************************************************************************
155 IDEBusDriverBindingStart (
156 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
157 IN EFI_HANDLE Controller
,
158 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
163 Start this driver on Controller by detecting all disks and installing
164 BlockIo protocol on them.
167 This - Protocol instance pointer.
168 Controller - Handle of device to bind driver to.
169 RemainingDevicePath - Not used, always produce all possible children.
172 EFI_SUCCESS - This driver is added to ControllerHandle.
173 EFI_ALREADY_STARTED - This driver is already running on ControllerHandle.
174 other - This driver does not support this device.
179 EFI_STATUS SavedStatus
;
180 EFI_PCI_IO_PROTOCOL
*PciIo
;
181 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
184 UINT8 BeginningIdeChannel
;
187 UINT8 BeginningIdeDevice
;
189 IDE_BLK_IO_DEV
*IdeBlkIoDevice
[IdeMaxChannel
][IdeMaxDevice
];
190 IDE_BLK_IO_DEV
*IdeBlkIoDevicePtr
;
191 IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr
[IdeMaxChannel
];
192 ATA_TRANSFER_MODE TransferMode
;
193 ATA_DRIVE_PARMS DriveParameters
;
194 EFI_DEV_PATH NewNode
;
195 UINT8 ConfigurationOptions
;
196 UINT16 CommandBlockBaseAddr
;
197 UINT16 ControlBlockBaseAddr
;
200 IDE_BUS_DRIVER_PRIVATE_DATA
*IdeBusDriverPrivateData
;
203 // Local variables declaration for IdeControllerInit support
205 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
207 BOOLEAN ChannelEnabled
;
210 EFI_IDENTIFY_DATA IdentifyData
;
211 EFI_ATA_COLLECTIVE_MODE
*SupportedModes
;
213 IdeBusDriverPrivateData
= NULL
;
214 SupportedModes
= NULL
;
217 // Perform IdeBus initialization
219 Status
= gBS
->OpenProtocol (
221 &gEfiDevicePathProtocolGuid
,
222 (VOID
**) &ParentDevicePath
,
223 This
->DriverBindingHandle
,
225 EFI_OPEN_PROTOCOL_BY_DRIVER
227 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
232 // Now open the IDE_CONTROLLER_INIT protocol. Step7.1
234 Status
= gBS
->OpenProtocol (
236 &gEfiIdeControllerInitProtocolGuid
,
238 This
->DriverBindingHandle
,
240 EFI_OPEN_PROTOCOL_BY_DRIVER
244 // The following OpenProtocol function with _GET_PROTOCOL attribute and
245 // will not return EFI_ALREADY_STARTED, so save it for now
247 SavedStatus
= Status
;
249 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
250 DEBUG ((EFI_D_ERROR
, "Open Init, Status=%x", Status
));
252 // open protocol is not SUCCESS or not ALREADY_STARTED, error exit
258 // Save Enumall and ChannelCount. Step7.2
260 EnumAll
= IdeInit
->EnumAll
;
261 ChannelCount
= IdeInit
->ChannelCount
;
264 // Consume PCI I/O protocol. Note that the OpenProtocol with _GET_PROTOCOL
265 // attribute will not return EFI_ALREADY_STARTED
267 Status
= gBS
->OpenProtocol (
269 &gEfiPciIoProtocolGuid
,
271 This
->DriverBindingHandle
,
273 EFI_OPEN_PROTOCOL_GET_PROTOCOL
275 if (EFI_ERROR (Status
)) {
276 DEBUG ((EFI_D_ERROR
, "Open PciIo, Status=%x", Status
));
281 // We must check EFI_ALREADY_STARTED because many ATAPI devices are removable
283 if (SavedStatus
!= EFI_ALREADY_STARTED
) {
284 IdeBusDriverPrivateData
= AllocatePool (sizeof (IDE_BUS_DRIVER_PRIVATE_DATA
));
285 if (IdeBusDriverPrivateData
== NULL
) {
286 Status
= EFI_OUT_OF_RESOURCES
;
290 ZeroMem (IdeBusDriverPrivateData
, sizeof (IDE_BUS_DRIVER_PRIVATE_DATA
));
291 Status
= gBS
->InstallMultipleProtocolInterfaces (
294 IdeBusDriverPrivateData
,
297 if (EFI_ERROR (Status
)) {
302 Status
= gBS
->OpenProtocol (
305 (VOID
**) &IdeBusDriverPrivateData
,
306 This
->DriverBindingHandle
,
308 EFI_OPEN_PROTOCOL_GET_PROTOCOL
310 if (EFI_ERROR (Status
)) {
311 IdeBusDriverPrivateData
= NULL
;
316 Status
= PciIo
->Attributes (
318 EfiPciIoAttributeOperationEnable
,
319 EFI_PCI_DEVICE_ENABLE
,
322 if (EFI_ERROR (Status
)) {
327 // Read the environment variable that contains the IDEBus Driver's
328 // Config options that were set by the Driver Configuration Protocol
330 DataSize
= sizeof (ConfigurationOptions
);
331 Status
= gRT
->GetVariable (
332 (CHAR16
*) L
"Configuration",
336 &ConfigurationOptions
338 if (EFI_ERROR (Status
)) {
339 ConfigurationOptions
= 0x0f;
344 // If IdeInit->EnumAll is TRUE, must enumerate all IDE device anyway
346 BeginningIdeChannel
= IdePrimary
;
347 EndIdeChannel
= IdeSecondary
;
348 BeginningIdeDevice
= IdeMaster
;
349 EndIdeDevice
= IdeSlave
;
350 } else if (RemainingDevicePath
== NULL
) {
352 // RemainingDevicePath is NULL, scan IDE bus for each device;
354 BeginningIdeChannel
= IdePrimary
;
355 EndIdeChannel
= IdeSecondary
;
356 BeginningIdeDevice
= IdeMaster
;
358 // default, may be redefined by IdeInit
360 EndIdeDevice
= IdeSlave
;
363 // RemainingDevicePath is not NULL, only scan the specified device.
365 Node
= (EFI_DEV_PATH
*) RemainingDevicePath
;
366 BeginningIdeChannel
= Node
->Atapi
.PrimarySecondary
;
367 EndIdeChannel
= BeginningIdeChannel
;
368 BeginningIdeDevice
= Node
->Atapi
.SlaveMaster
;
369 EndIdeDevice
= BeginningIdeDevice
;
373 // Obtain IDE IO port registers' base addresses
375 Status
= GetIdeRegistersBaseAddr (PciIo
, IdeRegsBaseAddr
);
376 if (EFI_ERROR (Status
)) {
381 // Report status code: begin IdeBus initialization
383 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
385 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_PC_RESET
),
390 // Strictly follow the enumeration based on IDE_CONTROLLER_INIT protocol
392 for (IdeChannel
= BeginningIdeChannel
; IdeChannel
<= EndIdeChannel
; IdeChannel
++) {
394 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelEnumeration
, IdeChannel
);
397 // now obtain channel information fron IdeControllerInit protocol. Step9
399 Status
= IdeInit
->GetChannelInfo (
405 if (EFI_ERROR (Status
)) {
406 DEBUG ((EFI_D_ERROR
, "[GetChannel, Status=%x]", Status
));
410 if (!ChannelEnabled
) {
414 EndIdeDevice
= (UINT8
) EFI_MIN ((MaxDevices
- 1), EndIdeDevice
);
417 // Now inform the IDE Controller Init Module. Sept10
419 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelReset
, IdeChannel
);
422 // No reset channel function implemented. Sept11
424 IdeInit
->NotifyPhase (IdeInit
, EfiIdeAfterChannelReset
, IdeChannel
);
429 IdeInit
->NotifyPhase (
431 EfiIdeBusBeforeDevicePresenceDetection
,
435 // -- 1st inner loop --- Master/Slave ------------ Step14
437 for (IdeDevice
= BeginningIdeDevice
; IdeDevice
<= EndIdeDevice
; IdeDevice
++) {
439 // Check whether the configuration options allow this device
441 if (!(ConfigurationOptions
& (1 << (IdeChannel
* 2 + IdeDevice
)))) {
446 // The device has been scanned in another Start(), No need to scan it again
447 // for perf optimization.
449 if (IdeBusDriverPrivateData
->HaveScannedDevice
[IdeChannel
* 2 + IdeDevice
]) {
454 // create child handle for the detected device.
456 IdeBlkIoDevice
[IdeChannel
][IdeDevice
] = AllocatePool (sizeof (IDE_BLK_IO_DEV
));
457 if (IdeBlkIoDevice
[IdeChannel
][IdeDevice
] == NULL
) {
461 IdeBlkIoDevicePtr
= IdeBlkIoDevice
[IdeChannel
][IdeDevice
];
463 ZeroMem (IdeBlkIoDevicePtr
, sizeof (IDE_BLK_IO_DEV
));
465 IdeBlkIoDevicePtr
->Signature
= IDE_BLK_IO_DEV_SIGNATURE
;
466 IdeBlkIoDevicePtr
->Channel
= IdeChannel
;
467 IdeBlkIoDevicePtr
->Device
= IdeDevice
;
470 // initialize Block IO interface's Media pointer
472 IdeBlkIoDevicePtr
->BlkIo
.Media
= &IdeBlkIoDevicePtr
->BlkMedia
;
475 // Initialize IDE IO port addresses, including Command Block registers
476 // and Control Block registers
478 IdeBlkIoDevicePtr
->IoPort
= AllocatePool (sizeof (IDE_BASE_REGISTERS
));
479 if (IdeBlkIoDevicePtr
->IoPort
== NULL
) {
483 ZeroMem (IdeBlkIoDevicePtr
->IoPort
, sizeof (IDE_BASE_REGISTERS
));
484 CommandBlockBaseAddr
= IdeRegsBaseAddr
[IdeChannel
].CommandBlockBaseAddr
;
485 ControlBlockBaseAddr
= IdeRegsBaseAddr
[IdeChannel
].ControlBlockBaseAddr
;
487 IdeBlkIoDevicePtr
->IoPort
->Data
= CommandBlockBaseAddr
;
488 (*(UINT16
*) &IdeBlkIoDevicePtr
->IoPort
->Reg1
) = (UINT16
) (CommandBlockBaseAddr
+ 0x01);
489 IdeBlkIoDevicePtr
->IoPort
->SectorCount
= (UINT16
) (CommandBlockBaseAddr
+ 0x02);
490 IdeBlkIoDevicePtr
->IoPort
->SectorNumber
= (UINT16
) (CommandBlockBaseAddr
+ 0x03);
491 IdeBlkIoDevicePtr
->IoPort
->CylinderLsb
= (UINT16
) (CommandBlockBaseAddr
+ 0x04);
492 IdeBlkIoDevicePtr
->IoPort
->CylinderMsb
= (UINT16
) (CommandBlockBaseAddr
+ 0x05);
493 IdeBlkIoDevicePtr
->IoPort
->Head
= (UINT16
) (CommandBlockBaseAddr
+ 0x06);
494 (*(UINT16
*) &IdeBlkIoDevicePtr
->IoPort
->Reg
) = (UINT16
) (CommandBlockBaseAddr
+ 0x07);
496 (*(UINT16
*) &IdeBlkIoDevicePtr
->IoPort
->Alt
) = ControlBlockBaseAddr
;
497 IdeBlkIoDevicePtr
->IoPort
->DriveAddress
= (UINT16
) (ControlBlockBaseAddr
+ 0x01);
499 IdeBlkIoDevicePtr
->IoPort
->MasterSlave
= (UINT16
) ((IdeDevice
== IdeMaster
) ? 1 : 0);
501 IdeBlkIoDevicePtr
->PciIo
= PciIo
;
502 IdeBlkIoDevicePtr
->IdeBusDriverPrivateData
= IdeBusDriverPrivateData
;
503 IdeBlkIoDevicePtr
->IoPort
->BusMasterBaseAddr
= IdeRegsBaseAddr
[IdeChannel
].BusMasterBaseAddr
;
506 // Report Status code: is about to detect IDE drive
508 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
510 (EFI_IO_BUS_ATA_ATAPI
| EFI_P_PC_PRESENCE_DETECT
),
511 IdeBlkIoDevicePtr
->DevicePath
515 // Discover device, now!
517 PERF_START (0, "DiscoverIdeDevice", "IDE", 0);
518 Status
= DiscoverIdeDevice (IdeBlkIoDevicePtr
);
519 PERF_END (0, "DiscoverIdeDevice", "IDE", 0);
521 IdeBusDriverPrivateData
->HaveScannedDevice
[IdeChannel
* 2 + IdeDevice
] = TRUE
;
522 IdeBusDriverPrivateData
->DeviceProcessed
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
524 if (!EFI_ERROR (Status
)) {
528 ZeroMem (&NewNode
, sizeof (NewNode
));
529 NewNode
.DevPath
.Type
= MESSAGING_DEVICE_PATH
;
530 NewNode
.DevPath
.SubType
= MSG_ATAPI_DP
;
531 SetDevicePathNodeLength (&NewNode
.DevPath
, sizeof (ATAPI_DEVICE_PATH
));
533 NewNode
.Atapi
.PrimarySecondary
= (UINT8
) IdeBlkIoDevicePtr
->Channel
;
534 NewNode
.Atapi
.SlaveMaster
= (UINT8
) IdeBlkIoDevicePtr
->Device
;
535 NewNode
.Atapi
.Lun
= IdeBlkIoDevicePtr
->Lun
;
536 IdeBlkIoDevicePtr
->DevicePath
= AppendDevicePathNode (
540 if (IdeBlkIoDevicePtr
->DevicePath
== NULL
) {
541 ReleaseIdeResources (IdeBlkIoDevicePtr
);
546 // Submit identify data to IDE controller init driver
548 CopyMem (&IdentifyData
, IdeBlkIoDevicePtr
->pIdData
, sizeof (IdentifyData
));
549 // IdentifyData = *IdeBlkIoDevicePtr->pIdData;
550 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = TRUE
;
551 IdeInit
->SubmitData (IdeInit
, IdeChannel
, IdeDevice
, &IdentifyData
);
554 // Device detection failed
556 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
557 IdeInit
->SubmitData (IdeInit
, IdeChannel
, IdeDevice
, NULL
);
558 ReleaseIdeResources (IdeBlkIoDevicePtr
);
559 IdeBlkIoDevicePtr
= NULL
;
562 // end of 1st inner loop ---
566 // end of 1st outer loop =========
571 // = 2nd outer loop == Primary/Secondary =================
573 for (IdeChannel
= BeginningIdeChannel
; IdeChannel
<= EndIdeChannel
; IdeChannel
++) {
576 // -- 2nd inner loop --- Master/Slave --------
578 for (IdeDevice
= BeginningIdeDevice
; IdeDevice
<= EndIdeDevice
; IdeDevice
++) {
580 if (IdeBusDriverPrivateData
->DeviceProcessed
[IdeChannel
* 2 + IdeDevice
]) {
584 if (!IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
]) {
588 Status
= IdeInit
->CalculateMode (
594 if (EFI_ERROR (Status
)) {
595 DEBUG ((EFI_D_ERROR
, "[bStStp20S=%x]", Status
));
599 IdeBlkIoDevicePtr
= IdeBlkIoDevice
[IdeChannel
][IdeDevice
];
602 // Set best supported PIO mode on this IDE device
604 if (SupportedModes
->PioMode
.Mode
<= ATA_PIO_MODE_2
) {
605 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_DEFAULT_PIO
;
607 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_FLOW_PIO
;
610 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->PioMode
.Mode
);
612 if (SupportedModes
->ExtModeCount
== 0){
613 Status
= SetDeviceTransferMode (IdeBlkIoDevicePtr
, &TransferMode
);
615 if (EFI_ERROR (Status
)) {
616 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
617 ReleaseIdeResources (IdeBlkIoDevicePtr
);
618 IdeBlkIoDevicePtr
= NULL
;
624 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
625 // be set together. Only one DMA mode can be set to a device. If setting
626 // DMA mode operation fails, we can continue moving on because we only use
627 // PIO mode at boot time. DMA modes are used by certain kind of OS booting
629 if (SupportedModes
->UdmaMode
.Valid
) {
631 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_UDMA
;
632 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->UdmaMode
.Mode
);
633 Status
= SetDeviceTransferMode (IdeBlkIoDevicePtr
, &TransferMode
);
635 if (EFI_ERROR (Status
)) {
636 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
637 ReleaseIdeResources (IdeBlkIoDevicePtr
);
638 IdeBlkIoDevicePtr
= NULL
;
642 EnableInterrupt (IdeBlkIoDevicePtr
);
643 } else if (SupportedModes
->MultiWordDmaMode
.Valid
) {
645 TransferMode
.ModeCategory
= ATA_MODE_CATEGORY_MDMA
;
646 TransferMode
.ModeNumber
= (UINT8
) SupportedModes
->MultiWordDmaMode
.Mode
;
647 Status
= SetDeviceTransferMode (IdeBlkIoDevicePtr
, &TransferMode
);
649 if (EFI_ERROR (Status
)) {
650 IdeBusDriverPrivateData
->DeviceFound
[IdeChannel
* 2 + IdeDevice
] = FALSE
;
651 ReleaseIdeResources (IdeBlkIoDevicePtr
);
652 IdeBlkIoDevicePtr
= NULL
;
656 EnableInterrupt (IdeBlkIoDevicePtr
);
659 // Init driver parameters
661 DriveParameters
.Sector
= (UINT8
) IdeBlkIoDevicePtr
->pIdData
->AtaData
.sectors_per_track
;
662 DriveParameters
.Heads
= (UINT8
) (IdeBlkIoDevicePtr
->pIdData
->AtaData
.heads
- 1);
663 DriveParameters
.MultipleSector
= (UINT8
) IdeBlkIoDevicePtr
->pIdData
->AtaData
.multi_sector_cmd_max_sct_cnt
;
665 // Set Parameters for the device:
667 // 2) Establish the block count for READ/WRITE MULTIPLE (EXT) command
669 if ((IdeBlkIoDevicePtr
->Type
== IdeHardDisk
) || (IdeBlkIoDevicePtr
->Type
== Ide48bitAddressingHardDisk
)) {
670 Status
= SetDriveParameters (IdeBlkIoDevicePtr
, &DriveParameters
);
674 // Record PIO mode used in private data
676 IdeBlkIoDevicePtr
->PioMode
= SupportedModes
->PioMode
.Mode
;
679 // Set IDE controller Timing Blocks in the PCI Configuration Space
681 IdeInit
->SetTiming (IdeInit
, IdeChannel
, IdeDevice
, SupportedModes
);
684 // Add Component Name for the IDE/ATAPI device that was discovered.
686 IdeBlkIoDevicePtr
->ControllerNameTable
= NULL
;
687 ADD_NAME (IdeBlkIoDevicePtr
);
689 Status
= gBS
->InstallMultipleProtocolInterfaces (
690 &IdeBlkIoDevicePtr
->Handle
,
691 &gEfiDevicePathProtocolGuid
,
692 IdeBlkIoDevicePtr
->DevicePath
,
693 &gEfiBlockIoProtocolGuid
,
694 &IdeBlkIoDevicePtr
->BlkIo
,
695 &gEfiDiskInfoProtocolGuid
,
696 &IdeBlkIoDevicePtr
->DiskInfo
,
700 if (EFI_ERROR (Status
)) {
701 ReleaseIdeResources (IdeBlkIoDevicePtr
);
706 &gEfiPciIoProtocolGuid
,
708 This
->DriverBindingHandle
,
709 IdeBlkIoDevicePtr
->Handle
,
710 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
713 IdeBusDriverPrivateData
->DeviceProcessed
[IdeChannel
* 2 + IdeDevice
] = TRUE
;
716 // Report status code: device eanbled!
718 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
720 (EFI_IO_BUS_ATA_ATAPI
| EFI_P_PC_ENABLE
),
721 IdeBlkIoDevicePtr
->DevicePath
724 // end of 2nd inner loop ----
728 // end of 2nd outer loop ==========
733 // All configurations done! Notify IdeController to do post initialization
734 // work such as saving IDE controller PCI settings for S3 resume
736 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBusPhaseMaximum
, 0);
738 if (SupportedModes
!= NULL
) {
739 gBS
->FreePool (SupportedModes
);
742 PERF_START (0, "Finish IDE detection", "IDE", 1);
743 PERF_END (0, "Finish IDE detection", "IDE", 0);
750 // Report error code: controller error
752 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
753 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
754 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_EC_CONTROLLER_ERROR
),
760 &gEfiIdeControllerInitProtocolGuid
,
761 This
->DriverBindingHandle
,
765 gBS
->UninstallMultipleProtocolInterfaces (
768 IdeBusDriverPrivateData
,
772 if (IdeBusDriverPrivateData
!= NULL
) {
773 gBS
->FreePool (IdeBusDriverPrivateData
);
776 if (SupportedModes
!= NULL
) {
777 gBS
->FreePool (SupportedModes
);
782 &gEfiPciIoProtocolGuid
,
783 This
->DriverBindingHandle
,
789 &gEfiDevicePathProtocolGuid
,
790 This
->DriverBindingHandle
,
799 // ***********************************************************************************
800 // IDEBusDriverBindingStop
801 // ***********************************************************************************
805 IDEBusDriverBindingStop (
806 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
807 IN EFI_HANDLE Controller
,
808 IN UINTN NumberOfChildren
,
809 IN EFI_HANDLE
*ChildHandleBuffer
814 Stop this driver on Controller Handle.
817 This - Protocol instance pointer.
818 DeviceHandle - Handle of device to stop driver on
819 NumberOfChildren - Not used
820 ChildHandleBuffer - Not used
823 EFI_SUCCESS - This driver is removed DeviceHandle
824 other - This driver was not removed from this device
827 // TODO: Controller - add argument and description to function comment
828 // TODO: EFI_DEVICE_ERROR - add return value to function comment
831 EFI_PCI_IO_PROTOCOL
*PciIo
;
832 BOOLEAN AllChildrenStopped
;
834 IDE_BUS_DRIVER_PRIVATE_DATA
*IdeBusDriverPrivateData
;
836 IdeBusDriverPrivateData
= NULL
;
838 if (NumberOfChildren
== 0) {
840 Status
= gBS
->OpenProtocol (
842 &gEfiPciIoProtocolGuid
,
844 This
->DriverBindingHandle
,
846 EFI_OPEN_PROTOCOL_GET_PROTOCOL
848 if (!EFI_ERROR (Status
)) {
851 EfiPciIoAttributeOperationDisable
,
852 EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO
| EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO
| EFI_PCI_DEVICE_ENABLE
,
860 (VOID
**) &IdeBusDriverPrivateData
,
861 This
->DriverBindingHandle
,
863 EFI_OPEN_PROTOCOL_GET_PROTOCOL
866 gBS
->UninstallMultipleProtocolInterfaces (
869 IdeBusDriverPrivateData
,
873 if (IdeBusDriverPrivateData
!= NULL
) {
874 gBS
->FreePool (IdeBusDriverPrivateData
);
877 // Close the bus driver
881 &gEfiIdeControllerInitProtocolGuid
,
882 This
->DriverBindingHandle
,
887 &gEfiPciIoProtocolGuid
,
888 This
->DriverBindingHandle
,
893 &gEfiDevicePathProtocolGuid
,
894 This
->DriverBindingHandle
,
901 AllChildrenStopped
= TRUE
;
903 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
905 Status
= DeRegisterIdeDevice (This
, Controller
, ChildHandleBuffer
[Index
]);
907 if (EFI_ERROR (Status
)) {
908 AllChildrenStopped
= FALSE
;
912 if (!AllChildrenStopped
) {
913 return EFI_DEVICE_ERROR
;
920 // ***********************************************************************************
921 // DeRegisterIdeDevice
922 // ***********************************************************************************
925 DeRegisterIdeDevice (
926 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
927 IN EFI_HANDLE Controller
,
934 Deregister an IDE device and free resources
938 This - Protocol instance pointer.
939 Controller - Ide device handle
940 Handle - Handle of device to deregister driver on
947 // TODO: EFI_SUCCESS - add return value to function comment
950 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
951 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
952 EFI_PCI_IO_PROTOCOL
*PciIo
;
955 Status
= gBS
->OpenProtocol (
957 &gEfiBlockIoProtocolGuid
,
959 This
->DriverBindingHandle
,
961 EFI_OPEN_PROTOCOL_GET_PROTOCOL
963 if (EFI_ERROR (Status
)) {
967 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo
);
970 // Report Status code: Device disabled
972 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
974 (EFI_IO_BUS_ATA_ATAPI
| EFI_P_PC_DISABLE
),
975 IdeBlkIoDevice
->DevicePath
979 // Close the child handle
981 Status
= gBS
->CloseProtocol (
983 &gEfiPciIoProtocolGuid
,
984 This
->DriverBindingHandle
,
988 Status
= gBS
->UninstallMultipleProtocolInterfaces (
990 &gEfiDevicePathProtocolGuid
,
991 IdeBlkIoDevice
->DevicePath
,
992 &gEfiBlockIoProtocolGuid
,
993 &IdeBlkIoDevice
->BlkIo
,
994 &gEfiDiskInfoProtocolGuid
,
995 &IdeBlkIoDevice
->DiskInfo
,
999 if (EFI_ERROR (Status
)) {
1002 &gEfiPciIoProtocolGuid
,
1004 This
->DriverBindingHandle
,
1006 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1012 // Release allocated resources
1014 Index
= IdeBlkIoDevice
->Channel
* 2 + IdeBlkIoDevice
->Device
;
1015 IdeBlkIoDevice
->IdeBusDriverPrivateData
->HaveScannedDevice
[Index
] = FALSE
;
1017 ReleaseIdeResources (IdeBlkIoDevice
);
1023 // ***********************************************************************************
1025 // ***********************************************************************************
1030 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1031 IN BOOLEAN ExtendedVerification
1035 Routine Description:
1044 // TODO: This - add argument and description to function comment
1045 // TODO: ExtendedVerification - add argument and description to function comment
1046 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1048 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1051 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (This
);
1053 // Requery IDE IO resources in case of the switch of native and legacy modes
1055 ReassignIdeResources (IdeBlkIoDevice
);
1058 // for ATA device, using ATA reset method
1060 if (IdeBlkIoDevice
->Type
== IdeHardDisk
) {
1061 return AtaSoftReset (IdeBlkIoDevice
);
1064 if (IdeBlkIoDevice
->Type
== IdeUnknown
) {
1065 return EFI_DEVICE_ERROR
;
1069 // for ATAPI device, using ATAPI reset method
1071 Status
= AtapiSoftReset (IdeBlkIoDevice
);
1072 if (ExtendedVerification
) {
1073 Status
= AtaSoftReset (IdeBlkIoDevice
);
1081 IDEBlkIoReadBlocks (
1082 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1085 IN UINTN BufferSize
,
1090 Routine Description:
1092 Read data from block io device
1096 This - Protocol instance pointer.
1097 MediaId - The media ID of the device
1098 LBA - Starting LBA address to read data
1099 BufferSize - The size of data to be read
1100 Buffer - Caller supplied buffer to save data
1107 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1109 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1111 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (This
);
1114 // Requery IDE IO resources in case of the switch of native and legacy modes
1116 ReassignIdeResources (IdeBlkIoDevice
);
1119 // For ATA compatible device, use ATA read block's mechanism
1121 if (IdeBlkIoDevice
->Type
== IdeHardDisk
||
1122 IdeBlkIoDevice
->Type
== Ide48bitAddressingHardDisk
) {
1123 return AtaBlkIoReadBlocks (
1132 if (IdeBlkIoDevice
->Type
== IdeUnknown
) {
1133 return EFI_DEVICE_ERROR
;
1137 // for ATAPI device, using ATAPI read block's mechanism
1139 return AtapiBlkIoReadBlocks (
1151 IDEBlkIoWriteBlocks (
1152 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1155 IN UINTN BufferSize
,
1160 Routine Description:
1162 Write data to block io device
1166 This - Protocol instance pointer.
1167 MediaId - The media ID of the device
1168 LBA - Starting LBA address to write data
1169 BufferSize - The size of data to be written
1170 Buffer - Caller supplied buffer to save data
1177 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1179 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1181 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_THIS (This
);
1183 // Requery IDE IO resources in case of the switch of native and legacy modes
1185 ReassignIdeResources (IdeBlkIoDevice
);
1188 // for ATA device, using ATA write block's mechanism
1190 if (IdeBlkIoDevice
->Type
== IdeHardDisk
||
1191 IdeBlkIoDevice
->Type
== Ide48bitAddressingHardDisk
) {
1193 return AtaBlkIoWriteBlocks (
1202 if (IdeBlkIoDevice
->Type
== IdeUnknown
) {
1203 return EFI_DEVICE_ERROR
;
1207 // for ATAPI device, using ATAPI write block's mechanism
1209 return AtapiBlkIoWriteBlocks (
1219 // ***********************************************************************************
1220 // IDEBlkIoFlushBlocks
1221 // ***********************************************************************************
1225 IDEBlkIoFlushBlocks (
1226 IN EFI_BLOCK_IO_PROTOCOL
*This
1230 Routine Description:
1239 // TODO: This - add argument and description to function comment
1240 // TODO: EFI_SUCCESS - add return value to function comment
1250 IDEDiskInfoInquiry (
1251 IN EFI_DISK_INFO_PROTOCOL
*This
,
1252 IN OUT VOID
*InquiryData
,
1253 IN OUT UINT32
*InquiryDataSize
1257 Routine Description:
1258 Return the results of the Inquiry command to a drive in InquiryData.
1259 Data format of Inquiry data is defined by the Interface GUID.
1262 This - Protocol instance pointer.
1263 InquiryData - Results of Inquiry command to device
1264 InquiryDataSize - Size of InquiryData in bytes.
1267 EFI_SUCCESS - InquiryData valid
1268 EFI_NOT_FOUND - Device does not support this data class
1269 EFI_DEVICE_ERROR - Error reading InquiryData from device
1270 EFI_BUFFER_TOO_SMALL - IntquiryDataSize not big enough
1274 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1276 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This
);
1278 if (*InquiryDataSize
< sizeof (INQUIRY_DATA
)) {
1279 *InquiryDataSize
= sizeof (INQUIRY_DATA
);
1280 return EFI_BUFFER_TOO_SMALL
;
1283 if (IdeBlkIoDevice
->pInquiryData
== NULL
) {
1284 return EFI_NOT_FOUND
;
1287 gBS
->CopyMem (InquiryData
, IdeBlkIoDevice
->pInquiryData
, sizeof (INQUIRY_DATA
));
1288 *InquiryDataSize
= sizeof (INQUIRY_DATA
);
1295 IDEDiskInfoIdentify (
1296 IN EFI_DISK_INFO_PROTOCOL
*This
,
1297 IN OUT VOID
*IdentifyData
,
1298 IN OUT UINT32
*IdentifyDataSize
1302 Routine Description:
1303 Return the results of the Identify command to a drive in IdentifyData.
1304 Data format of Identify data is defined by the Interface GUID.
1307 This - Protocol instance pointer.
1308 IdentifyData - Results of Identify command to device
1309 IdentifyDataSize - Size of IdentifyData in bytes.
1312 EFI_SUCCESS - IdentifyData valid
1313 EFI_NOT_FOUND - Device does not support this data class
1314 EFI_DEVICE_ERROR - Error reading IdentifyData from device
1315 EFI_BUFFER_TOO_SMALL - IdentifyDataSize not big enough
1319 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1321 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This
);
1323 if (*IdentifyDataSize
< sizeof (EFI_IDENTIFY_DATA
)) {
1324 *IdentifyDataSize
= sizeof (EFI_IDENTIFY_DATA
);
1325 return EFI_BUFFER_TOO_SMALL
;
1328 if (IdeBlkIoDevice
->pIdData
== NULL
) {
1329 return EFI_NOT_FOUND
;
1332 gBS
->CopyMem (IdentifyData
, IdeBlkIoDevice
->pIdData
, sizeof (EFI_IDENTIFY_DATA
));
1333 *IdentifyDataSize
= sizeof (EFI_IDENTIFY_DATA
);
1340 IDEDiskInfoSenseData (
1341 IN EFI_DISK_INFO_PROTOCOL
*This
,
1342 IN OUT VOID
*SenseData
,
1343 IN OUT UINT32
*SenseDataSize
,
1344 OUT UINT8
*SenseDataNumber
1348 Routine Description:
1349 Return the results of the Request Sense command to a drive in SenseData.
1350 Data format of Sense data is defined by the Interface GUID.
1353 This - Protocol instance pointer.
1354 SenseData - Results of Request Sense command to device
1355 SenseDataSize - Size of SenseData in bytes.
1356 SenseDataNumber - Type of SenseData
1359 EFI_SUCCESS - InquiryData valid
1360 EFI_NOT_FOUND - Device does not support this data class
1361 EFI_DEVICE_ERROR - Error reading InquiryData from device
1362 EFI_BUFFER_TOO_SMALL - SenseDataSize not big enough
1366 return EFI_NOT_FOUND
;
1371 IDEDiskInfoWhichIde (
1372 IN EFI_DISK_INFO_PROTOCOL
*This
,
1373 OUT UINT32
*IdeChannel
,
1374 OUT UINT32
*IdeDevice
1378 Routine Description:
1379 Return the results of the Request Sense command to a drive in SenseData.
1380 Data format of Sense data is defined by the Interface GUID.
1383 This - Protocol instance pointer.
1384 IdeChannel - Primary or Secondary
1385 IdeDevice - Master or Slave
1388 EFI_SUCCESS - IdeChannel and IdeDevice are valid
1389 EFI_UNSUPPORTED - This is not an IDE device
1393 IDE_BLK_IO_DEV
*IdeBlkIoDevice
;
1395 IdeBlkIoDevice
= IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This
);
1396 *IdeChannel
= IdeBlkIoDevice
->Channel
;
1397 *IdeDevice
= IdeBlkIoDevice
->Device
;