📄 ideutils.c
字号:
usStatus = IORD_ALTERA_AVALON_CF_IDE_ALTERNATE_STATUS(ide_base);
// i) If DRQ=1, the host transfers a block of data by reading the Data register.
// If any error conditions are present in the status read in step h), the
// data transfer may not be valid.
if (usStatus & AltStatusRegBitDRQ)
{
for (i = 0; i < 256; ++i)
{
iIndex = i + 256 * iSect;
// printf("writing byte at index %d\r", iIndex);
pusBuffer[iIndex] = IORD_ALTERA_AVALON_CF_IDE_DATA(ide_base);
}
}
else
{
printf("DRQ not set in status reg in readSectorsCHS()\r");
return 0;
}
// j) When the status register is read, the device negates INTRQ. In response to
// the complete data block being read, one of the following actions is taken:
// - if no error status was presented to the host in step h), and if transfer
// of another block is required, the device sets BSY and the above sequence
// is repeated starting from step g).
// - If an error status was present in the status read in step h), the device
// clears DRQ and the command execution is complete.
// - If the last block was transfered, the device clears DRQ and the command
// execution is complete.
}
return 1;
}
int readSectorsCHS(int iDevice, int iCylinder, int iHead, int iSectorNumber,
int iSectorCount, unsigned short *pusBuffer)
{
if (gbVerbose)
{
printf("CHS = (%d, %d, %d); numSectors: %d\r",
iCylinder, iHead, iSectorNumber, iSectorCount);
}
// 1: set up the request.
if (!PIODataInOrOutPreamble(iDevice))
{
printf("readSectorsCHS(): PIODataInOrOutPreamble failed.\r");
return 0;
}
// d) The host writes any required command parameters to the Features,
// Sector Count, Sector Number, Cylinder High, Cylinder Low and
// Device/Head registers.
IOWR_ALTERA_AVALON_CF_IDE_SECTOR_COUNT(ide_base, iSectorCount);
IOWR_ALTERA_AVALON_CF_IDE_SECTOR_NUMBER(ide_base, iSectorNumber);
IOWR_ALTERA_AVALON_CF_IDE_CYLINDER_LOW(ide_base, iCylinder & 0xFF);
IOWR_ALTERA_AVALON_CF_IDE_CYLINDER_HIGH(ide_base, iCylinder >> 8);
IOWR_ALTERA_AVALON_CF_IDE_DEVICE_HEAD(ide_base,
(iDevice ? DevHeadRegBitDEV : 0) |
(iHead & DevHeadRegBitHeads));
// e) The host writes the command code to the Command register.
IDEinterrupt = 0;
IOWR_ALTERA_AVALON_CF_IDE_COMMAND(ide_base, ReadSectorWithRetries);
// 2: wait for and read the data.
return readSectorsCHSResult(iSectorCount, pusBuffer);
}
int readSectorsLBA(int iDevice, unsigned long ulLBA,
int iSectorCount, unsigned short *pusBuffer)
{
if (gbVerbose)
{
printf("LBA = %u; numSectors: %d\r", (unsigned int)ulLBA, iSectorCount);
}
// 1: set up the request.
if (!PIODataInOrOutPreamble(iDevice))
{
printf("readSectorsLBA(): PIODataInOrOutPreamble failed.\r");
return 0;
}
// d) The host writes any required command parameters to the Features,
// Sector Count, Sector Number, Cylinder High, Cylinder Low and
// Device/Head registers.
IOWR_ALTERA_AVALON_CF_IDE_SECTOR_COUNT(ide_base, iSectorCount);
IOWR_ALTERA_AVALON_CF_IDE_SECTOR_NUMBER(ide_base, ulLBA & 0xFF);
ulLBA >>= 8;
IOWR_ALTERA_AVALON_CF_IDE_CYLINDER_LOW(ide_base, ulLBA & 0xFF);
ulLBA >>= 8;
IOWR_ALTERA_AVALON_CF_IDE_CYLINDER_HIGH(ide_base, ulLBA & 0xFF);
ulLBA >>= 8;
IOWR_ALTERA_AVALON_CF_IDE_DEVICE_HEAD(ide_base, (ulLBA & 0x0F) | 0xE0 | // LBA on
(iDevice ? DevHeadRegBitDEV : 0));
// e) The host writes the command code to the Command register.
IDEinterrupt = 0;
IOWR_ALTERA_AVALON_CF_IDE_COMMAND(ide_base, ReadSectorWithRetries);
// 2: wait for and read the data.
return readSectorsCHSResult(iSectorCount, pusBuffer);
}
int writeSectorsLBA(int iDevice, unsigned long ulLBA,
int iSectorCount, unsigned short *pusBuffer)
{
unsigned short usStatus;
int i;
int iNumSectorsWritten = 0;
if (gbVerbose)
{
printf("LBA = %u; numSectors: %d\r", (unsigned int)ulLBA, iSectorCount);
}
if (!PIODataInOrOutPreamble(iDevice))
{
printf("writeSectorsLBA(): PIODataInOrOutPreamble failed.\r");
return 0;
}
// d) The host writes any required command parameters to the Features,
// Sector Count, Sector Number, Cylinder High, Cylinder Low and
// Device/Head registers.
IOWR_ALTERA_AVALON_CF_IDE_SECTOR_COUNT(ide_base, iSectorCount);
IOWR_ALTERA_AVALON_CF_IDE_SECTOR_NUMBER(ide_base, ulLBA & 0xFF);
ulLBA >>= 8;
IOWR_ALTERA_AVALON_CF_IDE_CYLINDER_LOW(ide_base, ulLBA & 0xFF);
ulLBA >>= 8;
IOWR_ALTERA_AVALON_CF_IDE_CYLINDER_HIGH(ide_base, ulLBA & 0xFF);
ulLBA >>= 8;
IOWR_ALTERA_AVALON_CF_IDE_DEVICE_HEAD(ide_base, (ulLBA & 0x0F) | 0xE0 | // LBA on
(iDevice ? DevHeadRegBitDEV : 0));
// e) The host writes the command code to the Command register.
IOWR_ALTERA_AVALON_CF_IDE_COMMAND(ide_base, WriteSectorWithRetries);
// f) The device sets the BSY bit and prepares to execute the command
// including preparation to transfer the first block of data to the
// host. (Note: it may take up to 400ns for BSY to go high.)
usleep(1);
// g) When ready to receive the first block of data from the host, the device
// sets the DRQ bit (setting the DRQ bit is optional if an error condition
// exists) and any other status or error bits as required and clears the BSY
// bit.
// h) The host reads the status or alternate status register until BSY is
// equal to 0.
if (!awaitBSYZero(1000))
{
printf("timeout (2) awaiting BSY=0 in writeSectorsLBA()\r");
return 0;
}
usStatus = IORD_ALTERA_AVALON_CF_IDE_STATUS(ide_base);
// i) If the DRQ bit is set, the host transfers a complete block of data to
// the device by writing the Data register.
usStatus = IORD_ALTERA_AVALON_CF_IDE_ALTERNATE_STATUS(ide_base);
if (usStatus & StatusRegBitDRQ)
{
for (i = 0; i < 256; ++i)
{
IOWR_ALTERA_AVALON_CF_IDE_DATA(ide_base, pusBuffer[i]);
}
}
else
{
printf("writeSectorsLBA(): error: DRQ not set.\r");
return 0;
}
// j) Next, one of the following actions is taken:
// - if an error status was present in the status read in step h), the device
// clears the DRQ bit, asserts INTRQ and the command execution is complete.
// The data transferred in steup i) is not processed by the device.
// - if no error status was presented to the host in step h), the device sets
// the BSY bit and processing continues with the next step.
if (usStatus & AltStatusRegBitERR)
{
usStatus = IORD_ALTERA_AVALON_CF_IDE_STATUS(ide_base); // Clear INTRQ
printf("error occurred during write (error reg: 0x%X)\r",
IORD_ALTERA_AVALON_CF_IDE_ERROR(ide_base));
return 0;
}
#if 0
// Oddly, the QUANTUM FIREBALLP LM20.4 times out here. Also oddly,
// removing this test makes things work fine.
if (!awaitBSYOne(1000))
{
printf("writeSectorsLBA(): timeout awaiting BSY=1\r");
return 0;
}
#endif // 0
iNumSectorsWritten++;
while (1)
{
// k) The device processes the data block just received from the host. When
// this processing is completed, one of the following actions is taken:
// - If no error occurred while processing the data block and if no additional
// blocks are to be transferred, the device clears the BSY bit and then
// asserts INTRQ. Command execution is complete;
// - If an error occured while processing the data block the device sets the
// appropriate bits as required by the error condition. The device clears
// the BSY bit and then asserts INTRQ. Command execution is complete.
// - If no error occurred while processing the data block and if the transfer
// of another block is required, processing continues with the next step.
if (!awaitBSYZero(1000))
{
printf("timeout (3) awaiting BSY=0 in writeSectorsLBA()\r");
return 0;
}
// Clear INTRQ.
usStatus = IORD_ALTERA_AVALON_CF_IDE_STATUS(ide_base);
if (usStatus & StatusRegBitERR)
{
printf("writeSectorsLBA(): error register = 0x%X\r",
IORD_ALTERA_AVALON_CF_IDE_ERROR(ide_base));
return 0;
}
if (iNumSectorsWritten >= iSectorCount)
{
return 1;
}
// l) When ready to receive the next block from the host, the device sets the
// DRQ bit, clears the BSY bit and then asserts INTRQ;
if (!awaitDRQ(1000))
{
printf("writeSectorsLBA(): timeout awaiting DRQ for multiple sector write.\r");
return 0;
}
// m) After detecting either BSY=0 (alternate status) or INTRQ, the host reads
// the contents of the status register.
if (!awaitBSYZeroOrINTRQ(1000))
{
printf("timeout awaiting BSY=0 or INTRQ in writeSectorsLBA()\r");
return 0;
}
#if 0
if (!awaitBSYZero(1000))
{
printf("timeout (4) awaiting BSY=0 in writeSectorsLBA()\r");
return 0;
}
if (!awaitINTRQ(1000))
{
printf("timeout awaiting INTRQ in writeSectorsCHS()\r");
// return 0;
}
#endif
usStatus = IORD_ALTERA_AVALON_CF_IDE_STATUS(ide_base);
// The host transfers a complete block of data to the device by writing
// the data register
for (i = 0; i < 256; ++i)
{
IOWR_ALTERA_AVALON_CF_IDE_DATA(ide_base, pusBuffer[i + iNumSectorsWritten * 256]);
}
// o) The device sets the BSY bit and processing continues at step k).
iNumSectorsWritten++;
}
return 1;
}
// PIO Data out:
// a) The host reads the status or alt status reg until BSY=0.
// b) The host writes the dev/head register with the appropriate dev
// bit value.
// c) The host reads the status or alt status register until BSY=0 and
// DRDY=1.
int writeSectorsCHS(int iDevice, int iCylinder, int iHead, int iSectorNumber,
int iSectorCount, unsigned short *pusBuffer)
{
unsigned short usStatus;
int i;
int iNumSectorsWritten = 0;
if (gbVerbose)
{
printf("(%d, %d, %d)\r",
iCylinder, iHead, iSectorNumber);
}
if (!PIODataInOrOutPreamble(iDevice))
{
printf("writeSectorsCHS(): PIODataInOrOutPreamble failed.\r");
return 0;
}
// d) The host writes any required command parameters to the Features,
// Sector Count, Sector Number, Cylinder High, Cylinder Low and
// Device/Head registers.
IOWR_ALTERA_AVALON_CF_IDE_SECTOR_COUNT(ide_base, iSectorCount);
IOWR_ALTERA_AVALON_CF_IDE_SECTOR_NUMBER(ide_base, iSectorNumber);
IOWR_ALTERA_AVALON_CF_IDE_CYLINDER_LOW(ide_base, iCylinder & 0xFF);
IOWR_ALTERA_AVALON_CF_IDE_CYLINDER_HIGH(ide_base, iCylinder >> 8);
IOWR_ALTERA_AVALON_CF_IDE_DEVICE_HEAD(ide_base,
(iDevice ? DevHeadRegBitDEV : 0) |
(iHead & DevHeadRegBitHeads));
// e) The host writes the command code to the Command register.
IOWR_ALTERA_AVALON_CF_IDE_COMMAND(ide_base, WriteSectorWithRetries);
// f) The device sets the BSY bit and prepares to execute the command
// including preparation to transfer the first block of data to the
// host. (Note: it may take up to 400ns for BSY to go high.)
usleep(1);
// g) When ready to receive the first block of data from the host, the device
// sets the DRQ bit (setting the DRQ bit is optional if an error condition
// exists) and any other status or error bits as required and clears the BSY
// bit.
// h) The host reads the status or alternate status register until BSY is
// equal to 0.
if (!awaitBSYZero(1000))
{
printf("timeout (2) awaiting BSY=0 in writeSectorsCHS()\r");
return 0;
}
usStatus = IORD_ALTERA_AVALON_CF_IDE_STATUS(ide_base);
// i) If the DRQ bit is set, the host transfers a complete block of data to
// the device by writing the Data register.
usStatus = IORD_ALTERA_AVALON_CF_IDE_ALTERNATE_STATUS(ide_base);
if (usStatus & StatusRegBitDRQ)
{
for (i = 0; i < 256; ++i)
{
IOWR_ALTERA_AVALON_CF_IDE_DATA(ide_base, pusBuffer[i]);
}
}
else
{
printf("writeSectorsCHS(): error: DRQ not set.\r");
return 0;
}
// j) Next, one of the following actions is taken:
// - if an error status was present in the status read in step h), the device
// clears the DRQ bit, asserts INTRQ and the command execution is complete.
// The data transferred in steup i) is not processed by the device.
// - if no error status was presented to the host in step h), the device sets
// the BSY bit and processing continues with the next step.
if (usStatus & AltStatusRegBitERR)
{
usStatus = IORD_ALTERA_AVALON_CF_IDE_STATUS(ide_base); // Clear INTRQ
printf("error occurred during write (error reg: 0x%X)\r",
IORD_ALTERA_AVALON_CF_IDE_ERROR(ide_base));
return 0;
}
#if 0
// Oddly, the QUANTUM FIREBALLP LM20.4 times out here. Also oddly,
// removing this test makes things work fine.
if (!awaitBSYOne(1000))
{
printf("writeSectorsCHS(): timeout awaiting BSY=1\r");
return 0;
}
#endif // 0
iNumSectorsWritten++;
while (1)
{
// k) The device processes the data block just received from the host. When
// this processing is completed, one of the following actions is taken:
// - If no error occurred while processing the data block and if no additional
// blocks are to be transferred, the device clears the BSY bit and then
// asserts INTRQ. Command execution is complete;
// - If an error occured while processing the data block the device sets the
// appropriate bits as required by the error condition. The device clears
// the BSY bit and then asserts INTRQ. Command execution is complete.
// - If no error occurred while processing the data block and if the transfer
// of another block is required, processing continues with the next step.
if (!awaitBSYZero(1000))
{
printf("timeout (3) awaiting BSY=0 in writeSectorsCHS()\r");
return 0;
}
// Clear INTRQ.
usStatus = IORD_ALTERA_AVALON_CF_IDE_STATUS(ide_base);
if (usStatus & StatusRegBitERR)
{
printf("writeSectorsCHS(): error register = 0x%X\r",
IORD_ALTERA_AVALON_CF_IDE_ERROR(ide_base));
return 0;
}
if (iNumSectorsWritten >= iSectorCount)
{
return 1;
}
// l) When ready to receive the next block from the host, the device sets the
// DRQ bit, clears the BSY bit and then asserts INTRQ;
if (!awaitDRQ(1000))
{
printf("writeSectorsCHS(): timeout awaiting DRQ for multiple sector write.\r");
return 0;
}
// m) After detecting either BSY=0 (alternate status) or INTRQ, the host reads
// the contents of the status register.
if (!awaitBSYZeroOrINTRQ(1000))
{
printf("timeout awaiting BSY=0 or INTRQ in writeSectorsCHS()\r");
return 0;
}
#if 0
if (!awaitBSYZero(1000))
{
printf("timeout (4) awaiting BSY=0 in writeSectorsCHS()\r");
return 0;
}
if (!awaitINTRQ(1000))
{
printf("timeout awaiting INTRQ in writeSectorsCHS()\r");
// return 0;
}
#endif
usStatus = IORD_ALTERA_AVALON_CF_IDE_STATUS(ide_base);
// The host transfers a complete block of data to the device by writing
// the data register
for (i = 0; i < 256; ++i)
{
IOWR_ALTERA_AVALON_CF_IDE_DATA(ide_base, pusBuffer[i + iNumSectorsWritten * 256]);
}
// o) The device sets the BSY bit and processing continues at step k).
iNumSectorsWritten++;
}
return 1;
}
int executeDeviceDiagnostic(int iDevice)
{
unsigned short usStatus, usError;
// a) The host reads the status or alt status reg until BSY=0.
if (!awaitBSYZero(1000))
{
printf("timeout (1) awaiting BSY=0 in executeDeviceDiagnostic()\r");
return 0;
}
// b) The host writes the dev/head register with the appropriate dev
// bit value.
IOWR_ALTERA_AVALON_CF_IDE_DEVICE_HEAD(ide_base, iDevice ? DevHeadRegBitDEV : 0);
// c) The host reads the status or alt status register until BSY=0 and
// DRDY=1.
if (!awaitBSYZeroDRDYOne())
{
printf("timeout awaiting BSY=0, DRDY=1 in executeDeviceDiagnostic()\r");
return 0;
}
IDEinterrupt = 0;
IOWR_ALTERA_AVALON_CF_IDE_COMMAND(ide_base, ExecuteDeviceDiagnostic);
usleep(1);
usStatus = IORD_ALTERA_AVALON_CF_IDE_STATUS(ide_base);
if (StatusRegBitERR & usStatus)
{
printf("Error? error register: 0x%X\r",
IORD_ALTERA_AVALON_CF_IDE_ERROR(ide_base));
}
// Wait for BSY=0. This one takes seconds!
if (!awaitBSYZero(3000))
{
printf("timeout (2) awaiting BSY=0 in executeDeviceDiagnostic()\r");
return 0;
}
// Wait for INTRQ.
if (!awaitINTRQ(5000))
{
printf("timeout awaiting INTRQ=1 in executeDeviceDiagnostic()\r");
printf("error register: 0x%X\r", IORD_ALTERA_AVALON_CF_IDE_ERROR(ide_base));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -