📄 ideutils.c
字号:
printf("status register: 0x%X\r", IORD_ALTERA_AVALON_CF_IDE_STATUS(ide_base));
return 0;
}
// Read the status register to clear INTRQ.
usStatus = IORD_ALTERA_AVALON_CF_IDE_STATUS(ide_base);
usError = IORD_ALTERA_AVALON_CF_IDE_ERROR(ide_base);
if (usStatus & StatusRegBitERR)
{
printf("Device Diagnostic return code: 0x%X\r", 0xFF & usError);
}
else
{
// The meanings of other than bits 0 and 7 are vendor-specific.
switch (usError & 0x81)
{
case 0x0:
printf("Device 0 failed, device 1 passed or not present.\r");
break;
case 0x01:
printf("Device 0 passed; device 1 passed or not present.\r");
break;
case 0x80:
printf("Device 0 failed, device 1 failed.\r");
break;
case 0x81:
printf("Device 0 passed, device 1 failed.\r");
break;
default:
printf("unexpected case in executeDeviceDiagnostic()\r");
break;
}
}
return 1;
}
int getLogicalHeads(void)
{
return gusLogicalHeads;
}
int getLogicalCylinders(void)
{
return gusLogicalCylinders;
}
int getSectorsPerTrack(void)
{
return gusSectorsPerTrack;
}
char* getModel(void)
{
return gModel;
}
int IDE_initializeDeviceParameters(int iDevice,
unsigned short usLogicalHeads, unsigned short usLogicalCylinders,
unsigned short usSectorsPerTrack)
{
unsigned short usStatus, usError;
// a) The host reads the status or alt status reg until BSY=0.
if (!awaitBSYZero(1000))
{
printf("timeout awaiting BSY=0 in initializeDeviceParameters()\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 initializeDeviceParameters()\r");
return 0;
}
IOWR_ALTERA_AVALON_CF_IDE_SECTOR_COUNT(ide_base, usSectorsPerTrack);
IOWR_ALTERA_AVALON_CF_IDE_DEVICE_HEAD(ide_base,
(iDevice ? DevHeadRegBitDEV : 0) | (usLogicalHeads - 1));
IDEinterrupt = 0;
IOWR_ALTERA_AVALON_CF_IDE_COMMAND(ide_base, InitializeDeviceParameters);
// Wait for INTRQ.
if (!awaitINTRQ(5000))
{
printf("timeout awaiting INTRQ=1 in initializeDeviceParameters()\r");
printf("error register: 0x%X\r", IORD_ALTERA_AVALON_CF_IDE_ERROR(ide_base));
printf("status register: 0x%X\r", IORD_ALTERA_AVALON_CF_IDE_STATUS(ide_base));
return 0;
}
// Read the status register to clear INTRQ.
usStatus = IORD_ALTERA_AVALON_CF_IDE_STATUS(ide_base);
if (usStatus & StatusRegBitERR)
{
usError = IORD_ALTERA_AVALON_CF_IDE_ERROR(ide_base);
printf("Error? status: 0x%X; error: 0x%X\r", usStatus, usError);
}
else
{
if (IDE_getVerbosity())
{
printf("successfully wrote default parameters to IDE drive.\n");
}
}
return 1;
}
void parseIdentifyDeviceBuffer(unsigned short *pusBuffer)
{
int i;
char *p;
p = gModel;
for (i = 27; i <= 46; ++i) {
*p++ = (char) (pusBuffer[i] >> 8);
*p++ = (char) (pusBuffer[i] & 0xFF);
}
if (gbVerbose)
{
printf("serial number: ");
for (i = 10; i < 20; ++i)
{
printf("%c%c", pusBuffer[i] >> 8, pusBuffer[i] & 0xFF);
}
printf("\r");
printf("firmware revision: ");
for (i = 23; i < 27; ++i)
{
printf("%c%c", pusBuffer[i] >> 8, pusBuffer[i] & 0xFF);
}
printf("\r");
printf("model number: %s\r", gModel);
}
if (((0x2<<8) & pusBuffer[49] ) != 0) {
gusLBAmode = 1;
gulLBAcapacity = pusBuffer[60] + (pusBuffer[61]<<16);
}
if ((0x2 & pusBuffer[64] ) != 0)
gusPIOmode = 4;
else if ((0x01 & pusBuffer[64] ) != 0)
gusPIOmode = 3;
else
gusPIOmode = pusBuffer[51] >> 8;
if (gusPIOmode > 4)
gusPIOmode = 0;
gusLogicalCylinders = pusBuffer[1];
gusLogicalHeads = pusBuffer[3];
gusSectorsPerTrack = pusBuffer[6];
if (gbVerbose)
{
printf("LBA mode %ssupported\r", gusLBAmode ? "" : "not ");
printf("PIO mode supported: %d\r", gusPIOmode);
printf("device parameters:\r");
printf(
" # logical cylinders: %d\r"
" # logical heads: %d\r"
" # logical sectors/track: %d\r",
gusLogicalCylinders, gusLogicalHeads, gusSectorsPerTrack);
if (gusLBAmode)
printf(" LBA capacity = %u sectors\r", (unsigned int)gulLBAcapacity);
}
}
int IDE_identifyDevice(unsigned int uiDeviceNumber)
{
unsigned short usStatus;
int i;
unsigned short usBuffer[256];
if (gbVerbose)
{
printf("Identify Device:\r");
}
#if DEBUG
printf("\rIDE_identifyDevice()\r");
#endif // DEBUG
// Select the device to identify.
if (uiDeviceNumber > 1)
{
printf("invalid device number in IDE_identifyDevice (%d)\r",
uiDeviceNumber);
return 0;
}
if (IORD_ALTERA_AVALON_CF_CTL_STATUS(ctl_base)
& ALTERA_AVALON_CF_CTL_STATUS_PRESENT_MSK)
{
#if DEBUG
printf("IDE_identifyDevice: card is inserted\r");
#endif // DEBUG
}
else
{
printf("CompactFlash card is removed\r");
return 0;
}
// a) The host reads the status or alt status reg until BSY=0.
if (!awaitBSYZero(1000))
{
printf("timeout awaiting BSY=0 in IDE_identifyDevice()\r");
return 0;
}
#if DEBUG
printf("IDE_identifyDevice: found BSY=0\r");
#endif // DEBUG
// b) The host writes the dev/head register with the appropriate dev
// bit value.
IOWR_ALTERA_AVALON_CF_IDE_DEVICE_HEAD(ide_base, uiDeviceNumber ? 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 IDE_identifyDevice()\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.
// (No input parameters for Identify Device)
// e) The host writes the command code to the Command register.
IDEinterrupt = 0;
IOWR_ALTERA_AVALON_CF_IDE_COMMAND(ide_base, IdentifyDeviceCmd);
// 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 the block of data is available, the device sets the DRQ bit
// (setting the DRQ bit is optional if an error condition exists).
// If there is an error condition, the device sets the appropriate status
// and error bits as required by that error condition. Finally, the device
// clears BSY and then asserts INTRQ. (Note: there may be times when BSY
// is set in f) and then cleared in g) so quickly that the host may not
// be able to detect that BSY had been set.)
// Wait for INTRQ.
// Empirically, I note that after a hardware reset (press SW2), it can take
// an eternity (3.3 s) to get INTRQ here, on the Connor drive at least.
// Use a really long timeout.
if (!awaitINTRQ(5000))
{
printf("timeout awaiting INTRQ=1 in identifyDevice()\r");
printf("error register: 0x%X\r", IORD_ALTERA_AVALON_CF_IDE_ERROR(ide_base));
return 0;
}
// h) After detecting either BSY=0 (alt status) or INTRQ, the host reads and
// saves the contents of the status register.
usStatus = IORD_ALTERA_AVALON_CF_IDE_STATUS(ide_base); // (To clear INTRQ)
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 & StatusRegBitDRQ)
{
for (i = 0; i < 256; ++i)
{
usBuffer[i] = IORD_ALTERA_AVALON_CF_IDE_DATA(ide_base);
}
}
else
{
printf("DRQ not set in status reg in identifyDevice()\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.
parseIdentifyDeviceBuffer(usBuffer);
return 1;
}
void printSectorBuffer(unsigned long ulNumSectors, unsigned short *pusBuffer)
{
int i, j, k;
unsigned char ucStr[] = "0123456789012345";
unsigned char *pucBuffer = (unsigned char*)pusBuffer;
for (i = 0; i < ulNumSectors * 512; i += 512)
{
for (j = 0; j < 512; j += 16)
{
printf("%04X: ", i + j);
for (k = 0; k < 16; ++k)
{
printf("%02X ", pucBuffer[i + j + k]);
if (pucBuffer[i + j + k] >= 0x20 && pucBuffer[i + j + k] <= 0x7F)
{
ucStr[k] = pucBuffer[i + j + k];
}
else
{
ucStr[k] = '.';
}
}
printf(" %s\r", ucStr);
}
printf("\r");
}
}
void randomizeBuffer(unsigned long ulNumSectors, unsigned short *usBuffer)
{
unsigned long i;
for (i = 0; i < 256 * ulNumSectors; ++i)
{
usBuffer[i] = (rand() & 0xFFFF00) >> 8;
}
}
int multiRead(char *szArg)
{
#define MULTIPLE_SECTOR_READ 1
int iHead, iCylinder, iSectorNumber;
int iResult;
#if MULTIPLE_SECTOR_READ
unsigned short *pusBuffer;
#else
unsigned short usBuffer[256];
#endif // MULTIPLE_SECTOR_READ
int iNumSectorsRead = 0, iNumSectorsToRead;
volatile unsigned int uiStartTime;
volatile unsigned int uiDeltaTime;
if (1 != sscanf(szArg, "%d", &iNumSectorsToRead))
{
printf("multiRead: arg '%s' makes no sense.\r", szArg);
return 0;
}
#if MULTIPLE_SECTOR_READ
pusBuffer = (unsigned short*)malloc(256 * gusSectorsPerTrack * sizeof(unsigned short));
if (!pusBuffer)
{
printf("multiRead: memory allocation failure.\n");
return 0;
}
#endif // MULTIPLE_SECTOR_READ
printf("reading %d sectors on device 0. Hit any key to abort.\r", iNumSectorsToRead);
// Flush input buffer.
#if 0
while (-1 != nr_uart_rxchar(0)) {}
#else
getchar();
#endif
uiStartTime = getTime();
// Read forever (up to the number of sectors requested, or keypress).
while (1)
{
for (iCylinder = 0; iCylinder < gusLogicalCylinders; ++iCylinder)
{
for (iHead = 0; iHead < gusLogicalHeads; ++iHead)
{
// Do this checking here, rather than on a sector-by-sector basis, to
// boost performance.
#if 0
if (-1 != nr_uart_rxchar(0))
#else
getchar();
#endif
{
goto computeStats;
}
#if MULTIPLE_SECTOR_READ
// Done yet?
if (iNumSectorsRead >= iNumSectorsToRead)
{
goto computeStats;
}
iResult = readSectorsCHS(0, iCylinder, iHead, 1, gusSectorsPerTrack, pusBuffer);
if (1 != iResult)
{
printf("(0, %d, %d, %d, %d) failed.\r",
iCylinder, iHead, iSectorNumber, gusSectorsPerTrack);
}
else
{
iNumSectorsRead += gusSectorsPerTrack;
if (gbVerbose)
{
printf("(0, %d, %d, %d, %d) succeeded.\r",
iCylinder, iHead, iSectorNumber, gusSectorsPerTrack);
printSectorBuffer(gusSectorsPerTrack, pusBuffer);
}
}
#else // !MULTIPLE_SECTOR_READ
for (iSectorNumber = 1; iSectorNumber <= gusSectorsPerTrack; ++iSectorNumber)
{
// Done yet?
if (iNumSectorsRead >= iNumSectorsToRead)
{
goto computeStats;
}
iResult = readSectorsCHS(0, iCylinder, iHead, iSectorNumber, 1, usBuffer);
if (1 != iResult)
{
printf("(0, %d, %d, %d, 1) failed.\r",
iCylinder, iHead, iSectorNumber);
}
else
{
iNumSectorsRead++;
if (gbVerbose)
{
printf("(0, %d, %d, %d, 1) succeeded.\r",
iCylinder, iHead, iSectorNumber);
printSectorBuffer(1, usBuffer);
}
}
}
#endif // MULTIPLE_SECTOR_READ
}
}
}
computeStats:
#if MULTIPLE_SECTOR_READ
if (pusBuffer)
{
free(pusBuffer);
pusBuffer = 0;
}
#endif // MULTIPLE_SECTOR_READ
uiDeltaTime = getTime() - uiStartTime;
printf("%d sectors read in %d.%d s\r",
iNumSectorsRead, uiDeltaTime / 1000, uiDeltaTime % 1000);
printf("at 512 bytes/sector, that's %d bytes/second\r\r",
(int)(iNumSectorsRead * 512. * 1000 / uiDeltaTime));
return 1;
}
int multiWrite(char *szArg)
{
#define MULTIPLE_SECTOR_WRITE 1
int iHead, iCylinder, iSectorNumber;
int iResult;
#if MULTIPLE_SECTOR_WRITE
unsigned short *pusBuffer;
#else // !MULTIPLE_SECTOR_WRITE
unsigned short usBuffer[256];
#endif // MULTIPLE_SECTOR_WRITE
int iNumSectorsWritten = 0, iNumSectorsToWrite;
volatile unsigned int uiStartTime;
volatile unsigned int uiDeltaTime;
if (1 != sscanf(szArg, "%d", &iNumSectorsToWrite))
{
printf("multiWrite: arg '%s' makes no sense.\r", szArg);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -