vxworks7.0SD卡驱动流程及文件系统格式化

今天和大家谈谈vx7SD卡的vxbus挂接,及文件系统格式化流程,vx7的vxbus基于设备树,首先必须增加设备树节点,如下:

 sdhc0: sdhc@E0100000
   {
        compatible = "zynq,sdhc";
        reg = <0xE0100000 0x1000>;
        clock-frequency = <100000000>;
        interrupts = <56 0 4>;
        interrupt-parent = <&intc>;
        embedded = <0>;
        bus-width = <4>;
        max-dev-clock-frequency = <52000000>;
        card-status-check = <0>; 
       };
```

 了解清楚vxbus设备SD卡的挂接流程,对于我们设备驱动的开发至关重要,具体流程如下:
1、设备初始化时会自动加载并识别设备树的节点配置,并匹配相应的驱动程序,首先匹配到SDHC主控制器设备compatible = "zynq,sdhc";在这个驱动中会调用attach去初始化相应的设备,具体代码如下:

LOCAL STATUS zynqSdhcCtrlAttach
    (
    struct vxbDev * pDev /* Device information */
    )
    {
    ZYNQSDHC_CFG * pCfg;
    STATUS rc;
    SDHC_DEV_CTRL * pDrvCtrl;
    VXB_FDT_DEV * pFdtDev;
    const void * pValue;
    int len;

    rc = vxbClkEnableAll (pDev);
    if (rc == ERROR)
        {
        return ERROR;
        }

    rc = sdhcCtrlAttach (pDev);
    if (rc == ERROR)
        return (rc);

    pDrvCtrl = (SDHC_DEV_CTRL *)GET_DRVCTRL(pDev);
    if (pDrvCtrl == NULL)
        return ERROR;

    pFdtDev = vxbFdtDevGet(pDev);
    if (pFdtDev == NULL)
        return ERROR;

    (void)vxbPinMuxEnable(pDev);

    /* retrieve embedded information if provided */
    pValue = vxFdtPropGet(pFdtDev->offset, "embedded", &len);
    if(pValue != NULL)
        {
        pDrvCtrl->embedded = vxFdt32ToCpu(*(UINT32 *)pValue);
        }
    
    /* retrieve max-dev-clock-frequency information if provided */
    pValue = vxFdtPropGet(pFdtDev->offset, "max-dev-clock-frequency", &len);
    if(pValue != NULL)
        pDrvCtrl->maxDevClkFreq = vxFdt32ToCpu(*(UINT32 *)pValue);
    else
        pDrvCtrl->maxDevClkFreq = 0;

    /* retrieve user-set-clock-frequency information if provided */
    pValue = vxFdtPropGet(pFdtDev->offset, "user-set-clock-frequency", &len);
    if(pValue != NULL)
        pDrvCtrl->userSetClkFreq = vxFdt32ToCpu(*(UINT32 *)pValue);
    else
        pDrvCtrl->userSetClkFreq = 0;
        
    pCfg = (ZYNQSDHC_CFG *)vxbDevDrvDataGet(pDev);

    pDrvCtrl->flags = pCfg->flag;
    pDrvCtrl->sdHostCtrl.sdHostOps.vxbSdHostCtrlInit = zynqSdhcInit;

    if (pDrvCtrl->embedded == FALSE)
        {
        pDrvCtrl->sdHostCtrl.sdHostOps.vxbSdVddSetup = zynqSdhcVddSetup;
        }
    else
        {
        pDrvCtrl->sdHostCtrl.sdHostOps.vxbSdVddSetup = NULL;
        }

    pDrvCtrl->flags |= SDHC_MANUAL_SDMA_ADDRESS;
    
    rc = zynqSdhcInstConnect (pDev);
    return (rc);
    }

2、在attach函数最后会调用 zynqSdhcInstConnect,在zynqSdhcInstConnect函数中会创建线程sdBusMonitor,此线程会自动识别卡的插入和拔出,在卡插入时在其父节点下创建新的子节点,并增加的vxbus上去

LOCAL STATUS zynqSdhcInstConnect
    (
    VXB_DEV_HANDLE pDev
    )
    {
    UINT32 val;
    STATUS rc;
    SDHC_DEV_CTRL * pDrvCtrl;
    SD_HOST_CTRL * pHostCtrl;
    VXB_FDT_DEV * pFdtDev;
    const void * pValue;
    int len;
    
    pDrvCtrl = (SDHC_DEV_CTRL *)GET_DRVCTRL(pDev);
    if (pDrvCtrl == NULL)
        return ERROR;

    pHostCtrl = (SD_HOST_CTRL *)pDrvCtrl;
    rc = sdhcCtrlInstConnect(pHostCtrl);
    if (rc == ERROR)
        return ERROR;

    pFdtDev = vxbFdtDevGet(pDev);
    if (pFdtDev == NULL)
        return ERROR;

    pValue = vxFdtPropGet(pFdtDev->offset, "bus-width", &len);
    if (pValue != NULL)
        {
        pHostCtrl->sdHostSpec.busWidth = vxFdt32ToCpu(*(UINT32 *)pValue);
        }
    else
        {
        pHostCtrl->sdHostSpec.busWidth = 4;
        }

    pValue = vxFdtPropGet(pFdtDev->offset, "card-status-check", &len);
    if (pValue != NULL)
        {
        pHostCtrl->sdHostSpec.cardCheck = vxFdt32ToCpu(*(UINT32 *)pValue);
        }
    else
        {
        pHostCtrl->sdHostSpec.cardCheck = 0;
        }

    pHostCtrl->sdHostSpec.vxbSdBusWidthSetup = pHostCtrl->sdHostOps.vxbSdBusWidthSetup;
    pHostCtrl->sdHostSpec.vxbSdCardWpCheck = pHostCtrl->sdHostOps.vxbSdCardWpCheck;
    pHostCtrl->sdHostSpec.vxbSdClkFreqSetup = pHostCtrl->sdHostOps.vxbSdClkFreqSetup;
    pHostCtrl->sdHostSpec.vxbSdResumeSet = pHostCtrl->sdHostOps.vxbSdResumeSet;
    pHostCtrl->sdHostSpec.vxbSdVddSetup =  pHostCtrl->sdHostOps.vxbSdVddSetup;
    pHostCtrl->sdHostSpec.capbility = pHostCtrl->capbility;
    pHostCtrl->sdHostSpec.maxTranSpeed = pDrvCtrl->maxDevClkFreq;
    pHostCtrl->sdHostSpec.userSetTranSpeed = pDrvCtrl->userSetClkFreq;
    pHostCtrl->sdHostSpec.directBio = pHostCtrl->directBio;

    pDrvCtrl->monTaskId = taskSpawn ("sdBusMonitor", 100, 0,
                                     8192, (FUNCPTR)zynqSdhcCtrlMonitor,
                                     (_Vx_usr_arg_t)pDev, 
                                     0, 0, 0, 0, 0, 0, 0, 0, 0);

    if (pDrvCtrl->monTaskId == TASK_ID_ERROR)
        {
        ZYNQSDHC_DBG (ZYNQSDHC_DBG_ERR, "Create monitor task fault\n",
                     0, 0, 0, 0, 0, 0);
        return ERROR;
        }

    /* setup the interrupt mask */

    pDrvCtrl->intMask = (IRQ_DATA | IRQ_CMD);
    pDrvCtrl->intMask |= IRQ_AC12E; 

    if (pDrvCtrl->sdHostCtrl.dmaMode == SDHC_DMA_MODE_PIO)
        pDrvCtrl->intMask |= (IRQ_BRR | IRQ_BWR);

    if (pDrvCtrl->embedded == FALSE)
        pDrvCtrl->intMask |= (IRQ_CINS | IRQ_DINT | IRQ_CRM);
    else
        pDrvCtrl->intMask |= IRQ_DINT;

    CSR_WRITE_4 (pDev, SDHC_IRQSTATEN, pDrvCtrl->intMask);

    /* enable SDHC interrupts */

    if (pDrvCtrl->sdHostCtrl.polling == FALSE)
        {

        /* connect and enable interrupt */

        if (pDrvCtrl->sdHostCtrl.sdHostOps.vxbSdIsr == NULL)
            {
            (void)taskDelete (pDrvCtrl->monTaskId); 
            return ERROR;
            } 
        rc = vxbIntConnect (pDev,
                            pDrvCtrl->intRes,
                            (VOIDFUNCPTR)pDrvCtrl->sdHostCtrl.sdHostOps.vxbSdIsr,
                            pDev);
        if (rc == ERROR)
            {
            (void)taskDelete (pDrvCtrl->monTaskId); 
            return ERROR;
            } 

        rc = vxbIntEnable (pDev, pDrvCtrl->intRes);
        if (rc == ERROR)
            {
            (void)taskDelete (pDrvCtrl->monTaskId); 
            return ERROR;
            } 

        CSR_WRITE_4 (pDev, SDHC_IRQSIGEN, pDrvCtrl->intMask);
        }

    if (pDrvCtrl->embedded == FALSE)
        {
        /* don't miss an already inserted card */
            
        val  = CSR_READ_4(pDev, SDHC_PRSSTAT);
        if (val & PRSSTAT_CINS)
            {
            (void)semGive(pDrvCtrl->sdHostCtrl.devChange);
            }
        }
    else
        {
        (void)semGive(pDrvCtrl->sdHostCtrl.devChange);
        }

    return OK;
    }

 

在这个线程 中会调用zynqSdhcDevAdd,增加子节点到vxbus上并设备名为vxbDevNameSet (pDev, MMC_CARD_NAME, TRUE);或者 vxbDevNameSet (pDev, SD_CARD_NAME, TRUE);
vxbDevAdd函数在增加设备节点时会根据devName查找匹配函数并调用相关初始化操作,此时会找到相应的SD卡驱动函数:

LOCAL void zynqSdhcCtrlMonitor
    (
    VXB_DEV_HANDLE pDev
    )
    {
    STATUS rc;
    SD_HOST_CTRL * pSdHostCtrl;
    SDHC_DEV_CTRL * pDrvCtrl; 

    pDrvCtrl = (SDHC_DEV_CTRL *)GET_DRVCTRL(pDev);
    if (pDrvCtrl == NULL)
        return;
    else
        pSdHostCtrl = (SD_HOST_CTRL *)(&(pDrvCtrl->sdHostCtrl));

    while (erfLibInitialized == FALSE)
        (void)taskDelay (sysClkRateGet ());

    while(1)
        {
        rc = pSdHostCtrl->sdHostOps.vxbSdCardInsertSts(pDev);
        if (rc && (pSdHostCtrl->attached == FALSE))
            {
            zynqSdhcDevAdd(pDev);
            }
        else if (rc)
            {
            zynqSdhcDevRemove(pDev);
            zynqSdhcDevAdd(pDev);
            }
        if (!rc && (pSdHostCtrl->attached == TRUE))
            {
            zynqSdhcDevRemove (pDev);
            }
        }
    }

相应代码如下:

STATUS sdDeviceCreate
    (
    VXB_DEV_HANDLE pInst,
    void * pArg
    )
    {
    VXB_DEV_ID      pDev = NULL;
    SD_HARDWARE   * pSdHardWare;
    SD_HOST_SPEC  * pSdHostSpec;
    STATUS rc;

    /* initialize generic bus info */

    rc = vxbDevCreate (&pDev);

    if (rc != OK)
        {
        SD_LIB_DBG (SD_LIB_DBG_ERR,
                    "sdDeviceAnnounce() - vxbDevStructAlloc not success\n",
                    0, 0, 0, 0, 0, 0);
        return(ERROR);
        }

    /* initialize bus-specific info */

    pSdHardWare = (SD_HARDWARE *) vxbMemAlloc(sizeof (SD_HARDWARE));
    if (pSdHardWare == NULL)
        {
        SD_LIB_DBG (SD_LIB_DBG_ERR,
                    "sdDeviceAnnounce - hwMemAlloc not success for pSdHardWare\n",
                    0, 0, 0, 0, 0, 0);
        vxbMemFree(pDev);
        return(ERROR);
        }

    rc = VXB_SDSPECINFO_GET(pInst, &(pSdHardWare->pHostSpec), &(pSdHardWare->vxbSdCmdIssue));
    if (rc != OK)
        {
        SD_LIB_DBG(SD_LIB_DBG_ERR,
                   "sdDeviceAnnounce - VXB_SDSPECINFO_GET not success\n",
                   0, 0, 0, 0, 0 ,0);
        vxbMemFree(pDev);
        vxbMemFree(pSdHardWare);
        return(ERROR);
        }

    vxbDevClassSet(pDev, VXB_BUSID_SDMMC);

    vxbDevIvarsSet(pDev,pSdHardWare);

    pSdHostSpec = (SD_HOST_SPEC *)(pSdHardWare->pHostSpec);
    if (pSdHostSpec == NULL)
        {
        SD_LIB_DBG(SD_LIB_DBG_ERR, "sdDeviceAnnounce - pSdHostSpec null\n",
                0, 0, 0, 0, 0, 0);
        vxbMemFree(pDev);
        vxbMemFree(pSdHardWare);
        return(ERROR);
        }

    pSdHostSpec->childDev = pDev;

    /* get host controller unit number */
    pSdHostSpec->unitNumber = vxbDevUnitGet(pInst);

    pSdHardWare->pHostDev = pInst;

    if (pSdHostSpec->vxbSdGetHostCap)
        {
        (void)(pSdHostSpec->vxbSdGetHostCap)(pInst, &(pSdHostSpec->hostCap));
        }
    return sdDeviceInit(pDev,0);
    }

 

 

STATUS sdDeviceInit
    (
    VXB_DEV_HANDLE pDev,
    UINT32 reInit
    )
    {
    VXB_DEV_HANDLE pInst;
    SD_HARDWARE   * pSdHardWare;
    SD_HOST_SPEC  * pSdHostSpec;
    STATUS rc;
    int i = 0;
    UINT32  capbility;
    UINT32 timeOut = 0;

    pSdHardWare = (SD_HARDWARE *)GET_HARDWAREINFO(pDev);
    if (pSdHardWare == NULL)
        return ERROR;

    pSdHostSpec = (SD_HOST_SPEC *)(pSdHardWare->pHostSpec);
    if (pSdHostSpec == NULL)
        return ERROR;

    capbility = pSdHostSpec->capbility;
    pInst = pSdHardWare->pHostDev;

    rc = sdCmdGoIdleState (pDev);
    if (rc == ERROR)
        {

        SD_LIB_DBG(SD_LIB_DBG_ERR,
                   "sdDeviceAnnounce - sdCmdGoIdleState not success\n\n",
                   0, 0, 0, 0, 0, 0);
        vxbMemFree(pDev);
        vxbMemFree(pSdHardWare);
        return(ERROR);
        }

    /* CMD8 is required to support SDHC or SDXC */

    (void)sdCmdSendIfCond (pDev, 0);

    rc = sdioCmdIoSendOpCond(pDev, capbility & OCR_VDD_VOL_MASK);

    if ((pSdHardWare->cmdErr & SDMMC_CMD_ERR_TIMEOUT) != 0x0)
        {

        /* To conform to JEDEC specification */
        rc = sdMmcCmdSendOpCond(pDev, 0);
        if ((rc == ERROR) ||
            ((pSdHardWare->cmdErr & SDMMC_CMD_ERR_TIMEOUT) != 0x0))
            pSdHardWare->isMmc = FALSE;
        else
            pSdHardWare->isMmc = TRUE;

        if (pSdHardWare->isMmc)
            {
            sdCmdGoIdleState(pDev);
            while (timeOut++ < SDMMC_COMMAND_TIMEOUT)
                {
                rc = sdMmcCmdSendOpCond(pDev,
                                        (pSdHardWare->ocrValue |
                                        OCR_CARD_CAP_STS));
                if ((rc == OK) &&
                    ((pSdHardWare->ocrValue & (UINT32)OCR_CARD_PWRUP_STS) != 0x0))
                    {
                    pSdHardWare->voltage = (pSdHardWare->ocrValue) & OCR_VDD_VOL_MASK;
                    break;
                    }
                vxbMsDelay(1);
                }
            vxbDevNameSet (pDev, MMC_CARD_NAME, TRUE);
            }
        else
            {
            (void)sdCmdGoIdleState (pDev);
            (void)sdCmdSendIfCond (pDev, capbility);
            if (pSdHardWare->version == SD_VERSION_UNKNOWN)
                {
                SD_LIB_DBG(SD_LIB_DBG_ERR,
                           "sdDeviceAnnounce - sdCmdGoIdleState not success\n\n",
                           0, 0, 0, 0, 0, 0);
                vxbMemFree(pDev);
                vxbMemFree(pSdHardWare);
                return(ERROR);
                }
            while (timeOut++ < SDMMC_COMMAND_TIMEOUT)
                {
                rc = sdACmdSendOpCond (pDev, capbility, pSdHardWare->version, reInit);

                if ((rc == OK) && ((pSdHardWare->ocrValue & (UINT32)OCR_CARD_PWRUP_STS) != 0x0))
                    {
                    pSdHardWare->voltage = (pSdHardWare->ocrValue) & OCR_VDD_VOL_MASK;
                    break;
                    }
                vxbMsDelay(1);
                }
            if (timeOut >= SDMMC_COMMAND_TIMEOUT)
                {
                SD_LIB_DBG(SD_LIB_DBG_ERR,
                           "sdDeviceAnnounce - sdACmdSendOpCond not success\n",
                           0, 0, 0, 0, 0, 0);
                vxbMemFree(pDev);
                vxbMemFree(pSdHardWare);
                return(ERROR);
                }

            /* Use pSdHostSpec->capbility to record S18A */

            if (pSdHardWare->ocrValue & OCR_VDD_VOL_S18A)
                {
                pSdHostSpec->capbility |= OCR_VDD_VOL_S18A;
                }

            vxbDevNameSet (pDev, SD_CARD_NAME, TRUE);
            }

        pSdHardWare->isComboCard = FALSE;
        pSdHardWare->isSdio = FALSE;

        rc = vxbDevAdd (pInst, pDev);
        if (rc == ERROR)
            {
            SD_LIB_DBG(SD_LIB_DBG_ERR,
                       "sdDeviceAnnounce - vxbDevAdd not success\n",
                       0, 0, 0, 0, 0, 0);
            vxbMemFree(pDev);
            vxbMemFree(pSdHardWare);
            return(ERROR);
            }

        pSdHardWare->recover = TRUE;
        
        /* coverity[leaked_storage] */

        /*
         * pDev and pSdHardWare are used with vxBus system,
         * so we can't free it. Set coverity keyword
         */

        return OK;
        }

    if (rc == OK)
        {
        UINT8 funcNum = 0;

        funcNum = (pSdHardWare->ocrValue >> 28) & 0x07;

        if (funcNum > 0)
            {
            rc = sdioCmdIoSendOpCond(pDev, capbility & 0x00FFFFFF);
            if (rc == ERROR)
                {
                SD_LIB_DBG (SD_LIB_DBG_ERR,
                            "sdDeviceAnnounce - sdioCmdIoSendOpCond not success\n",
                            0, 0, 0, 0, 0, 0);
                vxbMemFree(pDev);
                vxbMemFree(pSdHardWare);
                return(ERROR);
                }
            do{
               rc = sdCmdSendRelativeAddr (pDev);
               if (rc == ERROR)
                   {
                   SD_LIB_DBG (SD_LIB_DBG_ERR,
                               "sdDeviceAnnounce - sdCmdSendRelativeAddr not success\n",
                               0, 0, 0, 0, 0, 0);
                   vxbMemFree(pDev);
                   vxbMemFree(pSdHardWare);
                   return(ERROR);
                   }
               } while (pSdHardWare->rcaValue == 0);

            rc = sdCmdSelectCard (pDev);
            if (rc == ERROR)
                {
                SD_LIB_DBG (SD_LIB_DBG_ERR,
                            "sdDeviceAnnounce - sdCmdSelectCard not success\n",
                            0, 0, 0, 0, 0, 0);
                vxbMemFree(pDev);
                vxbMemFree(pSdHardWare);
                return(ERROR);
                }

            for (i = 0; i < funcNum; i++)
                {
                if (pDev == NULL)
                    {
                    rc = vxbDevCreate (&pDev);
                    if (rc == ERROR)
                        {
                        SD_LIB_DBG (SD_LIB_DBG_ERR,
                                    "sdDeviceAnnounce - vxbDevCreate not success\n",
                                    0, 0, 0, 0, 0, 0);
                        vxbMemFree(pSdHardWare);
                        return(ERROR);
                        }
                    }
                if (pSdHardWare == NULL)
                    {
                    pSdHardWare = (SD_HARDWARE *) vxbMemAlloc(sizeof (SD_HARDWARE));

                    if (pSdHardWare == NULL)
                        {
                        SD_LIB_DBG (SD_LIB_DBG_ERR,
                                    "sdDeviceAnnounce - hwMemAlloc not success for pSdHardWare\n",
                                    0, 0, 0, 0, 0, 0);
                        vxbMemFree(pDev);
                        return(ERROR);
                        }

                    rc = VXB_SDSPECINFO_GET(pInst, &(pSdHardWare->pHostSpec), &(pSdHardWare->vxbSdCmdIssue));
                    if (rc != OK)
                        {
                        SD_LIB_DBG (SD_LIB_DBG_ERR,
                                    "sdDeviceAnnounce - VXB_SDSPECINFO_GET not success\n",
                                    0, 0, 0, 0, 0, 0);
                        vxbMemFree(pDev);
                        vxbMemFree(pSdHardWare);
                        return(ERROR);
                        }

                    vxbDevClassSet(pDev, VXB_BUSID_SDMMC);

                    vxbDevIvarsSet(pDev,pSdHardWare);

                    pSdHostSpec = (SD_HOST_SPEC *)(pSdHardWare->pHostSpec);
                    if (pSdHostSpec == NULL)
                        {
                        SD_LIB_DBG (SD_LIB_DBG_ERR,
                                    "sdDeviceAnnounce - pSdHostSpec null\n",
                                    0, 0, 0, 0, 0, 0);
                        vxbMemFree(pDev);
                        vxbMemFree(pSdHardWare);
                        return(ERROR);
                        }

                    capbility = pSdHostSpec->capbility;
                    }

                pSdHardWare->isSdio = TRUE;
                pSdHardWare->isComboCard = FALSE;
                pSdHardWare->funcNum = i + 1;

                /* Need not check return status at here */

                rc = vxbDevAdd (pInst, pDev);
                if (rc == ERROR)
                    {
                    SD_LIB_DBG (SD_LIB_DBG_ERR,
                                "sdDeviceAnnounce - vxbDevAdd not success\n",
                                0, 0, 0, 0, 0, 0);
                    vxbMemFree(pDev);
                    vxbMemFree(pSdHardWare);
                    return(ERROR);
                    }

                pDev = NULL;
                pSdHardWare = NULL;
                }
            }
        }

    return OK;
    }

 

 在SD卡的ATTACH函数中会挂接相应的read,write,ioctl等函数并创建xbd包装器

LOCAL STATUS sdIdentify
    (
    VXB_DEV_HANDLE pDev
    )
    {
    STATUS rc;
    UINT32 csize, csizeMulti;
    UINT64 blkNum;
    SD_CARD_CTRL * pDrvCtrl;
    SD_HARDWARE * pSdHardware;
    SD_HOST_SPEC * pHostSpec;
    SD_INFO * pSdInfo;
    device_t xbdSts;
    BLK_XBD_PARAMS blkXbdParams;
    UINT32 workSpeed;
    UINT32 i;

    pDrvCtrl = (SD_CARD_CTRL *)GET_DRVCTRL (pDev);
    if (pDrvCtrl == NULL)
        return ERROR;

    pSdHardware = (SD_HARDWARE *)GET_HARDWAREINFO(pDev);
    if (pSdHardware == NULL)
        return ERROR;

    pHostSpec = (SD_HOST_SPEC *)(pSdHardware->pHostSpec);
    if (pHostSpec == NULL)
        return ERROR;

#ifdef _WRS_CONFIG_VXBUS_LEGACY
    pDrvCtrl->pInfo = malloc (sizeof(SD_INFO));
#else
    pDrvCtrl->pInfo = vxbMemAlloc(sizeof(SD_INFO));
#endif /* _WRS_CONFIG_VXBUS_LEGACY */

    if (pDrvCtrl->pInfo == NULL)
        goto err1;

    /* apply one card index to system */

    rc = sdCardIdxAlloc (pDrvCtrl);
    if (rc != OK)
        {
        SD_CARD_DBG(SD_CARD_DBG_INIT, 
                       "sdIdentify() -  sdCardIdxAlloc fault\n",
                       0, 0, 0, 0, 0, 0);
        goto err;
        }

    pSdInfo = (SD_INFO *)(pDrvCtrl->pInfo);
    bcopy((char *)(&pSdHardware->cidValue[0]), (char *)(&pSdInfo->cid), CID_SIZE);
    pDrvCtrl->highCapacity = (((pSdHardware->ocrValue) &
                               OCR_CARD_CAP_STS) != 0x0) ? TRUE : FALSE;
    SD_CARD_DBG(SD_CARD_DBG_INIT,
                   "sdIdentify() -  pDrvCtrl->highCapacity = 0x%x\n",
                   pDrvCtrl->highCapacity, 0, 0, 0, 0, 0);
    if ((pHostSpec->capbility & OCR_VDD_VOL_S18A) != 0x0)
        {
        if ((pSdHardware->ocrValue & OCR_VDD_VOL_S18A) != 0x0)
            pSdInfo->uhsSupport = TRUE;
        else
            pSdInfo->uhsSupport = FALSE;
        }
    else
        pSdInfo->uhsSupport = FALSE;

    if (pSdInfo->uhsSupport)
        {

        if (pHostSpec->vxbSdSigVolSwitch != NULL)
            {
            rc = pHostSpec->vxbSdSigVolSwitch (pSdHardware->pHostDev, SD_VOLTAGE_S18);
            if (rc == ERROR)
                {
                SD_CARD_DBG(SD_CARD_DBG_ERR,
                            "sdIdentify() -  vxbSdSigVolSwitch error\n",
                            0, 0, 0, 0, 0, 0);
                pSdInfo->uhsSupport = FALSE;
                pHostSpec->capbility &= (~OCR_VDD_VOL_S18A);

            /*
             * If an error occurs during voltage switch procedure, stop providing 
             * the power to the card. In this case, Host Driver should retry 
             * initialization procedure by setting S18R to 0 at step (7) and (21) in
             * Figure 3-9. (Part A2)
             */

            /*
             * AM572X idk board doesn't support power cycle. So retry initialization
             * is not validated.
             */

#ifndef _WRS_CONFIG_VXBUS_LEGACY
                rc = sdPowerCycle(pDev);
                if (rc == OK)
                    {
                    vxbMemFree (pDrvCtrl->pInfo);
                    vxbMemFree (pDrvCtrl);
                    vxbDevSoftcSet(pDev, NULL);
                    return sdDeviceInit(pDev, 1);
                    }
                else
#endif /* _WRS_CONFIG_VXBUS_LEGACY */
                    goto err;
                }
            }
        else
            {
            pSdInfo->uhsSupport = FALSE;
            pHostSpec->capbility &= (~OCR_VDD_VOL_S18A);
            goto sendRca;
            }
        goto sendRca;
        }

sendRca:

    /* Need not take care of return value */

    (void)sdCmdAllSendCid(pDev, (void *) (&pSdHardware->cidValue[0]));

    /* CMD3: request card to send RCA */

    i = 0;
    do
        {
        (void)sdCmdSendRelativeAddr (pDev);
        } while ((pSdHardware->rcaValue == 0) && (i++ < CMD3_RETRY_NUM));

    if (i >= CMD3_RETRY_NUM)
        {
        SD_CARD_DBG(SD_CARD_DBG_ERR, "sdIdentify() - failed to get valid RCA.\n",
                0, 0, 0, 0, 0, 0);
        goto err;
        }
    else
        {
        SD_CARD_DBG(SD_CARD_DBG_INIT, "sdIdentify() -  pSdHardware->rcaValue = 0x%x\n",
                pSdHardware->rcaValue, 0, 0, 0, 0, 0);
        }

    /* CMD9: request card to send CSD */

    rc = sdCmdSendCsd (pDev, &(pSdInfo->csd));
    if (rc == ERROR)
        goto err;
    else
        {
        pSdInfo->csd.commClass = (UINT16)be16toh(pSdInfo->csd.commClass);
        pSdInfo->csd.eraseSize = (UINT16)be16toh(pSdInfo->csd.eraseSize);
        pSdInfo->csd.r2wFactor = (UINT16)be16toh(pSdInfo->csd.r2wFactor);
        pSdInfo->csd.fileFormat = (UINT16)be16toh(pSdInfo->csd.fileFormat);
        SD_CARD_DBG(SD_CARD_DBG_INIT, "sdIdentify() -  pSdInfo->csd.commClass = 0x%x\n"
                    "pSdInfo->csd.eraseSize = 0x%x\n"
                    "pSdInfo->csd.r2wFactor = 0x%x\n"
                    "pSdInfo->csd.fileFormat = 0x%x\n",
                    pSdInfo->csd.commClass, pSdInfo->csd.eraseSize,
                    pSdInfo->csd.r2wFactor, pSdInfo->csd.fileFormat, 0, 0);

        /* decode CSD fields */

        pDrvCtrl->tranSpeed = sdCsdTranSpdfUnit[(pSdInfo->csd.tranSpeed & 0x7)] *
                              sdCsdTranSpdTime[((pSdInfo->csd.tranSpeed >> 3) & 0x0f)];
        SD_CARD_DBG(SD_CARD_DBG_INIT, "sdIdentify() -  pDrvCtrl->tranSpeed = %d\n",
                    pDrvCtrl->tranSpeed, 0, 0, 0, 0, 0);

        if (pDrvCtrl->tranSpeed == CSD_TRAN_SPD_50MHZ)
            pDrvCtrl->highSpeed = TRUE;

        /* maximum read block length */

        pDrvCtrl->readBlkLen = 1 << (pSdInfo->csd.commClass & 0x0f);
        SD_CARD_DBG(SD_CARD_DBG_INIT, "sdIdentify() -  pDrvCtrl->readBlkLen = %d\n",
                    pDrvCtrl->readBlkLen, 0, 0, 0, 0, 0);

        /* per SD spec, the maximum write block length is equal to read block */

        pDrvCtrl->writeBlkLen = pDrvCtrl->readBlkLen;
        pSdHardware->blockSize = SDMMC_BLOCK_SIZE;

        /* calculate user data capacity */

        if (pDrvCtrl->highCapacity)
            {
            csize = ((pSdInfo->csd.resvData0[1] & 0x3f) << 16) |
                     (pSdInfo->csd.resvData0[2] << 8) |
                      pSdInfo->csd.resvData0[3];
            csizeMulti = 8;
            }
        else
            {
            csize = ((UINT32)(pSdInfo->csd.resvData0[0] & 0x03) << 10) |
                    ((UINT32)(pSdInfo->csd.resvData0[1]) << 2) |
                    ((pSdInfo->csd.resvData0[2] >> 6) & 0x03);
            csizeMulti = ((pSdInfo->csd.resvData0[3] & 0x03) << 1) |
                         ((pSdInfo->csd.eraseSize >> 7) & 0x01);
            }

        blkNum = ((UINT64)(csize + 1)) << (csizeMulti + 2);
        pDrvCtrl->blkNum = blkNum;
        pDrvCtrl->capacity = blkNum * pDrvCtrl->readBlkLen;
        SD_CARD_DBG(SD_CARD_DBG_INIT, "sdIdentify() -  pDrvCtrl->blkNum = %ld\n"
                    "pDrvCtrl->capacity = %ld\n",
                    pDrvCtrl->blkNum, pDrvCtrl->capacity, 0, 0, 0, 0);

        /* write protect model */
        if ((pSdInfo->csd.fileFormat >> 12) & 0x1)
            pDrvCtrl->tmpWp = TRUE;
        if ((pSdInfo->csd.fileFormat >> 13) & 0x1)
            pDrvCtrl->permWp = TRUE;
        }

    /* After Card Identification, the station go into Data Transfer Mode */

    if (pDrvCtrl->tranSpeed > SDMMC_CLK_FREQ_400KHZ)
        {
        workSpeed = pDrvCtrl->tranSpeed < SDMMC_CLK_FREQ_25MHZ ?
                    pDrvCtrl->tranSpeed : SDMMC_CLK_FREQ_25MHZ;

        pHostSpec->vxbSdClkFreqSetup (pSdHardware->pHostDev, workSpeed);
        }

    pDrvCtrl->highSpeed = FALSE;

    /* CMD7: select one card and put it into transfer state */

    rc = sdCmdSelectCard (pDev);
    if (rc == ERROR)
        goto err;

    /* AMD51: request card to send its SCR */

    rc = sdACmdSendScr (pDev, &(pSdInfo->scr));
    if (rc == ERROR)
        goto err;
    else
        {
        pSdInfo->sdSpec = pSdInfo->scr.spec & 0x0f;
        SD_CARD_DBG(SD_CARD_DBG_INIT, "sdIdentify() -  pSdInfo->sdSpec = 0x%x\n",
                    pSdInfo->sdSpec, 0, 0, 0, 0, 0);

        /* update the SD card version */

        pSdHardware->version = (UINT8)(pSdInfo->sdSpec + 1);


        if ((pSdInfo->scr.expConfig & SCR_SD_SPEC3_MASK) != 0x0)
            {
            if (pSdHardware->version == SD_VERSION_200)
                pSdHardware->version = SD_VERSION_300;
            }
            
        pSdInfo->sdSec = (pSdInfo->scr.config >> 4) & 0x7;
        if (pSdInfo->scr.config & SCR_SD_BUS_WIDTH_4BIT)
            pSdInfo->dat4Bit = TRUE;
        }

    /* switch to 4 bit mode if needed */

    if (pSdInfo->dat4Bit)
        {
        rc = sdACmdSetBusWidth (pDev, SDMMC_BUS_WIDTH_4BIT);
        if (rc == ERROR)
            goto err;

        /* setup host to enable 4-bit bus width */

        if (pHostSpec->vxbSdBusWidthSetup != NULL)
            {
            pHostSpec->vxbSdBusWidthSetup(pSdHardware->pHostDev, SDMMC_BUS_WIDTH_4BIT);
            }
        }
    /* ACMD42: clear card detect and set data3 as data line */
    rc = sdACmdClrCardDetect(pDev, SD_ACMD42_ARG_CLR_CARD_DETECT);
    if (rc == ERROR)
        goto err;	
        
    /* setup host to enable high speed clock (50 MHz) if needed */

    if (pSdInfo->uhsSupport)
        {
        rc = sdInitUhsCard(pDev);
        if (rc == ERROR)
            goto err;
        goto createXbd;
        }

    /* setup host to enable high speed clock (50 MHz) if needed */

    if (pSdHardware->version >= SD_VERSION_110)
        {
        int rc;
        rc = sdACmdSetHighSpeed(pDev);

        if ((pHostSpec->vxbSdClkFreqSetup != NULL))
            {
            if ((rc == OK) && (pHostSpec->workFreq == SDMMC_CLK_FREQ_25MHZ))
                pHostSpec->vxbSdClkFreqSetup(pSdHardware->pHostDev, SDMMC_CLK_FREQ_25MHZ);
            else if (rc == OK)
                {
                pHostSpec->vxbSdClkFreqSetup(pSdHardware->pHostDev, SDMMC_CLK_FREQ_50MHZ);
                pDrvCtrl->highSpeed = TRUE;
                SD_CARD_DBG(SD_CARD_DBG_INIT, "sdIdentify() -  change to 50MHZ success\n",
                            0, 0, 0, 0, 0, 0);
                }
            else if (rc == ENOTSUP)
                {
                pHostSpec->vxbSdClkFreqSetup(pSdHardware->pHostDev, SDMMC_CLK_FREQ_25MHZ);
                pDrvCtrl->highSpeed = FALSE;
                }
            else if (rc == ERROR)
                goto err;
            }
        }
    else
        {
        if (pHostSpec->vxbSdClkFreqSetup != NULL)
            {
            pHostSpec->vxbSdClkFreqSetup(pSdHardware->pHostDev, SDMMC_CLK_FREQ_25MHZ);
            }
        }

    /* check if card is write protected */

    if (pHostSpec->vxbSdCardWpCheck != NULL)
        {
        pDrvCtrl->isWp = pHostSpec->vxbSdCardWpCheck(pSdHardware->pHostDev);
        }

createXbd:

    /* set xbd params */

    blkXbdParams.xbdOps.blkRead = sdStorageBlkRead;
    blkXbdParams.xbdOps.blkWrite = sdStorageBlkWrite;
    blkXbdParams.xbdOps.blkDump = NULL;
    blkXbdParams.xbdOps.blkIoctl = sdStorageIoctl;
    blkXbdParams.xbdOps.xferReq  = NULL;
    blkXbdParams.maxActiveReqs = 1;
    blkXbdParams.maxBiosPerReq = 1;
    blkXbdParams.maxXferBlks = SDHC_MAX_RW_SECTORS;
    blkXbdParams.directModeFlag = pHostSpec->directBio;
    blkXbdParams.numBlks = (sector_t)(pDrvCtrl->capacity / pSdHardware->blockSize);
    blkXbdParams.blkSize = pSdHardware->blockSize;
    blkXbdParams.svcTskPri = SDMMC_XBD_SVC_TASK_PRI;
    blkXbdParams.pDev = (void *)pDev;
    (void)snprintf ((char *)&(blkXbdParams.devName[0]), sizeof(blkXbdParams.devName),
                    "/sd%d", pHostSpec->unitNumber);
    pDrvCtrl->attached = TRUE;
    xbdSts = blkXbdDevCreate (&(pDrvCtrl->xbdDev), &blkXbdParams);

    if (xbdSts == NULLDEV)
        {
        pDrvCtrl->attached = FALSE;
        goto err;
        }

    return OK;

    /*
     * We need to free memories we allocated in this function when we return
     * ERROR. If we return OK, we don't free these memories and use them in
     * normal process, until sdStorageInstUnlink() is called to free these
     * memories from vxbDevRemove() in Monitor task when card removal is detected.
     */

err:
#ifndef _WRS_CONFIG_VXBUS_LEGACY
    vxbMemFree (pDrvCtrl->pInfo);
#else
    free (pDrvCtrl->pInfo);
#endif /* _WRS_CONFIG_VXBUS_LEGACY */

err1:
#ifndef _WRS_CONFIG_VXBUS_LEGACY
    vxbMemFree (pDrvCtrl);
    vxbDevSoftcSet(pDev, NULL);
#else
    free (pDrvCtrl);
#endif /* _WRS_CONFIG_VXBUS_LEGACY */

    return ERROR;
    }

至此,设备驱动挂接完成,在shell里面输入devs 查看就可以看到设备/SD0:1,只需要调用文件系统格式化就可以了,dosFsVolFormat(“/sd0:1”,0,0);

 

 

 

 

 

 

 

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页