📄 atadrv.c
字号:
*
* 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_DRIVE * pDrive = &pCtrl->drive[drive];
ATA_DEV * pDev;
if ((ctrl >= ATA_MAX_CTRLS) || (drive >= ATA_MAX_DRIVES) ||
!ataDrvInstalled || !pCtrl->installed)
return (NULL);
#define HARRIET
#ifndef HARRIET
/* If no drive then return an error */
if (pDrive->state == ATA_DEV_NONE)
return (NULL);
#endif
ATA_DEBUG_MSG (1, "ataDevCreate entry%d/%d: entry: nBlocks %d blkOffset %d\n "
,ctrl,drive,nBlocks,blkOffset,0,0);
#if FALSE /* To forbid creation of some block devices for the same physycal
* device change FALSE to TRUE. Also freeing of BLK_DEV structure
* must be removed from PCMCIA code in this case.
*/
if (pDrive->pAtaDev != 0)
return (NULL); /* avoid creation of another block device */
#endif
if ((pDev = (ATA_DEV *)memalign(32,sizeof (ATA_DEV))) == NULL)
return (NULL);
memset(pDev,0,sizeof(ATA_DEV));
pDrive->pAtaDev = pDev;
dllAdd (&pDrive->ataDevList, &pDev->node);
pDev->ctrl = ctrl;
pDev->drive = drive;
pDev->blkOffset = blkOffset;
pDev->nBlocks = nBlocks;
ataBlkDevFill(pDrive->pAtaDev);
if (pDrive->type == ATA_TYPE_ATAPI) {
ataPiTestUnitRdy(&pDev->blkDev);
ataPiGetConfiguration(&pDev->blkDev);
}
#if 0
ataDriveInit( ctrl, drive );
#endif
#ifdef ATA_DEBUG
pgDevice[ctrl][drive] = &pDev->blkDev;
#endif
return (&pDev->blkDev);
} /* ataDevCreate */
/*******************************************************************************
*
* 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 ( (pDrive->state != ATA_DEV_OK) && (pDrive->state != ATA_DEV_MED_CH) )
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));
} /* ataRawio */
/*******************************************************************************
*
* 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
)
{
ATA_DEBUG_MSG (2, "**********ataBlkRd:0x%lx: readonly - startblk is 0x%x, nBlks=0x%x\n", hmpv_read_fcnt(),startBlk, nBlks, 0, 0, 0);
return (ataBlkRW (pDev, startBlk, nBlks, pBuf, O_RDONLY));
} /* ataBlkRd */
/*******************************************************************************
*
* 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
)
{
ATA_DEBUG_MSG (2, "**********ataBlkWrt:0x%lx: readonly - startblk is 0x%x, nBlks=0x%x\n", hmpv_read_fcnt(),startBlk, nBlks, 0, 0, 0);
return (ataBlkRW (pDev, startBlk, nBlks, pBuf, O_WRONLY));
} /* ataBlkWrt */
/*******************************************************************************
*
* 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];
ATA_DRIVE * pDrive = &pCtrl->drive[pDev->drive];
if (!pCtrl->installed)
return (ERROR);
if (pDrive->state != ATA_DEV_MED_CH)
{ /* power on, entire drive changed, or failure recovering */
semTake (&ataCtrl[0].muteSem, WAIT_FOREVER);
if (pDrive->state != ATA_DEV_INIT)
{ /* higher level tried to recover after failure */
if (pDrive->Reset (pDev->ctrl, pDev->drive) != OK)
{
semGive (&ataCtrl[0].muteSem);
return (ERROR);
}
}
#if 0
if (ataDriveInit (pDev->ctrl, pDev->drive) != OK)
{
semGive (&ataCtrl[0].muteSem);
return (ERROR);
}
#endif
semGive (&ataCtrl[0].muteSem);
}
/* Identify medium */
pDrive->state = ATA_DEV_OK;
return (OK);
} /* ataReset */
/*******************************************************************************
*
* 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];
ATA_DRIVE *pDrive = &pCtrl->drive[pDev->drive];
BLK_DEV *pBlkDev = &pDev->blkDev;
if (!pCtrl->installed)
return (ERROR);
if (pDrive->state != ATA_DEV_OK)
return (ERROR);
if (pCtrl->changed)
{
/*pBlkDev->bd_readyChanged = TRUE; */
ataSetbd_readyChanged(pDev);
pCtrl->changed = FALSE;
}
return (OK);
} /* ataStatus */
/*******************************************************************************
*
* 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];
ATA_DRIVE *pDrive = &pCtrl->drive[pDev->drive];
FAST int status = ERROR;
if (!pCtrl->installed)
return (ERROR);
if (pDrive->state != ATA_DEV_OK)
return (ERROR);
semTake (&ataCtrl[0].muteSem, WAIT_FOREVER);
#ifndef BUILD_BOOTROM
switch (function)
{
case FIODISKFORMAT:
(void) errnoSet (S_ioLib_UNKNOWN_REQUEST);
break;
default:
(void) errnoSet (S_ioLib_UNKNOWN_REQUEST);
}
#endif
semGive (&ataCtrl[0].muteSem);
return (status);
} /* ataIoctl */
/*******************************************************************************
*
* 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);
if (pDrive->state != ATA_DEV_OK)
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 (&ataCtrl[0].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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -