📄 mmcoem.c
字号:
}
/* Check for CRC read error */
else if ( dtmp & CRC_RD_ERR )
{
return MMC_DATA_STATUS_CRC_ERROR;
}
/* Check for command response */
else if ( dtmp & END_CMD_RES )
{
/* Get the command response information */
dtmp = (respLength + 1) & 0xFE;
respLength = dtmp;
i = 0;
while ( i < respLength )
{
dtmp = SDREAD_DATA16(portAddress+RES_FIFO_REG);
respBuff[i] = (UCHAR)(dtmp >> 8);
i++;
respBuff[i] = (UCHAR)(dtmp & 0xFF);
i++;
}
/* No error return */
return MMC_NO_ERROR;
}
}
/* Something goes wrong..., Clear interrupt mask */
SDWRITE_DATA16(portAddress+INT_MASK_REG, 0);
return (MMC_CARD_IS_NOT_RESPONDING);
}
/***************************************************************************
* Name: MMCTransmit - Handle data from host to device
*
* Description:
* Write data to the device. This routine handles single
* block (WRITE SINGLE BLOCK command) or multiple blocks
* (WRITE MULTIPLE BLOCK command) data transfer.
*
* Input:
* pc Device controller structure
* dataLength Data block length
* noBLocks Number of sectors to transfer
* xferMode Single or mulitiple mode transfer
*
* Output:
* Data is written to the device.
*
* Return:
* MMC Status code
*
***************************************************************************/
MMC_CC MMCTransmit(UCHAR *dBuf, UINT16 dataLength, UINT16 noBlocks, UINT16 xferMode)
{
UINT16 *dBufPtr;
UINT16 dStatus;
UINT16 dtmp, dtimer;
UINT16 dLength;
UINT16 nLoops;
/* Set up the buffer */
dBufPtr = (UINT16 *)dBuf;
for (nLoops = noBlocks; nLoops >= 1; nLoops--)
{
dtimer = 0x0FFF;
dLength = (dataLength + 1) >> 1; /* Convert to word */
while ( dtimer )
{
/* Get status */
dStatus = SDREAD_DATA16(portAddress+STATUS_REG);
dtimer--;
/* Check for CRC error */
if ( dStatus & CRC_WR_ERR )
{
DEBUGMSG (1, (L"SDMMC!MMCTransmit - Crc Error"));
return MMC_DATA_STATUS_CRC_ERROR;
}
/* Is the BUFFER empty? */
else if ( dStatus & FIFO_BUFFER_EMPTY )
{
/* Ready to transfer data */
break;
}
/* Check for BUFFER full */
else if ( dStatus & FIFO_BUFFER_FULL )
{
/*
Need to wait for the BUFFER to be empty
before sending data again.
*/
if (dtimer < 5)
OS_WAIT(1);
}
}
/* Time out ..... */
if ( !dtimer )
{
DEBUGMSG (1, (L"SDMMC!MMCTransmit - Card is not responding"));
return MMC_CARD_IS_NOT_RESPONDING;
}
/* The MMC BUFFER is available, write data to the BUFFER */
while ( dLength )
{
dtmp = *dBufPtr++;
dStatus = (dtmp >> 8);
dtmp <<= 8;
dtmp |= dStatus;
dLength--;
SDWRITE_DATA16((portAddress+FIFO_RD_WR_REG), dtmp);
}
/* Start the clock to send a block of data to the device */
startMMCClock();
/* Partial block length */
if ( dataLength != DEFAULT_BLK_LENGTH )
{
SDWRITE_DATA16((portAddress+BUF_PART_FULL_REG), BUFF_PARTIAL_FULL);
}
/*
Transferring data is finished but the device itself may be busy
to program the data. Wait for this process to be done with a time
counter. If the time counter is expired, sheeeee.....
*/
/* Look for a proper status condition from the controller */
dtimer = 0xFFFF;
while ( dtimer )
{
/* Get status */
dStatus = SDREAD_DATA16(portAddress+STATUS_REG);
dtimer--;
/* Is there any CRC error? */
if ( dStatus & CRC_WR_ERR )
{
DEBUGMSG (1, (L"SDMMC!MMCTransmit - CRC Error"));
return MMC_DATA_STATUS_CRC_ERROR;
}
/* At the end of the transfer, BIT 11, BIT 12 should
be set.
*/
if (nLoops < 2)
{
/* Is the PROGRAM DATA BITs set? */
if ( (dStatus & DONE_PROG_RDWR) &&
(dStatus & DONE_WDATA_XFER) )
{
/* Transferring data is finished */
return (MMC_NO_ERROR); /* Happy camper */
}
}
else
{
/* For write multiple */
dStatus = SDREAD_DATA16(portAddress+STATUS_REG);
if ((xferMode & 0xFF) == YES)
{
if ( (dStatus & DONE_PROG_RDWR) ||
(dStatus & DONE_WDATA_XFER) )
{
/* Data programmed done */
break;
}
if ( (dStatus & FIFO_BUFFER_EMPTY) &&
(dStatus & CLOCK_DISABLE) )
{
/* Bits 11 & 12 may not be set in Multiple mode */
/* bit 11:PROG_DONE; bit 12: DATA_TRAN_DONE */
break;
}
}
}
/* Wait for data to be programmed */
if ( (dtimer > 0xFFFD) || (dtimer < 400) )
OS_WAIT(1);
}
/* Time out? */
if ( !dtimer )
{
/* Time out ...... Sheeeeeee */
DEBUGMSG (1, (L"SDMMC!MMCTransmit - Time out in receiving"));
return MMC_TIME_OUT_RCVD; /* not received data */
}
}
/* SHOULD NOT BE HERE ..... */
return MMC_NO_ERROR;
}
/***************************************************************************
* Name: MMCReceive - Handle data from target to host
*
* Description:
* Read data from the device. This routine handles single
* block (READ SINGLE BLOCK command) or multiple blocks (READ
* MULTIPLE BLOCK command) data transfer.
*
* Input:
* pc Controller structure
* dataLength Data block length
* noBLocks Number of sectors to transfer
* xferMode Single or mulitiple mode transfer
*
* Output:
* Data Buffer is filled
*
* Return:
* MMC status code
*
***************************************************************************/
MMC_CC MMCReceive(UCHAR *dBuf, UINT16 dataLength, UINT16 noBlocks, UINT16 xferMode)
{
UINT16 *dBufPtr;
UINT16 dtmp, dtimer;
UINT16 dStatus;
UINT16 dLength;
UINT16 nLoops;
/* Set up the buffer */
dBufPtr = (UINT16 *)dBuf;
for (nLoops = noBlocks; nLoops >= 1; nLoops--)
{
dtimer = 0xFFFF;
dLength = (INT16)(dataLength + 1) >> 1;
while ( dtimer )
{
/* Get status */
dStatus = SDREAD_DATA16(portAddress+STATUS_REG);
dtimer--;
/* Check for TIME OUT on read */
if ( dStatus & TIME_OUT_RECEIVE )
{
return MMC_TIME_OUT_RCVD;
}
/* Check for CRC read error */
else if ( dStatus & CRC_RD_ERR )
{
return MMC_DATA_STATUS_CRC_ERROR;
}
/* Is the BUFFER full? */
else if ( (dStatus & RD_DATA_AVAILABLE) ||
(dStatus & FIFO_BUFFER_FULL) )
{
/* Ready to get data */
break;
}
/* Check for FIFO empty */
else if ( dStatus & FIFO_BUFFER_EMPTY )
{
/*
The BUFFER is empty... waiting for data.
Decrement the counter and wait for data to fill up
the BUFFER. If the counter is expired, sheeee.....
*/
if (dtimer < 5)
OS_WAIT(1);
}
}
/* Time out ..... */
if ( !dtimer )
return MMC_CARD_IS_NOT_RESPONDING;
/* Get data from BUFFER. It could be Full or partial full */
while ( dLength )
{
dtmp = SDREAD_DATA16(portAddress+FIFO_RD_WR_REG);
dLength--;
dStatus = (dtmp >> 8);
dtmp <<= 8;
*dBufPtr++ = (dtmp | dStatus);
}
/* Is it a partial block length? */
if ( dataLength != DEFAULT_BLK_LENGTH )
{
SDWRITE_DATA16((portAddress+BUF_PART_FULL_REG), BUFF_PARTIAL_FULL);
/* Clear the FIFO buffer */
dtmp = SDREAD_DATA16(portAddress+FIFO_RD_WR_REG);
dtmp = SDREAD_DATA16(portAddress+FIFO_RD_WR_REG);
}
/*
Check for multiple block mode and start the clock again
except for the last block
*/
if ( (nLoops > 1) && (xferMode & 0xFF) )
{
/* Start the clock for next block */
startMMCClock();
}
}
return MMC_NO_ERROR; /* Ha, Ha, Ha, I am happy */
}
extern SDVOID setupMMcHostDataRegister(UINT16 cmdIndex, UINT16 *cmdDatContReg, UINT16 *noBlocks, UINT16 *blkLength);
/***************************************************************************
* Name: MMCSetupXfer
*
* Description:
* Set up information and configure the MMC controller
*
* Input:
* pc Device controller structure
* cmdIndex Command index
* noBlocks Number of blocks to transfer
* respType Type of response
*
* Output:
* All related Registers are update
*
* Return:
* None
*
***************************************************************************/
SDVOID MMCSetupXfer( UINT16 cmdIndex, UINT16 nBlocks, UINT16 respType)
{
UINT16 cmdDatContReg;
UINT16 blkLength;
UINT16 noBlocks = nBlocks;
cmdDatContReg = NO;
blkLength = 0;
setupMMcHostDataRegister(cmdIndex, &cmdDatContReg, &noBlocks, &blkLength);
/* Clear interrupt mask */
#if (USE_INTERRUPT)
SDWRITE_DATA16((portAddress+INT_MASK_REG), 0);
#else
SDWRITE_DATA16((portAddress+INT_MASK_REG), 0);
#endif
if (cmdIndex != SSTOP_TRANSMISSION)
{
/* If None Data Transfer type, just skip */
if ( cmdDatContReg != NO )
{
/* BLOCK LENGTH */
SDWRITE_DATA16((portAddress+BLK_LEN_REG), blkLength);
/* NUMBER OF BLOCK */
SDWRITE_DATA16((portAddress+NOB_REG), noBlocks);
}
}
/* COMMAND DATA */
cmdDatContReg |= respType;
/* Set up the hardware */
SDWRITE_DATA16((portAddress+CMD_DAT_CONT_REG), cmdDatContReg);
}
/***************************************************************************
* Name: MMCPrepareAndSetup
*
* Description:
* Set up information and Send the command to MMC card
*
* Input:
* pc Device controller structure
* Cmd Command index
* Arg Argument
* noBlocks Number of blocks to transfer
* respType Type of response
*
* Output:
* Command is written to the device
*
* Return:
* MMC status code
*
***************************************************************************/
SDBOOL MMCPrepareAndSetup(UINT32 Arg, UINT16 Cmd, UINT16 noBlocks, UINT16 Resp)
{
/* Stop the clock to set up the requested information */
if ( !stopMMCClock() )
return NO;
/*
Setup the command. CRC is not needed because the MMC controller
can generate the CRC.
*/
MMCSendCommand( Arg, Cmd, 0 );
/* Setup the transfer */
MMCSetupXfer( Cmd, noBlocks, Resp );
/* Start the clock to execute the request */
startMMCClock();
return YES;
}
/***************************************************************************
* Name: checkCardBusy
*
* Description:
* Test the READY/BUSY status of the MMC card.
*
* Input:
* UINT16 inData not used
*
* Output:
* None
*
* Return:
* True or False
*
***************************************************************************/
SDBOOL checkCardBusy(UINT16 inData)
{
UINT16 dStatus, dtimer;
dtimer = 0x200;
/*
Wait for BUSY to go off before the next transfer. The
device may very well be programmed data into the flash memory.
*/
while ( dtimer )
{
/* Get status */
dStatus = SDREAD_DATA16(portAddress+STATUS_REG);
/* Check for the availability of the device for next transfer */
if ( (dStatus & DONE_PROG_RDWR) || (dStatus & DONE_WDATA_XFER) )
return YES;
dtimer--;
}
/* The device is busy ... */
return NO;
}
#endif /* (USE_MEMMODE) */
#else /* (USE_MMC_EMULATION) */
#define R2_BYTE_LENGTH 17 /* Length in bytes of MMC card R2 */
#define R2_BIT_LENGTH 136 /* Length in bit of MMC card R2 */
#define BYTE_LENGTH 6 /* Length in bytes of MMC responses */
#define R1R3_BYTE_LENGTH 6 /* Length in byte of MMC card R1, R3 */
#define R1R3_BIT_LENGTH 48 /* Length in bits of MMC responses R1, R3 */
#define WRITE_CLK0_PATTERN 0x30
#define WRITE_CLK1_PATTERN 0xB0
volatile UINT16 portIO;
INT16 driveSave;
volatile UCHAR lastTransByte = 0x03;
volatile UCHAR lastTransByte_drv[] = {0x03, 0x03};
SDVOID MMCSelectController(INT16 ctrlNo, INT16 phys_drive)
{
if (ctrlNo)
portIO = MMC_SECONDARY_IO_ADDRESS;
else
portIO = MMC_PRIMARY_IO_ADDRESS;
driveSave = phys_drive;
lastTransByte = lastTransByte_drv[phys_drive];
}
/* PARALLEL PORT to MMC Reader */
/***********************************************************************************|
* Name: mmcPowerOnOff
*
* Description:
* This functions control the power of the parallel port
* MMC reader.
* |
* Input:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -