📄 atadrv.c
字号:
** RETURNS: OK, ERROR if the command didn't succeed.*/LOCAL STATUS ataCmd ( int ctrl, int drive, int cmd, int arg0, int arg1 ) { ATA_CTRL *pCtrl = &ataCtrl[ctrl]; ATA_TYPE *pType = &ataTypes[ctrl][drive]; BOOL retry = TRUE; int retryCount = 0; int semStatus; ATA_DEBUG_MSG (1, "ataCmd%d/%d: cmd=0x%x\n", ctrl, drive, cmd, arg0, arg1, 0); while (retry) { ataWait (ctrl, ATA_STAT_READY); switch (cmd) { case ATA_CMD_DIAGNOSE: ATA_IO_BYTE_WRITE (pCtrl->sdh, ATA_SDH_IBM | (drive << 4)); break; case ATA_CMD_INITP: ATA_IO_BYTE_WRITE (pCtrl->cylLo, pType->cylinders); ATA_IO_BYTE_WRITE (pCtrl->cylHi, pType->cylinders >> 8); ATA_IO_BYTE_WRITE (pCtrl->seccnt, pType->sectors); ATA_IO_BYTE_WRITE (pCtrl->sdh, ATA_SDH_IBM | (drive << 4) | ((pType->heads - 1) & 0x0f)); break; case ATA_CMD_RECALIB: ATA_IO_BYTE_WRITE (pCtrl->sdh, ATA_SDH_IBM | (drive << 4)); break; case ATA_CMD_SEEK: ATA_IO_BYTE_WRITE (pCtrl->cylLo, arg0); ATA_IO_BYTE_WRITE (pCtrl->cylHi, arg0>>8); ATA_IO_BYTE_WRITE (pCtrl->sdh, ATA_SDH_IBM | (drive << 4) | (arg1 & 0xf)); break; case ATA_CMD_SET_FEATURE: ATA_IO_BYTE_WRITE (pCtrl->seccnt, arg1); ATA_IO_BYTE_WRITE (pCtrl->feature, arg0); ATA_IO_BYTE_WRITE (pCtrl->sdh, ATA_SDH_IBM | (drive << 4)); break; case ATA_CMD_SET_MULTI: ATA_IO_BYTE_WRITE (pCtrl->seccnt, arg0); ATA_IO_BYTE_WRITE (pCtrl->sdh, ATA_SDH_IBM | (drive << 4)); break; } ATA_IO_BYTE_WRITE (pCtrl->command, cmd); semStatus = semTake (&pCtrl->syncSem, sysClkRateGet() * pCtrl->semTimeout); if ((pCtrl->intStatus & ATA_STAT_ERR) || (semStatus == ERROR)) { ATA_DEBUG_MSG (1, "ataCmd err: status=0x%x semStatus=%d err=0x%x\n", pCtrl->intStatus, semStatus, ATA_IO_BYTE_READ (pCtrl->error), 0, 0, 0); if (++retryCount > ataRetry) return (ERROR); } else retry = FALSE; } switch (cmd) { case ATA_CMD_SEEK: ataWait (ctrl, ATA_STAT_SEEKCMPLT); break; } ATA_DEBUG_MSG (3, "ataCmd end - ctrl %d, drive %d: Ok\n", ctrl, drive, 0, 0, 0, 0); return (OK); }/********************************************************************************* ataPread - Read drive parameters** Read drive parameters.** RETURNS: OK, ERROR if the command didn't succeed.*/STATUS ataPread ( int ctrl, int drive, void *buffer ) { ATA_CTRL *pCtrl = &ataCtrl[ctrl]; BOOL retry = TRUE; int retryCount = 0; int semStatus; ATA_DEBUG_MSG (3, "ataPread: ctrl=%d drive=%d\n", ctrl, drive, 0, 0, 0, 0); while (retry) { ataWait (ctrl, ATA_STAT_READY); ATA_IO_BYTE_WRITE (pCtrl->sdh, ATA_SDH_IBM | (drive << 4)); ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_READP); semStatus = semTake (&pCtrl->syncSem, sysClkRateGet() * pCtrl->semTimeout); if ((pCtrl->intStatus & ATA_STAT_ERR) || (semStatus == ERROR)) { ATA_DEBUG_MSG (1, "ataPread%d/%d - err: status=0x%x intStatus=0x%x " "error=0x%x semStatus=%d\n", ctrl, drive, ATA_IO_BYTE_READ (pCtrl->aStatus), pCtrl->intStatus, ATA_IO_BYTE_READ (pCtrl->error), semStatus); if (++retryCount > ataRetry) return (ERROR); } else retry = FALSE; } ataWait (ctrl, ATA_STAT_DRQ); ATA_IO_NWORD_READ_SWAP (pCtrl->data, (short *)buffer, 256); ATA_DEBUG_MSG (3, "ataPread end:\n", 0, 0, 0, 0, 0, 0); return (OK); }/********************************************************************************* ataRW - 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 ataRW ( int ctrl, int drive, int cylinder, int head, int sector, void *buffer, int nSecs, int direction ) { ATA_CTRL *pCtrl = &ataCtrl[ctrl]; ATA_DRIVE *pDrive = &pCtrl->drive[drive]; ATA_TYPE *pType = &ataTypes[ctrl][drive]; int retryCount = 0; int block = 1; int nSectors; int nWords; int semStatus; short *pBuf; volatile int i=0; ATA_DEBUG_MSG (3, "ataRW: ctrl=%d drive=%d c=%d h=%d s=%d buf=0x%x ", ctrl, drive, cylinder, head, sector, (int)buffer); ATA_DEBUG_MSG (3, "n=%d dir=%d\n", nSecs, direction, 0, 0, 0, 0);retryRW: ataWait (ctrl, ATA_STAT_READY); for (i = 0;i < 20*4;i++) {}; /* Wait for BSY=0 & DRQ=0 */ while ( (ATA_IO_BYTE_READ (pCtrl->aStatus) & (ATA_STAT_BUSY | ATA_STAT_DRQ)) != 0 ) ; pBuf = (short *)buffer; nSectors = nSecs; ATA_IO_BYTE_WRITE (pCtrl->feature, pType->precomp); ATA_IO_BYTE_WRITE (pCtrl->seccnt, nSecs); ATA_IO_BYTE_WRITE (pCtrl->sector, sector); ATA_IO_BYTE_WRITE (pCtrl->cylLo, cylinder); ATA_IO_BYTE_WRITE (pCtrl->cylHi, cylinder>>8); for (i = 0;i < 20*4;i++) {}; /* Wait for BSY=0 & DRQ=0 */ while ( (ATA_IO_BYTE_READ (pCtrl->aStatus) & (ATA_STAT_BUSY | ATA_STAT_DRQ)) != 0 ) ; if (pDrive->okLba) ATA_IO_BYTE_WRITE (pCtrl->sdh, ATA_SDH_LBA | (drive << 4) | (head & 0xf)); else ATA_IO_BYTE_WRITE (pCtrl->sdh, ATA_SDH_IBM | (drive << 4) | (head & 0xf)); if (pDrive->rwPio == ATA_PIO_MULTI) block = pDrive->multiSecs; nWords = (pType->bytes * block) >> 1; for (i = 0;i < 20*4;i++) {}; /* Wait for BSY=0 & DRQ=0 */ while ( (ATA_IO_BYTE_READ (pCtrl->aStatus) & (ATA_STAT_BUSY | ATA_STAT_DRQ)) != 0 ) ; if (direction == O_WRONLY) { if (pDrive->rwPio == ATA_PIO_MULTI) ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_WRITE_MULTI); else ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_WRITE); while (nSectors > 0) { if ((pDrive->rwPio == ATA_PIO_MULTI) && (nSectors < block)) { block = nSectors; nWords = (pType->bytes * block) >> 1; } ataWait (ctrl, ATA_STAT_BUSY); ataWait (ctrl, ATA_STAT_DRQ); if (pDrive->rwBits == ATA_BITS_16) ATA_IO_NWORD_WRITE (pCtrl->data, pBuf, nWords); else ATA_IO_NLONG_WRITE (pCtrl->data, (long *)pBuf, nWords >> 1); semStatus = semTake (&pCtrl->syncSem, sysClkRateGet() * pCtrl->semTimeout); if ((pCtrl->intStatus & ATA_STAT_ERR) || (semStatus == ERROR)) goto errorRW; pBuf += nWords; nSectors -= block; } } else { if (pDrive->rwPio == ATA_PIO_MULTI) ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_READ_MULTI); else ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_READ); while (nSectors > 0) { if ((pDrive->rwPio == ATA_PIO_MULTI) && (nSectors < block)) { block = nSectors; nWords = (pType->bytes * block) >> 1; } semStatus = semTake (&pCtrl->syncSem, sysClkRateGet() * pCtrl->semTimeout); if ((pCtrl->intStatus & ATA_STAT_ERR) || (semStatus == ERROR)) goto errorRW; ataWait (ctrl, ATA_STAT_BUSY); /* wait for slow disk */ ataWait (ctrl, ATA_STAT_DRQ); if (pDrive->rwBits == ATA_BITS_16) ATA_IO_NWORD_READ (pCtrl->data, pBuf, nWords); else ATA_IO_NLONG_READ (pCtrl->data, (long *)pBuf, nWords >> 1); pBuf += nWords; nSectors -= block; } } ATA_DEBUG_MSG (3, "ataRW: end\n", 0, 0, 0, 0, 0, 0); return (OK);errorRW: ATA_DEBUG_MSG (1, "ataRW err: stat=0x%x 0x%x semStatus=%d error=0x%x\n", pCtrl->intStatus, ATA_IO_BYTE_READ (pCtrl->aStatus), semStatus, ATA_IO_BYTE_READ (pCtrl->error), 0, 0); if (++retryCount < ataRetry) goto retryRW; return (ERROR); }/******************************* ATAPI Devices *********************************//********************************************************************************* ataDevIdentify - identify device** This routine checks whether the device is connected to the controller, and if* so determines its type. The routine set `type' field in the corresponding * ATA_DRIVE structure.* If device identification failed, the routine set `state' field in the * corresponding ATA_DRIVE structure to ATA_DEV_NONE.** RETURNS: TRUE if a device is present, FALSE otherwise*/LOCAL STATUS ataDevIdentify ( int ctrl, int dev ) { ATA_CTRL *pCtrl = &ataCtrl[ctrl]; ATA_DRIVE *pDrive = &pCtrl->drive [dev]; ATA_PARAM *pParam = &pDrive->param; ATA_DEBUG_MSG (3, "Enter into ataDevIdentify\n", 0, 0, 0, 0, 0, 0); pDrive->type = ATA_TYPE_NONE; /* Select device */ ATA_IO_BYTE_WRITE (pCtrl->sdh, ATA_SDH_IBM | (dev << 4)); /* Wait for device selection */ ATA_WAIT_STATUS; /* Clear semaphore: Selection of nonexistent device may rise an interrupt */ semTake (&pCtrl->syncSem, NO_WAIT); ATA_IO_BYTE_WRITE (pCtrl->seccnt, 0xaa); ATA_IO_BYTE_WRITE (pCtrl->sector, 0x55); if (ATA_IO_BYTE_READ (pCtrl->seccnt) == 0xaa) { if (ataPiPread (ctrl, dev, pParam) == OK) { pDrive->type = ATA_TYPE_ATAPI; } else if ( ((ATA_IO_BYTE_READ (ATAPI_STATUS) & (ATA_STAT_BUSY | ATA_STAT_WRTFLT | ATA_STAT_DRQ | ATA_STAT_ERR)) == ATA_STAT_ERR) && (ATA_IO_BYTE_READ (ATAPI_ERROR) == ERR_ABRT) ) { if (ataPiWait (ctrl, ATA_STAT_READY, FALSE) == OK) pDrive->type = ATA_TYPE_ATA; } } if (pDrive->type != ATA_TYPE_NONE) return (OK); ATA_DEBUG_MSG (1, "ataDevIdentify%d/%d: ERROR: status=0x%x dev=0x%x " "error=0x%x\n", ctrl, dev, ATA_IO_BYTE_READ (pCtrl->status), ATA_IO_BYTE_READ (pCtrl->sdh), ATA_IO_BYTE_READ (pCtrl->error), 0); /* Select present device */ ATA_IO_BYTE_WRITE (pCtrl->sdh, ATA_SDH_IBM | (((~dev) & 0x1) << 4)); /* define macro for 0x1 */ pDrive->state = ATA_DEV_NONE; return (ERROR); } /* ataDevIdentify *//********************************************************************************* ataPiInit - init a ATAPI CD-ROM disk controller** This routine resets a ATAPI CD-ROM disk controller.** RETURNS: OK, ERROR if the command didn't succeed.*/LOCAL STATUS ataPiInit ( int ctrl, int drive ) { ATA_CTRL *pCtrl = &ataCtrl[ctrl]; int retryCount = 0; int i; ATA_DEBUG_MSG (3, "ataPiInit%d/%d: \n", ctrl, drive, 0, 0, 0, 0); while (TRUE) /* Forever */ { ATA_IO_BYTE_WRITE (ATAPI_D_SELECT, DSEL_FILLER | (drive << 4)); ATA_WAIT_STATUS; ATA_IO_BYTE_WRITE (ATAPI_COMMAND, ATA_PI_CMD_SRST); for (i = 0; i < 5000; i++) /* 2 ms */ { ATA_WAIT_STATUS; } ATA_IO_BYTE_WRITE (ATAPI_D_SELECT, DSEL_FILLER | (drive << 4)); ATA_WAIT_STATUS; pCtrl->wdgOkay = TRUE; wdStart (pCtrl->wdgId, (sysClkRateGet() * pCtrl->wdgTimeout), (FUNCPTR)ataWdog, ctrl); while ( (ATA_IO_BYTE_READ (ATAPI_STATUS) & (ATA_STAT_BUSY | ATA_STAT_READY | ATA_STAT_WRTFLT | ATA
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -