📄 atadrv.c
字号:
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;
}
nSecs = min (nBlks - ix, ATA_MAX_RW_SECTORS);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -