📄 atadrv.c
字号:
*
* pci bus master control macros
*
***********************************************************/
#define enableChan(ctrl) sysOutByte(busMasterRegs[ctrl] + BM_COMMAND_REG, \
rwControl[ctrl] | BM_CR_MASK_START )
#define disableChan(ctrl) sysOutByte( busMasterRegs[ctrl] + BM_COMMAND_REG, \
BM_CR_MASK_STOP )
#define clearChan(ctrl) sysOutByte( busMasterRegs[ctrl] + BM_STATUS_REG, \
statReg[ctrl] | BM_SR_MASK_INT | BM_SR_MASK_ERR )
typedef struct {
char * address;
struct {
unsigned long count:16;
unsigned long reserved:15;
unsigned long EOT:1;
}bits;
} PRD_ENTRY,*PPRD_ENTRY;
static STATUS ataDmaSetupXfer(int ctrl, int dir, char *buffer, int count);
static int ataDmaConfig(int ctrl, UINT32 regAddr );
/* function prototypes */
LOCAL STATUS ataBlkRd (ATA_DEV *pDev, int startBlk, int nBlks, char *p);
LOCAL STATUS ataBlkWrt (ATA_DEV *pDev, int startBlk, int nBlks, char *p);
LOCAL STATUS ataReset (ATA_DEV *pDev);
LOCAL STATUS ataStatus (ATA_DEV *pDev);
LOCAL STATUS ataIoctl (ATA_DEV *pDev, int function, int arg);
LOCAL STATUS ataBlkRW (ATA_DEV *pDev, int startBlk, int nBlks, char *p,
int direction);
LOCAL void ataWdog (int ctrl);
LOCAL void ataIntr (int ctrl);
LOCAL STATUS ataInit (int ctrl, int drive);
LOCAL STATUS ataWait (int ctrl, int drive, int request, BOOL reset);
LOCAL STATUS ataCmd (int ctrl, int drive, int cmd, int arg0, int arg1);
LOCAL STATUS ataPread (int ctrl, int drive, void *p);
LOCAL STATUS ataRW (int ctrl, int drive, int cylinder, int head, int sec,
void *p, int nSecs, int direction);
LOCAL STATUS ataPiBlkRd (ATA_DEV *pDev, int startBlk, int nBlks, char *pBuf);
LOCAL STATUS ataPiBlkWr (ATA_DEV *pDev, int startBlk, int nBlks, char *pBuf);
LOCAL STATUS ataPiIoctl (ATA_DEV *pDev, int function, int arg);
LOCAL STATUS ataPiReset (ATA_DEV *pAtapiDev);
LOCAL STATUS ataPiStatusChk (ATA_DEV *pDev);
LOCAL STATUS ataPiReadCapacity (ATA_DEV *pAtapiDev);
LOCAL STATUS ataPiInit (int ctrl, int dev);
LOCAL STATUS ataPiPread (int ctrl, int drive, void * buffer);
LOCAL STATUS ataDiagnose (int ctrl, int dev);
LOCAL STATUS ataDevIdentify (int ctrl, int dev);
LOCAL STATUS ataDmaRW(int ctrl,int drive,int cylinder,int head,int sector,void *buffer,int nSecs,int direction);
LOCAL STATUS ataSetbd_readyChanged(ATA_DEV *pAtapiDev);
STATUS ataPiToggleTray(ATA_DEV *pAtapiDev);
LOCAL STATUS ataPiReadDVDStructure(ATA_DEV *pAtapiDev,void *buffer,int size,int format);
LOCAL STATUS ataPiGetConfiguration(ATA_DEV *pAtapiDev);
/*******************************************************************************
*
* ataStub - block device stub
*
* This routine services as stub for a block device structure's routine pointers.
*
* RETURNS: ERROR always.
*/
LOCAL STATUS ataStub (void)
{
return (ERROR);
} /* ataStub */
ataWaitStatus(int timeNSEC)
{
const int i = CPU_MHZ/10;
float cycleTimeNSEC = (1/(float)CPU_MHZ)*i*1000;
float time = 0;
//printf("ataWaitStatus %f\n",cycleTimeNSEC);
while (time<timeNSEC) {
hmpv_mnop(CPU_MHZ/10);
time+=cycleTimeNSEC;
}
}
/*******************************************************************************
*
* ataBlkDevFill - fill BLK_DEV strucutre
*
* This routine fills a block device structure with real parameters
* corresponding to the given device, or with stubs if a device is not detected
* by prtevious ataDriveInit () call. The routine considers offset and size
* requested for the device in ataDevCreate () call.
*
* RETURNS: N/A
*
* SEE ALSO: ataDevCreate (), ataDriveInit ()
*/
LOCAL void ataBlkDevFill
(
ATA_DEV * pDev
)
{
ATA_CTRL * pCtrl = &ataCtrl[pDev->ctrl];
ATA_DRIVE * pDrive = &pCtrl->drive[pDev->drive];
ATA_PARAM * pParam = &pDrive->param;
ATA_TYPE * pType = &ataTypes[pDev->ctrl][pDev->drive];
BLK_DEV * pBlkDev = &pDev->blkDev;
uint32_t nBlocks = pDev->nBlocks;
uint32_t maxBlks;
if ( (pDrive->state == ATA_DEV_OK) || (pDrive->state == ATA_DEV_MED_CH) )
{
/* mlg 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[pDev->ctrl][pDev->drive] != 0) &&
(ataForceCHSonLBA != TRUE) &&
(ataLbaTotalSecs[pDev->ctrl][pDev->drive] >
(pType->cylinders * pType->heads * pType->sectors)))
{
maxBlks = (ataLbaTotalSecs[pDev->ctrl][pDev->drive]) - pDev->blkOffset;
#ifdef ATA_DEBUG
printErr ("Using LBA value: maxBlks =0x%08lx\n", maxBlks);
#endif /* ATA_DEBUG */
}
else /* just use CHS */
{
maxBlks = ((pType->cylinders * pType->heads * pType->sectors)
- pDev->blkOffset);
#ifdef ATA_DEBUG
printErr ("Using CHS value: maxBlks =0x%08lx\n", maxBlks);
#endif /* ATA_DEBUG */
}
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 = FALSE; // 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;
}
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_RDWR;
pBlkDev->bd_readyChanged = TRUE;
pBlkDev->bd_blkRd = ataPiBlkRd;
pBlkDev->bd_blkWrt = ataPiBlkWr;
pBlkDev->bd_ioctl = ataPiIoctl;
pBlkDev->bd_reset = ataPiReset;
pBlkDev->bd_statusChk = ataPiStatusChk;
pDev->ReadCdByte9 = 0x10;
}
return;
}
/* Set default values */
pBlkDev->bd_nBlocks = 0;
pBlkDev->bd_bytesPerBlk = 512;
pBlkDev->bd_blksPerTrack = 0;
pBlkDev->bd_nHeads = 0;
pBlkDev->bd_removable = TRUE;
pBlkDev->bd_retry = 1;
pBlkDev->bd_mode = O_RDWR;
pBlkDev->bd_readyChanged = TRUE;
pBlkDev->bd_blkRd = ataStub;
pBlkDev->bd_blkWrt = ataStub;
pBlkDev->bd_ioctl = ataStub;
pBlkDev->bd_reset = ataReset;
pBlkDev->bd_statusChk = ataStub;
} /* ataBlkDevFill */
/*******************************************************************************
*
* ataDriveInit - initialize ATA drive
*
* This routine checks the drive presents, identifies its type, initializes the
* drive controller and driver control structers.
*
* RETURNS: OK if drive was initialized successfuly, or ERROR.
*/
STATUS ataDriveInit
(
int ctrl,
int drive
)
{
ATA_CTRL * pCtrl = &ataCtrl[ctrl];
ATA_DRIVE * pDrive = &pCtrl->drive[drive];
ATA_PARAM * pParam = &pDrive->param;
ATA_TYPE * pType = &ataTypes[ctrl][drive];
int configType = pCtrl->configType; /* configuration type */
ATA_DEBUG_MSG (1, "ataDriveInit%d/%d: entry: state %d type %d\n "
,ctrl,drive,pDrive->state,pDrive->type,0,0);
if (!pCtrl->installed)
return (ERROR);
if (pType->cylinders == 0)
return (ERROR); /* user specified the device as not present */
semTake (&ataCtrl[0].muteSem, WAIT_FOREVER);
/* Identify device presence and its type */
#if FALSE /* Can be changed to FALSE, if Diagnostic command will be avoided */
if ( (pDrive->state == ATA_DEV_INIT) && (pDrive->type != ATA_TYPE_INIT) )
{ /* device type have been identified by ataDiagnose() call for coupled device */
if (pDrive->type == ATA_TYPE_NONE)
{
pDrive->state = ATA_DEV_NONE;
goto driveInitExit;
}
}
else
#endif
#if 0
if (pDrive->state != ATA_DEV_OK)
if (ataDevIdentify (ctrl, drive) != OK)
goto driveInitExit;
#endif
/* Set Reset function according to device type */
if (pDrive->type == ATA_TYPE_ATA)
pDrive->Reset = ataInit;
else if (pDrive->type == ATA_TYPE_ATAPI)
pDrive->Reset = ataPiInit;
// pDrive->Reset(ctrl,drive);
#if FALSE /* This code may be avoided, since it is not vital necessary. */
if ( (pDrive->state == ATA_DEV_INIT) && (pDrive->diagCode != 0) )
{ /* diagnostic already have been executed for coupled device */
if (pDrive->diagCode != ATA_DIAG_PASSED)
{
pDrive->state = ATA_DEV_DIAG_F;
goto driveInitExit;
}
}
else
if (ataDiagnose (ctrl, drive) != OK)
goto driveInitExit;
#endif
if (pDrive->type == ATA_TYPE_ATA)
{
ATA_DEBUG_MSG(3,"calling ataPread\n",0,0,0,0,0,0);
if (ataPread (ctrl, drive, (char *)pParam) == OK)
{
ATA_DEBUG_MSG(3,"after ataPread\n",0,0,0,0,0,0);
/* find out geometry */
if ((configType & ATA_GEO_MASK) == ATA_GEO_FORCE)
{
(void) ataCmd (ctrl, drive, ATA_CMD_INITP, NULL, NULL);
(void) ataPread (ctrl, drive, (char *)pParam);
}
else if ((configType & ATA_GEO_MASK) == ATA_GEO_PHYSICAL)
{
// HARRIET the other dirver subtracts 1...
pType->cylinders = pParam->cylinders;
// pType->cylinders = pParam->cylinders -1;
pType->heads = pParam->heads;
pType->sectors = pParam->sectors;
}
else if ((configType & ATA_GEO_MASK) == ATA_GEO_CURRENT)
{
if ((pParam->currentCylinders != 0) &&
(pParam->currentHeads != 0) &&
(pParam->currentSectors != 0))
{
pType->cylinders = pParam->currentCylinders;
pType->heads = pParam->currentHeads;
pType->sectors = pParam->currentSectors;
}
else
{
pType->cylinders = pParam->cylinders;
pType->heads = pParam->heads;
pType->sectors = pParam->sectors;
}
}
/*
* Not all modern hard drives report a true capacity value
* in their IDENTIFY DEVICE CHS fields.
* For example, a Western Digital 20 Gb drive reports
* its CHS as 16383 cylinders, 16 heads, and 63 spt.
* This is about 8.4GB, but the LBA sectors is reported
* as 0x02607780, which is closer to 20Gb, the true capacity
* of the drive. The reason for this is PC BIOS can have a
* 8.4GB limitation, and drive manufacturers have broken the
* ATA specification to be compatable. Negative competition.
* Note that the ATA specifications original limit is
* about 136.9 Gb, however when combinined with a PC BIOS
* interface, a 8.4 Gb limit is produced.
* VxWorks does not have such limitations being a true 32bit OS,
* but since the drive manufactures are not honoring the CHS
* values, we have to allow for devices that demand "pure" LBA
* and present incorrect CHS.
* If the drive supports Logical Block Addresses (LBA)
* then we need to check the field located at 16bit words 60 & 61,
* "Total number of user addressable sectors (LBA mode only)".
* If this value is greater than the CHS fields report,
* then 60-61 holds the true size of the disk and that
* will be reported to the block device interface.
* Note that the CHS values are still left as the disk reported.
* This is tracked at WRS as SPR#22830
*/
if (pParam->capabilities & 0x0200) /* if (drive supports LBA) */
{
ataLbaTotalSecs[ctrl][drive] = (UINT32)
((((UINT32) ((pParam->sectors0) & 0x0000ffff)) << 0) |
(((UINT32) ((pParam->sectors1) & 0x0000ffff)) << 16));
#ifdef ATA_DEBUG
logMsg ("ID_DRIVE reports LBA (60-61) as 0x%08lx\n",
ataLbaTotalSecs[ctrl][drive],0,0,0,0,0);
#endif /* ATA_DEBUG */
}
/*
* reinitialize the controller with parameters read from the
* controller.
*/
(void) ataCmd (ctrl, drive, ATA_CMD_INITP, NULL, NULL);
/* recalibrate (this command !!! is absent in ATA-4) */
(void) ataCmd (ctrl, drive, ATA_CMD_RECALIB, NULL, NULL);
}
else
{
pDrive->state = ATA_DEV_PREAD_F;
goto driveInitExit;
}
}
else if (pDrive->type == ATA_TYPE_ATAPI)
#if TRUE /* Can be changed to FALSE, if Diagnostic command will be avoided */
{
/* Although ATAPI device parameters have been read by ataDevIdentify(),
* execute ATAPI Identify Device command to allow ATA commands
* acceptance by an ATAPI device after Diagnostic or Reset commands.
*/
if (ataPiPread (ctrl, drive, pParam) != OK)
{
pDrive->state = ATA_DEV_PREAD_F;
goto driveInitExit;
}
}
#else
; /* ATAPI device parameters have been read by ataDevIdentify() */
#endif
/* find out supported capabilities of the drive */
pDrive->multiSecs = pParam->multiSecs & 0x00ff;
pDrive->okMulti = (pDrive->multiSecs != 0) ? TRUE : FALSE;
pDrive->okIordy = (pParam->capabilities & 0x0800) ? TRUE : FALSE;
pDrive->okLba = (pParam->capabilities & 0x0200) ? TRUE : FALSE;
pDrive->okDma = (pParam->capabilities & 0x0100) ? TRUE : FALSE;
/* find out supported max PIO mode */
pDrive->pioMode = (pParam->pioMode >> 8) & 0x03; /* PIO 0,1,2 */
if (pDrive->pioMode > 2)
pDrive->pioMode = 0;
if ((pDrive->okIordy) && (pParam->valid & 0x02)) /* PIO 3,4 */
{
if (pParam->advancedPio & 0x01)
pDrive->pioMode = 3;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -