⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmcoem.c

📁 基于RM9200主芯片
💻 C
📖 第 1 页 / 共 3 页
字号:
        }
        /* 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 + -