isafloppyctrl.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,560 行 · 第 1/3 页

C
1,560
字号
      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
    //
    gBS->Stall (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);

  EfiZeroMem (&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 |= 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
  //
  gBS->Stall (100);

  //
  // Calculate waiting time
  //
  if (FdcDev->PresentCylinderNumber > Cylinder) {
    DelayTime = (UINT8) (FdcDev->PresentCylinderNumber - Cylinder);
  } else {
    DelayTime = (UINT8) (Cylinder - FdcDev->PresentCylinderNumber);
  }

  gBS->Stall ((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
  //
  EfiZeroMem (&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 |= 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
  //
  gBS->Stall (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
  //
  gBS->Stall (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_INTERFACE_DEFINITION_FOR_ISA_IO           *IsaIo;
  UINTN                                         NumberofBytes;
  VOID                                          *Mapping;
  EFI_ISA_IO_PROTOCOL_OPERATION                 Operation;
  VOID                                          *Buffer;
  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;
  }

  Buffer = (UINT8 *) (UINTN) DeviceAddress;

  //
  // Allocate Read or Write command packet
  //
  EfiZeroMem (&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;
    }

    gBS->Stall (50);
    Times = Times - 1;
  } while (Times);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?