📄 m5200atadrv.c
字号:
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; ATA_DEBUG_MSG (2, "ataRW: ctrl=%d drive=%d c=%d h=%d s=%d buf=0x%x ", ctrl, drive, cylinder, head, sector, (int)buffer); ATA_DEBUG_MSG (2, "n=%d dir=%d\n", nSecs, direction, 0, 0, 0, 0);retryRW: ataWait (ctrl, ATA_STAT_READY); 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); 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; 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, (void *)pBuf, nWords); else ATA_IO_NLONG_WRITE (pCtrl->data, (void *)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, (void *)pBuf, nWords); else ATA_IO_NLONG_READ (pCtrl->data, (void *)pBuf, nWords >> 1); pBuf += nWords; nSectors -= block; } } ATA_DEBUG_MSG (2, "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; 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 (2, "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_STAT_DRQ | ATA_STAT_ECCCOR | ATA_STAT_ERR)) && (pCtrl->wdgOkay) ) ; wdCancel (pCtrl->wdgId); if (pCtrl->wdgOkay) break; pCtrl->wdgOkay = TRUE; ATA_DEBUG_MSG (1, "ataPiInit%d/%d: ERROR: status=0x%x error=0x%x\n", ctrl, drive, ATA_IO_BYTE_READ(ATAPI_STATUS), ATA_IO_BYTE_READ(ATAPI_ERROR), 0, 0); if (++retryCount == ataRetry) return (ERROR); } /* The following allow to recover after accidental interrupt */ if (semTake (&pCtrl->syncSem, NO_WAIT) == OK) { ATA_DEBUG_MSG (2, "ataPiInit%d/%d: WARNING: interrupt cleared: " "status=0x%x dev=0x%x error=0x%x\n", ctrl, drive, ATA_IO_BYTE_READ(ATAPI_STATUS), ATA_IO_BYTE_READ(ATAPI_D_SELECT), ATA_IO_BYTE_READ(ATAPI_ERROR), 0); } else { ATA_DEBUG_MSG (2, "ataPiInit%d/%d: Ok: status=0x%x dev=0x%x error=0x%x" "\n", ctrl, drive, ATA_IO_BYTE_READ(ATAPI_STATUS), ATA_IO_BYTE_READ(ATAPI_D_SELECT), ATA_IO_BYTE_READ(ATAPI_ERROR), 0); } return (OK); } /* ataPiInit *//********************************************************************************* ataPiPread - Read ATAPI drive parameters** This routine reads drive parameters.** RETURNS: OK, ERROR if the command didn't succeed.*/LOCAL STATUS ataPiPread ( int ctrl, int drive, void *buffer ) { ATA_CTRL *pCtrl = &ataCtrl[ctrl]; int status; int error; int semStatus; ATA_DEBUG_MSG (2, "ataPiPread%d/%d: \n", ctrl, drive, 0, 0, 0, 0); ataPiWait (ctrl, ATA_STAT_ACCESS, TRUE); /* Select device */ ATA_IO_BYTE_WRITE (ATAPI_D_SELECT, DSEL_FILLER | (drive << 4)); ATA_WAIT_STATUS; if (ataPiWait (ctrl, ATA_STAT_ACCESS, TRUE) != OK) { ATA_IO_BYTE_WRITE (ATAPI_D_SELECT, DSEL_FILLER | (drive << 4));; ATA_WAIT_STATUS; } /* ATAPI Identify Device Command */ ATA_IO_BYTE_WRITE (ATAPI_COMMAND, ATA_PI_CMD_IDENTD); ATA_WAIT_STATUS; /* * Poll Status Register instead of wait for interrupt to avoid needless * delay. */ ataPiWait (ctrl, ATA_STAT_BUSY, FALSE); semStatus = semTake (&pCtrl->syncSem, 1); status = ATA_IO_BYTE_READ (ATAPI_STATUS); if ( (status & ATA_STAT_ERR) || !(status & ATA_STAT_DRQ) || (semStatus != OK) ) { error = ATA_IO_BYTE_READ (ATAPI_ERROR); ATA_DEBUG_MSG (1, "ataPiPread%d/%d: ERROR: status=0x%x intStatus=0x%x " "error=0x%x semStatus=%d\n", ctrl, drive, status, pCtrl->intStatus, error, semStatus); return (ERROR); } /* Receive parameter information from the drive */ ATA_IO_NWORD_READ_SWAP (ATAPI_DATA, (void *)buffer, sizeof(ATA_PARAM)/sizeof(short)); /* To prevent from reading status before it is valid */ ATA_IO_BYTE_READ (pCtrl->aStatus); /* Wait for device to be ready !!! */ ataPiWait (ctrl, ATA_STAT_READY, TRUE); ATA_DEBUG_MSG (2, "ataPiPread%d/%d:Ok: status=0x%x devReg=0x%x\n", ctrl, drive, ATA_IO_BYTE_READ (pCtrl->status), ATA_IO_BYTE_READ (pCtrl->sdh), 0, 0); return (OK); } /* ataPiPread *//********************************************************************************* atapiDMAInit - initialize the DMA engine** This routine initializes the DMA engine.** RETURN: OK, or ERROR*/LOCAL STATUS atapiDMAInit (void) { printErr("ATAPI (DMA Init.) ERROR: DMA transfer is not emplemented.\n"); return ERROR; }/********************************************************************************* atapiDMATransfer - transfer a single data packet via DMA** This routine transfers a single data packet via DMA.** RETURN: OK, or ERROR** SEE ALSO: ataPiPIOTransfer()*/LOCAL STATUS atapiDMATransfer ( ATA_DEV *pAtapiDev ) { pAtapiDev->errNum = 27; return ERROR; }/********************************************************************************* ataPiOverlapTransferLoop - loop for DRQ Interrupts with Overlapping** This routine loops for Data Request Interrupts until all data packets are* transferred. It is invoked when ataPiPktCmd() executes an Overlapped command.* When Device executes an Overlapped command, it releases the ATA bus until the* device is ready to transfer a data or to present the completion st
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -