📄 doch_ata.c
字号:
}
else if(resetOccured)
{
if(beforeCommand)
DBG_PRINT_ERR(FLZONE_ATA, "\r\ndoch_command(): Suspend mode detected (Before Command)\r\n");
else
DBG_PRINT_ERR(FLZONE_ATA, "\r\ndoch_command(): Suspend mode detected (After Command)\r\n");
gDeviceTurnedOff = TRUE;
return DOCH_DeviceTurnedOff;
}
#ifdef DOCH_CHECK_CHIP_ID
else
{
if(beforeCommand)
DBG_PRINT_ERR(FLZONE_ATA, "\r\ndoch_command(): Suspend mode not detected but failed to read chip id (Before Command)\r\n");
else
DBG_PRINT_ERR(FLZONE_ATA, "\r\ndoch_command(): Suspend mode not detected but failed to read chip id (After Command)\r\n");
gDeviceTurnedOff = TRUE;
return DOCH_DeviceTurnedOff;
}
#else /*DOCH_CHECK_CHIP_ID*/
return DOCH_OK;
#endif /*DOCH_CHECK_CHIP_ID*/
}
#endif /*CHECK_POWER_ON_EVERY_COMMAND*/
/******************************************************************************
* *
* r e a d y *
* *
* Wait until particular bit pattern appears in specified DOCH register *
* *
* Parameters : *
* pdev : device to act on *
* reg : DOCH register offset from base address *
* mask : bits we are interested in *
* on_bits : bits we are waiting to become '1' *
* millisec : timeout value in milliseconds *
* *
* Returns : *
* DOCH_OK in success, otherwise respective error code. *
* *
******************************************************************************/
static
DOCH_Error ready ( DOCH_Socket * pdev,
FLSNative devNum,
DOCH_Reg reg,
FLByte mask,
FLByte on_bits,
FLDword millisec )
{
DOCH_Error error = DOCH_OK;
register FLDword tries;
FLByte status = 0;
FLDword use_interrupt =
( ((pdev->device[devNum].flags & DOCH_FLAGSB_USE_INTERRUPT) == DOCH_FLAGSB_USE_INTERRUPT) &&
(pdev->bUseInterrupt) );
/*Special case: ignore error bit
(should be ignored when performing ATA standard IDENTIFY DEVICE command)*/
if(gIgnoreErrorBit)
mask &= ~(DOCH_ERROR);
/*Protect against access time set to 0*/
if(gDochAccessNanosec == 0)
return DOCH_BadParameter;
tries = millisec * (1000000UL / gDochAccessNanosec);
/*If popper environment variable was set - set timeout to max*/
if(gATANoTimeout == DOCH_GLOBAL_BOOL_PATTERN)
{
tries = DOCH_ATA_MAX_TIMEOUT;
}
/*If gUseShortWaitOnBusy is set, use its value*/
if(gUseShortWaitOnBusy != 0)
{
tries = gUseShortWaitOnBusy;
}
/*Protect tries from being set to "0"
(in conjunction with tries-- might cause a very long delay...)*/
if(tries == 0)
tries = 1;
/*Wait for BUSY bit to clear*/
while (tries-- > 0)
{
if ((millisec >= DOCH_LONG_WAIT) && (use_interrupt))
{
/* wait for device's interrupt */
DOCH_SLEEP(pdev->wSocketNo, devNum, DOCH_DEFAULT_SLEEP_PERIOD);
}
status = DOCHREAD_ATA_REG(pdev->bRegBase, reg);
if ((status & mask) == on_bits)
{
/* read status once again, just to be sure .. */
/*if ((DOCHREAD_ATA_REG(pdev->device[devNum].bRegBase, reg) & mask) == on_bits)*/
return DOCH_OK;
}
/*If an error was detected - return the error code*/
else if( ((status & DOCH_ERROR) == DOCH_ERROR) &&
((status & DOCH_BUSY) != DOCH_BUSY))
{
error = (DOCH_Error)DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_ERROR_REG);
/*Special Case - Device returned "0" in the error register.
This DOES NOT mean that everything is OK, since the error bit was raised.
Hence, we will return "DOCH_ATA_ERROR_ABORT"*/
if(error == DOCH_OK)
error = DOCH_ATA_ERROR_ABORT;
if(pdev->bUseInterrupt && (millisec == DOCH_SHORT_WAIT))
DOCH_UNSERVICED_INTERRUPT(pdev->wSocketNo, devNum);
DBG_PRINT_ERR(FLZONE_ATA, "ready(): ATA Error: ");
DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("0x%x "), error));
DBG_PRINT_ERR(FLZONE_ATA, "\r\n");
return error;
}
}
DBG_PRINT_ERR(FLZONE_ATA, "\r\nready(): Timed Out\r\n");
/* If timeout had occurred, and not whilst looking for a device,
reset ATA and poll for ready */
if(gUseShortWaitOnBusy == 0)
{
DBG_PRINT_ERR(FLZONE_ATA, "ready(): Resetting device... ");
error = doch_reset (pdev->wSocketNo, devNum);
if(error == DOCH_OK)
DBG_PRINT_ERR(FLZONE_ATA, "Passed! \r\n");
else
{
DBG_PRINT_ERR(FLZONE_ATA, "Failed! \r\n");
return error;
}
}
return DOCH_TimedOut;
}
/******************************************************************************
* *
* i o _ i n p u t *
* *
* Read sectors from DOCH device. *
* *
* Parameters : *
* pdev : device to act on *
* regs : DOCH_Registers *
* buf : user buffer to read to *
* secNum : # of sectors to read *
* *
* Returns : *
* DOCH_OK in success, otherwise respective error code. *
* *
******************************************************************************/
DOCH_Error io_input ( DOCH_Socket * pdev,
FLSNative devNum,
DOCH_Registers * regs,
void * buf,
FLNative secNum)
{
FLNative sectors_to_read;
FLNative secPerformed;
FLNative offset = 0;
DOCH_Error rc;
FLSNative status;
FLByte multCount = 0;
FLByte multSecToRead = 0;
/*Calculate how many sectors are to be read*/
/*Note: "0" - 256 Sectors to read*/
sectors_to_read = (secNum ? secNum : 256);
/* First we write the device head register to ensure we are communicating
with the right device...*/
DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, regs->bDriveHead);
/*Wait for busy bit to clear*/
status = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_STATUS_REG);
if((status & DOCH_BUSY) == DOCH_BUSY)
{
if ((rc = ready(pdev, devNum, DOCH_ALT_STATUS_REG, DOCH_BUSY, 0, DOCH_SHORT_WAIT)) != DOCH_OK)
{
DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_input(): ATA not Ready (before command) \r\n");
DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc));
return rc;
}
}
/*Write ATA registers, without ATA command register*/
/*Note: if DMA was requested, registers will be written inside DMA context*/
if(!pdev->bUseDMA)
{
DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_CNT_REG, regs->bSectorCount);
DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_NO_REG, regs->bSectorNumber);
DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_LOW_REG, regs->bCylLow);
DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_HIGH_REG, regs->bCylHigh);
DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_FEATURES_REG, regs->bFeaturesError);
}
/*BURST transfer was requested*/
#ifdef DOCH_USE_BURST_MODE_READ
if((pdev->bUseBurst) && (!pdev->bUseDMA))
{
FLByte drqSize = 0;
FLByte burstSizeInBytes;
FLByte i;
if(pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_SINGLE)
{
drqSize = 1;
}
else if(pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_MULT)
{
drqSize = (FLByte)pdev->device[devNum].dwMulti_Current;
}
switch(DOCH_BURST_LENGTH)
{
case DOCH_BURST_LEN_4_CYC:
burstSizeInBytes = 8;
break;
case DOCH_BURST_LEN_8_CYC:
burstSizeInBytes = 16;
break;
case DOCH_BURST_LEN_16_CYC:
burstSizeInBytes = 32;
break;
case DOCH_BURST_LEN_32_CYC:
burstSizeInBytes = 64;
break;
default:
return DOCH_BadParameter;
}
/*Set DOCH BURST READ Control Register*/
DOCHWRITE_CTRL_REG (pdev->bRegBase,
HIB_BURST_READ_MODE_CTRL_REG,
(DOCH_BURST_ENABLE | DOCH_BURST_HOLD | DOCH_BURST_LENGTH | (DOCH_BURST_LATENCY<<8) | (DOCH_BURST_WAIT_STATE<<4))
);
/*Enter BURST Mode*/
DOCH_HOST_ENTER_READ_BURST_MODE
/*Initiate ATA Command*/
DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, regs->bCommandStatus);
for(i=0; i<sectors_to_read; i += drqSize)
{
/* Check DRQ ready and not BSY before data xfer */
/* (rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_DRQ | DOCH_BUSY | DOCH_ERROR),
DOCH_READY | DOCH_DRQ, DOCH_LONG_WAIT));
if(rc != DOCH_OK)
{
DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_input(): ATA not Ready (before BURST) \r\n");
DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc));
return rc;
}
*/
if(i == 0)
{
FLDword tempBuf[4];
FLWord temp;
volatile FLWord* vPtr = (volatile FLWord*)addToFarPointer(pdev->bRegBase, (DOCH_ALT_STATUS_REG<<1) + DOCH_CONT_REG_AREA);
do
{
tffscpy(tempBuf, (FLByte*)vPtr, burstSizeInBytes);
/*OMAP1610_Read512Bytes_SW_DMA_BURST((FLByte*)pdev->bRegBase,
((DOCH_ALT_STATUS_REG<<1) + DOCH_CONT_REG_AREA),
tempBuf,
burstSizeInBytes);*/
temp = (tempBuf[3] >> 16);
}
while((temp & (DOCH_READY | DOCH_DRQ | DOCH_BUSY | DOCH_ERROR)) !=
(DOCH_READY | DOCH_DRQ));
}
/*Perform Read using burst*/
DOCHREAD_BURST((FLByte*)pdev->bRegBase,
DOCH_DATA_PORT_AREA_OFFSET,
(FLByte*)buf + (i<<DOCH_SECTOR_SIZE_BITS),
drqSize);
}
/*Exit BURST Mode*/
DOCH_HOST_EXIT_READ_BURST_MODE
/*Set DOCH BURST READ Control Register*/
DOCHWRITE_CTRL_REG (pdev->bRegBase, HIB_BURST_READ_MODE_CTRL_REG , DOCH_BURST_DISABLE);
}
else
#endif /*DOCH_USE_BURST_MODE_READ*/
#ifdef DOCH_DMA_CONFIG
/*DMA transfer was requested*/
if(pdev->bUseDMA)
{
DMA_Params_S dmaParams;
FLDword dmaFirstReqSector,
dmaFirstSectorToPerform,
dmaRemainderSectors,
dmaRemainderOffset,
dmaBlocks,
dmaFrameSize;
FLWord wDmaRegValue = DOCHREAD_CTRL_REG (pdev->bRegBase, HIB_DMA_CTRL_REG);
/*Initial Value*/
dmaRemainderOffset = 0;
/*Save the first sector position*/
dmaFirstReqSector = (regs->bSectorNumber +
(regs->bCylLow<<8) +
(regs->bCylHigh<<16)+
((regs->bDriveHead & 0xF)<<24));
dmaFirstSectorToPerform = dmaFirstReqSector;
if(pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_SINGLE)
{
dmaRemainderSectors = 0;
dmaFrameSize = 1;
dmaBlocks = sectors_to_read;
}
else if (pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_MULT)
{
dmaRemainderSectors = (sectors_to_read % pdev->device[devNum].dwMulti_Current);
/*Set initial parameters (will be altered afterwards to transfer "remainder" sectors*/
dmaBlocks = (sectors_to_read / pdev->device[devNum].dwMulti_Current);
dmaFrameSize = pdev->device[devNum].dwMulti_Current;
}
else
{
DBG_PRINT_ERR(FLZONE_ATA, "io_input(): DMA Transfer Mode ");
DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("0x%x "), pdev->device[devNum].dataTransferMode));
DBG_PRINT_ERR(FLZONE_ATA, "not supported\r\n");
return DOCH_FeatureNotSupported;
} /* End of if/else on pdev->device[devNum].dataTransferMode */
dochIoInputDmaSequence:
if(dmaBlocks > 0)
{
/*Set up the DMA transfer - Platfrom*/
dmaParams.bOpType = DOCH_DMA_CONFIG_TRANSACTION_DEVICE_TO_HOST;
dmaParams.bDiskOnChip_BasePtr = (FLByte*)pdev->bRegBase;
dmaParams.wDiskOnChip_Offset = (FLWord)DOCH_DATA_PORT_AREA;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -