📄 m5200atadrv.c
字号:
return (NULL); if ((pDev = (ATA_DEV *)malloc(sizeof (ATA_DEV))) == NULL) return (NULL); pBlkdev = &pDev->blkDev; if ((pDrive->state == ATA_DEV_OK) || (pDrive->state == ATA_DEV_MED_CH)) { pDrive->state = ATA_DEV_MED_CH; if (pDrive->type == ATA_TYPE_ATA) { /* * if LBA is supported and ataLbaTotalSecs is not zero * and ataLbaTotalSecs is greater than the product of * CHS, then we should use the LBA value. */ if ((pDrive->okLba == TRUE) && (ataLbaTotalSecs[ctrl][drive] != 0) && (ataForceCHSonLBA != TRUE) && (ataLbaTotalSecs[ctrl][drive] > (pType->cylinders * pType->heads * pType->sectors))) { maxBlks = (ataLbaTotalSecs[ctrl][drive]) - blkOffset; } else /* just use CHS */ { maxBlks = ((pType->cylinders * pType->heads * pType->sectors) - blkOffset); } if (nBlocks == 0) nBlocks = maxBlks; if (nBlocks > maxBlks) nBlocks = maxBlks; pBlkdev->bd_nBlocks = nBlocks; pBlkdev->bd_bytesPerBlk = pType->bytes; pBlkdev->bd_blksPerTrack = pType->sectors; pBlkdev->bd_nHeads = pType->heads; pBlkdev->bd_removable = TRUE; pBlkdev->bd_retry = 1; pBlkdev->bd_mode = O_RDWR; pBlkdev->bd_readyChanged = TRUE; pBlkdev->bd_blkRd = ataBlkRd; pBlkdev->bd_blkWrt = ataBlkWrt; pBlkdev->bd_ioctl = ataIoctl; pBlkdev->bd_reset = ataReset; pBlkdev->bd_statusChk = ataStatus; pBlkdev->bd_reset = NULL; pBlkdev->bd_statusChk = NULL; pDev->ctrl = ctrl; pDev->drive = drive; pDev->blkOffset = blkOffset; } else if (pDrive->type == ATA_TYPE_ATAPI) { pBlkdev->bd_nBlocks = 100; pBlkdev->bd_bytesPerBlk = 2048; pBlkdev->bd_blksPerTrack = pBlkdev->bd_nBlocks; pBlkdev->bd_nHeads = 1; if (pParam->config & CONFIG_REMOVABLE) pBlkdev->bd_removable = TRUE; else pBlkdev->bd_removable = FALSE; pBlkdev->bd_retry = 1; pBlkdev->bd_mode = O_RDONLY; pBlkdev->bd_readyChanged = TRUE; pBlkdev->bd_blkRd = ataPiBlkRd; pBlkdev->bd_blkWrt = ataStub; pBlkdev->bd_ioctl = ataPiIoctl; pBlkdev->bd_reset = ataPiReset; pBlkdev->bd_statusChk = ataPiStatusChk; pDev->ctrl = ctrl; pDev->drive = drive; pDev->blkOffset = blkOffset; pDev->nBlocks = nBlocks; } ataDriveInit (ctrl, drive); pDrive->state = ATA_DEV_OK; } return (&pDev->blkDev); }/********************************************************************************* ataRawio - do raw I/O access** This routine is called to perform raw I/O access.** <drive> is a drive number for the hard drive: it must be 0 or 1.** The <pAtaRaw> is a pointer to the structure ATA_RAW which is defined in* ataDrv.h.** RETURNS:* OK, or ERROR if the parameters are not valid.**/STATUS ataRawio ( int ctrl, int drive, ATA_RAW *pAtaRaw ) { ATA_CTRL *pCtrl = &ataCtrl[ctrl]; ATA_DRIVE *pDrive = &pCtrl->drive[drive]; ATA_TYPE *pType = &ataTypes[ctrl][drive]; ATA_DEV ataDev; BLK_DEV *pBlkdev = &ataDev.blkDev; UINT startBlk; if ((ctrl >= ATA_MAX_CTRLS) || (drive >= ATA_MAX_DRIVES) || !ataDrvInstalled || !pCtrl->installed) return (ERROR); if ((pAtaRaw->cylinder >= pType->cylinders) || (pAtaRaw->head >= pType->heads) || (pAtaRaw->sector > pType->sectors) || (pAtaRaw->sector == 0)) return (ERROR); /* * if LBA is supported and ataLbaTotalSecs is not zero * and ataLbaTotalSecs is greater than the product of * CHS, then we should use the LBA value. */ if ((pDrive->okLba == TRUE) && (ataLbaTotalSecs[ctrl][drive] != 0) && (ataForceCHSonLBA != TRUE) && (ataLbaTotalSecs[ctrl][drive] > (pType->cylinders * pType->heads * pType->sectors))) { pBlkdev->bd_nBlocks = ataLbaTotalSecs[ctrl][drive]; } else /* just use CHS value */ { pBlkdev->bd_nBlocks = pType->cylinders * pType->heads * pType->sectors; } pBlkdev->bd_bytesPerBlk = pType->bytes; pBlkdev->bd_blksPerTrack = pType->sectors; pBlkdev->bd_nHeads = pType->heads; pBlkdev->bd_removable = FALSE; pBlkdev->bd_retry = 1; pBlkdev->bd_mode = O_RDWR; pBlkdev->bd_readyChanged = TRUE; pBlkdev->bd_blkRd = ataBlkRd; pBlkdev->bd_blkWrt = ataBlkWrt; pBlkdev->bd_ioctl = ataIoctl; pBlkdev->bd_reset = ataReset; pBlkdev->bd_statusChk = ataStatus; ataDev.ctrl = ctrl; ataDev.drive = drive; ataDev.blkOffset = 0; startBlk = pAtaRaw->cylinder * (pType->sectors * pType->heads) + pAtaRaw->head * pType->sectors + pAtaRaw->sector - 1; return (ataBlkRW (&ataDev, startBlk, pAtaRaw->nSecs, pAtaRaw->pBuf, pAtaRaw->direction)); }/********************************************************************************* ataBlkRd - read one or more blocks from a ATA/IDE disk** This routine reads one or more blocks from the specified device,* starting with the specified block number.** If any block offset was specified during ataDevCreate(), it is added* to <startBlk> before the transfer takes place.** RETURNS: OK, ERROR if the read command didn't succeed.*/LOCAL STATUS ataBlkRd ( ATA_DEV *pDev, int startBlk, int nBlks, char *pBuf ) { return (ataBlkRW (pDev, startBlk, nBlks, pBuf, O_RDONLY)); }/********************************************************************************* ataBlkWrt - write one or more blocks to a ATA/IDE disk** This routine writes one or more blocks to the specified device,* starting with the specified block number.** If any block offset was specified during ataDevCreate(), it is added* to <startBlk> before the transfer takes place.** RETURNS: OK, ERROR if the write command didn't succeed.*/LOCAL STATUS ataBlkWrt ( ATA_DEV *pDev, int startBlk, int nBlks, char *pBuf ) { return (ataBlkRW (pDev, startBlk, nBlks, pBuf, O_WRONLY)); }/********************************************************************************* ataReset - reset a ATA/IDE disk controller** This routine resets a ATA/IDE disk controller.** RETURNS: OK, always.*/LOCAL STATUS ataReset ( ATA_DEV *pDev ) { ATA_CTRL *pCtrl = &ataCtrl[pDev->ctrl]; if (!pCtrl->installed) return (ERROR); semTake (&pCtrl->muteSem, WAIT_FOREVER); (void) ataInit (pDev->ctrl, 0); semGive (&pCtrl->muteSem); return (OK); }/********************************************************************************* ataStatus - check status of a ATA/IDE disk controller** This routine check status of a ATA/IDE disk controller.** RETURNS: OK, ERROR if the card is removed.*/LOCAL STATUS ataStatus ( ATA_DEV *pDev ) { ATA_CTRL *pCtrl = &ataCtrl[pDev->ctrl]; BLK_DEV *pBlkdev = &pDev->blkDev; if (!pCtrl->installed) return (ERROR); if (pCtrl->changed) { pBlkdev->bd_readyChanged = TRUE; pCtrl->changed = FALSE; } return (OK); }/********************************************************************************* ataIoctl - do device specific control function** This routine is called when the file system cannot handle an ioctl()* function.** RETURNS: OK or ERROR.*/LOCAL STATUS ataIoctl ( ATA_DEV *pDev, int function, int arg ) { ATA_CTRL *pCtrl = &ataCtrl[pDev->ctrl]; FAST int status = ERROR; if (!pCtrl->installed) return (ERROR); semTake (&pCtrl->muteSem, WAIT_FOREVER); switch (function) { case FIODISKFORMAT: (void) errnoSet (S_ioLib_UNKNOWN_REQUEST); break; case FIOSYNC: (void)ataCmd (pDev->ctrl, pDev->drive, ATA_CMD_FLUSH_CACHE, 0, 0); status = OK; break; default: (void) errnoSet (S_ioLib_UNKNOWN_REQUEST); } semGive (&pCtrl->muteSem); return (status); }/********************************************************************************* ataBlkRW - read or write sectors to a ATA/IDE disk.** Read or write sectors to a ATA/IDE disk.** RETURNS: OK, ERROR if the command didn't succeed.*/LOCAL STATUS ataBlkRW ( ATA_DEV *pDev, int startBlk, int nBlks, char *pBuf, int direction ) { ATA_CTRL *pCtrl = &ataCtrl[pDev->ctrl]; ATA_DRIVE *pDrive = &pCtrl->drive[pDev->drive]; BLK_DEV *pBlkdev = &pDev->blkDev; ATA_TYPE *pType = &ataTypes[pDev->ctrl][pDev->drive]; int status = ERROR; int retryRW0 = 0; int retryRW1 = 0; int retrySeek = 0; int cylinder; int head; int sector; int nSecs; int ix; /* sanity check */ if (!pCtrl->installed) return (ERROR); nSecs = pBlkdev->bd_nBlocks; if ((startBlk + nBlks) > nSecs) { ATA_DEBUG_MSG (1, "startBlk=%d nBlks=%d: 0 - %d\n", startBlk, nBlks, nSecs, 0, 0, 0); return (ERROR); } startBlk += pDev->blkOffset; semTake (&pCtrl->muteSem, WAIT_FOREVER); for (ix = 0; ix < nBlks; ix += nSecs) { if (pDrive->okLba) { head = (startBlk & 0x0f000000) >> 24; cylinder = (startBlk & 0x00ffff00) >> 8; sector = (startBlk & 0x000000ff); } else { cylinder = startBlk / (pType->sectors * pType->heads); sector = startBlk % (pType->sectors * pType->heads); head = sector / pType->sectors; sector = sector % pType->sectors + 1; } nSecs = min (nBlks - ix, ATA_MAX_RW_SECTORS); retryRW1 = 0; retryRW0 = 0; while (ataRW(pDev->ctrl, pDev->drive, cylinder, head, sector, pBuf, nSecs, direction) != OK) { if (++retryRW0 > ataRetry) { (void)ataCmd (pDev->ctrl, pDev->drive, ATA_CMD_RECALIB, 0, 0); if (++retryRW1 > ataRetry) goto done; retrySeek = 0; while (ataCmd (pDev->ctrl, pDev->drive, ATA_CMD_SEEK, cylinder, head) != OK) if (++retrySeek > ataRetry) goto done; retryRW0 = 0; } } startBlk += nSecs; pBuf += pBlkdev->bd_bytesPerBlk * nSecs; } status = OK;done: if (status == ERROR) (void)errnoSet (S_ioLib_DEVICE_ERROR); semGive (&pCtrl->muteSem); return (status); }/********************************************************************************* ataIntr - ATA/IDE controller interrupt handler.** RETURNS: N/A*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -