📄 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 + -