📄 idedrv.c
字号:
default:
(void) errnoSet (S_ioLib_UNKNOWN_REQUEST);
}
doneIoctl:
semGive (&ideMuteSem);
return (status);
}
/*******************************************************************************
*
* ideBlkRW - read or write sectors to a IDE disk.
*
* Read or write sectors to a IDE disk.
*
* RETURNS: OK, ERROR if the command didn't succeed.
*/
LOCAL STATUS ideBlkRW
(
IDE_DEV *pIdeDev,
int startBlk,
int nBlks,
char *pBuf,
int direction
)
{
BLK_DEV *pBlkDev = &pIdeDev->blkDev;
int cylinder;
int head;
int sector;
int ix;
int nSecs;
int retryRW0 = 0;
int retryRW1 = 0;
int retrySeek = 0;
int status = ERROR;
IDE_TYPE *pType = &ideTypes[pIdeDev->drive];
/* sanity check */
nSecs = pBlkDev->bd_nBlocks;
if ((startBlk + nBlks) > nSecs)
{
if (ideDebugErr)
printErr ("startBlk=%d nBlks=%d: 0 - %d\n", startBlk, nBlks, nSecs);
return (ERROR);
}
startBlk += pIdeDev->blkOffset;
semTake (&ideMuteSem, WAIT_FOREVER);
for (ix = 0; ix < nBlks; ix += nSecs)
{
cylinder = startBlk / (pType->sectorsTrack * pType->heads);
sector = startBlk % (pType->sectorsTrack * pType->heads);
head = sector / pType->sectorsTrack;
sector = sector % pType->sectorsTrack + 1;
nSecs = min (nBlks - ix, pType->sectorsTrack - sector + 1);
retrySeek = 0;
while (ideSeek(pIdeDev->drive, cylinder, head) != OK)
if (++retrySeek > ideRetry)
goto done;
retryRW1 = 0;
retryRW0 = 0;
while (ideRW (pIdeDev->drive, cylinder, head, sector,
pBuf, nSecs, direction) != OK)
{
if (++retryRW0 > ideRetry)
{
(void) ideRecalib (pIdeDev->drive);
if (++retryRW1 > ideRetry)
goto done;
retrySeek = 0;
while (ideSeek(pIdeDev->drive, cylinder, head) != OK)
if (++retrySeek > ideRetry)
goto done;
retryRW0 = 0;
}
}
startBlk += nSecs;
pBuf += pBlkDev->bd_bytesPerBlk * nSecs;
}
status = OK;
done:
if (status == ERROR)
(void)errnoSet (S_ioLib_DEVICE_ERROR);
semGive (&ideMuteSem);
return (status);
}
/*******************************************************************************
*
* ideIntr - IDE controller interrupt handler.
*
* RETURNS: N/A
*/
LOCAL void ideIntr
(
int ctrl
)
{
ideIntCount++; /* XXX */
ideStatus = sysInByte (IDE_STATUS);
semGive (&ideSyncSem);
}
/*******************************************************************************
*
* ideIntr - IDE controller watchdog handler.
*
* RETURNS: N/A
*/
LOCAL void ideWdog
(
int ctrl
)
{
ideWaitForever = FALSE;
}
/*******************************************************************************
*
* ideWait - wait the drive ready
*
* Wait the drive ready
*
* RETURNS: OK, ERROR if the drive didn't become ready in certain period of time.
*/
LOCAL void ideWait
(
int request
)
{
switch (request)
{
case STAT_READY:
wdStart (ideWid, (sysClkRateGet() * ideWdSec), (FUNCPTR)ideInit, 0);
while (sysInByte (IDE_STATUS) & STAT_BUSY)
;
while ((sysInByte (IDE_STATUS) & STAT_READY) == 0)
;
wdCancel (ideWid);
break;
case STAT_DRQ:
while ((sysInByte (IDE_STATUS) & STAT_DRQ) == 0)
;
break;
case STAT_SEEKCMPLT:
while ((sysInByte (IDE_STATUS) & STAT_SEEKCMPLT) == 0)
;
break;
}
if (ideDebug)
printErr ("ideWait end: \n");
}
/*******************************************************************************
*
* ideInit - init a IDE disk controller
*
* This routine initializes a IDE disk controller.
*
* RETURNS: OK, ERROR if the command didn't succeed.
*/
LOCAL void ideInit (void)
{
int ix;
sysOutByte (IDE_D_CONTROL, CTL_RST | CTL_IDS);
for (ix = 0; ix < 100; ix++)
sysDelay ();
sysOutByte (IDE_D_CONTROL, CTL_IDS);
for (ix = 0; ix < 100; ix++)
sysDelay ();
while ((sysInByte (IDE_STATUS) & STAT_BUSY) && (ideWaitForever))
;
sysOutByte (IDE_D_CONTROL, CTL_4BIT);
for (ix = 0; ix < 100; ix++)
sysDelay ();
while (((sysInByte (IDE_STATUS) & STAT_READY) == 0) && (ideWaitForever))
;
semBInit (&ideSyncSem, SEM_Q_FIFO, SEM_EMPTY);
if (ideDebug)
printErr ("ideInit end: \n");
}
/*******************************************************************************
*
* ideDiagnose - diagnose the drive
*
* Diagnose the drive
*
* RETURNS: OK, ERROR if the command didn't succeed.
*/
LOCAL STATUS ideDiagnose (void)
{
int error;
int semStatus;
sysOutByte (IDE_SDH, SDH_IBM);
ideWait (STAT_READY);
sysOutByte (IDE_COMMAND, CMD_DIAGNOSE);
semStatus = semTake (&ideSyncSem, sysClkRateGet() * ideSemSec);
if (((error = sysInByte(IDE_ERROR)) != DIAG_OK) || (semStatus == ERROR))
{
if (ideDebugErr)
printErr ("ideDiagnose: status=0x%x error=0x%x\n",
ideStatus, error);
return (ERROR);
}
ideWait (STAT_READY);
if (ideDebug)
printErr ("ideDiagnose end: \n");
return (OK);
}
/*******************************************************************************
*
* idePinit - Initialize drive parameters
*
* Initialize drive parameters.
*
* RETURNS: OK, ERROR if the command didn't succeed.
*/
LOCAL STATUS idePinit
(
int drive
)
{
int status;
int error;
int semStatus;
int retryCount = 0;
IDE_TYPE *pType = &ideTypes[drive];
retryPinit:
sysOutByte (IDE_CYL_LO, pType->cylinders);
sysOutByte (IDE_CYL_HI, pType->cylinders >> 8);
sysOutByte (IDE_SECCNT, pType->sectorsTrack);
sysOutByte (IDE_SDH, SDH_IBM | (drive << 4) | ((pType->heads & 0xf) - 1));
ideWait (STAT_READY);
sysOutByte (IDE_COMMAND, CMD_INITP);
semStatus = semTake (&ideSyncSem, sysClkRateGet() * ideSemSec);
if ((ideStatus & STAT_ERR) || (semStatus == ERROR))
{
error = sysInByte (IDE_ERROR);
status = sysInByte (IDE_STATUS);
ideInit ();
if (ideDebugErr)
printErr ("idePinit%d err: stat=0x%x 0x%x error=0x%x\n",
drive, ideStatus, status, error);
if (++retryCount < ideRetry)
goto retryPinit;
return (ERROR);
}
ideWait (STAT_READY);
if (ideDebug)
printErr ("idePinit%d end: \n", drive);
return (OK);
}
/*******************************************************************************
*
* idePread - Read drive parameters
*
* Read drive parameters.
*
* RETURNS: OK, ERROR if the command didn't succeed.
*/
LOCAL STATUS idePread
(
int drive,
void *buffer
)
{
int status;
int error;
int semStatus;
int retryCount = 0;
retryPread:
sysOutByte (IDE_SDH, SDH_IBM | (drive << 4));
ideWait (STAT_READY);
sysOutByte (IDE_COMMAND, CMD_READP);
semStatus = semTake (&ideSyncSem, sysClkRateGet() * ideSemSec);
if ((ideStatus & STAT_ERR) || (semStatus == ERROR))
{
error = sysInByte (IDE_ERROR);
status = sysInByte (IDE_STATUS);
ideInit ();
if (ideDebugErr)
printErr ("idePread%d err: stat=0x%x 0x%x error=0x%x\n",
drive, ideStatus, status, error);
if (++retryCount < ideRetry)
goto retryPread;
return (ERROR);
}
ideWait (STAT_DRQ);
sysInWordString (IDE_DATA, (short *)buffer, 256);
ideWait (STAT_READY);
if (ideDebug)
printErr ("idePread%d end: \n", drive);
return (OK);
}
/*******************************************************************************
*
* ideRecalib - recalibrate the drive
*
* Recalibrate the drive
*
* RETURNS: OK, ERROR if the command didn't succeed.
*/
LOCAL STATUS ideRecalib
(
int drive
)
{
int status;
int error;
int semStatus;
int retryCount = 0;
retryRecalib:
sysOutByte (IDE_SDH, SDH_IBM | (drive << 4));
ideWait (STAT_READY);
sysOutByte (IDE_COMMAND, CMD_RECALIB);
semStatus = semTake (&ideSyncSem, sysClkRateGet() * ideSemSec);
if ((ideStatus & STAT_ERR) || (semStatus == ERROR))
{
error = sysInByte (IDE_ERROR);
status = sysInByte (IDE_STATUS);
ideInit ();
if (ideDebugErr)
printErr ("ideRecalib%d err: status=0x%x 0x%x error=0x%x\n",
drive, ideStatus, status, error);
if (++retryCount < ideRetry)
goto retryRecalib;
return (ERROR);
}
ideWait (STAT_READY);
if (ideDebug)
printErr ("ideRecalib%d end: \n", drive);
return (OK);
}
/*******************************************************************************
*
* ideSeek - seek the drive heads to the specified cylinder
*
* Seek the drive heads to the specified cylinder
*
* RETURNS: OK, ERROR if the command didn't succeed.
*/
LOCAL STATUS ideSeek
(
int drive,
int cylinder,
int head
)
{
int status;
int error;
int semStatus;
int retryCount = 0;
retrySeek:
sysOutByte (IDE_CYL_LO, cylinder);
sysOutByte (IDE_CYL_HI, cylinder>>8);
sysOutByte (IDE_SDH, SDH_IBM | (drive << 4) | (head & 0xf));
ideWait (STAT_READY);
sysOutByte (IDE_COMMAND, CMD_SEEK);
semStatus = semTake (&ideSyncSem, sysClkRateGet() * ideSemSec);
if ((ideStatus & STAT_ERR) || (semStatus == ERROR))
{
error = sysInByte (IDE_ERROR);
status = sysInByte (IDE_STATUS);
ideInit ();
if (ideDebugErr)
printErr ("ideSeek%d err: c=%d h=%d status=0x%x 0x%x error=0x%x\n",
drive, cylinder, head, ideStatus, status, error);
if (++retryCount < ideRetry)
goto retrySeek;
return (ERROR);
}
ideWait (STAT_SEEKCMPLT);
ideWait (STAT_READY);
if (ideDebug)
printErr ("ideSeek%d end: c=%d h=%d\n", drive, cylinder, head);
return (OK);
}
/*******************************************************************************
*
* ideRW - read/write a number of sectors on the current track
*
* Read/write a number of sectors on the current track
*
* RETURNS: OK, ERROR if the command didn't succeed.
*/
LOCAL STATUS ideRW
(
int drive,
int cylinder,
int head,
int sector,
void *buffer,
int nSecs,
int direction
)
{
int ix;
int status;
int error;
int semStatus;
int retryCount = 0;
short *pBuf = (short *)buffer;
IDE_TYPE *pType = &ideTypes[drive];
int nWords = pType->bytesSector >> 1;
retryRW:
sysOutByte (IDE_PRECOMP, pType->precomp);
sysOutByte (IDE_SECCNT, nSecs);
sysOutByte (IDE_SECTOR, sector);
sysOutByte (IDE_CYL_LO, cylinder);
sysOutByte (IDE_CYL_HI, cylinder>>8);
sysOutByte (IDE_SDH, SDH_IBM | (drive << 4) | (head & 0xf));
ideWait (STAT_READY);
if (direction == O_WRONLY)
{
sysOutByte (IDE_COMMAND, CMD_WRITE);
for (ix = 0; ix < nSecs; ix++)
{
ideWait (STAT_DRQ);
sysOutWordString (IDE_DATA, pBuf, nWords);
semStatus = semTake (&ideSyncSem, sysClkRateGet() * ideSemSec);
if ((ideStatus & STAT_ERR) || (semStatus == ERROR))
goto errorRW;
pBuf += nWords;
}
}
else
{
sysOutByte (IDE_COMMAND, CMD_READ);
for (ix = 0; ix < nSecs; ix++)
{
semStatus = semTake (&ideSyncSem, sysClkRateGet() * ideSemSec);
if ((ideStatus & STAT_ERR) || (semStatus == ERROR))
goto errorRW;
ideWait (STAT_DRQ);
sysInWordString (IDE_DATA, pBuf, nWords);
pBuf += nWords;
}
}
ideWait (STAT_READY);
if (ideDebug)
printErr ("ideRW%d end: c=%d h=%d s=%d buf=0x%x n=%d dir=%d\n",
drive, cylinder, head, sector, (int)buffer, nSecs, direction);
return (OK);
errorRW:
error = sysInByte (IDE_ERROR);
status = sysInByte (IDE_STATUS);
ideInit ();
if (ideDebugErr)
{
printErr ("ideRW%d err: c=%d h=%d s=%d buf=0x%x n=%d dir=%d ",
drive, cylinder, head, sector, (int)buffer, nSecs, direction);
printErr ("stat=0x%x 0x%x error=0x%x\n", ideStatus, status, error);
}
if (++retryCount < ideRetry)
goto retryRW;
return (ERROR);
}
/*******************************************************************************
*
* ideFormat - format the current track
*
* format the current track; not supported.
*
* RETURNS: ERROR always.
*/
LOCAL STATUS ideFormat
(
int drive,
int cylinder,
int head,
int interleave
)
{
return (ERROR);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -