hardware.c

来自「一个类似windows」· C语言 代码 · 共 1,084 行 · 第 1/3 页

C
1,084
字号
  Buffer[0] = COMMAND_SEEK;
  Buffer[1] = DriveInfo->UnitNumber;
  Buffer[2] = Cylinder;

  for(i = 0; i < 3; i++)
    if(Send_Byte(DriveInfo->ControllerInfo, Buffer[i]) != STATUS_SUCCESS)
      {
	DPRINT("floppy: HwSeek: failed to write fifo\n");
        return STATUS_UNSUCCESSFUL;
      }

  /* Wait for the head to settle */
  Delay.QuadPart = 10 * 1000;
  Delay.QuadPart *= -1;
  Delay.QuadPart *= DriveInfo->FloppyDeviceData.HeadSettleTime;

  KeDelayExecutionThread(KernelMode, FALSE, &Delay);

  return STATUS_SUCCESS;
}


NTSTATUS NTAPI HwConfigure(PCONTROLLER_INFO ControllerInfo,
                           BOOLEAN EIS,
			   BOOLEAN EFIFO,
			   BOOLEAN POLL,
			   UCHAR FIFOTHR,
			   UCHAR PRETRK)
/*
 * FUNCTION: Sends configuration to the drive
 * ARGUMENTS:
 *     ControllerInfo: controller to target with the request
 *     EIS: Enable implied seek
 *     EFIFO: Enable advanced fifo
 *     POLL: Enable polling
 *     FIFOTHR: fifo threshold
 *     PRETRK: precomp (see intel datasheet)
 * RETURNS:
 *     STATUS_SUCCESS if the command is successfully sent
 *     STATUS_UNSUCCESSFUL otherwise
 * NOTES:
 *     - No interrupt
 */
{
  UCHAR Buffer[4];
  int i;

  DPRINT("floppy: HwConfigure called\n");

  PAGED_CODE();

  Buffer[0] = COMMAND_CONFIGURE;
  Buffer[1] = 0;
  Buffer[2] = (EIS * CONFIGURE_EIS) + (EFIFO * CONFIGURE_EFIFO) + (POLL * CONFIGURE_POLL) + (FIFOTHR);
  Buffer[3] = PRETRK;

  for(i = 0; i < 4; i++)
    if(Send_Byte(ControllerInfo, Buffer[i]) != STATUS_SUCCESS)
      {
	DPRINT("floppy: HwConfigure: failed to write the fifo\n");
        return STATUS_UNSUCCESSFUL;
      }

  return STATUS_SUCCESS;
}


NTSTATUS NTAPI HwGetVersion(PCONTROLLER_INFO ControllerInfo)
/*
 * FUNCTION: Gets the version of the controller
 * ARGUMENTS:
 *     ControllerInfo: controller to target with the request
 *     ConfigValue: Configuration value to send to the drive (see header)
 * RETURNS:
 *     Version number returned by the command, or
 *     0 on failure
 * NOTE:
 *     - This command doesn't interrupt, so we go right to reading after
 *       we issue the command
 */
{
  UCHAR Buffer;

  PAGED_CODE();

  if(Send_Byte(ControllerInfo, COMMAND_VERSION) != STATUS_SUCCESS)
    {
      DPRINT("floppy: HwGetVersion: unable to write fifo\n");
      return STATUS_UNSUCCESSFUL;
    }

  if(Get_Byte(ControllerInfo, &Buffer) != STATUS_SUCCESS)
    {
      DPRINT("floppy: HwGetVersion: unable to write fifo\n");
      return STATUS_UNSUCCESSFUL;
    }

  DPRINT("floppy: HwGetVersion returning version 0x%x\n", Buffer);

  return Buffer;
}

NTSTATUS NTAPI HwDiskChanged(PDRIVE_INFO DriveInfo,
                             PBOOLEAN DiskChanged)
/*
 * FUNCTION: Detect whether the hardware has sensed a disk change
 * ARGUMENTS:
 *     DriveInfo: pointer to the drive that we are to check
 *     DiskChanged: boolean that is set with whether or not the controller thinks there has been a disk change
 * RETURNS:
 *     STATUS_SUCCESS if the drive is successfully queried
 * NOTES:
 *     - Does not interrupt.
 *     - Guessing a bit at the Model30 stuff
 */
{
  UCHAR Buffer;
  PCONTROLLER_INFO ControllerInfo = (PCONTROLLER_INFO) DriveInfo->ControllerInfo;

  Buffer = READ_PORT_UCHAR(ControllerInfo->BaseAddress + DIGITAL_INPUT_REGISTER);

  DPRINT("floppy: HwDiskChanged: read 0x%x from DIR\n", Buffer);

  if(ControllerInfo->Model30)
    {
      if(!(Buffer & DIR_DISKETTE_CHANGE))
	{
	  DPRINT("floppy: HdDiskChanged - Model30 - returning TRUE\n");
	  *DiskChanged = TRUE;
	}
      else
	{
	  DPRINT("floppy: HdDiskChanged - Model30 - returning FALSE\n");
	  *DiskChanged = FALSE;
	}
    }
  else
    {
      if(Buffer & DIR_DISKETTE_CHANGE)
	{
	  DPRINT("floppy: HdDiskChanged - PS2 - returning TRUE\n");
	  *DiskChanged = TRUE;
	}
      else
	{
	  DPRINT("floppy: HdDiskChanged - PS2 - returning FALSE\n");
	  *DiskChanged = FALSE;
	}
    }

  return STATUS_SUCCESS;
}

NTSTATUS NTAPI HwSenseDriveStatusResult(PCONTROLLER_INFO ControllerInfo,
                                        PUCHAR Status)
/*
 * FUNCTION: Get the result of a sense drive status command
 * ARGUMENTS:
 *     ControllerInfo: controller to query
 *     Status: Status from the drive sense command
 * RETURNS:
 *     STATUS_SUCCESS if we can successfully read the status
 *     STATUS_UNSUCCESSFUL otherwise
 * NOTES:
 *     - Called post-interrupt; does not interrupt
 */
{
  PAGED_CODE();

  if(Get_Byte(ControllerInfo, Status) != STATUS_SUCCESS)
    {
      DPRINT("floppy: HwSenseDriveStatus: unable to read fifo\n");
      return STATUS_UNSUCCESSFUL;
    }

  DPRINT("floppy: HwSenseDriveStatusResult: ST3: 0x%x\n", *Status);

  return STATUS_SUCCESS;
}


NTSTATUS NTAPI HwReadIdResult(PCONTROLLER_INFO ControllerInfo,
                              PUCHAR CurCylinder,
                              PUCHAR CurHead)
/*
 * FUNCTION: Get the result of a read id command
 * ARGUMENTS:
 *     ControllerInfo: controller to query
 *     CurCylinder: Returns the cylinder that we're at
 *     CurHead: Returns the head that we're at
 * RETURNS:
 *     STATUS_SUCCESS if the read id was a success
 *     STATUS_UNSUCCESSFUL otherwise
 * NOTES:
 *     - This function tests the error conditions itself, and boils the
 *       whole thing down to a single SUCCESS or FAILURE result
 *     - Called post-interrupt; does not interrupt
 * TODO
 *     - perhaps handle more status
 */
{
  UCHAR Buffer[7] = {0,0,0,0,0,0,0};
  int i;

  PAGED_CODE();

  for(i = 0; i < 7; i++)
    if(Get_Byte(ControllerInfo, &Buffer[i]) != STATUS_SUCCESS)
      {
	DPRINT("floppy: ReadIdResult(): can't read from the controller\n");
        return STATUS_UNSUCCESSFUL;
      }

  /* Validate  that it did what we told it to */
  DPRINT("floppy: ReadId results: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", Buffer[0], Buffer[1], Buffer[2], Buffer[3],
	   Buffer[4], Buffer[5], Buffer[6]);

  /* Last command successful? */
  if((Buffer[0] & SR0_LAST_COMMAND_STATUS) != SR0_LCS_SUCCESS)
    {
      DPRINT("floppy: ReadId didn't return last command success\n");
      return STATUS_UNSUCCESSFUL;
    }

  /* ID mark found? */
  if(Buffer[1] & SR1_CANNOT_FIND_ID_ADDRESS)
    {
      DPRINT("floppy: ReadId didn't find an address mark\n");
      return STATUS_UNSUCCESSFUL;
    }

  if(CurCylinder)
    *CurCylinder = Buffer[3];

  if(CurHead)
    *CurHead = Buffer[4];

  return STATUS_SUCCESS;
}


NTSTATUS NTAPI HwSpecify(PCONTROLLER_INFO ControllerInfo,
                         UCHAR HeadLoadTime,
                         UCHAR HeadUnloadTime,
                         UCHAR StepRateTime,
                         BOOLEAN NonDma)
/*
 * FUNCTION: Set up timing and DMA mode for the controller
 * ARGUMENTS:
 *     ControllerInfo: Controller to set up
 *     HeadLoadTime: Head load time (see data sheet for details)
 *     HeadUnloadTime: Head unload time
 *     StepRateTime: Step rate time
 *     NonDma: TRUE to disable DMA mode
 * RETURNS:
 *     STATUS_SUCCESS if the contrller is successfully programmed
 *     STATUS_UNSUCCESSFUL if not
 * NOTES:
 *     - Does not interrupt
 *
 * TODO: Figure out timings
 */
{
  UCHAR Buffer[3];
  int i;

  Buffer[0] = COMMAND_SPECIFY;
  /*
  Buffer[1] = (StepRateTime << 4) + HeadUnloadTime;
  Buffer[2] = (HeadLoadTime << 1) + (NonDma ? 1 : 0);
  */
  Buffer[1] = 0xdf;
  Buffer[2] = 0x2;

  //DPRINT("HwSpecify: sending 0x%x 0x%x 0x%x to FIFO\n", Buffer[0], Buffer[1], Buffer[2]);
  DPRINT("FLOPPY: HWSPECIFY: FIXME - sending 0x3 0xd1 0x2 to FIFO\n");

  for(i = 0; i < 3; i++)
    if(Send_Byte(ControllerInfo, Buffer[i]) != STATUS_SUCCESS)
      {
	DPRINT("floppy: HwSpecify: unable to write to controller\n");
        return STATUS_UNSUCCESSFUL;
      }

  return STATUS_SUCCESS;
}


NTSTATUS NTAPI HwReset(PCONTROLLER_INFO ControllerInfo)
/*
 * FUNCTION: Reset the controller
 * ARGUMENTS:
 *     ControllerInfo: controller to reset
 * RETURNS:
 *     STATUS_SUCCESS in all cases
 * NOTES:
 *     - Generates an interrupt that must be serviced four times (one per drive)
 */
{
  DPRINT("floppy: HwReset called\n");

  /* Write the reset bit in the DRSR */
  WRITE_PORT_UCHAR(ControllerInfo->BaseAddress + DATA_RATE_SELECT_REGISTER, DRSR_SW_RESET);

  /* Check for the reset bit in the DOR and set it if necessary (see Intel doc) */
  if(!(READ_PORT_UCHAR(ControllerInfo->BaseAddress + DIGITAL_OUTPUT_REGISTER) & DOR_RESET))
    {
      HwDumpRegisters(ControllerInfo);
      DPRINT("floppy: HwReset: Setting Enable bit\n");
      WRITE_PORT_UCHAR(ControllerInfo->BaseAddress + DIGITAL_OUTPUT_REGISTER, DOR_DMA_IO_INTERFACE_ENABLE|DOR_RESET);
      HwDumpRegisters(ControllerInfo);

      if(!(READ_PORT_UCHAR(ControllerInfo->BaseAddress + DIGITAL_OUTPUT_REGISTER) & DOR_RESET))
	{
	  DPRINT("floppy: HwReset: failed to set the DOR enable bit!\n");
          HwDumpRegisters(ControllerInfo);
	  return STATUS_UNSUCCESSFUL;
	}
    }

  return STATUS_SUCCESS;
}


NTSTATUS NTAPI HwPowerOff(PCONTROLLER_INFO ControllerInfo)
/*
 * FUNCTION: Power down a controller
 * ARGUMENTS:
 *     ControllerInfo: Controller to power down
 * RETURNS:
 *     STATUS_SUCCESS
 * NOTES:
 *     - Wake up with a hardware reset
 */
{
  DPRINT("floppy: HwPowerOff called on controller 0x%x\n", ControllerInfo);

  WRITE_PORT_UCHAR(ControllerInfo->BaseAddress + DATA_RATE_SELECT_REGISTER, DRSR_POWER_DOWN);

  return STATUS_SUCCESS;
}

VOID NTAPI HwDumpRegisters(PCONTROLLER_INFO ControllerInfo)
/*
 * FUNCTION: Dump all readable registers from the floppy controller
 * ARGUMENTS:
 *     ControllerInfo: Controller to dump registers from
 */
{
  UNREFERENCED_PARAMETER(ControllerInfo);

  DPRINT("floppy: STATUS: ");
  DPRINT("STATUS_REGISTER_A = 0x%x ", READ_PORT_UCHAR(ControllerInfo->BaseAddress + STATUS_REGISTER_A));
  DPRINT("STATUS_REGISTER_B = 0x%x ", READ_PORT_UCHAR(ControllerInfo->BaseAddress + STATUS_REGISTER_B));
  DPRINT("DIGITAL_OUTPUT_REGISTER = 0x%x ", READ_PORT_UCHAR(ControllerInfo->BaseAddress + DIGITAL_OUTPUT_REGISTER));
  DPRINT("MAIN_STATUS_REGISTER =0x%x ", READ_PORT_UCHAR(ControllerInfo->BaseAddress + MAIN_STATUS_REGISTER));
  DPRINT("DIGITAL_INPUT_REGISTER = 0x%x\n", READ_PORT_UCHAR(ControllerInfo->BaseAddress + DIGITAL_INPUT_REGISTER));
}

⌨️ 快捷键说明

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