📄 ide.c
字号:
} while(status & BUSY);
return ERR_NOERR;
}
/*
* name: WaitForDRDY()
* parameter: void
* return: bool
* true, no busy any data is ready; flase, failed.
* description: waiting, till no busy and data is ready.
*/
static unsigned int WaitForDRDY(void)
{
unsigned char status;
do
{
status = ReadStatus();
if(status & ERROR)
return ReadError();
} while((status & (BUSY|DRDY)) != DRDY);
return ERR_NOERR;
}
/*
* name: WaitForDRQ()
* parameter: void
* return: status code.
* description: waiting, till no busy and occur data request.
*/
static unsigned int WaitForDRQ(void)
{
unsigned char status;
do
{
status = ReadStatus();
if(status & ERROR)
return ReadError();
} while((status & (BUSY|DRQ)) != DRQ);
return ERR_NOERR;
}
/*
* name: CheckStatus()
* parameter: void
* return: status code.
* description: executed command, check status.
*/
static unsigned int CheckStatus(void)
{
unsigned char status;
status = ReadStatus();
if(status & (ERROR | DRQ))
{
if(status & ERROR)
return ReadError();
}
if(!(status & DRDY))
return ERR_AMNF;
return ERR_NOERR;
}
/*
* name: WriteLBA()
* parameter: lba ---input, logical block address.
* return: void
* description: write lba registers.
*/
static void WriteLBA(unsigned long lba)
{
WriteSectorNumber(lba & 0xff);
WriteCylinder((lba >> 16) & 0xffff);
WriteDriveHead((lba >> 8) & 0x1f);
}
/*
* name: IDE_Init()
* parameter: drive ---input, primary or slave drive.
* return: boolean
* true --- found IDE drive, false --- otherwise
* description: initialize IDE drive.
*/
int IDE_Init(int drive)
{
unsigned char err, cnt, num, dhd;
unsigned short cyl;
WriteDeviceControl(SRST|nIEN);
delay(100);
WriteDeviceControl(nIEN);
if(drive & 0x1)
WriteLBA(((drive & 0x1) << 12) | 1);
err = ReadError();
cnt = ReadSectorCount();
num = ReadSectorNumber();
cyl = ReadCylinder();
dhd = ReadDriveHead();
if(err == 1 && cnt == 1 && num == 1
&& cyl == 0 && (dhd == 0 || dhd == 0xb0))
{
return 1;
}
return 0;
}
/*
* name: IDE_Diagnostics()
* parameter: drive ---input, primary or slave drive.
* err ---output, drive error code.
* return: status code.
* description: diagnose IDE drive.
*/
unsigned int IDE_Diagnostics(int drive, enum DrvErr *err)
{
unsigned int status;
status = WaitForNoBUSY_igError();
if(status != ERR_NOERR)
return status;
WriteDriveHead(((drive & 0x1) << 4));
WriteCommand(EXECUTE_DRIVE_DIAGNOSTIC);
status = WaitForNoBUSY_igError();
if(status != ERR_NOERR)
return status;
*err = (enum DrvErr)ReadError();
return status;
}
/*
* name: IDE_Diagnostics()
* parameter: drive ---input, primary or slave drive.
* id ---output, receive drive identification.
* return: status code.
* description: read drive identification.
*/
unsigned int IDE_Identification(int drive, struct DriveId *id)
{
unsigned int i, status;
unsigned short word;
status = WaitForNoBUSY();
if(status != ERR_NOERR)
return status;
WriteDriveHead(((drive & 0x1) << 4));
WriteCommand(IDENTIFY_DRIVE);
status = WaitForDRQ();
if(status != ERR_NOERR)
return status;
memset(id, 0, sizeof(struct DriveId));
ReadData(); /* 00h */
id->cylinders = ReadData(); /* 01h */
ReadData(); /* 02h */
id->heads = ReadData(); /* 03h */
id->bytes_per_track = ReadData(); /* 04h */
id->bytes_per_sector = ReadData(); /* 05h */
id->sectors_per_track = ReadData(); /* 06h */
ReadData(); /* 07h */
ReadData(); /* 08h */
id->vendor_id = ReadData(); /* 09h */
for(i=0; i<10; i++) /* 0Ah - 13h */
{
word = ReadData();
word = ((word & 0xff) << 8) | ((word & 0xff00) >> 8);
*(unsigned short *)(id->serial_number + i*sizeof(short)) = word;
}
ReadData(); /* 14h */
ReadData(); /* 15h */
ReadData(); /* 16h */
for(i=0; i<4; i++) /* 17h - 1Ah */
{
word = ReadData();
word = ((word & 0xff) << 8) | ((word & 0xff00) >> 8);
*(unsigned short *)(id->firmware_version + i*sizeof(short)) = word;
}
for(i=0; i<20; i++) /* 1Bh - 2Eh */
{
word = ReadData();
word = ((word & 0xff) << 8) | ((word & 0xff00) >> 8);
*(unsigned short *)(id->model_number + i*sizeof(short)) = word;
}
ReadData(); /* 2Fh */
ReadData(); /* 30h */
ReadData(); /* 31h */
ReadData(); /* 32h */
id->minimum_pio = ReadData(); /* 33h */
id->minimum_dma = ReadData(); /* 34h */
for(i=0x35; i<SECTOR_WORDS; i++) /* 35h - 99h */
ReadData();
return CheckStatus();
}
/*
* name: IDE_ReadSectors()
* parameter: lba ---input, logical block address.
* buf ---output, receive sector data.
* count ---input, number of sector buffer.
* return: status code.
* description: read sectors data.
*/
unsigned int IDE_ReadSectors(unsigned long lba,
struct Sector *buf, unsigned char count)
{
unsigned int i, status;
unsigned short *ptr;
status = WaitForNoBUSY();
if(status != ERR_NOERR)
return status;
WriteSectorCount(count);
WriteLBA(lba);
WriteCommand(READ_SECTORS_WITH_RETRY);
ptr = (unsigned short *)buf;
do
{
status = WaitForDRQ();
if(status != ERR_NOERR)
return status;
for(i=0; i<SECTOR_WORDS; i++)
*ptr++ = ReadData();
}while(--count);
return CheckStatus();
}
/*
* name: IDE_WriteSectors()
* parameter: lba ---input, logical block address.
* buf ---input, sector data will be write.
* count ---input, number of sector buffer.
* return: status code.
* description: write sectors data.
*/
unsigned int IDE_WriteSectors(unsigned long lba,
const struct Sector *buf, unsigned char count)
{
unsigned int i, status;
unsigned short *ptr;
status = WaitForNoBUSY();
if(status != ERR_NOERR)
return status;
WriteSectorCount(count);
WriteLBA(lba);
WriteCommand(WRITE_SECTORS_WITH_RETRY);
ptr = (unsigned short *)buf;
do
{
status = WaitForDRQ();
if(status != ERR_NOERR)
return status;
for(i=0; i<SECTOR_WORDS; i++)
WriteData(*ptr++);
}while(--count);
return CheckStatus();
}
/*
* name: IDE_GetStatusString()
* parameter: status ---input, status
* return: string.
* description: convert status code to corresponding string.
*/
const char* IDE_GetStatusString(unsigned long status)
{
int i, cnt;
status &= 0xff;
if(status)
{
for(i=0; i<sizeof(char); i++)
{
if(status & 0x1)
return StaString[i];
status >>= 1;
}
}
return 0;
}
/*
* name: IDE_GetErrorString()
* parameter: err ---input, drive error code.
* return: string.
* description: convert error code to corresponding string.
*/
const char* IDE_GetErrorString(enum DrvErr err)
{
int i = (err & 0x7f);
if(i > 0 && i <= 5)
{
i--;
if(err & 0x80)
i += 5;
return ErrString[i];
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -