isafloppyctrl.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,560 行 · 第 1/3 页
C
1,560 行
if (Times == 0) {
return EFI_TIMEOUT;
}
//
// Read result bytes from FDC
//
CommandPointer = (UINT8 *) (&Result);
for (Index = 0; Index < sizeof (FDD_RESULT_PACKET); Index++) {
if (EFI_ERROR (DataInByte (FdcDev, CommandPointer++))) {
return EFI_DEVICE_ERROR;
}
}
//
// Flush before Unmap
//
if (Read == READ) {
Status1 = IsaIo->Flush (IsaIo);
if (EFI_ERROR (Status1)) {
return Status1;
}
}
//
// Unmap Dma
//
Status1 = IsaIo->Unmap (IsaIo, Mapping);
if (EFI_ERROR (Status1)) {
return Status1;
}
return CheckResult (Result, FdcDev);
}
VOID
FillPara (
IN FDC_BLK_IO_DEV *FdcDev,
IN EFI_LBA Lba,
IN FDD_COMMAND_PACKET1 *Command
)
/*++
Routine Description: Fill in Parameter
Parameters:
Returns:
--*/
// GC_TODO: function comment is missing 'Arguments:'
// GC_TODO: FdcDev - add argument and description to function comment
// GC_TODO: Lba - add argument and description to function comment
// GC_TODO: Command - add argument and description to function comment
{
UINT8 EndOfTrack;
//
// Get EndOfTrack from the Para table
//
EndOfTrack = DISK_1440K_EOT;
//
// Fill the command parameter
//
if (FdcDev->Disk == FDC_DISK0) {
Command->DiskHeadSel = 0;
} else {
Command->DiskHeadSel = 1;
}
Command->Cylinder = (UINT8) ((UINTN) Lba / EndOfTrack / 2);
Command->Head = (UINT8) ((UINTN) Lba / EndOfTrack % 2);
Command->Sector = (UINT8) ((UINT8) ((UINTN) Lba % EndOfTrack) + 1);
Command->DiskHeadSel |= Command->Head << 2;
Command->Number = DISK_1440K_NUMBER;
Command->EndOfTrack = DISK_1440K_EOT;
Command->GapLength = DISK_1440K_GPL;
Command->DataLength = DISK_1440K_DTL;
}
EFI_STATUS
DataInByte (
IN FDC_BLK_IO_DEV *FdcDev,
IN OUT UINT8 *Pointer
)
/*++
Routine Description: Read result byte from Data Register of FDC
Parameters:
Pointer UINT8 *: Be used to save result byte read from FDC
Returns:
EFI_SUCCESS: Read result byte from FDC successfully
EFI_DEVICE_ERROR: The FDC is not ready to be read
--*/
// GC_TODO: function comment is missing 'Arguments:'
// GC_TODO: FdcDev - add argument and description to function comment
// GC_TODO: Pointer - add argument and description to function comment
{
UINT8 data;
//
// wait for 1ms and detect the FDC is ready to be read
//
if (EFI_ERROR (FddDRQReady (FdcDev, DATA_IN, 1))) {
return EFI_DEVICE_ERROR;
//
// is not ready
//
}
data = FdcReadPort (FdcDev, FDC_REGISTER_DTR);
//
// Io delay
//
gBS->Stall (50);
*Pointer = data;
return EFI_SUCCESS;
}
EFI_STATUS
DataOutByte (
IN FDC_BLK_IO_DEV *FdcDev,
IN UINT8 *Pointer
)
/*++
Routine Description: Write command byte to Data Register of FDC
Parameters:
Pointer UINT8 *: Be used to save command byte written to FDC
Returns:
EFI_SUCCESS: Write command byte to FDC successfully
EFI_DEVICE_ERROR: The FDC is not ready to be written
--*/
// GC_TODO: function comment is missing 'Arguments:'
// GC_TODO: FdcDev - add argument and description to function comment
// GC_TODO: Pointer - add argument and description to function comment
{
UINT8 data;
//
// wait for 1ms and detect the FDC is ready to be written
//
if (EFI_ERROR (FddDRQReady (FdcDev, DATA_OUT, 1))) {
return EFI_DEVICE_ERROR;
//
// is not ready
//
}
data = *Pointer;
FdcWritePort (FdcDev, FDC_REGISTER_DTR, data);
//
// Io delay
//
gBS->Stall (50);
return EFI_SUCCESS;
}
EFI_STATUS
FddWaitForBSYClear (
IN FDC_BLK_IO_DEV *FdcDev,
IN UINTN TimeoutInSeconds
)
/*++
Routine Description: Detect the specified floppy logic drive is busy or
not within a period of time
Parameters:
Disk EFI_FDC_DISK: Indicate it is drive A or drive B
TimeoutInSeconds UINTN: the time period for waiting
Returns:
EFI_SUCCESS: The drive and command are not busy
EFI_TIMEOUT: The drive or command is still busy after a period time that
set by TimeoutInSeconds
--*/
// GC_TODO: function comment is missing 'Arguments:'
// GC_TODO: FdcDev - add argument and description to function comment
// GC_TODO: TimeoutInSeconds - add argument and description to function comment
{
UINTN Delay;
UINT8 StatusRegister;
UINT8 Mask;
//
// How to determine drive and command are busy or not: by the bits of
// Main Status Register
// bit0: Drive 0 busy (drive A)
// bit1: Drive 1 busy (drive B)
// bit4: Command busy
//
//
// set mask: for drive A set bit0 & bit4; for drive B set bit1 & bit4
//
Mask = (UINT8) ((FdcDev->Disk == FDC_DISK0 ? MSR_DAB : MSR_DBB) | MSR_CB);
Delay = ((TimeoutInSeconds * STALL_1_MSECOND) / 50) + 1;
do {
StatusRegister = FdcReadPort (FdcDev, FDC_REGISTER_MSR);
if ((StatusRegister & Mask) == 0x00) {
break;
//
// not busy
//
}
gBS->Stall (50);
Delay = Delay - 1;
} while (Delay);
if (Delay == 0) {
return EFI_TIMEOUT;
}
return EFI_SUCCESS;
}
EFI_STATUS
FddDRQReady (
IN FDC_BLK_IO_DEV *FdcDev,
IN BOOLEAN Dio,
IN UINTN TimeoutInSeconds
)
/*++
Routine Description: Determine whether FDC is ready to write or read
Parameters:
Dio BOOLEAN: Indicate the FDC is waiting to write or read
TimeoutInSeconds UINTN: The time period for waiting
Returns:
EFI_SUCCESS: FDC is ready to write or read
EFI_NOT_READY: FDC is not ready within the specified time period
--*/
// GC_TODO: function comment is missing 'Arguments:'
// GC_TODO: FdcDev - add argument and description to function comment
// GC_TODO: Dio - add argument and description to function comment
// GC_TODO: TimeoutInSeconds - add argument and description to function comment
{
UINTN Delay;
UINT8 StatusRegister;
UINT8 DataInOut;
//
// Before writing to FDC or reading from FDC, the Host must examine
// the bit7(RQM) and bit6(DIO) of the Main Status Register.
// That is to say:
// command bytes can not be written to Data Register
// unless RQM is 1 and DIO is 0
// result bytes can not be read from Data Register
// unless RQM is 1 and DIO is 1
//
DataInOut = (UINT8) (Dio << 6);
//
// in order to compare bit6
//
Delay = ((TimeoutInSeconds * STALL_1_MSECOND) / 50) + 1;
do {
StatusRegister = FdcReadPort (FdcDev, FDC_REGISTER_MSR);
if ((StatusRegister & MSR_RQM) == MSR_RQM && (StatusRegister & MSR_DIO) == DataInOut) {
break;
//
// FDC is ready
//
}
gBS->Stall (50);
//
// Stall for 50 us
//
Delay = Delay - 1;
} while (Delay);
if (Delay == 0) {
return EFI_NOT_READY;
//
// FDC is not ready within the specified time period
//
}
return EFI_SUCCESS;
}
EFI_STATUS
CheckResult (
IN FDD_RESULT_PACKET Result,
IN OUT FDC_BLK_IO_DEV *FdcDev
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
Result - GC_TODO: add argument description
FdcDev - GC_TODO: add argument description
Returns:
EFI_DEVICE_ERROR - GC_TODO: Add description for return value
EFI_DEVICE_ERROR - GC_TODO: Add description for return value
EFI_DEVICE_ERROR - GC_TODO: Add description for return value
EFI_SUCCESS - GC_TODO: Add description for return value
--*/
{
//
// Check Status Register0
//
if ((Result.Status0 & STS0_IC) != IC_NT) {
if ((Result.Status0 & STS0_SE) == 0x20) {
//
// seek error
//
FdcDev->ControllerState->NeedRecalibrate = TRUE;
}
FdcDev->ControllerState->NeedRecalibrate = TRUE;
return EFI_DEVICE_ERROR;
}
//
// Check Status Register1
//
if (Result.Status1 & (STS1_EN | STS1_DE | STS1_OR | STS1_ND | STS1_NW | STS1_MA)) {
FdcDev->ControllerState->NeedRecalibrate = TRUE;
return EFI_DEVICE_ERROR;
}
//
// Check Status Register2
//
if (Result.Status2 & (STS2_CM | STS2_DD | STS2_WC | STS2_BC | STS2_MD)) {
FdcDev->ControllerState->NeedRecalibrate = TRUE;
return EFI_DEVICE_ERROR;
}
return EFI_SUCCESS;
}
EFI_STATUS
CheckStatus3 (
IN UINT8 StatusRegister3
)
/*++
Routine Description: Check the drive status information
Parameters:
StatusRegister3 UINT8: the value of Status Register 3
Returns:
EFI_SUCCESS:
EFI_WRITE_PROTECTED: The disk is write protected
--*/
// GC_TODO: function comment is missing 'Arguments:'
// GC_TODO: StatusRegister3 - add argument and description to function comment
{
if (StatusRegister3 & STS3_WP) {
return EFI_WRITE_PROTECTED;
}
return EFI_SUCCESS;
}
UINTN
GetTransferBlockCount (
IN FDC_BLK_IO_DEV *FdcDev,
IN EFI_LBA LBA,
IN UINTN NumberOfBlocks
)
/*++
Routine Description: Calculate the number of block in the same cylinder
according to LBA
Parameters:
FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
LBA EFI_LBA: The starting logic block address
NumberOfBlocks UINTN: The number of blocks
Returns:
UINTN : The number of blocks in the same cylinder which the starting
logic block address is LBA
--*/
// GC_TODO: function comment is missing 'Arguments:'
// GC_TODO: FdcDev - add argument and description to function comment
// GC_TODO: LBA - add argument and description to function comment
// GC_TODO: NumberOfBlocks - add argument and description to function comment
{
UINT8 EndOfTrack;
UINT8 Head;
UINT8 SectorsInTrack;
//
// Calculate the number of block in the same cylinder
//
EndOfTrack = DISK_1440K_EOT;
Head = (UINT8) ((UINTN) LBA / EndOfTrack % 2);
SectorsInTrack = (UINT8) (EndOfTrack * (2 - Head) - (UINT8) ((UINTN) LBA % EndOfTrack));
if (SectorsInTrack < NumberOfBlocks) {
return SectorsInTrack;
} else {
return NumberOfBlocks;
}
}
VOID
EFIAPI
FddTimerProc (
IN EFI_EVENT Event,
IN VOID *Context
)
/*++
Routine Description: When the Timer(2s) off, turn the drive's motor off
Parameters:
Event EFI_EVENT: Event(the timer) whose notification function is being
invoked
Context VOID *: Pointer to the notification function's context
Returns:
VOID
--*/
// GC_TODO: function comment is missing 'Arguments:'
// GC_TODO: Event - add argument and description to function comment
// GC_TODO: Context - add argument and description to function comment
{
FDC_BLK_IO_DEV *FdcDev;
UINT8 data;
FdcDev = (FDC_BLK_IO_DEV *) Context;
//
// Get the motor status
//
data = FdcReadPort (FdcDev, FDC_REGISTER_DOR);
if (((FdcDev->Disk == FDC_DISK0) && ((data & 0x10) != 0x10)) ||
((FdcDev->Disk == FDC_DISK1) && ((data & 0x21) != 0x21))
) {
return ;
}
//
// the motor is on, so need motor off
//
data = 0x0C;
data |= (SELECT_DRV & FdcDev->Disk);
FdcWritePort (FdcDev, FDC_REGISTER_DOR, data);
gBS->Stall (500);
}
UINT8
FdcReadPort (
IN FDC_BLK_IO_DEV *FdcDev,
IN UINT32 Offset
)
/*++
Routine Description: Read I/O port for FDC
Parameters:
Returns:
--*/
// GC_TODO: function comment is missing 'Arguments:'
// GC_TODO: FdcDev - add argument and description to function comment
// GC_TODO: Offset - add argument and description to function comment
{
UINT8 Data;
EFI_STATUS Status;
//
// Call IsaIo
//
Status = FdcDev->IsaIo->Io.Read (
FdcDev->IsaIo,
EfiIsaIoWidthUint8,
FdcDev->BaseAddress + Offset,
1,
&Data
);
return Data;
}
VOID
FdcWritePort (
IN FDC_BLK_IO_DEV *FdcDev,
IN UINT32 Offset,
IN UINT8 Data
)
/*++
Routine Description: Write I/O port for FDC
Parameters:
Returns:
--*/
// GC_TODO: function comment is missing 'Arguments:'
// GC_TODO: FdcDev - add argument and description to function comment
// GC_TODO: Offset - add argument and description to function comment
// GC_TODO: Data - add argument and description to function comment
{
EFI_STATUS Status;
//
// Call IsaIo
//
Status = FdcDev->IsaIo->Io.Write (
FdcDev->IsaIo,
EfiIsaIoWidthUint8,
FdcDev->BaseAddress + Offset,
1,
&Data
);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?