今天和大家谈谈VxWorks 7下SD卡的vxbus驱动挂接,以及文件系统格式化的流程,VxWorks 7下的的vxbus驱动基于设备树,首先必须增加设备树节点,如下:
sdhc0: sdhc@E0100000
{
compatible = "zynq,sdhc";
reg = ;
clock-frequency = ;
interrupts = ;
interrupt-parent = <&intc>;
embedded = ;
bus-width = ;
max-dev-clock-frequency = ;
card-status-check = ;
};
了解清楚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);