VxWorks 7.0下SD卡驱动流程及文件系统格式化

今天和大家谈谈VxWorks 7.0下SD卡的vxbus挂接,及文件系统格式化流程,VxWorks 7的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);

下一篇
« Prev Post
上一篇
Next Post »