idebus.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,475 行 · 第 1/3 页
C
1,475 行
//
// The device has been scanned in another Start(), No need to scan it again
// for perf optimization.
//
if (IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice]) {
continue;
}
//
// create child handle for the detected device.
//
IdeBlkIoDevice[IdeChannel][IdeDevice] = EfiLibAllocatePool (sizeof (IDE_BLK_IO_DEV));
if (IdeBlkIoDevice[IdeChannel][IdeDevice] == NULL) {
continue;
}
IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice];
EfiZeroMem (IdeBlkIoDevicePtr, sizeof (IDE_BLK_IO_DEV));
IdeBlkIoDevicePtr->Signature = IDE_BLK_IO_DEV_SIGNATURE;
IdeBlkIoDevicePtr->Channel = IdeChannel;
IdeBlkIoDevicePtr->Device = IdeDevice;
//
// initialize Block IO interface's Media pointer
//
IdeBlkIoDevicePtr->BlkIo.Media = &IdeBlkIoDevicePtr->BlkMedia;
//
// Initialize IDE IO port addresses, including Command Block registers
// and Control Block registers
//
IdeBlkIoDevicePtr->IoPort = EfiLibAllocatePool (sizeof (IDE_BASE_REGISTERS));
if (IdeBlkIoDevicePtr->IoPort == NULL) {
continue;
}
EfiZeroMem (IdeBlkIoDevicePtr->IoPort, sizeof (IDE_BASE_REGISTERS));
CommandBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].CommandBlockBaseAddr;
ControlBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].ControlBlockBaseAddr;
IdeBlkIoDevicePtr->IoPort->Data = CommandBlockBaseAddr;
(*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01);
IdeBlkIoDevicePtr->IoPort->SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02);
IdeBlkIoDevicePtr->IoPort->SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03);
IdeBlkIoDevicePtr->IoPort->CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04);
IdeBlkIoDevicePtr->IoPort->CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05);
IdeBlkIoDevicePtr->IoPort->Head = (UINT16) (CommandBlockBaseAddr + 0x06);
(*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg) = (UINT16) (CommandBlockBaseAddr + 0x07);
(*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Alt) = ControlBlockBaseAddr;
IdeBlkIoDevicePtr->IoPort->DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x01);
IdeBlkIoDevicePtr->IoPort->MasterSlave = (UINT16) ((IdeDevice == IdeMaster) ? 1 : 0);
IdeBlkIoDevicePtr->PciIo = PciIo;
IdeBlkIoDevicePtr->IdeBusDriverPrivateData = IdeBusDriverPrivateData;
IdeBlkIoDevicePtr->IoPort->BusMasterBaseAddr = IdeRegsBaseAddr[IdeChannel].BusMasterBaseAddr;
//
// Report Status code: is about to detect IDE drive
//
EfiLibReportStatusCode (
EFI_PROGRESS_CODE,
(EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_PRESENCE_DETECT),
0,
&gIDEBusDriverGuid,
NULL
);
//
// Discover device, now!
//
PERF_START (0, L"DiscoverIdeDevice", L"IDE", 0);
Status = DiscoverIdeDevice (IdeBlkIoDevicePtr);
PERF_END (0, L"DiscoverIdeDevice", L"IDE", 0);
IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice] = TRUE;
IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice] = FALSE;
if (!EFI_ERROR (Status)) {
//
// Set Device Path
//
EfiZeroMem (&NewNode, sizeof (NewNode));
NewNode.DevPath.Type = MESSAGING_DEVICE_PATH;
NewNode.DevPath.SubType = MSG_ATAPI_DP;
SetDevicePathNodeLength (&NewNode.DevPath, sizeof (ATAPI_DEVICE_PATH));
NewNode.Atapi.PrimarySecondary = (UINT8) IdeBlkIoDevicePtr->Channel;
NewNode.Atapi.SlaveMaster = (UINT8) IdeBlkIoDevicePtr->Device;
NewNode.Atapi.Lun = IdeBlkIoDevicePtr->Lun;
IdeBlkIoDevicePtr->DevicePath = EfiAppendDevicePathNode (
ParentDevicePath,
&NewNode.DevPath
);
if (IdeBlkIoDevicePtr->DevicePath == NULL) {
ReleaseIdeResources (IdeBlkIoDevicePtr);
continue;
}
//
// Submit identify data to IDE controller init driver
//
IdentifyData = *IdeBlkIoDevicePtr->pIdData;
IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = TRUE;
IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, &IdentifyData);
} else {
//
// Device detection failed
//
IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, NULL);
ReleaseIdeResources (IdeBlkIoDevicePtr);
IdeBlkIoDevicePtr = NULL;
}
//
// end of 1st inner loop ---
//
}
//
// end of 1st outer loop =========
//
}
//
// = 2nd outer loop == Primary/Secondary =================
//
for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) {
//
// -- 2nd inner loop --- Master/Slave --------
//
for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) {
if (IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice]) {
continue;
}
if (!IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice]) {
continue;
}
Status = IdeInit->CalculateMode (
IdeInit,
IdeChannel,
IdeDevice,
&SupportedModes
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "[bStStp20S=%x]", Status));
continue;
}
IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice];
//
// Set best supported PIO mode on this IDE device
//
if (SupportedModes->PioMode.Mode <= ATA_PIO_MODE_2) {
TransferMode.ModeCategory = ATA_MODE_CATEGORY_DEFAULT_PIO;
} else {
TransferMode.ModeCategory = ATA_MODE_CATEGORY_FLOW_PIO;
}
TransferMode.ModeNumber = (UINT8) (SupportedModes->PioMode.Mode);
if (SupportedModes->ExtModeCount == 0){
Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);
if (EFI_ERROR (Status)) {
IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
ReleaseIdeResources (IdeBlkIoDevicePtr);
IdeBlkIoDevicePtr = NULL;
continue;
}
}
//
// Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
// be set together. Only one DMA mode can be set to a device. If setting
// DMA mode operation fails, we can continue moving on because we only use
// PIO mode at boot time. DMA modes are used by certain kind of OS booting
//
if (SupportedModes->UdmaMode.Valid) {
TransferMode.ModeCategory = ATA_MODE_CATEGORY_UDMA;
TransferMode.ModeNumber = (UINT8) (SupportedModes->UdmaMode.Mode);
Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);
if (EFI_ERROR (Status)) {
IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
ReleaseIdeResources (IdeBlkIoDevicePtr);
IdeBlkIoDevicePtr = NULL;
continue;
}
//
// Record Udma Mode
//
IdeBlkIoDevicePtr->UdmaMode.Valid = TRUE;
IdeBlkIoDevicePtr->UdmaMode.Mode = SupportedModes->UdmaMode.Mode;
EnableInterrupt (IdeBlkIoDevicePtr);
} else if (SupportedModes->MultiWordDmaMode.Valid) {
TransferMode.ModeCategory = ATA_MODE_CATEGORY_MDMA;
TransferMode.ModeNumber = (UINT8) SupportedModes->MultiWordDmaMode.Mode;
Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);
if (EFI_ERROR (Status)) {
IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
ReleaseIdeResources (IdeBlkIoDevicePtr);
IdeBlkIoDevicePtr = NULL;
continue;
}
EnableInterrupt (IdeBlkIoDevicePtr);
}
//
// Init driver parameters
//
DriveParameters.Sector = (UINT8) IdeBlkIoDevicePtr->pIdData->AtaData.sectors_per_track;
DriveParameters.Heads = (UINT8) (IdeBlkIoDevicePtr->pIdData->AtaData.heads - 1);
DriveParameters.MultipleSector = (UINT8) IdeBlkIoDevicePtr->pIdData->AtaData.multi_sector_cmd_max_sct_cnt;
//
// Set Parameters for the device:
// 1) Init
// 2) Establish the block count for READ/WRITE MULTIPLE (EXT) command
//
if ((IdeBlkIoDevicePtr->Type == IdeHardDisk) || (IdeBlkIoDevicePtr->Type == Ide48bitAddressingHardDisk)) {
Status = SetDriveParameters (IdeBlkIoDevicePtr, &DriveParameters);
}
//
// Record PIO mode used in private data
//
IdeBlkIoDevicePtr->PioMode = SupportedModes->PioMode.Mode;
//
// Set IDE controller Timing Blocks in the PCI Configuration Space
//
IdeInit->SetTiming (IdeInit, IdeChannel, IdeDevice, SupportedModes);
//
// Add Component Name for the IDE/ATAPI device that was discovered.
//
IdeBlkIoDevicePtr->ControllerNameTable = NULL;
ADD_NAME (IdeBlkIoDevicePtr);
Status = gBS->InstallMultipleProtocolInterfaces (
&IdeBlkIoDevicePtr->Handle,
&gEfiDevicePathProtocolGuid,
IdeBlkIoDevicePtr->DevicePath,
&gEfiBlockIoProtocolGuid,
&IdeBlkIoDevicePtr->BlkIo,
&gEfiDiskInfoProtocolGuid,
&IdeBlkIoDevicePtr->DiskInfo,
NULL
);
if (EFI_ERROR (Status)) {
ReleaseIdeResources (IdeBlkIoDevicePtr);
}
gBS->OpenProtocol (
Controller,
&gEfiPciIoProtocolGuid,
(VOID **) &PciIo,
This->DriverBindingHandle,
IdeBlkIoDevicePtr->Handle,
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
);
IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice] = TRUE;
//
// Report status code: device eanbled!
//
ReportStatusCodeWithDevicePath (
EFI_PROGRESS_CODE,
(EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_ENABLE),
0,
&gIDEBusDriverGuid,
IdeBlkIoDevicePtr->DevicePath
);
//
// Create event to clear pending IDE interrupt
//
Status = gBS->CreateEvent (
EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES,
EFI_TPL_NOTIFY,
ClearInterrupt,
IdeBlkIoDevicePtr,
&IdeBlkIoDevicePtr->ExitBootServiceEvent
);
//
// end of 2nd inner loop ----
//
}
//
// end of 2nd outer loop ==========
//
}
//
// All configurations done! Notify IdeController to do post initialization
// work such as saving IDE controller PCI settings for S3 resume
//
IdeInit->NotifyPhase (IdeInit, EfiIdeBusPhaseMaximum, 0);
if (SupportedModes != NULL) {
gBS->FreePool (SupportedModes);
}
PERF_START (0, L"Finish IDE detection", L"IDE", 1);
PERF_END (0, L"Finish IDE detection", L"IDE", 0);
return EFI_SUCCESS;
ErrorExit:
//
// Report error code: controller error
//
ReportStatusCodeWithDevicePath (
EFI_ERROR_CODE | EFI_ERROR_MINOR,
(EFI_IO_BUS_ATA_ATAPI | EFI_IOB_EC_CONTROLLER_ERROR),
0,
&gIDEBusDriverGuid,
ParentDevicePath
);
gBS->CloseProtocol (
Controller,
&gEfiIdeControllerInitProtocolGuid,
This->DriverBindingHandle,
Controller
);
gBS->UninstallMultipleProtocolInterfaces (
Controller,
&gIDEBusDriverGuid,
IdeBusDriverPrivateData,
NULL
);
if (IdeBusDriverPrivateData != NULL) {
gBS->FreePool (IdeBusDriverPrivateData);
}
if (SupportedModes != NULL) {
gBS->FreePool (SupportedModes);
}
gBS->CloseProtocol (
Controller,
&gEfiPciIoProtocolGuid,
This->DriverBindingHandle,
Controller
);
gBS->CloseProtocol (
Controller,
&gEfiDevicePathProtocolGuid,
This->DriverBindingHandle,
Controller
);
return Status;
}
//
// ***********************************************************************************
// IDEBusDriverBindingStop
// ***********************************************************************************
//
EFI_STATUS
EFIAPI
IDEBusDriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
)
/*++
Routine Description:
Stop this driver on Controller Handle.
Arguments:
This - Protocol instance pointer.
DeviceHandle - Handle of device to stop driver on
NumberOfChildren - Not used
ChildHandleBuffer - Not used
Returns:
EFI_SUCCESS - This driver is removed DeviceHandle
other - This driver was not removed from this device
--*/
// TODO: Controller - add argument and description to function comment
// TODO: EFI_DEVICE_ERROR - add return value to function comment
{
EFI_STATUS Status;
EFI_PCI_IO_PROTOCOL *PciIo;
BOOLEAN AllChildrenStopped;
UINTN Index;
IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData;
IdeBusDriverPrivateData = NULL;
if (NumberOfChildren == 0) {
Status = gBS->OpenProtocol (
Controller,
&gEfiPciIoProtocolGuid,
(VOID **) &PciIo,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (!EFI_ERROR (Status)) {
PciIo->Attributes (
PciIo,
EfiPciIoAttributeOperationDisable,
EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE,
NULL
);
}
gBS->OpenProtocol (
Controller,
&gIDEBusDriverGuid,
(VOID **) &IdeBusDriverPrivateData,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
gBS->UninstallMultipleProtocolInterfaces (
Controller,
&gIDEBusDriverGuid,
IdeBusDriverPrivateData,
NULL
);
if (IdeBusDriverPrivateData != NULL) {
gBS->FreePool (IdeBusDriverPrivateData);
}
//
// Close the bus driver
//
gBS->CloseProtocol (
Controller,
&gEfiIdeControllerInitProtocolGuid,
This->DriverBindingHandle,
Controller
);
gBS->CloseProtocol (
Controller,
&gEfiPciIoProtocolGuid,
This->DriverBindingHandle,
Controller
);
gBS->CloseProtocol (
Controller,
&gEfiDevicePathProtocolGuid,
This->DriverBindingHandle,
Controller
);
return EFI_SUCCESS;
}
AllChildrenStopped = TRUE;
for (Index = 0; Index < NumberOfChildren; Index++) {
Status = DeRegisterIdeDevice (This, Controller, ChildHandleBuffer[Index]);
if (EFI_ERROR (Status)) {
AllChildrenStopped = FALSE;
}
}
if (!AllChildrenStopped) {
return EFI_DEVICE_ERROR;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?