summaryrefslogtreecommitdiff
path: root/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/Dxe/IsaFloppyCtrl.c
diff options
context:
space:
mode:
Diffstat (limited to 'IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/Dxe/IsaFloppyCtrl.c')
-rw-r--r--IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/Dxe/IsaFloppyCtrl.c1551
1 files changed, 1551 insertions, 0 deletions
diff --git a/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/Dxe/IsaFloppyCtrl.c b/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/Dxe/IsaFloppyCtrl.c
new file mode 100644
index 0000000000..2fd13c3a4b
--- /dev/null
+++ b/IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/Dxe/IsaFloppyCtrl.c
@@ -0,0 +1,1551 @@
+/*++
+
+ Copyright (c) 2006 - 2007, Intel Corporation<BR>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ IsaFloppyCtrl.c
+
+Abstract:
+
+ ISA Floppy Driver
+ 1. Support two types diskette drive
+ 1.44M drive and 2.88M drive (and now only support 1.44M)
+ 2. Support two diskette drives
+ 3. Use DMA channel 2 to transfer data
+ 4. Do not use interrupt
+ 5. Support diskette change line signal and write protect
+
+ The internal function for the floppy driver
+
+Revision History:
+
+--*/
+
+#include "IsaFloppy.h"
+
+EFI_STATUS
+DiscoverFddDevice (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+ Routine Description: Detect the floppy drive is presented or not
+ Parameters:
+ FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
+ Returns:
+ EFI_SUCCESS Drive is presented
+ EFI_NOT_FOUND Drive is not presented
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+{
+ EFI_STATUS Status;
+
+ FdcDev->BlkIo.Media = &FdcDev->BlkMedia;
+
+ //
+ // Call FddIndentify subroutine
+ //
+ Status = FddIdentify (FdcDev);
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ FdcDev->BlkIo.Reset = FdcReset;
+ FdcDev->BlkIo.FlushBlocks = FddFlushBlocks;
+ FdcDev->BlkIo.ReadBlocks = FddReadBlocks;
+ FdcDev->BlkIo.WriteBlocks = FddWriteBlocks;
+ FdcDev->BlkMedia.LogicalPartition = FALSE;
+ FdcDev->BlkMedia.WriteCaching = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FddIdentify (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+ Routine Description: Do recalibrate and see the drive is presented or not
+ Set the media parameters
+ Parameters:
+ FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
+ Returns:
+ EFI_SUCCESS:
+ EFI_DEVICE_ERROR:
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+{
+ EFI_STATUS Status;
+
+ //
+ // Set Floppy Disk Controller's motor on
+ //
+ Status = MotorOn (FdcDev);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = Recalibrate (FdcDev);
+
+ if (EFI_ERROR (Status)) {
+ MotorOff (FdcDev);
+ FdcDev->ControllerState->NeedRecalibrate = TRUE;
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Set Media Parameter
+ //
+ FdcDev->BlkIo.Media->RemovableMedia = TRUE;
+ FdcDev->BlkIo.Media->MediaPresent = TRUE;
+ //
+ // investigate
+ //
+ FdcDev->BlkIo.Media->MediaId = 0;
+
+ //
+ // Check Media
+ //
+ Status = DisketChanged (FdcDev);
+ switch (Status) {
+ case EFI_NO_MEDIA:
+ FdcDev->BlkIo.Media->MediaPresent = FALSE;
+ break;
+
+ case EFI_MEDIA_CHANGED:
+ case EFI_SUCCESS:
+ break;
+
+ default:
+ MotorOff (FdcDev);
+ return Status;
+ }
+ //
+ // Check Disk Write Protected
+ //
+ Status = SenseDrvStatus (FdcDev, 0);
+ switch (Status) {
+ case EFI_WRITE_PROTECTED:
+ FdcDev->BlkIo.Media->ReadOnly = TRUE;
+ break;
+
+ case EFI_SUCCESS:
+ FdcDev->BlkIo.Media->ReadOnly = FALSE;
+ break;
+
+ default:
+ return EFI_DEVICE_ERROR;
+ break;
+ }
+
+ MotorOff (FdcDev);
+
+ //
+ // Set Media Default Type
+ //
+ FdcDev->BlkIo.Media->BlockSize = DISK_1440K_BYTEPERSECTOR;
+ FdcDev->BlkIo.Media->LastBlock = DISK_1440K_EOT * 2 * (DISK_1440K_MAXTRACKNUM + 1) - 1;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FddReset (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+ Routine Description: Reset the Floppy Logic Drive
+ Parameters:
+ FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
+ Returns:
+ EFI_SUCCESS: The Floppy Logic Drive is reset
+ EFI_DEVICE_ERROR: The Floppy Logic Drive is not functioning correctly and
+ can not be reset
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+{
+ UINT8 data;
+ UINT8 StatusRegister0;
+ UINT8 PresentCylinderNumber;
+ UINTN Index;
+
+ //
+ // Report reset progress code
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_RESET,
+ FdcDev->DevicePath
+ );
+
+ //
+ // Reset specified Floppy Logic Drive according to FdcDev -> Disk
+ // Set Digital Output Register(DOR) to do reset work
+ // bit0 & bit1 of DOR : Drive Select
+ // bit2 : Reset bit
+ // bit3 : DMA and Int bit
+ // Reset : a "0" written to bit2 resets the FDC, this reset will remain
+ // active until
+ // a "1" is written to this bit.
+ // Reset step 1:
+ // use bit0 & bit1 to select the logic drive
+ // write "0" to bit2
+ //
+ data = 0x0;
+ data = (UINT8) (data | (SELECT_DRV & FdcDev->Disk));
+ FdcWritePort (FdcDev, FDC_REGISTER_DOR, data);
+
+ //
+ // wait some time,at least 120us
+ //
+ MicroSecondDelay (500);
+
+ //
+ // Reset step 2:
+ // write "1" to bit2
+ // write "1" to bit3 : enable DMA
+ //
+ data |= 0x0C;
+ FdcWritePort (FdcDev, FDC_REGISTER_DOR, data);
+
+ //
+ // Experience value
+ //
+ MicroSecondDelay (2000);
+
+ //
+ // wait specified floppy logic drive is not busy
+ //
+ if (EFI_ERROR (FddWaitForBSYClear (FdcDev, 1))) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Set the Transfer Data Rate
+ //
+ FdcWritePort (FdcDev, FDC_REGISTER_CCR, 0x0);
+
+ //
+ // Experience value
+ //
+ MicroSecondDelay (100);
+
+ //
+ // Issue Sense interrupt command for each drive (total 4 drives)
+ //
+ for (Index = 0; Index < 4; Index++) {
+ if (EFI_ERROR (SenseIntStatus (FdcDev, &StatusRegister0, &PresentCylinderNumber))) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ //
+ // issue Specify command
+ //
+ if (EFI_ERROR (Specify (FdcDev))) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+MotorOn (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+ Routine Description: Turn the drive's motor on
+ The drive's motor must be on before any command can be executed
+ Parameters:
+ FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
+ Returns:
+ EFI_SUCCESS: Turn the drive's motor on successfully
+ EFI_DEVICE_ERROR: The drive is busy, so can not turn motor on
+ EFI_INVALID_PARAMETER: Fail to Set timer(Cancel timer)
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ UINT8 data;
+
+ //
+ // Control of the floppy drive motors is a big pain. If motor is off, you have
+ // to turn it on first. But you can not leave the motor on all the time, since
+ // that would wear out the disk. On the other hand, if you turn the motor off
+ // after each operation, the system performance will be awful. The compromise
+ // used in this driver is to leave the motor on for 2 seconds after
+ // each operation. If a new operation is started in that interval(2s),
+ // the motor need not be turned on again. If no new operation is started,
+ // a timer goes off and the motor is turned off
+ //
+ //
+ // Cancel the timer
+ //
+ Status = gBS->SetTimer (FdcDev->Event, TimerCancel, 0);
+
+ if (EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // 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 EFI_SUCCESS;
+ }
+ //
+ // The drive's motor is off, so need turn it on
+ // first look at command and drive are busy or not
+ //
+ if (EFI_ERROR (FddWaitForBSYClear (FdcDev, 1))) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // for drive A: 1CH, drive B: 2DH
+ //
+ data = 0x0C;
+ data = (UINT8) (data | (SELECT_DRV & FdcDev->Disk));
+ if (FdcDev->Disk == FDC_DISK0) {
+ //
+ // drive A
+ //
+ data |= DRVA_MOTOR_ON;
+ } else {
+ //
+ // drive B
+ //
+ data |= DRVB_MOTOR_ON;
+ }
+
+ FdcWritePort (FdcDev, FDC_REGISTER_DOR, data);
+
+ //
+ // Experience value
+ //
+ MicroSecondDelay (4000);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+MotorOff (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+ Routine Description: Set a Timer and when Timer goes off, turn the motor off
+ Parameters:
+ FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
+ Returns:
+ EFI_SUCCESS: Set the Timer successfully
+ EFI_INVALID_PARAMETER: Fail to Set the timer
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+{
+ //
+ // Set the timer : 2s
+ //
+ return gBS->SetTimer (FdcDev->Event, TimerRelative, 20000000);
+}
+
+EFI_STATUS
+DisketChanged (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+ Routine Description: Detect the disk in the drive is changed or not
+ Parameters:
+ FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
+ Returns:
+ EFI_SUCCESS: No disk media change
+ EFI_DEVICE_ERROR: Fail to do the recalibrate or seek operation
+ EFI_NO_MEDIA: No disk in the drive
+ EFI_MEDIA_CHANGED: There is a new disk in the drive
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ UINT8 data;
+
+ //
+ // Check change line
+ //
+ data = FdcReadPort (FdcDev, FDC_REGISTER_DIR);
+
+ //
+ // Io delay
+ //
+ MicroSecondDelay (50);
+
+ if ((data & DIR_DCL) == 0x80) {
+ //
+ // disk change line is active
+ //
+ if (FdcDev->PresentCylinderNumber != 0) {
+ Status = Recalibrate (FdcDev);
+ } else {
+ Status = Seek (FdcDev, 0x30);
+ }
+
+ if (EFI_ERROR (Status)) {
+ FdcDev->ControllerState->NeedRecalibrate = TRUE;
+ return EFI_DEVICE_ERROR;
+ //
+ // Fail to do the seek or recalibrate operation
+ //
+ }
+
+ data = FdcReadPort (FdcDev, FDC_REGISTER_DIR);
+
+ //
+ // Io delay
+ //
+ MicroSecondDelay (50);
+
+ if ((data & DIR_DCL) == 0x80) {
+ return EFI_NO_MEDIA;
+ }
+
+ return EFI_MEDIA_CHANGED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Specify (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+ Routine Description: Do the Specify command, this command sets DMA operation
+ and the initial values for each of the three internal
+ times: HUT, SRT and HLT
+ Parameters:
+ None
+ Returns:
+ EFI_SUCCESS: Execute the Specify command successfully
+ EFI_DEVICE_ERROR: Fail to execute the command
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+{
+ FDD_SPECIFY_CMD Command;
+ UINTN Index;
+ UINT8 *CommandPointer;
+
+ ZeroMem (&Command, sizeof (FDD_SPECIFY_CMD));
+ Command.CommandCode = SPECIFY_CMD;
+ //
+ // set SRT, HUT
+ //
+ Command.SrtHut = 0xdf;
+ //
+ // 0xdf;
+ //
+ // set HLT and DMA
+ //
+ Command.HltNd = 0x02;
+
+ CommandPointer = (UINT8 *) (&Command);
+ for (Index = 0; Index < sizeof (FDD_SPECIFY_CMD); Index++) {
+ if (EFI_ERROR (DataOutByte (FdcDev, CommandPointer++))) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Recalibrate (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+ Routine Description: Set the head of floppy drive to track 0
+ Parameters:
+ FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
+ Returns:
+ EFI_SUCCESS: Execute the Recalibrate operation successfully
+ EFI_DEVICE_ERROR: Fail to execute the Recalibrate operation
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+{
+ FDD_COMMAND_PACKET2 Command;
+ UINTN Index;
+ UINT8 StatusRegister0;
+ UINT8 PresentCylinderNumber;
+ UINT8 *CommandPointer;
+ UINT8 Count;
+
+ Count = 2;
+
+ while (Count > 0) {
+ ZeroMem (&Command, sizeof (FDD_COMMAND_PACKET2));
+ Command.CommandCode = RECALIBRATE_CMD;
+ //
+ // drive select
+ //
+ if (FdcDev->Disk == FDC_DISK0) {
+ Command.DiskHeadSel = 0;
+ //
+ // 0
+ //
+ } else {
+ Command.DiskHeadSel = 1;
+ //
+ // 1
+ //
+ }
+
+ CommandPointer = (UINT8 *) (&Command);
+ for (Index = 0; Index < sizeof (FDD_COMMAND_PACKET2); Index++) {
+ if (EFI_ERROR (DataOutByte (FdcDev, CommandPointer++))) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ //
+ // Experience value
+ //
+ MicroSecondDelay (250000);
+ //
+ // need modify according to 1.44M or 2.88M
+ //
+ if (EFI_ERROR (SenseIntStatus (FdcDev, &StatusRegister0, &PresentCylinderNumber))) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ((StatusRegister0 & 0xf0) == 0x20 && PresentCylinderNumber == 0) {
+ FdcDev->PresentCylinderNumber = 0;
+ FdcDev->ControllerState->NeedRecalibrate = FALSE;
+ return EFI_SUCCESS;
+ } else {
+ Count--;
+ if (Count == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ }
+ //
+ // end while
+ //
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Seek (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN EFI_LBA Lba
+ )
+/*++
+
+ Routine Description: Set the head of floppy drive to the new cylinder
+ Parameters:
+ FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
+ Lba EFI_LBA : The logic block address want to seek
+ Returns:
+ EFI_SUCCESS: Execute the Seek operation successfully
+ EFI_DEVICE_ERROR: Fail to execute the Seek operation
+
+--*/
+// 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
+{
+ FDD_SEEK_CMD Command;
+ UINT8 EndOfTrack;
+ UINT8 Head;
+ UINT8 Cylinder;
+ UINT8 StatusRegister0;
+ UINT8 *CommandPointer;
+ UINT8 PresentCylinderNumber;
+ UINTN Index;
+ UINT8 DelayTime;
+
+ if (FdcDev->ControllerState->NeedRecalibrate) {
+ if (EFI_ERROR (Recalibrate (FdcDev))) {
+ FdcDev->ControllerState->NeedRecalibrate = TRUE;
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ EndOfTrack = DISK_1440K_EOT;
+ //
+ // Calculate cylinder based on Lba and EOT
+ //
+ Cylinder = (UINT8) ((UINTN) Lba / EndOfTrack / 2);
+
+ //
+ // if the destination cylinder is the present cylinder, unnecessary to do the
+ // seek operation
+ //
+ if (FdcDev->PresentCylinderNumber == Cylinder) {
+ return EFI_SUCCESS;
+ }
+ //
+ // Calculate the head : 0 or 1
+ //
+ Head = (UINT8) ((UINTN) Lba / EndOfTrack % 2);
+
+ ZeroMem (&Command, sizeof (FDD_SEEK_CMD));
+ Command.CommandCode = SEEK_CMD;
+ if (FdcDev->Disk == FDC_DISK0) {
+ Command.DiskHeadSel = 0;
+ //
+ // 0
+ //
+ } else {
+ Command.DiskHeadSel = 1;
+ //
+ // 1
+ //
+ }
+
+ Command.DiskHeadSel = (UINT8) (Command.DiskHeadSel | (Head << 2));
+ Command.NewCylinder = Cylinder;
+
+ CommandPointer = (UINT8 *) (&Command);
+ for (Index = 0; Index < sizeof (FDD_SEEK_CMD); Index++) {
+ if (EFI_ERROR (DataOutByte (FdcDev, CommandPointer++))) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ //
+ // Io delay
+ //
+ MicroSecondDelay (100);
+
+ //
+ // Calculate waiting time
+ //
+ if (FdcDev->PresentCylinderNumber > Cylinder) {
+ DelayTime = (UINT8) (FdcDev->PresentCylinderNumber - Cylinder);
+ } else {
+ DelayTime = (UINT8) (Cylinder - FdcDev->PresentCylinderNumber);
+ }
+
+ MicroSecondDelay ((DelayTime + 1) * 4000);
+
+ if (EFI_ERROR (SenseIntStatus (FdcDev, &StatusRegister0, &PresentCylinderNumber))) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ((StatusRegister0 & 0xf0) == 0x20) {
+ FdcDev->PresentCylinderNumber = Command.NewCylinder;
+ return EFI_SUCCESS;
+ } else {
+ FdcDev->ControllerState->NeedRecalibrate = TRUE;
+ return EFI_DEVICE_ERROR;
+ }
+}
+
+EFI_STATUS
+SenseIntStatus (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN OUT UINT8 *StatusRegister0,
+ IN OUT UINT8 *PresentCylinderNumber
+ )
+/*++
+
+ Routine Description: Do the Sense Interrupt Status command, this command
+ resets the interrupt signal
+ Parameters:
+ StatusRegister0 UINT8 *: Be used to save Status Register 0 read from FDC
+ PresentCylinderNumber UINT8 *: Be used to save present cylinder number
+ read from FDC
+ Returns:
+ EFI_SUCCESS: Execute the Sense Interrupt Status command successfully
+ EFI_DEVICE_ERROR: Fail to execute the command
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+// GC_TODO: StatusRegister0 - add argument and description to function comment
+// GC_TODO: PresentCylinderNumber - add argument and description to function comment
+{
+ UINT8 command;
+
+ command = SENSE_INT_STATUS_CMD;
+ if (EFI_ERROR (DataOutByte (FdcDev, &command))) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (EFI_ERROR (DataInByte (FdcDev, StatusRegister0))) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (EFI_ERROR (DataInByte (FdcDev, PresentCylinderNumber))) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SenseDrvStatus (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN EFI_LBA Lba
+ )
+/*++
+
+ Routine Description: Do the Sense Drive Status command
+ Parameters:
+ FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
+ Lba EFI_LBA : Logic block address
+ Returns:
+ EFI_SUCCESS: Execute the Sense Drive Status command successfully
+ EFI_DEVICE_ERROR: Fail to execute the command
+ EFI_WRITE_PROTECTED:The disk is write protected
+
+--*/
+// 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
+{
+ FDD_COMMAND_PACKET2 Command;
+ UINT8 Head;
+ UINT8 EndOfTrack;
+ UINTN Index;
+ UINT8 StatusRegister3;
+ UINT8 *CommandPointer;
+
+ //
+ // Sense Drive Status command obtains drive status information,
+ // it has not execution phase and goes directly to the result phase from the
+ // command phase, Status Register 3 contains the drive status information
+ //
+ ZeroMem (&Command, sizeof (FDD_COMMAND_PACKET2));
+ Command.CommandCode = SENSE_DRV_STATUS_CMD;
+
+ if (FdcDev->Disk == FDC_DISK0) {
+ Command.DiskHeadSel = 0;
+ } else {
+ Command.DiskHeadSel = 1;
+ }
+
+ EndOfTrack = DISK_1440K_EOT;
+ Head = (UINT8) ((UINTN) Lba / EndOfTrack % 2);
+ Command.DiskHeadSel = (UINT8) (Command.DiskHeadSel | (Head << 2));
+
+ CommandPointer = (UINT8 *) (&Command);
+ for (Index = 0; Index < sizeof (FDD_COMMAND_PACKET2); Index++) {
+ if (EFI_ERROR (DataOutByte (FdcDev, CommandPointer++))) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ if (EFI_ERROR (DataInByte (FdcDev, &StatusRegister3))) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Io delay
+ //
+ MicroSecondDelay (50);
+
+ //
+ // Check Status Register 3 to get drive status information
+ //
+ return CheckStatus3 (StatusRegister3);
+}
+
+EFI_STATUS
+DetectMedia (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+ Routine Description: Update the disk media properties and if necessary
+ reinstall Block I/O interface
+ Parameters:
+ FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
+ Returns:
+ EFI_SUCCESS: Do the operation successfully
+ EFI_DEVICE_ERROR: Fail to the operation
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ BOOLEAN bReset;
+ BOOLEAN bReadOnlyLastTime;
+ BOOLEAN bMediaPresentLastTime;
+
+ bReset = FALSE;
+ bReadOnlyLastTime = FdcDev->BlkIo.Media->ReadOnly;
+ bMediaPresentLastTime = FdcDev->BlkIo.Media->MediaPresent;
+
+ //
+ // Check disk change
+ //
+ Status = DisketChanged (FdcDev);
+ switch (Status) {
+ case EFI_MEDIA_CHANGED:
+ FdcDev->BlkIo.Media->MediaId++;
+ FdcDev->BlkIo.Media->MediaPresent = TRUE;
+ bReset = TRUE;
+ break;
+
+ case EFI_NO_MEDIA:
+ FdcDev->BlkIo.Media->MediaPresent = FALSE;
+ break;
+
+ case EFI_SUCCESS:
+ break;
+
+ default:
+ MotorOff (FdcDev);
+ return Status;
+ //
+ // EFI_DEVICE_ERROR
+ //
+ }
+
+ if (FdcDev->BlkIo.Media->MediaPresent) {
+ //
+ // Check disk write protected
+ //
+ Status = SenseDrvStatus (FdcDev, 0);
+ if (Status == EFI_WRITE_PROTECTED) {
+ FdcDev->BlkIo.Media->ReadOnly = TRUE;
+ } else {
+ FdcDev->BlkIo.Media->ReadOnly = FALSE;
+ }
+ }
+
+ if (FdcDev->BlkIo.Media->MediaPresent && (bReadOnlyLastTime != FdcDev->BlkIo.Media->ReadOnly)) {
+ bReset = TRUE;
+ }
+
+ if (bMediaPresentLastTime != FdcDev->BlkIo.Media->MediaPresent) {
+ bReset = TRUE;
+ }
+
+ if (bReset) {
+ Status = gBS->ReinstallProtocolInterface (
+ FdcDev->Handle,
+ &gEfiBlockIoProtocolGuid,
+ &FdcDev->BlkIo,
+ &FdcDev->BlkIo
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Setup (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+ Routine Description: Set the data rate and so on
+ Parameters:
+ None
+ Returns:
+ EFI_SUCCESS:
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment
+{
+ EFI_STATUS Status;
+
+ //
+ // Set data rate 500kbs
+ //
+ FdcWritePort (FdcDev, FDC_REGISTER_CCR, 0x0);
+
+ //
+ // Io delay
+ //
+ MicroSecondDelay (50);
+
+ Status = Specify (FdcDev);
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ReadWriteDataSector (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN VOID *HostAddress,
+ IN EFI_LBA Lba,
+ IN UINTN NumberOfBlocks,
+ IN BOOLEAN Read
+ )
+/*++
+
+ Routine Description: Read or Write a number of blocks in the same cylinder
+ Parameters:
+ FdcDev FDC_BLK_IO_DEV * : A pointer to Data Structure FDC_BLK_IO_DEV
+ Buffer VOID *:
+ Lba EFI_LBA:
+ NumberOfBlocks UINTN:
+ Read BOOLEAN:
+ Returns:
+ EFI_SUCCESS:
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+// GC_TODO: HostAddress - 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
+// GC_TODO: Read - add argument and description to function comment
+// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment
+// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment
+// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment
+// GC_TODO: EFI_TIMEOUT - add return value to function comment
+// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment
+{
+ EFI_STATUS Status;
+ FDD_COMMAND_PACKET1 Command;
+ FDD_RESULT_PACKET Result;
+ UINTN Index;
+ UINTN Times;
+ UINT8 *CommandPointer;
+
+ EFI_PHYSICAL_ADDRESS DeviceAddress;
+ EFI_ISA_IO_PROTOCOL *IsaIo;
+ UINTN NumberofBytes;
+ VOID *Mapping;
+ EFI_ISA_IO_PROTOCOL_OPERATION Operation;
+ EFI_STATUS Status1;
+ UINT8 Channel;
+ EFI_ISA_ACPI_RESOURCE *ResourceItem;
+ UINT32 Attribute;
+
+ Status = Seek (FdcDev, Lba);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Map Dma
+ //
+ IsaIo = FdcDev->IsaIo;
+ NumberofBytes = NumberOfBlocks * 512;
+ if (Read == READ) {
+ Operation = EfiIsaIoOperationSlaveWrite;
+ } else {
+ Operation = EfiIsaIoOperationSlaveRead;
+ }
+
+ ResourceItem = IsaIo->ResourceList->ResourceItem;
+ Index = 0;
+ while (ResourceItem[Index].Type != EfiIsaAcpiResourceEndOfList) {
+ if (ResourceItem[Index].Type == EfiIsaAcpiResourceDma) {
+ break;
+ }
+
+ Index++;
+ }
+
+ if (ResourceItem[Index].Type == EfiIsaAcpiResourceEndOfList) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Channel = (UINT8) IsaIo->ResourceList->ResourceItem[Index].StartRange;
+ Attribute = IsaIo->ResourceList->ResourceItem[Index].Attribute;
+
+ Status1 = IsaIo->Map (
+ IsaIo,
+ Operation,
+ Channel,
+ Attribute,
+ HostAddress,
+ &NumberofBytes,
+ &DeviceAddress,
+ &Mapping
+ );
+ if (EFI_ERROR (Status1)) {
+ return Status1;
+ }
+
+ //
+ // Allocate Read or Write command packet
+ //
+ ZeroMem (&Command, sizeof (FDD_COMMAND_PACKET1));
+ if (Read == READ) {
+ Command.CommandCode = READ_DATA_CMD | CMD_MT | CMD_MFM | CMD_SK;
+ } else {
+ Command.CommandCode = WRITE_DATA_CMD | CMD_MT | CMD_MFM;
+ }
+
+ FillPara (FdcDev, Lba, &Command);
+
+ //
+ // Write command bytes to FDC
+ //
+ CommandPointer = (UINT8 *) (&Command);
+ for (Index = 0; Index < sizeof (FDD_COMMAND_PACKET1); Index++) {
+ if (EFI_ERROR (DataOutByte (FdcDev, CommandPointer++))) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ //
+ // wait for some time
+ //
+ Times = (STALL_1_SECOND / 50) + 1;
+ do {
+ if ((FdcReadPort (FdcDev, FDC_REGISTER_MSR) & 0xc0) == 0xc0) {
+ break;
+ }
+
+ MicroSecondDelay (50);
+ Times = Times - 1;
+ } while (Times);
+
+ 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 = (UINT8) (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
+ //
+ MicroSecondDelay (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
+ //
+ MicroSecondDelay (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
+ //
+ }
+
+ MicroSecondDelay (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
+ //
+ }
+
+ MicroSecondDelay (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 = (UINT8) (data | (SELECT_DRV & FdcDev->Disk));
+ FdcWritePort (FdcDev, FDC_REGISTER_DOR, data);
+ MicroSecondDelay (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;
+
+ //
+ // Call IsaIo
+ //
+ 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
+{
+
+ //
+ // Call IsaIo
+ //
+ FdcDev->IsaIo->Io.Write (
+ FdcDev->IsaIo,
+ EfiIsaIoWidthUint8,
+ FdcDev->BaseAddress + Offset,
+ 1,
+ &Data
+ );
+}