📄 atadrv.c
字号:
if (pDrive->pioMode > 2) pDrive->pioMode = 0; if ((pDrive->okIordy) && (pParam->valid & 0x02)) /* PIO 3,4 */ { if (pParam->advancedPio & 0x01) pDrive->pioMode = 3; if (pParam->advancedPio & 0x02) pDrive->pioMode = 4; } /* find out supported max DMA mode */ if ((pDrive->okDma) && (pParam->valid & 0x02)) { pDrive->singleDmaMode = (pParam->dmaMode >> 8) & 0x03; if (pDrive->singleDmaMode >= 2) pDrive->singleDmaMode = 0; pDrive->multiDmaMode = 0; if (pParam->singleDma & 0x04) pDrive->singleDmaMode = 2; else if (pParam->singleDma & 0x02) pDrive->singleDmaMode = 1; else if (pParam->singleDma & 0x01) pDrive->singleDmaMode = 0; if (pParam->multiDma & 0x04) pDrive->multiDmaMode = 2; else if (pParam->multiDma & 0x02) pDrive->multiDmaMode = 1; else if (pParam->multiDma & 0x01) pDrive->multiDmaMode = 0; } /* find out transfer mode to use */ pDrive->rwBits = configType & ATA_BITS_MASK; pDrive->rwPio = configType & ATA_PIO_MASK; pDrive->rwDma = configType & ATA_DMA_MASK; pDrive->rwMode = ATA_PIO_DEF_W; switch (configType & ATA_MODE_MASK) { case ATA_PIO_0: case ATA_PIO_1: case ATA_PIO_2: case ATA_PIO_3: case ATA_PIO_4: case ATA_PIO_DEF_0: case ATA_PIO_DEF_1: pDrive->rwMode = configType & ATA_MODE_MASK; break; case ATA_PIO_AUTO: pDrive->rwMode = ATA_PIO_W_0 + pDrive->pioMode; break; case ATA_DMA_0: case ATA_DMA_1: case ATA_DMA_2: if (pDrive->okDma) { if (pDrive->rwDma == ATA_DMA_SINGLE) pDrive->rwMode |= ATA_DMA_SINGLE_0; if (pDrive->rwDma == ATA_DMA_MULTI) pDrive->rwMode |= ATA_DMA_MULTI_0; } break; case ATA_DMA_AUTO: if (pDrive->okDma) { if (pDrive->rwDma == ATA_DMA_SINGLE) pDrive->rwMode = ATA_DMA_SINGLE_0 + pDrive->singleDmaMode; if (pDrive->rwDma == ATA_DMA_MULTI) pDrive->rwMode = ATA_DMA_MULTI_0 + pDrive->multiDmaMode; } break; default: break; } /* set the transfer mode */ (void) ataCmd (ctrl, drive, ATA_CMD_SET_FEATURE, ATA_SUB_SET_RWMODE, pDrive->rwMode); if (pDrive->rwPio == ATA_PIO_MULTI) { if (pDrive->okMulti) (void) ataCmd (ctrl, drive, ATA_CMD_SET_MULTI, pDrive->multiSecs, NULL); else pDrive->rwPio = ATA_PIO_SINGLE; } } pCtrl->installed = TRUE;#ifdef ATA_DEBUG printErr ("ataDrv Calling sysAtaInit (if present):\n");#endif /* ATA_DEBUG */ /* Call system INIT routine to allow proper PIO mode setup */ SYS_ATA_INIT_RTN (ctrl); #ifdef ATA_DEBUG printErr ("ataDrv sysAtaInit returned:\n");#endif /* ATA_DEBUG */ semGive (&pCtrl->muteSem); } return (OK); }/********************************************************************************* ataDevCreate - create a device for a ATA/IDE disk** This routine creates a device for a specified ATA/IDE disk.** <drive> is a drive number for the hard drive; it must be 0 or 1.** The <nBlocks> parameter specifies the size of the device in blocks.* If <nBlocks> is zero, the whole disk is used.** The <blkOffset> parameter specifies an offset, in blocks, from the start* of the device to be used when writing or reading the hard disk. This* offset is added to the block numbers passed by the file system during* disk accesses. (VxWorks file systems always use block numbers beginning* at zero for the start of a device.)*** RETURNS:* A pointer to a block device structure (BLK_DEV) or NULL if memory cannot* be allocated for the device structure.** SEE ALSO: dosFsMkfs(), dosFsDevInit(), rt11FsDevInit(), rt11FsMkfs(),* rawFsDevInit()*/BLK_DEV *ataDevCreate ( int ctrl, int drive, int nBlocks, int blkOffset ) { ATA_CTRL *pCtrl = &ataCtrl[ctrl]; ATA_TYPE *pType = &ataTypes[ctrl][drive]; ATA_DRIVE *pDrive = &pCtrl->drive[drive]; ATA_DEV *pDev; BLK_DEV *pBlkdev; int maxBlks; if ((ctrl >= ATA_MAX_CTRLS) || (drive >= ATA_MAX_DRIVES) || !ataDrvInstalled || !pCtrl->installed) return (NULL); if ((pDev = (ATA_DEV *)malloc(sizeof (ATA_DEV))) == NULL) return (NULL); pBlkdev = &pDev->blkDev; /* * 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; 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); 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; 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) {#ifdef ATA_DEBUG printErr ("startBlk=%d nBlks=%d: 0 - %d\n", startBlk, nBlks, nSecs);#endif /* ATA_DEBUG */ 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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -