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

📄 sdmmc.c

📁 intel xscale pxa270的完整wince4.2 BSP包
💻 C
📖 第 1 页 / 共 5 页
字号:
/********************************************************************************
* Filename: sdmmc.c - SD/MMC protocol
*
* SanDisk Host Developer's Toolkit
*
* Copyright (c) 1997 - 2000 SanDisk Corporation
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*
* Description:
*       This module can be used to interface to the MMC card in MMC or
*       SPI modes. It supports a multiple card environment. The reset and
*       identification processes assume multiple cards on the bus.
*       In MMC mode, the card number is used as the RCA operand in the
*       commands.
*       In SPI mode, the card number is passed to the low level hardware drivers
*       where the appropriate CS signal should be asserted.
*
********************************************************************************/

#include "sdconfig.h"
#include "sdmmc.h"
#include <bvd1.h>

extern MMC_REGS	*v_pMMCReg;
extern void test_mmc(void);
#if (USE_SPI || USE_MMC || USE_SPI_EMULATION || USE_MMC_EMULATION || USE_SD)

#include "sdmmc.h"

int SD_Card_In_Use;



#if (USE_SD)
/*******************************************************************************
* Name: mmcSDApplCmd - Handle all application commands
*
* Description:
*       Send CMD55 to switch the card into application mode. Then,
*       the application command is sent.
*
* NOTE: buff is a pointer to data buffer. This buffer is ONLY for the
*       command associated with data to/from the card.  For the command
*       without data requirement, this buff should be set to NULL before
*       calling this routine.
*
* Input:
*       PDEVICE_CONTROLLER pc
*       UCHAR *buff
*       ULONG multipp
*       UINT16 RCA
*       RESP_TYPE resp
*       UINT16 Cmd
*
* Output:
*       Depending on the type of the command.
*
* Returns:
*       Completion code
* 
********************************************************************************/
MMC_CC mmcSDApplCmd(PDEVICE_CONTROLLER pc, UCHAR *buff, ULONG multipp, UINT16 noBlocks, UINT16 RCA, RESP_TYPE resp, UINT16 Cmd)
{
    MMC_CC  respErr;
        UINT16  tLength;

        tLength = 0;
        if (Cmd & SECURITY_CMD_BIT)
                tLength = noBlocks;

#if (USE_SPI || USE_SPI_EMULATION)
        /* SD ACMD6 command is not supported in SPI mode. Only 1-bit bus is supported. */
    
    /* Turn Chip select signal on */
    selectChip( RCA );

    /* Send CMD55 to the card to start Application Specific Command */
    respErr = mmcCommandAndResponse ( pc,
            (((ULONG)RCA) << 16),
                        APPL_CMD,
            0,
            R1 );
    
    /* Turn Chip select signal off */
    deSelectChip( RCA );
#else
        /* ONLY FOR data transfer when buff is set */ 
    if (buff)
    {
        /* Put the card in transfer state. */
                respErr = mmcSetXferState (pc, RCA);
    }

    /* Send CMD55 to the card to start Application Specific Command */
    respErr = mmcCommandAndResponse ( pc,
                        (((ULONG)RCA) << 16),
                        APPL_CMD, 
            0,
            R1 );

#endif

        /* The CMD55 is not supported by MMC card.  The MMC card may
           not responded or responded with an error to this command.
           Check for error here to tell if it is MMC or SD card. 
    */
        /***********************************************************
           An SD card should behave well to this command (NO ERROR).
           MMC card in SPI mode should reject or not respond to it.
           MMC card in MMC mode should reject or not respond to it.
        ***********************************************************/
        if ( ( respErr != MMC_NO_ERROR) && (respErr == MMC_COMUNC_ILLEG_COM) )
    {
        pc->error_code = (UINT16)respErr;
        return respErr;
    }

    /* Application Specific command follows CMD55. */
#if (USE_SPI || USE_SPI_EMULATION)
        /* Turn Chip select signal on. */
    selectChip( RCA );
#endif

    respErr = mmcCommandAndResponse ( pc,
                                multipp,
                                Cmd,
                                tLength,
                                resp );

        /* The buff is ONLY for data transfer. Check it here for that purpose. */
        if (buff)
        {
                /* Security data will be handled different module */
                if (Cmd & SECURITY_CMD_BIT)
                        return respErr;

                /* Set up the buffer */
                pc->user_address = (USERADDRESS)buff;

                /* Get information */
                if (respErr == MMC_NO_ERROR)
                {
                        if (Cmd == SD_SEND_SCR)
                        {
                                tLength = SD_SCR_LENGTH;
                        }
                        else if (Cmd == SD_STATUS)
                        {
                                tLength = SD_STATUS_LENGTH;
                        }

                        /* Get data */
                        respErr = receive_data( pc, tLength, 1, NO );
                }
        }

#if (USE_SPI || USE_SPI_EMULATION)
        /* Turn Chip select signal off. */
        deSelectChip( RCA );
#endif

    return respErr;
}
#endif /* (USE_SD) */

/*******************************************************************************
* Name: mmcReset - Initialize the card
*
* Description:
*       Resets the cards and the MMC or SPI HW port.
*       It must be called after power on before any other commands.
*
*       This function sends reset command (CMD0) to the card and waits for the
*       card to complete the initialization process by polling its status using
*       send_op_condition command (CMD1) to complete its reset process.
*
*       In MMC mode, this function can be used to query a card stack for the
*       the common voltage range or to set a voltage range and initialize
*       the cards to be ready.
*
*       In SPI mode, the reset is card specific. The card number is used for the
*       device to be intialized for the card to be ready.
*
* Input:
*       setupInfo       In MMC mode, Host operating voltage range.
*                       In SPI mode, Card Address.
*
* Output:
*       Initialization process is finished.
*
* Returns:
*       Completion code
* 
********************************************************************************/
MMC_CC mmcReset( PDEVICE_CONTROLLER pc, ULONG setupInfo )
{
        UINT32  cardType;
    MMC_CC  resErr;
        UINT16  sdFlag;
        UINT16  readyFlag;
	
#if (USE_SPI || USE_SPI_EMULATION)
    INT16   ChipNum;

    ChipNum = (INT16)setupInfo;
    pc->timer = (RESET_DELAY << 2);
        cardType = NO;
        readyFlag = NO;
        resErr = MMC_NO_ERROR;
        pc->drive_active = ChipNum;

    /* Turn Chip select signal on */
    selectChip( ChipNum );

        /* Reset the card */
    resErr = mmcCommandAndResponse ( pc,
                0L,
                GO_IDLE_STATE,
                0,
                R1 );

        /* Turn Chip select signal off */
    deSelectChip ( ChipNum );

        /* Make sure the card is presented. The card should not be ready. */
        if ( (resErr != MMC_CARD_IS_NOT_READY) )
        {
                /* At this time if resErr == 0, it's really an error. */
        pc->error_code = MMC_INTERFACE_ERROR;
        return MMC_INTERFACE_ERROR;
    }

        /* It is very much to tell at this point, the card is in the slot
           because CMD0 has been executed correctly. Now, it is the focus
           of figuring out what type of the card is in the slot.
        */
#if (USE_SD)
        sdFlag = YES;           /* For SD card first */
#else
        sdFlag = NO;
#endif
    while ( pc->timer )
    {
                /* There is no way to tell what the card type is at this
                   point. The application command ACMD41 is sent first to
                   test.  If there is no response,  or error with ACMD41,
                   the card is not an SD card.  Then, the MMC card will
                   be tested next by sending CMD1.
        */   

#if (USE_SD)
                /* Check for SD card first. */
                if (sdFlag)
					  
        {
                        /* Make sure the card is ready */
					     
                        resErr = mmcSDApplCmd(pc, SDNULL, 0L, 0, 0, R1, SD_SEND_OP_COND);
//						RETAILMSG(, (TEXT("after mmcSDApplCmd\r\n")));

                        /* The returned error indicates the card type. */
                        if (resErr == MMC_COMUNC_ILLEG_COM)
            {
                                /* An error shows that the card could be SPI
                                   or no card in the slot. We will retest this
                                   again in SPI mode to verify the card is an
                                   MMC card in SPI mode.
                                */
                                sdFlag = NO;
                        }
                        else if (resErr == MMC_NO_ERROR)
                        {
                                /* Hee Ha, Got an SD card. */
                                cardType = SD_TYPE;     /* Set card type */
                                readyFlag = CARD_READY_FLAG;
								SD_Card_In_Use = 1;
								RETAILMSG(1, (TEXT("SD card is present\r\n")));

/* Comment out for the FPGA is not working at this time */
#if 0
                                /* Get OCR. Checking for card ready. The OCR
                                   information is returned in pc->LastResponse[1..3].
                                */
                                selectChip( ChipNum );
                                resErr = mmcCommandAndResponse ( pc,
                                                        0L,
                                                        SD_READ_OCR,
                                                        0,
                                                        R3 );
                                deSelectChip ( ChipNum );

                                if (resErr == MMC_NO_ERROR)
                                {
                                        /* Get the card BUSY/READY bit */
                                        readyFlag = to_WORD((UCHAR *)&pc->LastResponse[1]);
                                        if (!(readyFlag & CARD_READY_FLAG))
                                        {
                                                /* If the card is not ready, do it again */
                                                resErr = MMC_CARD_IS_NOT_READY;
                                        }
                                }
#endif
            }
        }
#endif /* (USE_SD) */

                /* Now, check for MMC card in SPI mode. */
                if (!sdFlag)    /* The current card may be an MMC card */
        {
                        /* Check the card to make sure the device is ready */
//			RETAILMSG(1, (TEXT(" Before sending SEND_OP_COND command"\r\n")));
      //      selectChip( ChipNum );        
            resErr = mmcCommandAndResponse ( pc,
                    0L,
                    SEND_OP_COND,
                                        0,
                                        R1 );
    //        deSelectChip ( ChipNum );

                        /* MMC card will respond to CMD1. Verify it here. */
                        if ( (resErr == MMC_CARD_IS_NOT_READY) || (resErr == MMC_NO_ERROR) )
                        {
                                /* Set the card type */
                                cardType = SPI_TYPE;

                                sdFlag = NO;
//								RETAILMSG(1, (TEXT(" After sending SEND_OP_COND command, MMC_CARD_NOT_READY\r\n")));
                        }
        }                

                /* Now, make sure the card behaves well. */
        if ( (resErr != MMC_CARD_IS_NOT_READY) && resErr )
        {
            pc->error_code = (UINT16)resErr;
            return resErr;
        }

                /* Make sure the card is in the slot. */
        if ( resErr == MMC_CARD_IS_NOT_READY )
        {
            pc->timer--;
            OS_WAIT(1);     /* Delay to 1 ms */
            if ( !pc->timer )
            {
                pc->error_code = MMC_CARD_IS_NOT_READY;
                return MMC_CARD_IS_NOT_READY;
            }
        }
                else if (resErr == MMC_NO_ERROR)
                {
                        /* Set the card type. */
                        pc->drive[ChipNum].drv_type = cardType;
                  
                        /* The RCA is the Chip number. */
                        pc->drive[ChipNum].RCA = (UINT16)ChipNum;
                        break;
                }
    }
    
#else /* This is for MMC */
        UINT16  i, bInterface;
        UINT16  devCount;
//	RETAILMSG(1, (TEXT("mmcReset() entered \r\n")));
    pc->timer = (RESET_DELAY << 2);
        cardType = NO;
        readyFlag = NO;
        resErr = MMC_NO_ERROR;

        /* Reset all devices on the bus. */
 /*   mmcCommandAndResponse ( pc,
            0L,
            GO_IDLE_STATE, 
            0,
            R0 );
*/
        bInterface = 0;
        devCount = 0;

        sdFlag = NO;

#if (USE_SD)
DO_ALL_BUS_INTERFACE:
#endif
    for (i = 0; i < (CID_BYTE_LENGTH/2); pc->LastResponse[i++] = 0); /* Clear buffer */

        /* Delay it for a while */
        OS_WAIT(25);

        /* Wait for all cards to be ready */
    while (pc->timer)
    {
                /* There is no way to tell what type of the card is at this
                   point. The command CMD1 is sent first to test the card.
                   Because the MMC card is always responded to CMD1, if there
                   is no response, or an error, on the return, we could assume
                   that the card is not MMC card, the application command ACMD41
                   will be sent next to test for SD card.
        */   
                /* Now, check for MMC card. SD do not support CMD1 in MMC mode. */
                if (!sdFlag)    /* The current card may be an MMC card */
        {
                        /* Check for MMC card. */
            resErr = mmcCommandAndResponse ( pc,
                    setupInfo,
                                        SEND_OP_COND,
                    0,
                    R3 );

                        /* Check if the card is an MMC card. */
                        if (resErr == MMC_NO_ERROR)
                        {
                                /* Got the response from the card. */
                                /* The card is indeed an MMC card. */
                                cardType = MMC_TYPE;
                                readyFlag = to_WORD((UCHAR *)&pc->LastResponse[0]);
//								RETAILMSG(1, (TEXT("is the card ready? %x\r\n"), readyFlag));
                        }
                        /* CMD1 failed.  There are two ways to explain this:
                           1. SD card seems not to respond to CMD1 at all (MMC mode).
                              Therefore, based on the error, this could be an SD card.
                              Try ACMD41 command to verify this claim.
                           2. There is no card in the slot.
                        */
                        /* Try SD application command. This application command should
                           return an error. It is unclear why the card returns an error
                           after CMD1. Is it a firmware bug? or...

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -