📄 satadrv.c
字号:
return (&pDev->blkDev);
}
/*******************************************************************************
*
* sataBlkRd - read one or more blocks from a SATA/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 sataDevCreate(), it is added
* to <startBlk> before the transfer takes place.
*
* RETURNS: OK, ERROR if the read command didn't succeed.
*/
LOCAL STATUS sataBlkRd
(
SATA_DEV *pDev,
int startBlk,
int nBlks,
char *pBuf
)
{
MOT_SATA_LOG (MOT_SATA_DBG_SATABRW, "Enter into sataBlkRd: nBlks=%d\n", nBlks, 0, 0, 0, 0, 0);
return (sataBlkRW (pDev, startBlk, nBlks, pBuf, O_RDONLY));
}
/*******************************************************************************
*
* sataBlkWrt - write one or more blocks to a SATA/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 sataDevCreate(), it is added
* to <startBlk> before the transfer takes place.
*
* RETURNS: OK, ERROR if the write command didn't succeed.
*/
LOCAL STATUS sataBlkWrt
(
SATA_DEV *pDev,
int startBlk,
int nBlks,
char *pBuf
)
{
MOT_SATA_LOG (MOT_SATA_DBG_SATABRW, "Enter into sataBlkWrt: nBlks=%d\n", nBlks, 0, 0, 0, 0, 0);
return (sataBlkRW (pDev, startBlk, nBlks, pBuf, O_WRONLY));
}
/*******************************************************************************
*
* sataReset - reset a SATA/IDE disk controller
*
* This routine resets a SATA/IDE disk controller.
*
* RETURNS: OK, always.
*/
LOCAL STATUS sataReset
(
SATA_DEV *pDev
)
{
SATA_CTRL *pCtrl = &sataCtrl[pDev->ctrl];
MOT_SATA_LOG (MOT_SATA_DBG_SATARESET, "Enter into sataReset\n", 0, 0, 0, 0, 0, 0);
if (!pCtrl->installed)
return (ERROR);
semTake (&pCtrl->muteSem, WAIT_FOREVER);
(void) sataInit (pDev->ctrl, 0);
semGive (&pCtrl->muteSem);
return (OK);
}
/*******************************************************************************
*
* sataStatus - check status of a SATA/IDE disk controller
*
* This routine check status of a SATA/IDE disk controller.
*
* RETURNS: OK, ERROR if the card is removed.
*/
LOCAL STATUS sataStatus
(
SATA_DEV *pDev
)
{
SATA_CTRL *pCtrl = &sataCtrl[pDev->ctrl];
BLK_DEV *pBlkdev = &pDev->blkDev;
MOT_SATA_LOG (MOT_SATA_DBG_SSTAT, "Enter into ataStatus\n", 0, 0, 0, 0, 0, 0);
if (!pCtrl->installed)
return (ERROR);
if (pCtrl->changed)
{
pBlkdev->bd_readyChanged = TRUE;
pCtrl->changed = FALSE;
}
return (OK);
}
/*******************************************************************************
*
* sataIoctl - do device specific control function
*
* This routine is called when the file system cannot handle an ioctl()
* function.
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS sataIoctl
(
SATA_DEV *pDev,
int function,
int arg
)
{
SATA_CTRL *pCtrl = &sataCtrl[pDev->ctrl];
register UINT localStatus; /* local status variable */
MOT_SATA_LOG (MOT_SATA_DBG_SATAIOCTL, "Enter into sataStatus\n", 0, 0, 0, 0, 0, 0);
if (!pCtrl->installed)
return (ERROR);
semTake (&pCtrl->muteSem, WAIT_FOREVER);
switch (function)
{
case FIODISKFORMAT:
/*(void) errnoSet (S_ioLib_UNKNOWN_REQUEST);
localStatus = ERROR;*/
pDev->blkDev.bd_readyChanged = TRUE;
break;
default:
(void) errnoSet (S_ioLib_UNKNOWN_REQUEST);
localStatus = ERROR;
break;
}
semGive (&pCtrl->muteSem);
return ((localStatus ? ERROR : OK));
}
/*******************************************************************************
*
* sataBlkRW - read or write sectors to a SATA/IDE disk.
*
* Read or write sectors to a SATA/IDE disk.
*
* RETURNS: OK, ERROR if the command didn't succeed.
*/
LOCAL STATUS sataBlkRW
(
SATA_DEV *pDev,
int startBlk,
int nBlks,
char *pBuf,
int direction
)
{
SATA_CTRL *pCtrl = &sataCtrl[pDev->ctrl];
SATA_DRIVE *pDrive = &pCtrl->drive[pDev->drive];
BLK_DEV *pBlkdev = &pDev->blkDev;
SATA_TYPE *pType = &sataTypes[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 */
MOT_SATA_LOG (MOT_SATA_DBG_SATABRW, "Enter into sataBlkRW\n", 0, 0, 0, 0, 0, 0);
if (!pCtrl->installed)
return (ERROR);
nSecs = pBlkdev->bd_nBlocks;
if ((startBlk + nBlks) > nSecs)
{
MOT_SATA_LOG (MOT_SATA_DBG_SATABRW, "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 (sataRW(pDev->ctrl, pDev->drive, cylinder, head, sector, pBuf, nSecs, direction) != OK)
{
if (++retryRW0 > ataRetry)
{
(void)sataCmd (pDev->ctrl, pDev->drive, ATA_CMD_RECALIB, 0, 0);
if (++retryRW1 > ataRetry)
goto done;
retrySeek = 0;
while (sataCmd (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);
}
/*******************************************************************************
*
* sataRW - 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 sataRW
(
int ctrl,
int drive,
int cylinder,
int head,
int sector,
char *buffer,
int nSecs,
int direction
)
{
SATA_CTRL *pCtrl = &sataCtrl[ctrl];
SATA_DRIVE *pDrive = &pCtrl->drive[drive];
SATA_TYPE *pType = &sataTypes[ctrl][drive];
int retryCount = 0;
int nBytes;
int semStatus;
char *pBuf;
UINT32 tmp;
MOT_SATA_LOG (MOT_SATA_DBG_SATABRW, "ataRW: ctrl=%d drive=%d c=%d h=%d s=%d buf=0x%x ",
ctrl, drive, cylinder, head, sector, (int)buffer);
MOT_SATA_LOG (MOT_SATA_DBG_SATABRW, "n=%d dir=%d\n", nSecs, direction, 0, 0, 0, 0);
retryRW:
pBuf = (char *)buffer;
nBytes = pType->bytes * nSecs;
if (direction == O_WRONLY)
{
sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE), 0x00000000);
sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 4), 0x00000000);
sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 8), 0x00CA8027);
if (pDrive->okLba)
tmp = sector | (cylinder << 8) |((ATA_SDH_LBA | (head & 0xf)) << 24);
else
tmp = sector | (cylinder << 8) |((ATA_SDH_IBM | (head & 0xf)) << 24);
sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 12), tmp);
sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 16), 0x00000000);
sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 20), nSecs);
sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 24), 0x00000000);
sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 28), 0x00000000);
sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 32), (UINT32)pBuf);
sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 36), 0x00000000);
sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 40), nBytes);
sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 44), 0x80000000);
/* write excutin FIFO */
sysPciOutLong ((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + PORT_EXEC_FIFO), 0x0);
semStatus = semTake (&pCtrl->syncSem, sysClkRateGet() * pCtrl->semTimeout);
if ((pCtrl->intStatus) || (semStatus == ERROR))
goto errorRW;
}
else
{
sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE), 0x00000000);
sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 4), 0x00000000);
sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 8), 0x00C88027);
if (pDrive->okLba)
tmp = sector | (cylinder << 8) |((ATA_SDH_LBA | (head & 0xf)) << 24);
else
tmp = sector | (cylinder << 8) |((ATA_SDH_IBM | (head & 0xf)) << 24);
sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 12), tmp);
sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 16), 0x00000000);
sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 20), nSecs);
sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 24), 0x00000000);
sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 28), 0x00000000);
sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 32), (UINT32)pBuf);
sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 36), 0x00000000);
sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 40), nBytes);
sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 44), 0x80000000);
/* write excutin FIFO */
sysPciOutLong ((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + PORT_EXEC_FIFO), 0x0);
semStatus = semTake (&pCtrl->syncSem, sysClkRateGet() * pCtrl->semTimeout);
if ((pCtrl->intStatus) || (semStatus == ERROR))
goto errorRW;
}
MOT_SATA_LOG (MOT_SATA_DBG_SATABRW, "ataRW: end!\n", 0, 0, 0, 0, 0, 0);
return (OK);
errorRW:
MOT_SATA_LOG (MOT_SATA_DBG_SATABRW, "ataRW: failed!\n", 0, 0, 0, 0, 0, 0);
if (++retryCount < ataRetry)
goto retryRW;
return (ERROR);
}
STATUS sataDevIdentify (int ctrl, int drive)
{
SATA_CTRL *pCtrl = &sataCtrl[ctrl];
SATA_DRIVE *pDrive = &pCtrl->drive [drive];
pDrive->type = SATA_TYPE_NONE;
MOT_SATA_LOG(MOT_SATA_DBG_IDENT,"enter sataDevIdentify!\n",1,2,3,4,5,6);
if (Sata_Device_Reset(ctrl, drive) != OK)
{
pDrive->state = SATA_DEV_NONE;
return (ERROR);
}
if (Sata_Port_SoftReset(ctrl, drive) != OK)
{
pDrive->state = SATA_DEV_NONE;
return (ERROR);
}
sata_update_tf(ctrl, drive);
CACHE_DMA_INVALIDATE (sata_cmd_block, 64);
if((sata_cmd_block->prb.fis[12] != 0x01) || (sata_cmd_block->prb.fis[4] != 0x01) || (sata_cmd_block->prb.fis[5] != 0x00) || (sata_cmd_block->prb.fis[6] != 0x00))
{
MOT_SATA_LOG(MOT_SATA_DBG_IDENT,"device attachment is not a disk drive!\n",1,2,3,4,5,6);
pDrive->state = SATA_DEV_NONE;
return (ERROR);
}
MOT_SATA_LOG(MOT_SATA_DBG_IDENT,"device attachment is a disk drive!\n",1,2,3,4,5,6);
pDrive->type = SATA_TYPE_ATA;
return (OK);
}
STATUS Sata_Device_Present(int ctrl, int drive)
{
UINT32 tmp=0;
SATA_CTRL *pCtrl = &sataCtrl[ctrl];
if(Sata_Portwait_Status(ctrl, drive, PORT_SSTATUS, 0x00000003, FALSE) != OK)
{
MOT_SATA_LOG(MOT_SATA_DBG_PRESENT,"device is not present!\n",1,2,3,4,5,6);
return (ERROR);
}
tmp = sysPciInLong ((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + PORT_SSTATUS));
MOT_SATA_LOG(MOT_SATA_DBG_PRESENT,"device is present! status = 0x%x!\n",tmp,2,3,4,5,6);
return (OK);
}
STATUS Sata_Port_Initialize(int ctrl, int drive)
{
SATA_CTRL *pCtrl = &sataCtrl[ctrl];
sysPciOutLong ((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + PORT_CTRL_STAT), PORT_CS_INIT);
if(Sata_Portwait_Status( ctrl, drive, PORT_CTRL_STAT, PORT_CS_INIT, TRUE) != OK)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -