cbi0.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,088 行 · 第 1/2 页
C
1,088 行
This->DriverBindingHandle,
ControllerHandle
);
//
// Free all allocated resources
//
if (UsbCbiDev->ControllerNameTable) {
EfiLibFreeUnicodeStringTable (UsbCbiDev->ControllerNameTable);
}
gBS->FreePool (UsbCbiDev);
return Status;
}
STATIC
EFI_STATUS
Cbi0RecoveryReset (
IN USB_CBI_DEVICE *UsbCbiDev
)
/*++
Routine Description:
Cbi0 Recovery Reset routine
Arguments:
UsbCbiDev - Cbi0RecoveryReset
Returns:
EFI_SUCCESS - Success
--*/
{
UINT8 ResetCommand[12];
UINT8 Index;
EFI_STATUS Status;
EFI_USB_IO_PROTOCOL *UsbIo;
UINT8 EndpointAddress;
UINT32 Result;
UINT16 Timeout;
UsbIo = UsbCbiDev->UsbIo;
Cbi0ReportStatusCode (
UsbCbiDev->DevicePath,
EFI_PROGRESS_CODE,
(EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_RESET)
);
//
// CBI reset command protocol
//
ResetCommand[0] = 0x1d;
ResetCommand[1] = 0x04;
for (Index = 2; Index < 12; Index++) {
ResetCommand[Index] = 0xff;
}
//
// (in millisecond unit)
//
Timeout = STALL_1_SECOND;
Status = Cbi0AtapiCommand (
&UsbCbiDev->UsbAtapiProtocol,
ResetCommand,
12,
NULL,
0,
EfiUsbNoData,
Timeout
);
if (EFI_ERROR (Status)) {
return Status;
}
gBS->Stall (100 * 1000);
//
// clear bulk in endpoint stall feature
//
EndpointAddress = UsbCbiDev->BulkInEndpointDescriptor.EndpointAddress;
Status = UsbClearEndpointHalt (
UsbIo,
EndpointAddress,
&Result
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// clear bulk out endpoint stall feature
//
EndpointAddress = UsbCbiDev->BulkOutEndpointDescriptor.EndpointAddress;
Status = UsbClearEndpointHalt (
UsbIo,
EndpointAddress,
&Result
);
//
// according to CBI spec, no need to clear interrupt endpoint feature.
//
return Status;
}
STATIC
EFI_STATUS
Cbi0CommandPhase (
IN USB_CBI_DEVICE *UsbCbiDev,
IN VOID *Command,
IN UINT8 CommandSize,
IN UINT16 Timeout
)
/*++
Routine Description:
Send ATAPI command through CBI0 interface.
Arguments:
UsbCbiDev - USB_CBI_DEVICE
Command - Command to send
CommandSize - Command size
Timeout - Time out value in milliseconds
Returns:
EFI_SUCCESS - Success
EFI_DEVICE_ERROR - Fail
Others
--*/
{
EFI_STATUS Status;
UINT32 Result;
EFI_USB_IO_PROTOCOL *UsbIo;
EFI_USB_DEVICE_REQUEST Request;
UsbIo = UsbCbiDev->UsbIo;
EfiZeroMem (&Request, sizeof (EFI_USB_DEVICE_REQUEST));
//
// Device request see CBI specification
//
Request.RequestType = 0x21;
Request.Request = 0x00;
Request.Value = 0;
Request.Index = 0;
Request.Length = CommandSize;
Status = UsbIo->UsbControlTransfer (
UsbIo,
&Request,
EfiUsbDataOut,
Timeout,
Command,
CommandSize,
&Result
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
Cbi0DataPhase (
IN USB_CBI_DEVICE *UsbCbiDev,
IN UINT32 *DataSize,
IN OUT VOID *DataBuffer,
IN EFI_USB_DATA_DIRECTION Direction,
IN UINT16 Timeout
)
/*++
Routine Description:
Get/Send Data through CBI0 interface
Arguments:
UsbCbiDev - USB_CBI_DEVICE
DataSize - Data size
DataBuffer - Data buffer
Direction - IN/OUT/NODATA
Timeout - Time out value in milliseconds
Returns:
EFI_SUCCESS
Others
--*/
{
EFI_STATUS Status;
EFI_USB_IO_PROTOCOL *UsbIo;
UINT8 EndpointAddress;
UINTN Remain;
UINTN Increment;
UINT32 MaxPacketLength;
UINT8 *BufferPtr;
UINT32 Result;
UINTN TransferredSize;
UsbIo = UsbCbiDev->UsbIo;
Remain = *DataSize;
BufferPtr = (UINT8 *) DataBuffer;
TransferredSize = 0;
//
// retrieve the the max packet length of the given endpoint
//
if (Direction == EfiUsbDataIn) {
MaxPacketLength = UsbCbiDev->BulkInEndpointDescriptor.MaxPacketSize;
EndpointAddress = UsbCbiDev->BulkInEndpointDescriptor.EndpointAddress;
} else {
MaxPacketLength = UsbCbiDev->BulkOutEndpointDescriptor.MaxPacketSize;
EndpointAddress = UsbCbiDev->BulkOutEndpointDescriptor.EndpointAddress;
}
while (Remain > 0) {
if (Remain > 16 * MaxPacketLength) {
Increment = 16 * MaxPacketLength;
} else {
Increment = Remain;
}
Status = UsbIo->UsbBulkTransfer (
UsbIo,
EndpointAddress,
BufferPtr,
&Increment,
Timeout,
&Result
);
TransferredSize += Increment;
if (EFI_ERROR (Status)) {
goto ErrorExit;
}
BufferPtr += Increment;
Remain -= Increment;
}
return EFI_SUCCESS;
ErrorExit:
if (Direction == EfiUsbDataIn) {
Cbi0ReportStatusCode (
UsbCbiDev->DevicePath,
EFI_ERROR_CODE | EFI_ERROR_MINOR,
(EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_INPUT_ERROR)
);
} else {
Cbi0ReportStatusCode (
UsbCbiDev->DevicePath,
EFI_ERROR_CODE | EFI_ERROR_MINOR,
(EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_OUTPUT_ERROR)
);
}
if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
Status = Cbi0RecoveryReset (UsbCbiDev);
}
*DataSize = (UINT32) TransferredSize;
return Status;
}
STATIC
EFI_STATUS
Cbi0StatusPhase (
IN USB_CBI_DEVICE *UsbCbiDev,
OUT INTERRUPT_DATA_BLOCK *InterruptDataBlock,
IN UINT16 Timeout
)
/*++
Routine Description:
Get transfer status through BOT interface
Arguments:
UsbCbiDev - USB_CBI_DEVICE
InterruptDataBlock - Interrupt Data Block for interrupt transfer
Timeout - Time out value in milliseconds
Returns:
EFI_SUCCESS
Others
--*/
{
UINT8 EndpointAddress;
UINTN InterruptDataBlockLength;
UINT32 Result;
EFI_STATUS Status;
EfiZeroMem (InterruptDataBlock, sizeof (INTERRUPT_DATA_BLOCK));
EndpointAddress = UsbCbiDev->InterruptEndpointDescriptor.EndpointAddress;
InterruptDataBlockLength = sizeof (INTERRUPT_DATA_BLOCK);
Status = UsbCbiDev->UsbIo->UsbSyncInterruptTransfer (
UsbCbiDev->UsbIo,
EndpointAddress,
InterruptDataBlock,
&InterruptDataBlockLength,
Timeout,
&Result
);
if (EFI_ERROR (Status)) {
if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
//
// just endpoint stall happens
//
UsbClearEndpointHalt (
UsbCbiDev->UsbIo,
EndpointAddress,
&Result
);
gBS->Stall (100 * 1000);
}
return Status;
}
return EFI_SUCCESS;
}
//
// Cbi0 Atapi Protocol Implementation
//
STATIC
EFI_STATUS
EFIAPI
Cbi0MassStorageReset (
IN EFI_USB_ATAPI_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
)
/*++
Routine Description:
Reset CBI Devices
Arguments:
This - Protocol instance pointer.
ExtendedVerification - TRUE if we need to do strictly reset.
Returns:
EFI_SUCCESS - Command succeeded.
EFI_DEVICE_ERROR - Command failed.
--*/
{
EFI_STATUS Status;
EFI_USB_IO_PROTOCOL *UsbIo;
USB_CBI_DEVICE *UsbCbiDev;
UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (This);
UsbIo = UsbCbiDev->UsbIo;
if (ExtendedVerification) {
//
// UsbIo->UsbPortReset (UsbIo);
//
}
Status = Cbi0RecoveryReset (UsbCbiDev);
return Status;
}
STATIC
EFI_STATUS
EFIAPI
Cbi0AtapiCommand (
IN EFI_USB_ATAPI_PROTOCOL *This,
IN VOID *Command,
IN UINT8 CommandSize,
IN VOID *DataBuffer,
IN UINT32 BufferLength,
IN EFI_USB_DATA_DIRECTION Direction,
IN UINT16 TimeOutInMilliSeconds
)
/*++
Routine Description:
Send ATAPI command using BOT protocol.
Arguments:
This - Protocol instance pointer.
Command - Command buffer
CommandSize - Size of Command Buffer
DataBuffer - Data buffer
BufferLength - Length of Data buffer
Direction - Data direction of this command
TimeOutInMilliSeconds - Timeout value in ms
Returns:
EFI_SUCCESS - Command succeeded.
EFI_DEVICE_ERROR - Command failed.
EFI_INVALID_PARAMETER - Invalidate parameter
--*/
{
EFI_STATUS Status;
USB_CBI_DEVICE *UsbCbiDev;
UINT32 BufferSize;
INTERRUPT_DATA_BLOCK InterruptDataBlock;
EFI_STATUS DataPhaseStatus;
if (Direction != EfiUsbNoData) {
if (DataBuffer == NULL || BufferLength == 0) {
return EFI_INVALID_PARAMETER;
}
}
DataPhaseStatus = EFI_SUCCESS;
//
// Get the context
//
UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (This);
//
// First send ATAPI command through Cbi
//
Status = Cbi0CommandPhase (
UsbCbiDev,
Command,
CommandSize,
TimeOutInMilliSeconds
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
//
// Send/Get Data if there is a Data Stage
//
switch (Direction) {
case EfiUsbDataIn:
case EfiUsbDataOut:
BufferSize = BufferLength;
DataPhaseStatus = Cbi0DataPhase (
UsbCbiDev,
&BufferSize,
DataBuffer,
Direction,
TimeOutInMilliSeconds
);
break;
case EfiUsbNoData:
break;
}
if (EFI_ERROR (DataPhaseStatus)) {
return EFI_DEVICE_ERROR;
}
//
// Status Phase
//
Status = Cbi0StatusPhase (
UsbCbiDev,
&InterruptDataBlock,
TimeOutInMilliSeconds
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
if (This->CommandProtocol != EFI_USB_SUBCLASS_UFI) {
if (InterruptDataBlock.bType == 0) {
//
// indicates command completion
//
switch (InterruptDataBlock.bValue & 0x03) {
case 0:
Status = EFI_SUCCESS;
break;
case 1:
Status = EFI_DEVICE_ERROR;
break;
case 2:
Status = Cbi0RecoveryReset (UsbCbiDev);
if (EFI_ERROR (Status)) {
UsbCbiDev->UsbIo->UsbPortReset (UsbCbiDev->UsbIo);
}
Status = EFI_DEVICE_ERROR;
break;
case 3:
Status = EFI_DEVICE_ERROR;
}
} else {
Status = DataPhaseStatus;
}
} else {
//
// UFI device, InterruptDataBlock.bType: ASC (Additional Sense Code)
// InterruptDataBlock.bValue: ASCQ (Additional Snese Code Qualifier)
//
Status = DataPhaseStatus;
}
return Status;
}
VOID
Cbi0ReportStatusCode (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
IN EFI_STATUS_CODE_TYPE CodeType,
IN EFI_STATUS_CODE_VALUE Value
)
/*++
Routine Description:
Report Status Code in Usb Cbi0 Driver
Arguments:
DevicePath - Use this to get Device Path
CodeType - Status Code Type
CodeValue - Status Code Value
Returns:
None
--*/
{
ReportStatusCodeWithDevicePath (
CodeType,
Value,
0,
&gEfiUsbCbi0DriverGuid,
DevicePath
);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?