📄 atadrv.c
字号:
if (pParam->advancedPio & 0x02)
pDrive->pioMode = 4;
}
/* find out supported max DMA mode */
if (pDrive->okDma)
{
if (pParam->multiDma & 0x04)
pDrive->multiDmaMode = 2;
else if (pParam->multiDma & 0x02)
pDrive->multiDmaMode = 1;
else if (pParam->multiDma & 0x01)
pDrive->multiDmaMode = 0;
}
/* Is Ultra DMA supported */
if (pParam->valid & 0x04) {
if (pParam->ultraDma & 0x20)
pDrive->ultraDmaMode = 5;
else if (pParam->ultraDma & 0x10)
pDrive->ultraDmaMode = 4;
else if (pParam->ultraDma & 0x08)
pDrive->ultraDmaMode = 3;
else if (pParam->ultraDma & 0x04)
pDrive->ultraDmaMode = 2;
else if (pParam->ultraDma & 0x02)
pDrive->ultraDmaMode = 1;
else if (pParam->ultraDma & 0x01)
pDrive->ultraDmaMode = 0;
} else
pDrive->ultraDmaMode = -1;
/* 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;
logMsg("setting pio mode to PIO_%d\n",pDrive->pioMode, 0,0,0,0,0);
break;
}
if(pDrive->okDma)
switch (configType & ATA_DMA_MODE_MASK)
{
case ATA_DMA_MULTI_0:
pDrive->rwDma = ATA_DMA_MULTI_W_0;
break;
case ATA_DMA_MULTI_1:
pDrive->rwDma = ATA_DMA_MULTI_W_1;
break;
case ATA_DMA_MULTI_2:
pDrive->rwDma = ATA_DMA_MULTI_W_2;
break;
case ATA_DMA_ULTRA_0:
pDrive->rwDma = ATA_DMA_ULTRA_W_0;
break;
case ATA_DMA_ULTRA_1:
pDrive->rwDma = ATA_DMA_ULTRA_W_1;
break;
case ATA_DMA_ULTRA_2:
pDrive->rwDma = ATA_DMA_ULTRA_W_2;
break;
case ATA_DMA_ULTRA_3:
pDrive->rwDma = ATA_DMA_ULTRA_W_3;
break;
case ATA_DMA_ULTRA_4:
pDrive->rwDma = ATA_DMA_ULTRA_W_4;
break;
case ATA_DMA_ULTRA_5:
pDrive->rwDma = ATA_DMA_ULTRA_W_5;
break;
case ATA_DMA_AUTO:
// if (pDrive->type == ATA_TYPE_ATA) {
if (pDrive->ultraDmaMode != -1)
pDrive->rwDma = ATA_DMA_ULTRA_W_0 + pDrive->ultraDmaMode;
else
pDrive->rwDma = ATA_DMA_MULTI_W_0 + pDrive->multiDmaMode;
// }
/* bugbug don't know why cdrom drive reports ultraDmaMode but only
works if multidma mode */
// else if (pDrive->type == ATA_TYPE_ATAPI)
// pDrive->rwDma = ATA_DMA_MULTI_W_0 + pDrive->multiDmaMode;
break;
default:
//
// Turn off dma
//
pDrive->okDma = FALSE;
break;
} //end switch
/* Set the transfer mode */
(void) ataCmd (ctrl, drive, ATA_CMD_SET_FEATURE, ATA_SUB_SET_RWMODE,
pDrive->rwMode);
/* Disable reverting to power on defaults */
#if 1
(void) ataCmd (ctrl, drive, ATA_CMD_SET_FEATURE, 0x5, 0xFE);
#endif
/* Set multiple mode (multisector read/write) */
if ((pDrive->rwPio == ATA_PIO_MULTI) &&
(pDrive->type == ATA_TYPE_ATA))
{
if (pDrive->okMulti)
(void) ataCmd (ctrl, drive, ATA_CMD_SET_MULTI,
pDrive->multiSecs, NULL);
else
pDrive->rwPio = ATA_PIO_SINGLE;
}
pDrive->state = ATA_DEV_OK;
config_chipset_for_dma (ctrl,drive);
driveInitExit:
semGive (&ataCtrl[0].muteSem);
if (pDrive->state != ATA_DEV_OK)
{
ATA_DEBUG_MSG (1, "ataDriveInit%d/%d: ERROR: state=%d dev=0x%x "
"status=0x%x error=0x%x\n", ctrl, drive, pDrive->state,
ATA_IO_BYTE_READ (pCtrl->sdh),
ATA_IO_BYTE_READ (pCtrl->status),
ATA_IO_BYTE_READ (pCtrl->error));
return (ERROR);
}
return (OK);
} /* ataDriveInit */
void sysInWordString
(
ULONG port,
UINT16 *pData,
int count
)
{
UINT32 volatile_noncached *x;
UINT32 volatile_noncached *y;
int status;
int i;
x = (UINT32 volatile_noncached *)PCIA_PIO_CMD;
y = (((UINT32)port & 0x4) == 0) ?
(UINT32 volatile_noncached *)PCIA_PIO_DATA_E :
(UINT32 volatile_noncached *)PCIA_PIO_DATA_O;
status = intLock();
*x = PCI_CMD_IO_READ;
*(x+1) = (UINT32)port;
for (i=0;i<count;i++) {
*(pData + i) = *((UINT16 volatile_noncached *)(((UINT32)y) | ((UINT32)port & 0x3)));
}
intUnlock(status);
return;
}
void sysInLongString
(
ULONG port,
ULONG *pData,
int count
)
{
int i;
/*logMsg("params to sysInLongString: port:0x%x pData:0x%x count:0x%x\n",port,pData,count,0,0,0);
taskDelay(5);*/
if ((unsigned int)pData & 3) {
/*logMsg("Not aligned sysInLongString: breaking into sysInWordString()\n",0,0,0,0,0,0); */
/* wkc -- hack, if not aligned, then do words... */
//sysInWordString(port,(short *)pData,count*2);
for(i=0;i<count*2;i++) {
sysInWordString(port,((UINT16 *)pData)+i,2);
}
return;
}
for(i=0;i<count;i++)
*(pData + i) = sysInLong(port);
}
void sysOutWordString
(
ULONG port,
UINT16 *pData,
int count
)
{
int i;
UINT32 volatile_noncached *x;
UINT32 volatile_noncached *y;
int status;
x = (UINT32 volatile_noncached *)PCIA_PIO_CMD;
y = (((UINT32)port & 0x4) == 0) ?
(UINT32 volatile_noncached *)PCIA_PIO_DATA_E :
(UINT32 volatile_noncached *)PCIA_PIO_DATA_O;
status = intLock();
for(i=0;i<count;i++) {
*x = PCI_CMD_IO_WRITE;
*(x+1) = (UINT32)port;
*((UINT16 volatile_noncached *)(((UINT32)y) | ((UINT32)port & 0x3))) = *(pData + i);
}
intUnlock(status);
return;
}
void sysOutLongString
(
ULONG port,
ULONG *pData,
int count
)
{
int i;
for(i=0;i<count;i++)
sysOutLong(port,*(pData+i));
}
/*******************************************************************************
*
* ataDrv - initialize the ATA driver
*
* This routine initializes the ATA/IDE driver, sets up interrupt vectors,
* and performs hardware initialization of the ATA/IDE chip.
*
* This routine must be called exactly once, before any reads, writes,
* or calls to ataDevCreate(). Normally, it is called by usrRoot()
* in usrConfig.c.
*
* RETURNS: OK, or ERROR if initialization fails.
*
* SEE ALSO: ataDevCreate()
*/
STATUS ataDrv
(
int ctrl, /* controller no. */
int drives, /* number of drives */
int vector, /* interrupt vector */
int level, /* interrupt level */
int configType, /* configuration type */
int semTimeout, /* timeout seconds for sync semaphore */
int wdgTimeout /* timeout seconds for watch dog */
)
{
ATA_CTRL *pCtrl = &ataCtrl[ctrl];
ATA_RESOURCE *pAta = &ataResources[ctrl];
PCCARD_RESOURCE *pResource = &pAta->resource;
int ix;
ATA_DRIVE *pDrive;
int drive;
STATUS status;
if ((ctrl >= ATA_MAX_CTRLS) || (drives > ATA_MAX_DRIVES))
return (ERROR);
if (!ataDrvInstalled)
{
for (ix = 0; ix < ATA_MAX_CTRLS; ix++) {
memset(&ataCtrl[ix],0,sizeof(ATA_CTRL));
ataCtrl[ix].wdgId = wdCreate ();
}
semBInit (&ataCtrl[0].syncSem, SEM_Q_FIFO, SEM_EMPTY);
semMInit (&ataCtrl[0].muteSem, SEM_Q_PRIORITY | SEM_DELETE_SAFE |
SEM_INVERSION_SAFE);
/* clear any unexpected pci interrupts */
ATA_IO_BYTE_READ (ATA_STATUS (ataResources[0].resource.ioStart[0]));
ATA_IO_BYTE_READ (ATA_STATUS (ataResources[1].resource.ioStart[0]));
status = pciIntConnect((VOIDFUNCPTR *)INUM_TO_IVEC (ataResources[ctrl].intVector),(VOIDFUNCPTR)ataIntr, 0);
if (status != OK) {
#ifdef ATA_DEBUG
printErr ("ERROR: pciIntConnect\n");
#endif /* ATA_DEBUG */
return status;
}
ataDrvInstalled = TRUE;
}
if (!pCtrl->installed)
{
if (semTimeout == 0)
pCtrl->semTimeout = ATA_SEM_TIMEOUT_DEF;
else
pCtrl->semTimeout = semTimeout;
if (wdgTimeout == 0)
pCtrl->wdgTimeout = ATA_WDG_TIMEOUT_DEF;
else
pCtrl->wdgTimeout = wdgTimeout;
pCtrl->data = ATA_DATA (pResource->ioStart[0]);
pCtrl->error = ATA_ERROR (pResource->ioStart[0]);
pCtrl->feature = ATA_FEATURE (pResource->ioStart[0]);
pCtrl->seccnt = ATA_SECCNT (pResource->ioStart[0]);
pCtrl->sector = ATA_SECTOR (pResource->ioStart[0]);
pCtrl->cylLo = ATA_CYL_LO (pResource->ioStart[0]);
pCtrl->cylHi = ATA_CYL_HI (pResource->ioStart[0]);
pCtrl->sdh = ATA_SDH (pResource->ioStart[0]);
pCtrl->command = ATA_COMMAND (pResource->ioStart[0]);
pCtrl->status = ATA_STATUS (pResource->ioStart[0]);
pCtrl->aStatus = ATA_A_STATUS (pResource->ioStart[1]);
pCtrl->dControl = ATA_D_CONTROL (pResource->ioStart[1]);
pCtrl->dAddress = ATA_D_ADDRESS (pResource->ioStart[1]);
#ifdef INCLUDE_VCON_MODULE
(void) VCIOintConnect ((VOIDFUNCPTR *)INUM_TO_IVEC(ataResources[ctrl].intVector),(VOIDFUNCPTR)ataIntr, ctrl);
#endif
#ifdef INCLUDE_VT82C686B
(void) SuperIOintConnect ((VOIDFUNCPTR *)INUM_TO_IVEC(ataResources[ctrl].intVector),(VOIDFUNCPTR)ataIntr, ctrl);
#else
#endif
pCtrl->intLevel = level;
pCtrl->wdgOkay = TRUE;
pCtrl->configType = configType;
pCtrl->installed = TRUE;
status = ataInit (ctrl,0);
if (status != OK)
return status;
for (drive = 0; drive < ATA_MAX_DRIVES; drive++)
ataDevIdentify (ctrl, drive);
for (drive = 0; drive < drives; drive++) {
pDrive = &pCtrl->drive[drive];//only one drive on each chain
pDrive->state = ATA_DEV_INIT;
//pDrive->type = ATA_TYPE_INIT;
pDrive->diagCode = 0;
pDrive->Reset = ataInit;
dllInit(&pDrive->ataDevList);
if (pDrive->type != ATA_TYPE_NONE) {
status = ataDriveInit(ctrl,drive);
if (status == OK) {
pCtrl->drives++;
}
}
}
/* Call system INIT routine to allow proper PIO mode setup and mount drives */
SYS_ATA_INIT_RTN (ctrl);
}
return (OK);
} /* ataDrv */
/*******************************************************************************
*
* 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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -