Windows CE SDHC驱动简析(2)-CSDIOControllerBase类(基于WinCE5.0 SMDK2410 BSP的SDHC驱动)

本文深入解析了CSDIOControllerBase类,包括其原型、成员变量、函数及其作用。详细阐述了如何通过注册表获取配置信息、初始化硬件、处理不同类型的响应以及与实际平台相关的初始化工作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

接下来我们来看看CSDIOControllerBase类,该类实现了主控制器驱动的硬件实现,定义了很多成员变量和函数,如有错误,欢迎指正.
CSDIOControllerBase原型如下:

[c-sharp]  view plain copy
  1. class CSDIOControllerBase  
  2. {  
  3. public:  
  4.     explicit CSDIOControllerBase( PSDCARD_HC_CONTEXT pHCContext );  
  5.     virtual ~CSDIOControllerBase();  
  6.   
  7.     PSDCARD_HC_CONTEXT GetHostContext() const;  
  8.   
  9.     virtual BOOL InterpretCapabilities( LPCTSTR pszRegistryPath );  
  10.     void OnPowerUp();  
  11.     void OnPowerDown();  
  12.     void PreDeinit();  
  13.   
  14. protected:  
  15.     // override to customize for specific hardware  
  16.     virtual BOOL InitializeHardware( BOOL bOnPowerUp = FALSE ) = 0;  
  17.     virtual void DeinitializeHardware( BOOL bOnPowerDown = FALSE ) = 0;  
  18.     virtual BOOL CustomSetup( LPCTSTR pszRegistryPath ) = 0;  
  19.     virtual BOOL IsCardWriteProtected() = 0;  
  20.     virtual BOOL IsCardPresent() = 0;  
  21.   
  22. protected:  
  23.   
  24.     volatile S3C2410X_SDI_REG    *vm_pSDIReg;                // pointer to the SDI special registers  
  25.     volatile S3C2410X_IOPORT_REG *vm_pIOPreg;                // pointer to the GPIO control registers  
  26.     volatile S3C2410X_CLKPWR_REG *vm_pCLKPWR;                // pointer to the clock control register  
  27.     volatile S3C2410X_DMA_REG    *vm_pDMAreg;                // pointer to the DMA special registers  
  28.   
  29.     DWORD                   m_dwSDIOIrq;                     // SDIO IRQ  
  30.     DWORD                   m_dwSDIOSysIntr;                 // SDIO SysIntr  
  31.   
  32.     PBYTE                   m_pDMABuffer;                    // pointer to buffers used for DMA transfers  
  33.     PHYSICAL_ADDRESS        m_pDMABufferPhys;                // physical address of the SMA buffer  
  34.     DWORD                   m_dwDMAChannel;                  // DMA channel to use for data transfers  
  35.     DWORD                   m_dwDMAIrq;                      // DMA IRQ  
  36.     DWORD                   m_dwDMASysIntr;                  // DMA SysIntr  
  37.   
  38.     DWORD                   m_dwPollingTimeout;              // card detect thread polling timeout  
  39.   
  40.     char                    m_chCardDetectGPIO;              // GPIO used for card detection  
  41.     DWORD                   m_dwCardDetectMask;  
  42.     DWORD                   m_dwCardDetectFlag;  
  43.     DWORD                   m_dwCardDetectControlMask;  
  44.     DWORD                   m_dwCardDetectControlFlag;  
  45.     DWORD                   m_dwCardDetectPullupMask;  
  46.     DWORD                   m_dwCardDetectPullupFlag;  
  47.   
  48.     char                    m_chCardReadWriteGPIO;           // GPIO used for card read/write detection  
  49.     DWORD                   m_dwCardReadWriteMask;  
  50.     DWORD                   m_dwCardReadWriteFlag;  
  51.     DWORD                   m_dwCardReadWriteControlMask;  
  52.     DWORD                   m_dwCardReadWriteControlFlag;  
  53.     DWORD                   m_dwCardReadWritePullupMask;  
  54.     DWORD                   m_dwCardReadWritePullupFlag;  
  55.   
  56.     PSDCARD_HC_CONTEXT      m_pHCContext;                    // the host controller context  
  57.     HANDLE                  m_hResponseReceivedEvent;        // Used to post command response info asynchronously  
  58.   
  59.     int                     m_nCardDetectIstThreadPriority;  // controller IST thread priority  
  60.     HANDLE                  m_hCardInsertInterruptEvent;     // card insert/remove interrupt event  
  61.     HANDLE                  m_hCardInsertInterruptThread;    // card insert/remove interrupt event  
  62.   
  63.     int                     m_nSDIOIstThreadPriority;        // SDIO IST thread priority  
  64.     HANDLE                  m_hSDIOInterruptEvent;           // SDIO Interrupt event  
  65.     HANDLE                  m_hSDIOInterruptThread;          // SDIO Interrupt Thread Event  
  66.   
  67.     int                     m_nControllerIstThreadPriority;  // controller IST thread priority  
  68.     HANDLE                  m_hControllerInterruptEvent;     // controller interrupt event  
  69.     HANDLE                  m_hControllerInterruptThread;    // controller interrupt thread  
  70.   
  71.     int                     m_DMAIstThreadPriority;          // DMA IST thread priority  
  72.     HANDLE                  m_hDMAInterruptEvent;            // DMA interrupt event  
  73.     HANDLE                  m_hDMAInterruptThread;           // DMA interrupt thread     
  74.   
  75.     BOOL                    m_bReinsertTheCard;              // Indicates if a card insertion should be simulated now  
  76.     BOOL                    m_bUseDMAForTransfer;            // Indicates whether DMA is used for I/O requests  
  77.     BOOL                    m_bDriverShutdown;               // controller shutdown  
  78.     CRITICAL_SECTION        m_ControllerCriticalSection;     // controller critical section   
  79.     BOOL                    m_bDevicePresent;                // indicates if device is present in the slot                                              
  80.     WCHAR                   m_rgchRegPath[256];              // reg path    
  81.     SDHCDSTATE              m_CurrentState;                  // current transfer state  
  82.     BOOL                    m_bSendInitClocks;               // indicates if this is the first command sent  
  83.     DWORD                   m_dwLastTypeOfTransfer;          // inidcates the last type of data transfer initiated  
  84.   
  85.     DWORD                   m_dwNumBytesToTransfer;          // # of bytes that still need to be transferred  
  86.     DWORD                   m_dwNumBytesUnaligned;           // # of bytes from a DWORD-aligned address  
  87.     DWORD                   m_dwNumBytesExtra;               // # of extra bytes in buffer that aren't a multiple of sizeof(DWORD)  
  88.   
  89.     DWORD                   m_dwSDIBusWidth;                 // SD data transfer mode (1 bit or 4 bit) flag  
  90.     DWORD                   m_dwClockRate;                   // current clock rate  
  91.   
  92.     BOOL                    m_fCardInTheSlot;                // TRUE - a card is inserted in the slot, FALSE otherwise  
  93.     BOOL                    m_fHandleBusyCheckOnCommand38;  
  94.     DWORD                   m_dwDMATransferTimeoutFactor;  
  95.     DWORD                   m_dwDMATransferTimeoutConstant;  
  96.   
  97.     SD_API_STATUS   SendCommand(UINT16 Cmd, UINT32 Arg, UINT16 respType, BOOL bDataTransfer);  
  98.     SD_API_STATUS   GetCommandResponse(PSD_BUS_REQUEST pRequest);  
  99.     DWORD           SetClockRate(DWORD dwClockRate);  
  100.     BOOL            IsCardBusy(UINT16 inData);  
  101.   
  102.     BOOL            SetupDmaXfer(PSD_BUS_REQUEST pRequest);  
  103.   
  104.     BOOL            SetupPollingXfer(PSD_BUS_REQUEST pRequest);  
  105.     BOOL            PollingTransmit(PSD_BUS_REQUEST pRequest, DWORD dwLen);  
  106.     BOOL            PollingReceive(PSD_BUS_REQUEST pRequest, DWORD dwLen);  
  107.   
  108.     inline void     MMC_Hardware_PowerUp();  
  109.     inline void     MMC_Hardware_PowerDown();  
  110.     inline void     Stop_SDI_Hardware();  
  111.     inline void     Set_SDI_Bus_Width_1Bit();  
  112.     inline void     Set_SDI_Bus_Width_4Bit();  
  113.     inline DWORD    Get_SDI_Bus_Width();  
  114.     inline void     Wait_80_SDI_Clock_Cycles();  
  115.     inline void     Start_SDI_Clock();  
  116.     inline void     Stop_SDI_Clock();  
  117.     inline BOOL     Is_SDI_Clock_Running();  
  118.     inline void     Enable_SDIO_Interrupts();  
  119.     inline void     Disable_SDIO_Interrupts();  
  120.     inline BOOL     Is_SDIO_Interrupt_Enabled();  
  121.     inline void     Ack_SDIO_Interrupts();  
  122.     inline void     Enable_SDIO_DMA_Channel();  
  123.     inline void     Disable_SDIO_DMA_Channel();  
  124.     inline void     Stop_SDIO_DMA_Channel();  
  125.   
  126.     // thread routines  
  127.     virtual DWORD   CardDetectThread();  
  128.     virtual DWORD   IOInterruptIstThread();  
  129.     virtual DWORD   TransferIstThread();  
  130.   
  131.     // implementation of the callbacks for the SD Bus driver  
  132.     SD_API_STATUS   Deinitialize();  
  133.     SD_API_STATUS   Initialize();  
  134.     BOOLEAN         CancelIoHandler(DWORD dwSlot, PSD_BUS_REQUEST pRequest);  
  135.     SD_API_STATUS   BusRequestHandler(DWORD dwSlot, PSD_BUS_REQUEST pRequest);  
  136.     SD_API_STATUS   SlotOptionHandler(DWORD dwSlot, SD_SLOT_OPTION_CODE Option, PVOID pData, ULONG OptionSize);  
  137.   
  138.     // thread start routines  
  139.     static DWORD            SD_CardDetectThread(CSDIOControllerBase *pController);  
  140.     static DWORD            SD_IOInterruptIstThread(CSDIOControllerBase *pController);  
  141.     static DWORD            SD_TransferIstThread(CSDIOControllerBase *pController);  
  142.   
  143.     // SD Bus driver callback functions  
  144.     static SD_API_STATUS    SDHCDDeinitialize(PSDCARD_HC_CONTEXT pHCContext);  
  145.     static SD_API_STATUS    SDHCDInitialize(PSDCARD_HC_CONTEXT pHCContext);  
  146.     static BOOLEAN          SDHCDCancelIoHandler(PSDCARD_HC_CONTEXT pHCContext, DWORD dwSlot, PSD_BUS_REQUEST pRequest);  
  147.     static SD_API_STATUS    SDHCDBusRequestHandler(PSDCARD_HC_CONTEXT pHCContext, DWORD dwSlot, PSD_BUS_REQUEST pRequest);  
  148.     static SD_API_STATUS    SDHCDSlotOptionHandler(PSDCARD_HC_CONTEXT pHCContext, DWORD dwSlot,   
  149.                                         SD_SLOT_OPTION_CODE Option, PVOID pData, ULONG OptionSize);  
  150. };  

其中有几个纯虚函数是由继承类实现的(CSDIOController类,sdiocontroller.cpp)
    virtual BOOL InitializeHardware( BOOL bOnPowerUp = FALSE ) = 0;
    virtual void DeinitializeHardware( BOOL bOnPowerDown = FALSE ) = 0;
    virtual BOOL CustomSetup( LPCTSTR pszRegistryPath ) = 0;
    virtual BOOL IsCardWriteProtected() = 0;
    virtual BOOL IsCardPresent() = 0;
下面我们来一一看看每个成员函数:
1.构造函数CSDIOControllerBase
初始化成员变量,大部分初始化为0或NULL,当前状态m_CurrentState设为Idle
[c-sharp]  view plain copy
  1. CSDIOControllerBase::CSDIOControllerBase( PSDCARD_HC_CONTEXT pHCContext )  
  2. {  
  3.     vm_pSDIReg = NULL;  
  4.     vm_pIOPreg = NULL;  
  5.     vm_pCLKPWR = NULL;  
  6.     vm_pDMAreg = NULL;  
  7.     m_pDMABuffer = NULL;  
  8.     m_dwDMAChannel = 0;  
  9.   
  10.     m_pHCContext = pHCContext;  
  11.   
  12.     m_hResponseReceivedEvent = NULL;  
  13.     m_nCardDetectIstThreadPriority = 0;  
  14.     m_hCardInsertInterruptEvent = NULL;  
  15.     m_hCardInsertInterruptThread = NULL;  
  16.   
  17.     m_nSDIOIstThreadPriority = 0;  
  18.     m_hSDIOInterruptEvent = NULL;  
  19.     m_hSDIOInterruptThread = NULL;  
  20.   
  21.     m_nControllerIstThreadPriority = 0;  
  22.     m_hControllerInterruptEvent = NULL;  
  23.     m_hControllerInterruptThread = NULL;  
  24.   
  25.     m_DMAIstThreadPriority = 0;  
  26.     m_hDMAInterruptEvent = NULL;  
  27.     m_hDMAInterruptThread = NULL;  
  28.   
  29.     m_bUseDMAForTransfer = FALSE;  
  30.     m_bDriverShutdown = FALSE;  
  31.   
  32.     m_bDevicePresent = FALSE;  
  33.     m_CurrentState = Idle;  
  34.     m_bSendInitClocks = TRUE;  
  35.     m_dwLastTypeOfTransfer = SD_READ;  
  36.   
  37.     m_dwNumBytesToTransfer = 0;  
  38.     m_dwNumBytesUnaligned = 0;  
  39.     m_dwNumBytesExtra = 0;  
  40.   
  41.     m_rgchRegPath[0] = 0;  
  42.     m_dwSDIBusWidth = 0;  
  43.   
  44.     m_bReinsertTheCard = FALSE;  
  45.   
  46.     m_fHandleBusyCheckOnCommand38 = FALSE;  
  47.     m_dwDMATransferTimeoutFactor = 8;  
  48.     m_dwDMATransferTimeoutConstant = 3000;  
  49.   
  50.     m_fCardInTheSlot = FALSE;  
  51. }  
 
2.~CSDIOControllerBase
未做任何工作.

3.PreDeinit
这个函数被SDH_PreDeinit调用,m_bDriverShutdown为FALSE时调用Deinitialize进行资源释放.
[c-sharp]  view plain copy
  1. void CSDIOControllerBase::PreDeinit()  
  2. {  
  3.     if( !m_bDriverShutdown )  
  4.     {  
  5.         Deinitialize();  
  6.     }  
  7. }  
 
4.Initialize
该函数被SDHCDInitialize调用.
(1)设置crtical section临界访问,然后映射GPIO寄存器空SDI控制器,时钟能源管理寄存器,DMA控制器IO地址空间. 然后分配内存给DMA传输(64KB大小).
接着初始化寄存器
(2)MMC_Hardware_PowerUp设置CLKCON使能SDI PCLK.
(3)设置GPIO寄存器使能SDI功能
(4)SetClockRate设置SDI时钟(100HZ)
(5)设置SDI寄存器模式,little edian,512 bytes per block,设置timeout,reset fifo
(6)创建SD卡检测事件m_hCardInsertInterruptEvent及线程SD_CardDetectThread
(7)创建接收应答事件m_hResponseReceivedEvent
(8)创建IST线程m_hSDIOInterruptThread处理SDIO数据传输中断事件m_hSDIOInterruptEvent,并初始化中断
(9)设置DMA传输中断事件m_hDMAInterruptEvent和线程m_hDMAInterruptThread
(10)调用继承类InitializeHardware函数.
(11)出错处理,调用Deinitialize
[c-sharp]  view plain copy
  1. SD_API_STATUS CSDIOControllerBase::Initialize()  
  2. {  
  3.     DEBUGMSG (SDCARD_ZONE_INIT,(TEXT("SDHCDInitialize starts")));  
  4.     SD_API_STATUS status = SD_API_STATUS_SUCCESS;   // intermediate status  
  5.     DWORD         threadID;                         // thread ID  
  6.   
  7.     InitializeCriticalSection(&m_ControllerCriticalSection);  
  8.   
  9.     //----- 1. Map the GPIO registers needed to enable the SDI controller -----  
  10.     vm_pIOPreg = (S3C2410X_IOPORT_REG *)VirtualAlloc(0, sizeof(S3C2410X_IOPORT_REG), MEM_RESERVE, PAGE_NOACCESS);  
  11.     if (vm_pIOPreg == NULL)   
  12.     {  
  13.         DEBUGMSG (1,(TEXT("GPIO registers not allocated")));  
  14.         status = SD_API_STATUS_INSUFFICIENT_RESOURCES;  
  15.         goto INIT_ERROR;  
  16.     }  
  17.     if (!VirtualCopy((PVOID)vm_pIOPreg, (PVOID)(S3C2410X_BASE_REG_PA_IOPORT >> 8), sizeof(S3C2410X_IOPORT_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE)) {  
  18.         DEBUGMSG (1,(TEXT("GPIO registers not mapped")));  
  19.         status = SD_API_STATUS_INSUFFICIENT_RESOURCES;  
  20.         goto INIT_ERROR;  
  21.     }  
  22.     DEBUGMSG (1,(TEXT("GPIO registers mapped to %x"), vm_pIOPreg));  
  23.   
  24.     //----- 2. Map the SDI control registers into the device drivers address space -----  
  25.     vm_pSDIReg = (S3C2410X_SDI_REG *)VirtualAlloc(0, sizeof(S3C2410X_SDI_REG), MEM_RESERVE, PAGE_NOACCESS);  
  26.     if (vm_pSDIReg == NULL)   
  27.     {  
  28.         DEBUGMSG (1,(TEXT("SDI control registers not allocated/n/r")));  
  29.         status = SD_API_STATUS_INSUFFICIENT_RESOURCES;  
  30.         goto INIT_ERROR;  
  31.     }  
  32.     if (!VirtualCopy((PVOID)vm_pSDIReg, (PVOID)(S3C2410X_BASE_REG_PA_SDI >> 8), sizeof(S3C2410X_SDI_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE)) {  
  33.         DEBUGMSG (1,(TEXT("SDI control registers not mapped/n/r")));  
  34.         status = SD_API_STATUS_INSUFFICIENT_RESOURCES;  
  35.         goto INIT_ERROR;  
  36.     }  
  37.     DEBUGMSG (1,(TEXT("SDI control registers mapped to %x/n/r"), vm_pSDIReg));  
  38.   
  39.     vm_pCLKPWR = (S3C2410X_CLKPWR_REG *)VirtualAlloc(0, sizeof(S3C2410X_CLKPWR_REG), MEM_RESERVE, PAGE_NOACCESS);  
  40.     if (vm_pCLKPWR == NULL)   
  41.     {  
  42.         DEBUGMSG (1,(TEXT("Clock & Power Management Special Register not allocated/n/r")));  
  43.         status = SD_API_STATUS_INSUFFICIENT_RESOURCES;  
  44.         goto INIT_ERROR;  
  45.     }  
  46.     if (!VirtualCopy((PVOID)vm_pCLKPWR, (PVOID)(S3C2410X_BASE_REG_PA_CLOCK_POWER >> 8), sizeof(S3C2410X_CLKPWR_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE)) {  
  47.         DEBUGMSG (1,(TEXT("Clock & Power Management Special Register not mapped/n/r")));  
  48.         goto INIT_ERROR;  
  49.     }  
  50.     DEBUGMSG (1,(TEXT("Clock & Power Management Special Register mapped to %x/n/r"), vm_pCLKPWR));  
  51.   
  52.     if( m_dwDMAChannel != 0xffffffff )  
  53.     {  
  54.         //----- 3. Map the DMA control registers used for SDI data transfers -----  
  55.         vm_pDMAreg = (S3C2410X_DMA_REG *)VirtualAlloc(0, sizeof(S3C2410X_DMA_REG), MEM_RESERVE, PAGE_NOACCESS);  
  56.         if (vm_pDMAreg == NULL)   
  57.         {  
  58.             DEBUGMSG (1,(TEXT("DMA Register not allocated/n/r")));  
  59.             status = SD_API_STATUS_INSUFFICIENT_RESOURCES;  
  60.             goto INIT_ERROR;  
  61.         }  
  62.         if (!VirtualCopy((PVOID)vm_pDMAreg, (PVOID)(S3C2410X_BASE_REG_PA_DMA >> 8), sizeof(S3C2410X_DMA_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE)) {  
  63.             DEBUGMSG (1,(TEXT("DMA Register not mapped/n/r")));  
  64.             status = SD_API_STATUS_INSUFFICIENT_RESOURCES;  
  65.             goto INIT_ERROR;  
  66.         }  
  67.         DEBUGMSG (1,(TEXT("DMA Register mapped to %x/n/r"), vm_pDMAreg));  
  68.   
  69.         //----- 4. Allocate a block of memory for DMA transfers -----  
  70.         DMA_ADAPTER_OBJECT dmaAdapter;  
  71.         dmaAdapter.ObjectSize = sizeof(dmaAdapter);  
  72.         dmaAdapter.InterfaceType = Internal;  
  73.         dmaAdapter.BusNumber = 0;  
  74.         m_pDMABuffer = (PBYTE)HalAllocateCommonBuffer( &dmaAdapter, MAXIMUM_DMA_TRANSFER_SIZE, &m_pDMABufferPhys, FALSE );  
  75.         if( m_pDMABuffer == NULL )  
  76.         {  
  77.             RETAILMSG(1, (TEXT("SHCDriver: - Unable to allocate memory for DMA buffers!/r/n")));  
  78.             status = SD_API_STATUS_INSUFFICIENT_RESOURCES;  
  79.             goto INIT_ERROR;  
  80.         }  
  81.     }  
  82.   
  83.     //  Supply the clock to the SDI controller  
  84.     MMC_Hardware_PowerUp();  
  85.   
  86.     //----- 6. Configure the GPIO lines for SDI mode and enable the pullup resistor -----  
  87.     vm_pIOPreg->GPEUP  &= 0xF83F;  
  88.     vm_pIOPreg->GPECON |= 0x2AA800;  
  89.   
  90.     //----- 7. Set the SD/SDI controller to some reasonable default values -----  
  91.     SetClockRate(SD_DEFAULT_CARD_ID_CLOCK_RATE);        // 100Khz  
  92.   
  93.     vm_pSDIReg->SDICON     |= LITTLE_ENDIAN_BYTE_ORDER;    // Windows CE is always Little Endian.  
  94.     vm_pSDIReg->SDICON     |= RESET_FIFO;                  // Reset the FIFO  
  95.     vm_pSDIReg->SDIBSIZE    = BYTES_PER_SECTOR;   
  96.     vm_pSDIReg->SDIDTIMER   = MAX_DATABUSY_TIMEOUT;        // Data/busy timeout  
  97.   
  98.     //----- 8. Setup the thread for detecting card insertion/deletion -----  
  99.     m_hCardInsertInterruptEvent = CreateEvent(NULL, FALSE, FALSE,NULL);  
  100.       
  101.     if(NULL == m_hCardInsertInterruptEvent)   
  102.     {  
  103.         status = SD_API_STATUS_INSUFFICIENT_RESOURCES;  
  104.         goto INIT_ERROR;  
  105.     }  
  106.   
  107.     m_bDevicePresent                    = FALSE;  
  108.   
  109.     m_hCardInsertInterruptThread = CreateThread(NULL, 0,   
  110.                                                 (LPTHREAD_START_ROUTINE)SD_CardDetectThread,  
  111.                                                 this, 0, &threadID);  
  112.       
  113.     if(NULL == m_hCardInsertInterruptThread)   
  114.     {  
  115.         status = SD_API_STATUS_INSUFFICIENT_RESOURCES;  
  116.         goto INIT_ERROR;  
  117.     }  
  118.   
  119.   
  120.     //----- 9 . Setup an event used for signaling our response thread -----  
  121.     m_hResponseReceivedEvent = CreateEvent(NULL, FALSE, FALSE,NULL);  
  122.       
  123.     if(NULL == m_hResponseReceivedEvent)   
  124.     {  
  125.         status = SD_API_STATUS_INSUFFICIENT_RESOURCES;  
  126.         goto INIT_ERROR;  
  127.     }  
  128.   
  129.   
  130.     //----- 10. Setup the IST for handling SDIO data transfer interrupts -----  
  131.     m_hSDIOInterruptEvent = CreateEvent(NULL, FALSE, FALSE,NULL);  
  132.       
  133.     if(NULL == m_hSDIOInterruptEvent)   
  134.     {  
  135.         status = SD_API_STATUS_INSUFFICIENT_RESOURCES;  
  136.         goto INIT_ERROR;  
  137.     }  
  138.   
  139.     // initialize the card insertion interrupt event  
  140.     if(!InterruptInitialize (m_dwSDIOSysIntr, m_hSDIOInterruptEvent,  
  141.                              NULL, 0))   
  142.     {  
  143.         status = SD_API_STATUS_INSUFFICIENT_RESOURCES;  
  144.         goto INIT_ERROR;  
  145.     }  
  146.   
  147.     m_hSDIOInterruptThread = CreateThread(NULL, 0,  
  148.                                           (LPTHREAD_START_ROUTINE)SD_IOInterruptIstThread,  
  149.                                           this, 0, &threadID);  
  150.       
  151.     if(NULL == m_hSDIOInterruptThread)   
  152.     {  
  153.         status = SD_API_STATUS_INSUFFICIENT_RESOURCES;  
  154.         goto INIT_ERROR;  
  155.     }  
  156.   
  157.     //----- 11. Setup the interrupt event for handling SDIO DMA data transfers -----  
  158.     m_hDMAInterruptEvent = CreateEvent(NULL, FALSE, FALSE,NULL);  
  159.       
  160.     if(NULL == m_hDMAInterruptEvent)   
  161.     {  
  162.         status = SD_API_STATUS_INSUFFICIENT_RESOURCES;  
  163.         goto INIT_ERROR;  
  164.     }  
  165.   
  166.     // initialize the dma transfer interrupt event  
  167.     if(!InterruptInitialize (m_dwDMASysIntr, m_hDMAInterruptEvent,  
  168.                              NULL, 0))   
  169.     {  
  170.         status = SD_API_STATUS_INSUFFICIENT_RESOURCES;  
  171.         goto INIT_ERROR;  
  172.     }  
  173.   
  174.     m_hDMAInterruptThread = CreateThread(NULL, 0,  
  175.                                                 (LPTHREAD_START_ROUTINE)SD_TransferIstThread,  
  176.                                                 this, 0, &threadID);  
  177.       
  178.     if(NULL == m_hDMAInterruptThread)   
  179.     {  
  180.         status = SD_API_STATUS_INSUFFICIENT_RESOURCES;  
  181.         goto INIT_ERROR;  
  182.     }  
  183.   
  184.     m_dwLastTypeOfTransfer = SD_READ;     
  185.     m_bUseDMAForTransfer = FALSE;  
  186.   
  187.     if( !InitializeHardware() )  
  188.     {  
  189.         DEBUGMSG (1,(TEXT("InitializeHardware failed!/n/r")));  
  190.         status = SD_API_STATUS_UNSUCCESSFUL;  
  191.         goto INIT_ERROR;  
  192.     }  
  193.   
  194. INIT_ERROR:  
  195.   
  196.     if(!SD_API_SUCCESS(status))   
  197.     {  
  198.         Deinitialize();  
  199.     }  
  200.   
  201.     DEBUGMSG (SDCARD_ZONE_INIT,(TEXT("SDHCDInitialize ends")));  
  202.     return status;  
  203. }  

5.Deinitialize
Deinitialize用来关闭Initialize创建的事件IST线程,释放DMA buffer,关闭SDI power等
[c-sharp]  view plain copy
  1. SD_API_STATUS CSDIOControllerBase::Deinitialize()  
  2. {  
  3.     DEBUGMSG (SDCARD_ZONE_INIT,(TEXT("SDHCDDeinitialize starts")));  
  4.     //----- 1. Set the controller state to "shutdown" -----  
  5.     m_bDriverShutdown = TRUE;  
  6.   
  7.     //----- 2. Disable and cleanup the ISTs/events ------  
  8.     InterruptDisable (m_dwSDIOSysIntr);  
  9.     SetEvent(m_hResponseReceivedEvent);  
  10.     InterruptDisable (m_dwDMASysIntr);  
  11.   
  12.     if(NULL != m_hResponseReceivedEvent)   
  13.     {  
  14.         CloseHandle(m_hResponseReceivedEvent);  
  15.         m_hResponseReceivedEvent = NULL;  
  16.     }  
  17.   
  18.     if(NULL != m_hSDIOInterruptThread)   
  19.     {             
  20.         WaitForSingleObject(m_hSDIOInterruptThread, INFINITE);   
  21.         CloseHandle(m_hSDIOInterruptThread);  
  22.         m_hSDIOInterruptThread = NULL;  
  23.     }  
  24.           
  25.     if(NULL != m_hSDIOInterruptEvent)   
  26.     {  
  27.         CloseHandle(m_hSDIOInterruptEvent);  
  28.         m_hSDIOInterruptEvent = NULL;  
  29.     }  
  30.   
  31.     if(NULL != m_hDMAInterruptThread)   
  32.     {             
  33.         WaitForSingleObject(m_hDMAInterruptThread, INFINITE);   
  34.         CloseHandle(m_hDMAInterruptThread);  
  35.         m_hDMAInterruptThread = NULL;  
  36.     }  
  37.       
  38.     if(NULL != m_hDMAInterruptEvent)   
  39.     {  
  40.         CloseHandle(m_hDMAInterruptEvent);  
  41.         m_hDMAInterruptEvent = NULL;  
  42.     }  
  43.   
  44.     if(NULL != m_hCardInsertInterruptThread)   
  45.     {             
  46.         WaitForSingleObject(m_hCardInsertInterruptThread, INFINITE);   
  47.         CloseHandle(m_hCardInsertInterruptThread);  
  48.         m_hCardInsertInterruptThread = NULL;  
  49.     }  
  50.           
  51.     if(NULL != m_hCardInsertInterruptEvent)   
  52.     {  
  53.         CloseHandle(m_hCardInsertInterruptEvent);  
  54.         m_hCardInsertInterruptEvent = NULL;  
  55.     }  
  56.   
  57.     if( m_dwDMAChannel != 0xffffffff )  
  58.     {  
  59.         //----- 3. Free the DMA memory -----  
  60.         HalFreeCommonBuffer( NULL, 0, m_pDMABufferPhys, m_pDMABuffer, FALSE );  
  61.     }  
  62.   
  63.     //----- 4. Close the handle to the utility driver (used for fast driver-->driver calling -----  
  64.     MMC_Hardware_PowerDown();  
  65.   
  66.     DeleteCriticalSection(&m_ControllerCriticalSection);  
  67.   
  68.     DEBUGMSG (SDCARD_ZONE_INIT,(TEXT("SDHCDDeinitialize ends")));  
  69.     return SD_API_STATUS_SUCCESS;  
  70. }  

6.CancelIoHandler
CancelIoHandler被SDHCDCancelIoHandler调用.首先调用Stop_SDI_Hardware设置SDIDCON强制停止数据传输.调用SDHCDReleaseHCLock释放lock,最后调用SDHCDIndicateBusRequestComplete使用Cancel状态(SD_API_STATUS_CANCELED)来完成Bus请求.
[c-sharp]  view plain copy
  1. BOOLEAN CSDIOControllerBase::CancelIoHandler(DWORD dwSlot, PSD_BUS_REQUEST pRequest)  
  2. {  
  3.     DEBUGMSG (SDCARD_ZONE_FUNC,(TEXT("SDHCDCancelIoHandler starts")));  
  4.   
  5.     //--- Stop hardware, cancel the request!  
  6.     Stop_SDI_Hardware();  
  7.   
  8.     // release the lock before we complete the request  
  9.     SDHCDReleaseHCLock(m_pHCContext);  
  10.    
  11.     // complete the request with a cancelled status  
  12.     SDHCDIndicateBusRequestComplete(m_pHCContext, pRequest,SD_API_STATUS_CANCELED);  
  13.   
  14.     DEBUGMSG (SDCARD_ZONE_FUNC,(TEXT("SDHCDCancelIoHandler ends")));  
  15.     return TRUE;  
  16. }  

7.SlotOptionHandler
CancelIoHandler被SDHCDSlotOptionHandler调用.Slot选项变化时该函数被调用.
(1)SDHCDSetSlotPower:设置slot power,因为系统一直工作在3.3V,不会变化,这里不做任何处理.
(2)SDHCDSetSlotInterface:设置slot接口模式,根据输入数据(pData)设置4bit还是1bit bus模式,调用SetClockRate设置SDI时钟频率.
(3)SDHCDEnableSDIOInterrupts:调用Enable_SDIO_Interrupts使能SDIO中断.
(4)SDHCDDisableSDIOInterrupts:调用Disable_SDIO_Interrupts禁止SDIO中断.
(5)SDHCDAckSDIOInterrupt:调用Ack_SDIO_Interrupts和InterruptDone(m_dwSDIOSysIntr)确认SDIO中断完成.
(6)SDHCDGetWriteProtectStatus:调用IsCardWriteProtected获得写保护状态.
(7)SDHCDQueryBlockCapability:查询Block性能参数.通过输入参数pData来获得ReadBlockSize,WriteBlockSize并根据设定的最大最小值进行修正.
(8)SDHCDGetSlotInfo:获得特定slot的信息.调用SDHCDSetSlotCapabilities等函数设置slot参数,如电压,时钟频率,上电延时等.
[c-sharp]  view plain copy
  1. SD_API_STATUS CSDIOControllerBase::SlotOptionHandler(DWORD dwSlot, SD_SLOT_OPTION_CODE Option,   
  2.                                      PVOID pData, ULONG OptionSize)  
  3. {  
  4.     DEBUGMSG (SDCARD_ZONE_FUNC,(TEXT("SDHCDSlotOptionHandler starts")));  
  5.   
  6.     SD_API_STATUS status = SD_API_STATUS_SUCCESS;   // status  
  7.     PSD_HOST_BLOCK_CAPABILITY pBlockCaps;           // block capabilities  
  8.   
  9.     switch(Option)   
  10.     {  
  11.         case SDHCDSetSlotPower:  
  12.             DEBUGMSG (SDCARD_ZONE_INFO,(TEXT("SDHCDSlotOptionHandler option=SDHCDSetSlotPower")));  
  13.             // Nothing to do because this system only operates at the reported 3.3V  
  14.             break;  
  15.   
  16.         case SDHCDSetSlotInterface:  
  17.             DEBUGMSG (SDCARD_ZONE_INFO,(TEXT("SDHCDSlotOptionHandler option=SDHCDSetSlotInterface")));  
  18.             // First set the bus width   
  19.             if(((PSD_CARD_INTERFACE)pData)->InterfaceMode == SD_INTERFACE_SD_4BIT)  
  20.             {  
  21.                 Set_SDI_Bus_Width_4Bit();  
  22.             }else  
  23.             {  
  24.                 // Standard (i.e. 1bit) bus width  
  25.                 Set_SDI_Bus_Width_1Bit();  
  26.             }  
  27.   
  28.             // Next, set the clock rate  
  29.             ((PSD_CARD_INTERFACE)pData)->ClockRate = SetClockRate(((PSD_CARD_INTERFACE)pData)->ClockRate);  
  30.             break;  
  31.   
  32.         case SDHCDEnableSDIOInterrupts:                                   
  33.             DEBUGMSG (SDCARD_ZONE_INFO,(TEXT("SDHCDSlotOptionHandler option=SDHCDEnableSDIOInterrupts")));  
  34.             Enable_SDIO_Interrupts();  
  35.             break;  
  36.   
  37.         case SDHCDDisableSDIOInterrupts:                                  
  38.             DEBUGMSG (SDCARD_ZONE_INFO,(TEXT("SDHCDSlotOptionHandler option=SDHCDDisableSDIOInterrupts")));  
  39.             Disable_SDIO_Interrupts();  
  40.             break;  
  41.   
  42.         case SDHCDAckSDIOInterrupt:                                       
  43.               
  44.             DEBUGMSG (SDCARD_ZONE_INFO,(TEXT("SDHCDSlotOptionHandler option=SDHCDAckSDIOInterrupt")));  
  45.             //----- 2. Clear the SDIO interrupt pending bit -----  
  46.             Ack_SDIO_Interrupts();  
  47.             InterruptDone(m_dwSDIOSysIntr);  
  48.             break;  
  49.   
  50.         case SDHCDGetWriteProtectStatus:  
  51.             DEBUGMSG (SDCARD_ZONE_INFO,(TEXT("SDHCDSlotOptionHandler option=SDHCDGetWriteProtectStatus")));  
  52.             ((PSD_CARD_INTERFACE)pData)->WriteProtected = IsCardWriteProtected();  
  53.             break;  
  54.   
  55.         case SDHCDQueryBlockCapability:  
  56.   
  57.             DEBUGMSG (SDCARD_ZONE_INFO,(TEXT("SDHCDSlotOptionHandler option=SDHCDQueryBlockCapability")));  
  58.             pBlockCaps = (PSD_HOST_BLOCK_CAPABILITY)pData;  
  59.   
  60.             DEBUGMSG(SDCARD_ZONE_INFO, (TEXT("SDHCD:SDHCDSlotOptionHandler() - Read Block Length: %d , Read Blocks: %d/n"),   
  61.                                                 pBlockCaps->ReadBlockSize, pBlockCaps->ReadBlocks));  
  62.   
  63.             DEBUGMSG(SDCARD_ZONE_INFO, (TEXT("SDHCD:SDHCDSlotOptionHandler() - Write Block Length: %d , Write Blocks: %d/n"),   
  64.                                                 pBlockCaps->WriteBlockSize, pBlockCaps->WriteBlocks));  
  65.   
  66.             pBlockCaps = (PSD_HOST_BLOCK_CAPABILITY)pData;  
  67.   
  68.             //----- Validate block transfer properties -----  
  69.             if (pBlockCaps->ReadBlockSize < MINIMUM_BLOCK_TRANSFER_SIZE )  
  70.             {  
  71.                 pBlockCaps->ReadBlockSize = MINIMUM_BLOCK_TRANSFER_SIZE;  
  72.             }  
  73.   
  74.             if (pBlockCaps->WriteBlockSize < MINIMUM_BLOCK_TRANSFER_SIZE )  
  75.             {  
  76.                 pBlockCaps->WriteBlockSize = MINIMUM_BLOCK_TRANSFER_SIZE;  
  77.             }  
  78.   
  79.             if (pBlockCaps->ReadBlockSize > MAXIMUM_BLOCK_TRANSFER_SIZE )  
  80.             {  
  81.                 pBlockCaps->ReadBlockSize = MAXIMUM_BLOCK_TRANSFER_SIZE;  
  82.             }  
  83.    
  84.             if (pBlockCaps->WriteBlockSize > MAXIMUM_BLOCK_TRANSFER_SIZE )  
  85.             {  
  86.                 pBlockCaps->WriteBlockSize = MAXIMUM_BLOCK_TRANSFER_SIZE;  
  87.             }              
  88.             break;  
  89.   
  90.         case SDHCDGetSlotInfo:  
  91.             DEBUGMSG (SDCARD_ZONE_INFO,(TEXT("SDHCDSlotOptionHandler option=SDHCDGetSlotInfo")));  
  92.             if( OptionSize != sizeof(SDCARD_HC_SLOT_INFO) || pData == NULL )  
  93.             {  
  94.                 status = SD_API_STATUS_INVALID_PARAMETER;  
  95.             }  
  96.             else  
  97.             {  
  98.                 PSDCARD_HC_SLOT_INFO pSlotInfo = (PSDCARD_HC_SLOT_INFO)pData;  
  99.   
  100.                 // set the slot capabilities  
  101.                 SDHCDSetSlotCapabilities(pSlotInfo, SD_SLOT_SD_4BIT_CAPABLE |   
  102.                     SD_SLOT_SD_1BIT_CAPABLE |   
  103.                     SD_SLOT_SDIO_CAPABLE    |  
  104.                     SD_SLOT_SDIO_INT_DETECT_4BIT_MULTI_BLOCK);  
  105.   
  106.                 SDHCDSetVoltageWindowMask(pSlotInfo, (SD_VDD_WINDOW_3_2_TO_3_3 | SD_VDD_WINDOW_3_3_TO_3_4));   
  107.   
  108.                 // Set optimal voltage  
  109.                 SDHCDSetDesiredSlotVoltage(pSlotInfo, SD_VDD_WINDOW_3_2_TO_3_3);  
  110.   
  111.                 SDHCDSetMaxClockRate(pSlotInfo, MAX_SDI_BUS_TRANSFER_SPEED);    
  112.   
  113.                 // Set power up delay. We handle this in SetVoltage().  
  114.                 SDHCDSetPowerUpDelay(pSlotInfo, 300);  
  115.             }  
  116.             break;  
  117.   
  118.         default:  
  119.             DEBUGMSG (SDCARD_ZONE_WARN,(TEXT("SDHCDSlotOptionHandler option=SD_API_STATUS_INVALID_PARAMETER")));  
  120.            status = SD_API_STATUS_INVALID_PARAMETER;  
  121.   
  122.     }  
  123.     DEBUGMSG (SDCARD_ZONE_FUNC,(TEXT("SDHCDSlotOptionHandler ends")));  
  124.     return status;  
  125. }  

8.BusRequestHandler
BusRequestHandler被SDHCDBusRequestHandler调用,用来处理总线请求.
首先复位FIFO和状态寄存器,然后使能SDI CLOCK,计算要传输数据大小,判断是否DMA传输以及是否4字节对齐,4字节整数倍来进行DMA传输(SetupDmaXfer)或者轮询IO传输(SetupPollingXfer).
接着判断传输的是单独命令还是命令和数据,第一次传输命令时需延时80个clock周期.SendCommand最后一个参数表示是传输命令(FALSE)还是命令和数据(TRUE).
最后设置设置事件m_hResponseReceivedEvent来通知传输IST命令应答发生.
[c-sharp]  view plain copy
  1. SD_API_STATUS CSDIOControllerBase::BusRequestHandler(DWORD dwSlot, PSD_BUS_REQUEST pRequest)   
  2. {  
  3.     DEBUGMSG (SDCARD_ZONE_FUNC,(TEXT("BusRequestHandler starts (CMD:%d)"), pRequest->CommandCode));  
  4.     SD_API_STATUS   status;  
  5.   
  6.     // Reset FIFO and status registers  
  7.     vm_pSDIReg->SDICON |= RESET_FIFO;  
  8.     vm_pSDIReg->SDIDSTA = 0xffff;  
  9.     vm_pSDIReg->SDIDCON = 0;  
  10.     vm_pSDIReg->SDICSTA = 0xffff;  
  11.     vm_pSDIReg->SDICCON = 0;   
  12.   
  13.    Start_SDI_Clock();  
  14.   
  15.     //----- 1. Determine the type of command (data vs. no data) and send the command -----  
  16.     m_dwNumBytesToTransfer  = pRequest->BlockSize * pRequest->NumBlocks;  
  17.   
  18.     //----- 2 Can we schedule a DMA operation using the caller's buffer as-is?  -----  
  19.     //  
  20.     //        There are two situations that we need to account for:  
  21.     //  
  22.     //             1) A non-DWORD aligned buffer  
  23.     //             2) A buffer whose "transfer size" isn't a multiple of sizeof(DWORD)  
  24.     //  
  25.     //        For the first case, an data-alignment exception will occur if the buffer is  
  26.     //        addressed at the non-DWORD aligned address.  For the second case, the SDI   
  27.     //        controller will pad zeros into the remaining bytes of the last unfilled DWORD.    
  28.     //        Practically, this means that the SD Card will get a corrupted data string.  
  29.     //  
  30.     //        To handle these two situations, we can simply use our polling I/O routines to  
  31.     //        fulfill the I/O request.  
  32.     //  
  33.     if( ( m_dwDMAChannel == 0xffffffff ) || (!IS_BUFFER_DWORD_ALIGNED(pRequest->pBlockBuffer)) || (!IS_BUFFER_SIZE_A_DWORD_MULTPLE(pRequest->BlockSize)) || m_dwNumBytesToTransfer > MAXIMUM_DMA_TRANSFER_SIZE )  
  34.     {     
  35.         m_bUseDMAForTransfer = FALSE;  
  36.         SetupPollingXfer(pRequest);                     // Use polling I/O routines for data transfer  
  37.     }else{  
  38.         m_bUseDMAForTransfer = TRUE;  
  39.         SetupDmaXfer(pRequest);                         // Use DMA for data transfer  
  40.     }  
  41.   
  42.     if(pRequest->TransferClass == SD_COMMAND)   
  43.     {  
  44.         // Command only  
  45.         status = SendCommand(pRequest->CommandCode, pRequest->CommandArgument, pRequest->CommandResponse.ResponseType, FALSE);  
  46.   
  47.         if(!SD_API_SUCCESS(status))  
  48.         {  
  49.             DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHCDBusRequestHandler() - Error sending command:0x%02x/r/n"), pRequest->CommandCode));  
  50.             goto BUS_REQUEST_COMPLETE;        
  51.         }  
  52.   
  53.         //----- 2. Is this the first command sent to the card?  If so, delay the 74 (or 80) clock cycles per the SD spec -----  
  54.         if(m_bSendInitClocks)  
  55.         {  
  56.             m_bSendInitClocks = FALSE;  
  57.             Wait_80_SDI_Clock_Cycles();  
  58.         }  
  59.     }  
  60.     else  
  61.     {     
  62.         // Command with data transfer  
  63.         status = SendCommand(pRequest->CommandCode, pRequest->CommandArgument, pRequest->CommandResponse.ResponseType, TRUE);  
  64.   
  65.         if(!SD_API_SUCCESS(status))  
  66.         {  
  67.             DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHCDBusRequestHandler() - Error sending command:0x%02x/r/n"), pRequest->CommandCode));  
  68.             goto BUS_REQUEST_COMPLETE;        
  69.         }  
  70.     }  
  71.   
  72.     //----- 3. Signal an IST that processes response information and cache our state -----  
  73.     //         NOTE: It is critical that this API NOT complete the bus request directly (which  
  74.     //               is why another thread is used).  The bus driver expects bus requests to complete  
  75.     //               asynchronously and a stack overflow WILL eventually occur if this rule isn't honored.  
  76.     SetEvent(m_hResponseReceivedEvent);  
  77.     m_CurrentState = CommandSent;  
  78.     status = SD_API_STATUS_PENDING;  
  79.   
  80. BUS_REQUEST_COMPLETE:  
  81.     DEBUGMSG (SDCARD_ZONE_FUNC,(TEXT("SDHCD:BusRequestHandler ends")));  
  82.     return status;  
  83. }  

9.TransferIstThread
TransferIstThread被SD_TransferIstThread调用,而SD_TransferIstThread在Initialize中被创建,对应于m_hDMAInterruptThread句柄.这个IST线程用来处理SDIO的DMA通道通信.
首先设置该线程的优先级(从注册表中获得,"DMA_IST_Priority"=dword:96),然后等待m_hResponseReceivedEvent事件的发生,该事件发生后继续运行,否则挂起.
m_hResponseReceivedEvent触发后,如果controller down则线程退出.调用SDHCDGetAndLockCurrentRequest(实现在sdhclib)来获取当前slot的请求,并锁住禁止取消.
然后处理一个特殊情况,SD_CMD_STOP_TRANSMISSION命令在SD_CMD_WRITE_MULTIPLE_BLOCK后发送,需要进行BUSY_CHECK.
如果BusyCheck为true,CommandCode为SD_CMD_ERASE或者CommandCode为SD_CMD_STOP_TRANSMISSION,m_dwLastTypeOfTransfer为SD_WRITE时,需要等待IO传输结束.检查SDIDSTA寄存器BusyFin位,如果为0(busy not finish),则进行等待,并判断超时,IsCardPresent,以及一些错误状态,如果任何一种情况发生,就设置BUSY_CHECKS_FINISH,跳转到TRANSFER_DONE通知BusRequest完成.
如果BUSY_CHECKS_FINISH成立,则准备DMA传输.如果ResponseType为NoResponse,跳转到TRANSFER_DONE.否则调用GetCommandResponse获取CommandResponse状态.如果是命令,直接TRANSFER_DONE.数据传输分两种情况是否使用DMA,m_bUseDMAForTransfer为false,启动IO传输,为true,并判断是SD_WRITE写操作时,复制数据到DMA memory,调用Enable_SDIO_DMA_Channel,启动DMA通道,然后等待DMA完成中断事件m_hDMAInterruptEvent,完成后调用InterruptDone和Stop_SDIO_DMA_Channel通知中断完成并停止DMA通道.然后等待读取SDIDSTA等待data transfer结束.如果是SD_READ,读取从DMA memory放到调用缓存区pBlockBuffer中.
最后停止SDI clock,通知总线请求结束(SDHCDIndicateBusRequestComplete).
[c-sharp]  view plain copy
  1. DWORD CSDIOControllerBase::TransferIstThread()  
  2. {  
  3.     PSD_BUS_REQUEST     pRequest = NULL;       // the request to complete  
  4.     SD_API_STATUS       status;  
  5.   
  6.     if( m_DMAIstThreadPriority != 0xffffffff && !CeSetThreadPriority( GetCurrentThread(), m_DMAIstThreadPriority ) )  
  7.     {  
  8.         DEBUGMSG(SDCARD_ZONE_WARN,(TEXT("SDHCDriver:TransferIstThread(): warning, failed to set CEThreadPriority /n")));  
  9.     }  
  10.       
  11.     for(;;)  
  12.     {  
  13.         //----- 1. Wait for the command response -----  
  14.         status = SD_API_STATUS_PENDING;  
  15.         if(WaitForSingleObject(m_hResponseReceivedEvent, INFINITE) == WAIT_FAILED)  
  16.         {  
  17.             DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCDriver:TransferIstThread(): Wait Failed!/n")));  
  18.             return FALSE;  
  19.         }  
  20.   
  21.         if(m_bDriverShutdown)   
  22.         {  
  23.             DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("SDHCD:TransferIstThread(): Thread Exiting/n")));  
  24.             return FALSE;  
  25.         }  
  26.   
  27.         //----- 2. Get and lock the current bus request -----  
  28.         if(pRequest == NULL)  
  29.         {  
  30.             if((pRequest = SDHCDGetAndLockCurrentRequest(m_pHCContext, 0)) == NULL)  
  31.             {  
  32.                 DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - Unable to get/lock current request!/r/n")));  
  33.                 status = SD_API_STATUS_INVALID_DEVICE_REQUEST;  
  34.                 goto TRANSFER_DONE;  
  35.             }  
  36.         }  
  37.   
  38.         //----- 3. SPECIAL CASE: The SD_CMD_STOP_TRANSMISSION that is sent after a SD_CMD_WRITE_MULTIPLE_BLOCK command -----  
  39.         //                       requires a BUSY_CHECK  
  40.         if( ( m_fHandleBusyCheckOnCommand38 && pRequest->CommandCode == SD_CMD_ERASE ) ||  
  41.             ( ( pRequest->CommandCode == SD_CMD_STOP_TRANSMISSION ) && ( m_dwLastTypeOfTransfer == SD_WRITE ) ) )  
  42.         {  
  43.             DWORD dwWaitCount = 0;  
  44.             //----- 4. Wait until the I/O transfer is complete -----  
  45.             while(!(vm_pSDIReg->SDIDSTA & BUSY_CHECKS_FINISH))  
  46.             {  
  47.                 dwWaitCount++;  
  48.                 if( dwWaitCount > WAIT_TIME )  
  49.                 {  
  50.                     DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - timeout waiting for BUSY_CHECKS to finish!/r/n")));  
  51.                     status = SD_API_STATUS_DATA_TIMEOUT;  
  52.                     goto TRANSFER_DONE;  
  53.                 }  
  54.   
  55.                 if( !IsCardPresent() )  
  56.                 {  
  57.                     DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - Card ejected!/r/n")));  
  58.                     status = SD_API_STATUS_DEVICE_REMOVED;  
  59.                     goto TRANSFER_DONE;  
  60.                 }  
  61.                 if((vm_pSDIReg->SDIDSTA & FIFO_FAIL_ERROR))  
  62.                 {  
  63.                     vm_pSDIReg->SDIDSTA = BUSY_CHECKS_FINISH | FIFO_FAIL_ERROR;  
  64.                     DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - FIFO Error waiting for BUSY_CHECKS to finish!/r/n")));  
  65.                     status = SD_API_STATUS_DATA_ERROR;  
  66.                     goto TRANSFER_DONE;  
  67.                 }  
  68.                 if((vm_pSDIReg->SDIDSTA & DATA_TRANSMIT_CRC_ERROR))  
  69.                 {  
  70.                     vm_pSDIReg->SDIDSTA = BUSY_CHECKS_FINISH | DATA_TRANSMIT_CRC_ERROR;  
  71.                     DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - Transmit CRC Error waiting for BUSY_CHECKS to finish!/r/n")));  
  72.                     status = SD_API_STATUS_DATA_ERROR;  
  73.                     goto TRANSFER_DONE;  
  74.                 }  
  75.                 if((vm_pSDIReg->SDIDSTA & DATA_RECEIVE_CRC_ERROR))  
  76.                 {  
  77.                     vm_pSDIReg->SDIDSTA = BUSY_CHECKS_FINISH | DATA_RECEIVE_CRC_ERROR;  
  78.                     DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - Receive CRC Error waiting for BUSY_CHECKS to finish!/r/n")));  
  79.                     status = SD_API_STATUS_DATA_ERROR;  
  80.                     goto TRANSFER_DONE;  
  81.                 }  
  82.                 if((vm_pSDIReg->SDIDSTA & DATA_TIME_OUT))  
  83.                 {  
  84.                     vm_pSDIReg->SDIDSTA = BUSY_CHECKS_FINISH | DATA_TIME_OUT;  
  85.                     DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - Data timeout waiting for BUSY_CHECKS to finish!/r/n")));  
  86.                     status = SD_API_STATUS_DATA_TIMEOUT;  
  87.                     goto TRANSFER_DONE;  
  88.                 }  
  89.             }  
  90.             vm_pSDIReg->SDIDSTA = BUSY_CHECKS_FINISH;  
  91.         }  
  92.   
  93.         //----- 5. Get the response information -----  
  94.         if(pRequest->CommandResponse.ResponseType == NoResponse)  
  95.         {  
  96.             goto TRANSFER_DONE;  
  97.         }else{  
  98.             status = GetCommandResponse(pRequest);  
  99.   
  100.             if(!SD_API_SUCCESS(status))  
  101.             {  
  102.                 DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHCDBusRequestHandler() - Error getting response for command:0x%02x/r/n"), pRequest->CommandCode));  
  103.                 goto TRANSFER_DONE;       
  104.             }  
  105.         }  
  106.   
  107.         //----- 6. If this is a data transfer, start the I/O operation; otherwise, finish the request -----  
  108.         if(pRequest->TransferClass == SD_COMMAND)  
  109.         {  
  110.             goto TRANSFER_DONE;  
  111.         }  
  112.   
  113.   
  114.         //----- 7. If this is a DMA transfer, we enable interrupts and wait for the DMA interrupt.  Otherwise, -----  
  115.         //         we use our polling routines to complete the I/O.  
  116.         if(m_bUseDMAForTransfer == FALSE)  
  117.         {  
  118.   
  119.             //----- 8. Polling I/O, use our special routines to handle this request  
  120.             switch(pRequest->TransferClass)  
  121.             {  
  122.             case SD_READ:  
  123.                 if(!PollingReceive(pRequest, m_dwNumBytesToTransfer))  
  124.                 {  
  125.                     DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:BusRequestHandler() - PollingReceive() failed/r/n")));  
  126.                     goto TRANSFER_DONE;  
  127.                 }  
  128.                 break;  
  129.   
  130.             case SD_WRITE:  
  131.                 if(!PollingTransmit(pRequest, m_dwNumBytesToTransfer))  
  132.                 {  
  133.                     DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:BusRequestHandler() - PollingReceive() failed/r/n")));  
  134.                     goto TRANSFER_DONE;  
  135.                 }  
  136.                 break;  
  137.             }  
  138.   
  139.             status = SD_API_STATUS_SUCCESS;  
  140.         }else  
  141.         {  
  142.   
  143.   
  144.             //----- 9. For WRITE requests, be sure to copy the write data from the caller's buffer into DMA memory-----  
  145.             if(pRequest->TransferClass == SD_WRITE)  
  146.             {  
  147.                 BOOL fNoException;  
  148.                 DEBUGCHK(m_dwNumBytesToTransfer <= MAXIMUM_DMA_TRANSFER_SIZE);  
  149.               
  150.                 SD_SET_PROC_PERMISSIONS_FROM_REQUEST( pRequest ) {                 
  151.                     fNoException = SDPerformSafeCopy( m_pDMABuffer, pRequest->pBlockBuffer, m_dwNumBytesToTransfer );  
  152.                 } SD_RESTORE_PROC_PERMISSIONS();  
  153.   
  154.                 if (fNoException == FALSE) {  
  155.                     status = SD_API_STATUS_ACCESS_VIOLATION;  
  156.                     goto TRANSFER_DONE;  
  157.                 }  
  158.             }  
  159.   
  160.             //----- 10. DMA I/O, enable the DMA channel -----  
  161.             Enable_SDIO_DMA_Channel();  
  162.   
  163.             //----- 11. Wait for a DMA interrupt -----  
  164.             // first estimate the maximum DMA transfer time  
  165.             DWORD dwDelay = m_dwNumBytesToTransfer * m_dwDMATransferTimeoutFactor / ( m_dwClockRate / 2000 );  
  166.             if( Get_SDI_Bus_Width() != WIDE_BUS_ENABLE )  
  167.             {  
  168.                 dwDelay *= 4;  
  169.             }  
  170.             dwDelay += m_dwDMATransferTimeoutConstant;  
  171.   
  172.             // now wait for the interrupt  
  173.             if(WaitForSingleObject(m_hDMAInterruptEvent, dwDelay) != WAIT_OBJECT_0)  
  174.             {  
  175.                 DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("TransferIstThread(): Wait Failed!/n")));  
  176.                 Stop_SDIO_DMA_Channel();  
  177.                 status = SD_API_STATUS_DATA_TIMEOUT;  
  178.                 goto TRANSFER_DONE;  
  179.             }  
  180.   
  181.             if(m_bDriverShutdown)   
  182.             {  
  183.                 DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("SDHCD:TransferIstThread(): Thread Exiting/n")));  
  184.                 return FALSE;  
  185.             }  
  186.   
  187.             //----- 12. ACK the DMA completion interrupt and stop the DMA channel -----  
  188.             InterruptDone(m_dwDMASysIntr);  
  189.             Stop_SDIO_DMA_Channel();  
  190.   
  191.             DWORD dwWaitCount = 0;  
  192.             //----- 13. Wait until the I/O transfer is complete -----  
  193.             while(!(vm_pSDIReg->SDIDSTA & DATA_TRANSMIT_FINISHED))  
  194.             {  
  195.                 dwWaitCount++;  
  196.                 if( dwWaitCount > WAIT_TIME )  
  197.                 {  
  198.                     DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - timeout waiting for DMA transfer completion!/r/n")));  
  199.                     status = SD_API_STATUS_DATA_TIMEOUT;  
  200.                     goto TRANSFER_DONE;  
  201.                 }  
  202.   
  203.                 if( !IsCardPresent() )  
  204.                 {  
  205.                     DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - Card ejected!/r/n")));  
  206.                     status = SD_API_STATUS_DEVICE_REMOVED;  
  207.                     goto TRANSFER_DONE;  
  208.                 }  
  209.                 if((vm_pSDIReg->SDIDSTA & FIFO_FAIL_ERROR))  
  210.                 {  
  211.                     vm_pSDIReg->SDIDSTA = BUSY_CHECKS_FINISH | FIFO_FAIL_ERROR;  
  212.                     DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - FIFO Error waiting for DMA transfer completion!/r/n")));  
  213.                     status = SD_API_STATUS_DATA_ERROR;  
  214.                     goto TRANSFER_DONE;  
  215.                 }  
  216.                 if((vm_pSDIReg->SDIDSTA & DATA_TRANSMIT_CRC_ERROR))  
  217.                 {  
  218.                     vm_pSDIReg->SDIDSTA = BUSY_CHECKS_FINISH | DATA_TRANSMIT_CRC_ERROR;  
  219.                     DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - Transmit CRC Error waiting for DMA transfer completion!/r/n")));  
  220.                     status = SD_API_STATUS_DATA_ERROR;  
  221.                     goto TRANSFER_DONE;  
  222.                 }  
  223.                 if((vm_pSDIReg->SDIDSTA & DATA_RECEIVE_CRC_ERROR))  
  224.                 {  
  225.                     vm_pSDIReg->SDIDSTA = BUSY_CHECKS_FINISH | DATA_RECEIVE_CRC_ERROR;  
  226.                     DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - Receive CRC Error waiting for DMA transfer completion!/r/n")));  
  227.                     status = SD_API_STATUS_DATA_ERROR;  
  228.                     goto TRANSFER_DONE;  
  229.                 }  
  230.                 if((vm_pSDIReg->SDIDSTA & DATA_TIME_OUT))  
  231.                 {  
  232.                     vm_pSDIReg->SDIDSTA = BUSY_CHECKS_FINISH | DATA_TIME_OUT;  
  233.                     DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - Data timeout waiting for DMA transfer completion!/r/n")));  
  234.                     status = SD_API_STATUS_DATA_TIMEOUT;  
  235.                     goto TRANSFER_DONE;  
  236.                 }  
  237.             }  
  238.   
  239.             vm_pSDIReg->SDIDSTA = DATA_TRANSMIT_FINISHED;  
  240.   
  241.             //----- 14. For READ requests, be sure to copy the data read from the DMA memory into the caller's buffer -----  
  242.             if(pRequest->TransferClass == SD_READ)  
  243.             {  
  244.                 BOOL fNoException;  
  245.                 DEBUGCHK(m_dwNumBytesToTransfer <= MAXIMUM_DMA_TRANSFER_SIZE);  
  246.               
  247.                 SD_SET_PROC_PERMISSIONS_FROM_REQUEST( pRequest ) {                 
  248.                     fNoException = SDPerformSafeCopy( pRequest->pBlockBuffer, m_pDMABuffer, m_dwNumBytesToTransfer );  
  249.                 } SD_RESTORE_PROC_PERMISSIONS();  
  250.   
  251.                 if (fNoException == FALSE) {  
  252.                     status = SD_API_STATUS_ACCESS_VIOLATION;  
  253.                     goto TRANSFER_DONE;  
  254.                 }  
  255.             }  
  256.   
  257.             //----- 15. I/O is complete.  Finish the bus request! -----  
  258.             status = SD_API_STATUS_SUCCESS;  
  259.         }  
  260.   
  261. TRANSFER_DONE:  
  262.         if( !( Is_SDIO_Interrupt_Enabled() && ( Get_SDI_Bus_Width() == WIDE_BUS_ENABLE ) ) )  
  263.         {  
  264.             Stop_SDI_Clock();  
  265.         }  
  266.         m_CurrentState = CommandComplete;     
  267.         SDHCDIndicateBusRequestComplete(m_pHCContext, pRequest, status);  
  268.         pRequest = NULL;  
  269.     }  
  270.   
  271.     return TRUE;  
  272. }  

10.IOInterruptIstThread
被SD_IOInterruptIstThread调用,对应于句柄m_hSDIOInterruptThread.同样首先设置线程优先级(从注册表中获取"SDIO_IST_Priority"=dword:97),然后等待m_hSDIOInterruptEvent事件发生,如果事件发生同时卡存在的话,调用SDHCDIndicateSlotStateChange通知总线驱动SD卡中断发生.
[c-sharp]  view plain copy
  1. DWORD CSDIOControllerBase::IOInterruptIstThread()  
  2. {  
  3.   
  4.     if( m_nSDIOIstThreadPriority != 0xffffffff && !CeSetThreadPriority( GetCurrentThread(), m_nSDIOIstThreadPriority ) )   
  5.     {  
  6.         DEBUGMSG(SDCARD_ZONE_WARN,(TEXT("SDHCDriver:SDIOInterruptIstThread(): warning, failed to set CEThreadPriority /n")));  
  7.     }  
  8.       
  9.     for(;;)  
  10.     {  
  11.         //----- 1. Wait for a SDIO interrupt -----  
  12.         if(WaitForSingleObject(m_hSDIOInterruptEvent, INFINITE) != WAIT_OBJECT_0)  
  13.         {  
  14.             DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("SDHCD:SDIOInterruptIstThread(): Wait Failed!/n")));  
  15.             return FALSE;  
  16.         }  
  17.           
  18.         if(m_bDriverShutdown)   
  19.         {  
  20.             DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("SDHCD:SDIOInterruptIstThread(): Thread Exiting/n")));  
  21.             return FALSE;  
  22.         }  
  23.   
  24.         if(m_bDevicePresent && IsCardPresent())  
  25.         {  
  26.             // indicate that the card is interrupting  
  27.             SDHCDIndicateSlotStateChange(m_pHCContext, 0, DeviceInterrupting);  
  28.         }  
  29.   
  30.         // NOTE: SDHCDIndicateSlotStateChange() is called above to inform the bus driver  
  31.         //       that the SDIO card has generated an interrupt.  After this notification, the  
  32.         //       bus driver will eventually call back SDHCDSlotOptionHandler() to enable/disable  
  33.         //       and ACK the SDIO interrupt as necessary.  Consequently, we DO NOT acknowledge   
  34.         //       the interrupt here...  
  35.   
  36.     }  
  37. }  

11.CardDetectThread
被SD_CardDetectThread调用.首先设置线程优先级(从注册表中获取"CardDetect_Thread_Priority"=dword:98"),然后等待m_hCardInsertInterruptEvent事件,调用IsCardPresent监测卡是否插入.如果卡拔出,调用SDHCDIndicateSlotStateChange通知DeviceEjected,否则卡插入,进行SDI寄存器初始化,设置clock rate(100KHz),启动SDI clock,调用SDHCDIndicateSlotStateChange通知DeviceInserted.
[c-sharp]  view plain copy
  1. DWORD CSDIOControllerBase::CardDetectThread()  
  2. {  
  3.     BOOL  bSlotStateChanged = FALSE;  
  4.     DWORD dwWaitResult  = WAIT_TIMEOUT;  
  5.   
  6.     if( m_nCardDetectIstThreadPriority != 0xffffffff && !CeSetThreadPriority( GetCurrentThread(), m_nCardDetectIstThreadPriority ) )  
  7.     {  
  8.         DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("SDHCDriver:CardDetectThread(): warning, failed to set CEThreadPriority /n")));  
  9.     }  
  10.   
  11.     for(;;)  
  12.     {  
  13.         //----- 1. Wait for the next insertion/removal interrupt -----  
  14.         dwWaitResult = WaitForSingleObject(m_hCardInsertInterruptEvent, m_dwPollingTimeout);  
  15.           
  16.         if(m_bDriverShutdown)   
  17.         {  
  18.             DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("SDHCardDetectIstThread: Thread Exiting/n")));  
  19.             return FALSE;  
  20.         }  
  21.   
  22.         // Test if a card is present  
  23.         if( IsCardPresent() == m_bDevicePresent )  
  24.         {  
  25.             bSlotStateChanged = FALSE;  
  26.         }  
  27.         else  
  28.         {  
  29.             bSlotStateChanged = TRUE;  
  30.         }  
  31.   
  32.         if( bSlotStateChanged || m_bReinsertTheCard )  
  33.         {  
  34.             m_bReinsertTheCard = FALSE;  
  35.   
  36.             // If a card is inserted, unload the driver...  
  37.             if(m_bDevicePresent == TRUE)  
  38.             {  
  39.                 m_fCardInTheSlot = FALSE;  
  40.                 // indicate the slot change   
  41.                 SDHCDIndicateSlotStateChange(m_pHCContext, 0, DeviceEjected);   
  42.                 m_bDevicePresent = FALSE;  
  43.   
  44.                 Stop_SDI_Clock();  
  45.             }  
  46.   
  47.             if(IsCardPresent())  
  48.             {  
  49.                 m_fCardInTheSlot = TRUE;  
  50.                 m_bDevicePresent = TRUE;  
  51.   
  52.                 //----- 5. Reset the clock to the ID rate -----  
  53.                 vm_pSDIReg->SDICON     |= LITTLE_ENDIAN_BYTE_ORDER;    // Windows CE is always Little Endian.  
  54.                 vm_pSDIReg->SDICON     |= RESET_FIFO;                  // Reset the FIFO  
  55.                 vm_pSDIReg->SDIBSIZE    = BYTES_PER_SECTOR;   
  56.                 vm_pSDIReg->SDIDTIMER   = MAX_DATABUSY_TIMEOUT;        // Data/busy timeout  
  57.                 SetClockRate(SD_DEFAULT_CARD_ID_CLOCK_RATE);  
  58.   
  59.                 // give the card enough time for initialization  
  60.                 Start_SDI_Clock();  
  61.                 Wait_80_SDI_Clock_Cycles();  
  62.   
  63.                 //----- 6. Inform the bus handler that this is the first command sent -----  
  64.                 m_bSendInitClocks = TRUE;  
  65.   
  66.                 //----- 7. Indicate the slot change -----  
  67.                 SDHCDIndicateSlotStateChange(m_pHCContext, 0, DeviceInserted);  
  68.             }  
  69.         } // if  
  70.     } // for  
  71.   
  72.     return TRUE;  
  73. }  

12.SendCommand
在BusRequestHandler中被调用,首先清除SDICSTA状态标志位,设置SDICARG命令参数寄存器.判断命令是否带数据设置SDICCON.根据不同的Response类型SDICCON进行不同设置.NoResponse时,写命令到SDICCON并发送命令,并确定发送完成.Short response时,SDICCON设置WAIT_FOR_RESPONSE.ResponseR2时,SDICCON设置LONG_RESPONSE | WAIT_FOR_RESPONSE.
[c-sharp]  view plain copy
  1. SD_API_STATUS CSDIOControllerBase::SendCommand(UINT16 Cmd, UINT32 Arg, UINT16 respType, BOOL bDataTransfer)  
  2. {  
  3.     unsigned int uiNewCmdRegVal = 0;  
  4.     DWORD dwWaitCount = 0;  
  5.   
  6.     DEBUGMSG (SDHC_SEND_ZONE,(TEXT("SendCommand (0x%08x, 0x%04x, 0x%08x, 0x%04x, 0x%x) starts"),   
  7.                 this, Cmd, Arg, respType, bDataTransfer));  
  8.     //----- 1. Reset any pending status flags -----  
  9.     vm_pSDIReg->SDICSTA = (CRC_CHECK_FAILED | COMMAND_SENT | COMMAND_TIMED_OUT | RESPONSE_RECEIVED);  
  10.   
  11.     //----- 2. Specify the command's argument -----  
  12.     vm_pSDIReg->SDICARG = Arg;  
  13.   
  14.     //----- 3. Specify the command's data transfer requirements -----  
  15.     if(bDataTransfer == TRUE)  
  16.     {  
  17.         vm_pSDIReg->SDICCON  |= SDIO_COMMAND_WITH_DATA;  
  18.     }else  
  19.     {  
  20.         vm_pSDIReg->SDICCON  &= ~SDIO_COMMAND_WITH_DATA;  
  21.     }  
  22.   
  23.     //----- 4. Send the command to the MMC controller -----  
  24.     switch(respType)  
  25.     {  
  26.     case NoResponse:                // Response is not required, but make sure the command was sent  
  27.         DEBUGMSG (SDHC_RESPONSE_ZONE,(TEXT("SendCommand no response required")));  
  28.         vm_pSDIReg->SDICCON = START_COMMAND | COMMAND_START_BIT | (Cmd & MAX_CMD_VALUE);  
  29.   
  30.         while(!(vm_pSDIReg->SDICSTA & COMMAND_SENT))  
  31.         {  
  32.             dwWaitCount++;  
  33.             if( dwWaitCount > WAIT_TIME )  
  34.             {  
  35.                 DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SendCommand() - timeout waiting for command completion!/r/n")));  
  36.                 return SD_API_STATUS_RESPONSE_TIMEOUT;  
  37.             }  
  38.   
  39.             if( !IsCardPresent() )  
  40.             {  
  41.                 DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SendCommand() - Card ejected!/r/n")));  
  42.                 return SD_API_STATUS_DEVICE_REMOVED;  
  43.             }  
  44.             if(vm_pSDIReg->SDICSTA & COMMAND_TIMED_OUT)  
  45.             {  
  46.                 DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SendCommand() - Command 0x%04x timed out!/r/n"), Cmd));  
  47.                 vm_pSDIReg->SDICSTA = COMMAND_TIMED_OUT;                // Clear the error  
  48.                 return SD_API_STATUS_RESPONSE_TIMEOUT;  
  49.             }  
  50.         }  
  51.         vm_pSDIReg->SDICSTA = COMMAND_SENT;                         // Clear the status   
  52.         break;  
  53.   
  54.     case ResponseR1:                // Short response required  
  55.     case ResponseR1b:  
  56.     case ResponseR3:  
  57.     case ResponseR4:  
  58.     case ResponseR5:                  
  59.     case ResponseR6:      
  60.         DEBUGMSG (SDHC_RESPONSE_ZONE,(TEXT("sendSDICommand short response required")));  
  61. //      vm_pSDIReg->SDICCON = uiNewCmdRegVal | WAIT_FOR_RESPONSE | START_COMMAND | COMMAND_START_BIT | (Cmd & MAX_CMD_VALUE);  
  62.         vm_pSDIReg->SDICCON = WAIT_FOR_RESPONSE | START_COMMAND | COMMAND_START_BIT | (Cmd & MAX_CMD_VALUE);  
  63.         break;  
  64.   
  65.     case ResponseR2:                // Long response required         
  66.         DEBUGMSG (SDHC_RESPONSE_ZONE,(TEXT("sendSDICommand long response required")));  
  67. //      vm_pSDIReg->SDICCON = uiNewCmdRegVal | LONG_RESPONSE | WAIT_FOR_RESPONSE | START_COMMAND | COMMAND_START_BIT | (Cmd & MAX_CMD_VALUE);  
  68.         vm_pSDIReg->SDICCON = LONG_RESPONSE | WAIT_FOR_RESPONSE | START_COMMAND | COMMAND_START_BIT | (Cmd & MAX_CMD_VALUE);  
  69.         break;  
  70.   
  71.     default:      
  72.         DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:sendSDICommand() - Invalid response type.  Command not sent!/r/n")));  
  73.         return SD_API_STATUS_NOT_IMPLEMENTED;  
  74.         break;  
  75.     }  
  76.       
  77.     return SD_API_STATUS_SUCCESS;  
  78. }  

13.GetCommandResponse
该函数用来获取命令应答,在TransferIstThread被调用.读取SDICSTA直到命令应答接收,如果有错误状态就返回错误.然后根据不同的应答类型分别读取SDIRSP0,SDIRSP1,SDIRSP2,SDIRSP3,具体格式参加代码注释.
[c-sharp]  view plain copy
  1. SD_API_STATUS CSDIOControllerBase::GetCommandResponse(PSD_BUS_REQUEST pRequest)  
  2. {  
  3.     DEBUGMSG (SDHC_RESPONSE_ZONE,(TEXT("GetCommandResponse started")));  
  4.     PUCHAR              respBuff;       // response buffer  
  5.     DWORD dwWaitCount = 0;  
  6.   
  7.     //----- 1. Wait for the response information to get arrive at the controller -----  
  8.     while(!(vm_pSDIReg->SDICSTA & RESPONSE_RECEIVED))  
  9.     {  
  10.         dwWaitCount++;  
  11.         if( dwWaitCount > WAIT_TIME )  
  12.         {  
  13.             DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:GetCommandResponse() - timeout waiting for command response!/r/n")));  
  14.             return SD_API_STATUS_RESPONSE_TIMEOUT;  
  15.         }  
  16.   
  17.         if( !IsCardPresent() )  
  18.         {  
  19.             DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:GetCommandResponse() - Card ejected!/r/n")));  
  20.             return SD_API_STATUS_DEVICE_REMOVED;  
  21.         }  
  22.         if(vm_pSDIReg->SDICSTA & COMMAND_TIMED_OUT)  
  23.         {  
  24.             vm_pSDIReg->SDICSTA = COMMAND_TIMED_OUT;                // Clear the error  
  25.             DEBUGMSG (SDCARD_ZONE_ERROR,(TEXT("GetCommandResponse returned SD_API_STATUS_RESPONSE_TIMEOUT (COMMAND_TIMED_OUT)")));  
  26.             return SD_API_STATUS_RESPONSE_TIMEOUT;  
  27.         }  
  28.   
  29.         if(vm_pSDIReg->SDIDSTA & CRC_CHECK_FAILED)  
  30.         {  
  31.             vm_pSDIReg->SDIDSTA = CRC_CHECK_FAILED;             // Clear the error  
  32.             DEBUGMSG (SDCARD_ZONE_ERROR,(TEXT("GetCommandResponse returned SD_API_STATUS_CRC_ERROR (CRC_CHECK_FAILED)")));  
  33.             return SD_API_STATUS_CRC_ERROR;  
  34.         }  
  35.   
  36.         if(vm_pSDIReg->SDIDSTA & DATA_TRANSMIT_CRC_ERROR)  
  37.         {  
  38.             vm_pSDIReg->SDIDSTA = DATA_TRANSMIT_CRC_ERROR;      // Clear the error  
  39.             DEBUGMSG (SDCARD_ZONE_ERROR,(TEXT("getSDICommandResponse returned SD_API_STATUS_CRC_ERROR (DATA_TRANSMIT_CRC_ERROR)")));  
  40.             return SD_API_STATUS_CRC_ERROR;   
  41.         }  
  42.   
  43.         if(vm_pSDIReg->SDIDSTA & DATA_RECEIVE_CRC_ERROR)  
  44.         {  
  45.             vm_pSDIReg->SDIDSTA = DATA_RECEIVE_CRC_ERROR;           // Clear the error  
  46.             DEBUGMSG (SDCARD_ZONE_ERROR,(TEXT("GetCommandResponse returned SD_API_STATUS_CRC_ERROR (DATA_RECEIVE_CRC_ERROR)")));  
  47.             return SD_API_STATUS_CRC_ERROR;  
  48.         }  
  49.   
  50.         if(vm_pSDIReg->SDIDSTA & DATA_TIME_OUT)  
  51.         {  
  52.             vm_pSDIReg->SDIDSTA = DATA_TIME_OUT;                    // Clear the error  
  53.             DEBUGMSG (SDCARD_ZONE_ERROR,(TEXT("GetCommandResponse returned SD_API_STATUS_DATA_TIMEOUT (DATA_TIME_OUT)")));  
  54.             return SD_API_STATUS_DATA_TIMEOUT;  
  55.         }  
  56.     }  
  57.     vm_pSDIReg->SDICSTA = RESPONSE_RECEIVED;                        // Clear the status   
  58.   
  59.   
  60.     //----- 2. Copy the response information to our "response buffer" -----  
  61.     //         NOTE: All START_BIT and TRANSMISSION_BIT bits ='0'. All END_BIT bits ='0'. All RESERVED bits ='1'  
  62.     respBuff = pRequest->CommandResponse.ResponseBuffer;  
  63.     switch(pRequest->CommandResponse.ResponseType)  
  64.     {  
  65.         case NoResponse:  
  66.             break;  
  67.   
  68.         case ResponseR1:                  
  69.         case ResponseR1b:  
  70.             //--- SHORT RESPONSE (48 bits total)---   
  71.             // Format: { START_BIT(1) | TRANSMISSION_BIT(1) | COMMAND_INDEX(6) | CARD_STATUS(32) | CRC7(7) | END_BIT(1) }  
  72.             // NOTE: START_BIT and TRANSMISSION_BIT = 0, END_BIT = 1  
  73.             //  
  74.             *(respBuff    ) = (BYTE)(START_BIT | TRANSMISSION_BIT | pRequest->CommandCode);  
  75.             *(respBuff + 1) = (BYTE)(vm_pSDIReg->SDIRSP0      );  
  76.             *(respBuff + 2) = (BYTE)(vm_pSDIReg->SDIRSP0 >> 8 );  
  77.             *(respBuff + 3) = (BYTE)(vm_pSDIReg->SDIRSP0 >> 16);  
  78.             *(respBuff + 4) = (BYTE)(vm_pSDIReg->SDIRSP0 >> 24);  
  79.             *(respBuff + 5) = (BYTE)(END_RESERVED | END_BIT);  
  80.             break;  
  81.   
  82.         case ResponseR3:  
  83.         case ResponseR4:  
  84.             //--- SHORT RESPONSE (48 bits total)---   
  85.             // Format: { START_BIT(1) | TRANSMISSION_BIT(1) | RESERVED(6) | CARD_STATUS(32) | RESERVED(7) | END_BIT(1) }  
  86.             //  
  87.             *(respBuff    ) = (BYTE)(START_BIT | TRANSMISSION_BIT | START_RESERVED);  
  88.             *(respBuff + 1) = (BYTE)(vm_pSDIReg->SDIRSP0      );  
  89.             *(respBuff + 2) = (BYTE)(vm_pSDIReg->SDIRSP0 >> 8 );  
  90.             *(respBuff + 3) = (BYTE)(vm_pSDIReg->SDIRSP0 >> 16);  
  91.             *(respBuff + 4) = (BYTE)(vm_pSDIReg->SDIRSP0 >> 24);  
  92.             *(respBuff + 5) = (BYTE)(END_RESERVED | END_BIT);     
  93.             break;  
  94.   
  95.         case ResponseR5:                  
  96.         case ResponseR6:  
  97.             //--- SHORT RESPONSE (48 bits total)---   
  98.             // Format: { START_BIT(1) | TRANSMISSION_BIT(1) | COMMAND_INDEX(6) | RCA(16) | CARD_STATUS(16) | CRC7(7) | END_BIT(1) }  
  99.             //  
  100.             *(respBuff    ) = (BYTE)(START_BIT | TRANSMISSION_BIT | pRequest->CommandCode);  
  101.             *(respBuff + 1) = (BYTE)(vm_pSDIReg->SDIRSP0      );  
  102.             *(respBuff + 2) = (BYTE)(vm_pSDIReg->SDIRSP0 >> 8 );  
  103.             *(respBuff + 3) = (BYTE)(vm_pSDIReg->SDIRSP0 >> 16);  
  104.             *(respBuff + 4) = (BYTE)(vm_pSDIReg->SDIRSP0 >> 24);  
  105.             *(respBuff + 5) = (BYTE)(vm_pSDIReg->SDIRSP1 >> 24);     
  106.             break;  
  107.   
  108.         case ResponseR2:  
  109.             //--- LONG RESPONSE (136 bits total)---   
  110.             // Format: { START_BIT(1) | TRANSMISSION_BIT(1) | RESERVED(6) | CARD_STATUS(127) | END_BIT(1) }  
  111.             //  
  112.             // NOTE: In this implementation, the caller doesn't require the upper 8 bits of reserved data.  
  113.             //       Consequently, these bits aren't included and the response info is copied directly into  
  114.             //       the beginning of the supplied buffer.        
  115.             //  
  116.             //*(respBuff    )   = (BYTE)(START_BIT | TRANSMISSION_BIT | START_RESERVED);  
  117.             //  
  118.             *(respBuff + 0) = (BYTE)(vm_pSDIReg->SDIRSP3      );  
  119.             *(respBuff + 1) = (BYTE)(vm_pSDIReg->SDIRSP3 >> 8 );  
  120.             *(respBuff + 2) = (BYTE)(vm_pSDIReg->SDIRSP3 >> 16);  
  121.             *(respBuff + 3) = (BYTE)(vm_pSDIReg->SDIRSP3 >> 24);  
  122.   
  123.             *(respBuff + 4) = (BYTE)(vm_pSDIReg->SDIRSP2      );  
  124.             *(respBuff + 5) = (BYTE)(vm_pSDIReg->SDIRSP2 >> 8 );  
  125.             *(respBuff + 6) = (BYTE)(vm_pSDIReg->SDIRSP2 >> 16);  
  126.             *(respBuff + 7) = (BYTE)(vm_pSDIReg->SDIRSP2 >> 24);  
  127.   
  128.             *(respBuff + 8) = (BYTE)(vm_pSDIReg->SDIRSP1      );  
  129.             *(respBuff + 9) = (BYTE)(vm_pSDIReg->SDIRSP1 >> 8 );  
  130.             *(respBuff + 10)= (BYTE)(vm_pSDIReg->SDIRSP1 >> 16);  
  131.             *(respBuff + 11)= (BYTE)(vm_pSDIReg->SDIRSP1 >> 24);  
  132.   
  133.             *(respBuff + 12)= (BYTE)(vm_pSDIReg->SDIRSP0      );  
  134.             *(respBuff + 13)= (BYTE)(vm_pSDIReg->SDIRSP0 >> 8 );  
  135.             *(respBuff + 14)= (BYTE)(vm_pSDIReg->SDIRSP0 >> 16);  
  136.             *(respBuff + 15)= (BYTE)(vm_pSDIReg->SDIRSP0 >> 24);  
  137.             break;  
  138.   
  139.         default:  
  140.             DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:GetCmdResponse(): Unrecognized response type!/r/n")));  
  141.             break;  
  142.     }  
  143.   
  144.     DEBUGMSG (SDHC_RESPONSE_ZONE,(TEXT("GetCommandResponse returned SD_API_STATUS_SUCCESS")));  
  145.     return SD_API_STATUS_SUCCESS;  
  146. }  

14.SetupDmaXfer
DMA传输,分两种情况SD_READ和SD_WRITE,首先设置request类型(SD_READ或SD_WRITE),reset fifo,设置BlockSize(SDIBSIZE寄存器),根据m_dwDMAChannel(0-3)设置DMA寄存器,设置源/目的地址,源地址periperal bus, fixed addr,目的地址system bus, increment addr,设置DMA通道传输特性handshake, sync PCLK, interrupt, single RX, single service,, MMC request, no auto-reload, word (32 bits), RX count,SD_READ和SD_WRITE的源和目的地址正好相反.
当SD_CMD_STOP_TRANSMISSION命令时,设置BUSY_AFTER_COMMAND
[c-sharp]  view plain copy
  1. BOOL CSDIOControllerBase::SetupDmaXfer(PSD_BUS_REQUEST pRequest)  
  2. {  
  3.     //----- 1. Check the parameters -----  
  4.     if(!pRequest)  
  5.     {  
  6.         DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SetupDmaXfer() - Invalid parameters!/r/n")));  
  7.         return FALSE;  
  8.     }  
  9.   
  10.     //----- 2. Setup the SD/MMC controller according to the type of transfer -----  
  11.     switch(pRequest->TransferClass)  
  12.     {  
  13.     case SD_READ:  
  14.   
  15.         //********* 3. READ request *********  
  16.         m_dwLastTypeOfTransfer = SD_READ;  
  17.   
  18.         //----- 3a. Reset the FIFO -----  
  19.         vm_pSDIReg->SDIDTIMER   = MAX_DATABUSY_TIMEOUT;          
  20.         vm_pSDIReg->SDIBSIZE      = pRequest->BlockSize;  
  21.         Stop_SDIO_DMA_Channel();  
  22.   
  23.         switch( m_dwDMAChannel )  
  24.         {  
  25.         case 0:  
  26.             //----- 3b. Initialize the DMA channel for input mode -----  
  27.             vm_pDMAreg->DISRC0   = (int)MMCFIF_PHYS;     
  28.             vm_pDMAreg->DISRCC0 |= (SOURCE_PERIPHERAL_BUS | FIXED_SOURCE_ADDRESS); // Source is periperal bus, fixed addr  
  29.             vm_pDMAreg->DIDST0   = (int)m_pDMABufferPhys.LowPart;  
  30.             vm_pDMAreg->DIDSTC0 &= ~(DESTINATION_PERIPHERAL_BUS | FIXED_DESTINATION_ADDRESS); // Destination is system bus, increment addr  
  31.             //----- 3c. Configure the DMA channel's transfer characteristics: handshake, sync PCLK, interrupt, -----  
  32.             //         single RX, single service,, MMC request, no auto-reload, word (32 bits), RX count  
  33.             vm_pDMAreg->DCON0  = (  HANDSHAKE_MODE | GENERATE_INTERRUPT | MMC_DMA0 | DMA_TRIGGERED_BY_HARDWARE   
  34.                                     | NO_DMA_AUTO_RELOAD | TRANSFER_WORD | ((pRequest->BlockSize / sizeof(DWORD)) * pRequest->NumBlocks));  
  35.             break;  
  36.   
  37.         case 1:  
  38.             //----- 3b. Initialize the DMA channel for input mode -----  
  39.             vm_pDMAreg->DISRC1 = (int)MMCFIF_PHYS;   
  40.             vm_pDMAreg->DISRCC1    |= (SOURCE_PERIPHERAL_BUS | FIXED_SOURCE_ADDRESS);              // Source is periperal bus, fixed addr  
  41.             vm_pDMAreg->DIDST1 = (int)m_pDMABufferPhys.LowPart;   
  42.             vm_pDMAreg->DIDSTC1 &= ~(DESTINATION_PERIPHERAL_BUS | FIXED_DESTINATION_ADDRESS);  // Destination is system bus, increment addr  
  43.             //----- 3c. Configure the DMA channel's transfer characteristics: handshake, sync PCLK, interrupt, -----  
  44.             //         single RX, single service,, MMC request, no auto-reload, word (32 bits), RX count  
  45.             vm_pDMAreg->DCON1  = (  HANDSHAKE_MODE | GENERATE_INTERRUPT | MMC_DMA0 | DMA_TRIGGERED_BY_HARDWARE   
  46.                                     | NO_DMA_AUTO_RELOAD | TRANSFER_WORD | ((pRequest->BlockSize / sizeof(DWORD)) * pRequest->NumBlocks));  
  47.             break;  
  48.   
  49.         case 2:  
  50.             //----- 3b. Initialize the DMA channel for input mode -----  
  51.             vm_pDMAreg->DISRC2 = (int)MMCFIF_PHYS;   
  52.             vm_pDMAreg->DISRCC2    |= (SOURCE_PERIPHERAL_BUS | FIXED_SOURCE_ADDRESS);              // Source is periperal bus, fixed addr  
  53.             vm_pDMAreg->DIDST2 = (int)m_pDMABufferPhys.LowPart;   
  54.             vm_pDMAreg->DIDSTC2 &= ~(DESTINATION_PERIPHERAL_BUS | FIXED_DESTINATION_ADDRESS);  // Destination is system bus, increment addr  
  55.             //----- 3c. Configure the DMA channel's transfer characteristics: handshake, sync PCLK, interrupt, -----  
  56.             //         single RX, single service,, MMC request, no auto-reload, word (32 bits), RX count  
  57.             vm_pDMAreg->DCON2  = (  HANDSHAKE_MODE | GENERATE_INTERRUPT | MMC_DMA0 | DMA_TRIGGERED_BY_HARDWARE   
  58.                                     | NO_DMA_AUTO_RELOAD | TRANSFER_WORD | ((pRequest->BlockSize / sizeof(DWORD)) * pRequest->NumBlocks));  
  59.             break;  
  60.   
  61.         case 3:  
  62.             //----- 3b. Initialize the DMA channel for input mode -----  
  63.             vm_pDMAreg->DISRC3 = (int)MMCFIF_PHYS;   
  64.             vm_pDMAreg->DISRCC3    |= (SOURCE_PERIPHERAL_BUS | FIXED_SOURCE_ADDRESS);              // Source is periperal bus, fixed addr  
  65.             vm_pDMAreg->DIDST3 = (int)m_pDMABufferPhys.LowPart;   
  66.             vm_pDMAreg->DIDSTC3 &= ~(DESTINATION_PERIPHERAL_BUS | FIXED_DESTINATION_ADDRESS);  // Destination is system bus, increment addr  
  67.             //----- 3c. Configure the DMA channel's transfer characteristics: handshake, sync PCLK, interrupt, -----  
  68.             //         single RX, single service,, MMC request, no auto-reload, word (32 bits), RX count  
  69.             vm_pDMAreg->DCON3  = (  HANDSHAKE_MODE | GENERATE_INTERRUPT | MMC_DMA0 | DMA_TRIGGERED_BY_HARDWARE   
  70.                                     | NO_DMA_AUTO_RELOAD | TRANSFER_WORD | ((pRequest->BlockSize / sizeof(DWORD)) * pRequest->NumBlocks));  
  71.             break;  
  72.   
  73.         default:  
  74.             ASSERT(0); // invalid DMA Channel... we should never get here  
  75.         }     
  76.   
  77.         //----- 3d. Setup the controller and DMA channel appropriately -----  
  78.         vm_pSDIReg->SDIDCON   = RECEIVE_AFTER_COMMAND | TRANSFER_BLOCK_MODE | Get_SDI_Bus_Width() | DMA_ENABLE | DATA_RECEIVE_START | pRequest->NumBlocks;  
  79.   
  80.         break;  
  81.       
  82.     case SD_WRITE:  
  83.   
  84.         //********* 4. WRITE request *********  
  85.         m_dwLastTypeOfTransfer = SD_WRITE;  
  86.   
  87.         //----- 4a. Reset the FIFO -----  
  88.         vm_pSDIReg->SDIDTIMER   = MAX_DATABUSY_TIMEOUT;          
  89.         vm_pSDIReg->SDIBSIZE      = pRequest->BlockSize;  
  90.         Stop_SDIO_DMA_Channel();  
  91.   
  92.         switch( m_dwDMAChannel )  
  93.         {  
  94.         case 0:  
  95.             //----- 4b. Initialize the DMA channel for output mode -----  
  96.             vm_pDMAreg->DISRC0 = (int)m_pDMABufferPhys.LowPart;   
  97.             vm_pDMAreg->DISRCC0    &= ~(SOURCE_PERIPHERAL_BUS | FIXED_SOURCE_ADDRESS);             // Source is periperal bus, fixed addr  
  98.   
  99.             vm_pDMAreg->DIDST0 = (int)MMCFIF_PHYS;   
  100.             vm_pDMAreg->DIDSTC0 |= (DESTINATION_PERIPHERAL_BUS | FIXED_DESTINATION_ADDRESS);       // Destination is system bus, increment addr  
  101.   
  102.             //----- 4c. Configure the DMA channel's transfer characteristics: handshake, sync PCLK, interrupt, -----  
  103.             //          single TX, single service, MMC request, no auto-reload, word (32 bits), TX count  
  104.             vm_pDMAreg->DCON0  = (  HANDSHAKE_MODE | GENERATE_INTERRUPT | MMC_DMA0 | DMA_TRIGGERED_BY_HARDWARE   
  105.                                             | NO_DMA_AUTO_RELOAD | TRANSFER_WORD | ((pRequest->BlockSize / sizeof(DWORD)) * pRequest->NumBlocks));  
  106.             break;  
  107.   
  108.         case 1:  
  109.             //----- 4b. Initialize the DMA channel for output mode -----  
  110.             vm_pDMAreg->DISRC1 = (int)m_pDMABufferPhys.LowPart;   
  111.             vm_pDMAreg->DISRCC1    &= ~(SOURCE_PERIPHERAL_BUS | FIXED_SOURCE_ADDRESS);             // Source is periperal bus, fixed addr  
  112.   
  113.             vm_pDMAreg->DIDST1 = (int)MMCFIF_PHYS;   
  114.             vm_pDMAreg->DIDSTC1 |= (DESTINATION_PERIPHERAL_BUS | FIXED_DESTINATION_ADDRESS);       // Destination is system bus, increment addr  
  115.   
  116.             //----- 4c. Configure the DMA channel's transfer characteristics: handshake, sync PCLK, interrupt, -----  
  117.             //          single TX, single service, MMC request, no auto-reload, word (32 bits), TX count  
  118.             vm_pDMAreg->DCON1  = (  HANDSHAKE_MODE | GENERATE_INTERRUPT | MMC_DMA0 | DMA_TRIGGERED_BY_HARDWARE   
  119.                                             | NO_DMA_AUTO_RELOAD | TRANSFER_WORD | ((pRequest->BlockSize / sizeof(DWORD)) * pRequest->NumBlocks));  
  120.             break;  
  121.   
  122.         case 2:  
  123.             //----- 4b. Initialize the DMA channel for output mode -----  
  124.             vm_pDMAreg->DISRC2 = (int)m_pDMABufferPhys.LowPart;   
  125.             vm_pDMAreg->DISRCC2    &= ~(SOURCE_PERIPHERAL_BUS | FIXED_SOURCE_ADDRESS);             // Source is periperal bus, fixed addr  
  126.   
  127.             vm_pDMAreg->DIDST2 = (int)MMCFIF_PHYS;   
  128.             vm_pDMAreg->DIDSTC2 |= (DESTINATION_PERIPHERAL_BUS | FIXED_DESTINATION_ADDRESS);       // Destination is system bus, increment addr  
  129.   
  130.             //----- 4c. Configure the DMA channel's transfer characteristics: handshake, sync PCLK, interrupt, -----  
  131.             //          single TX, single service, MMC request, no auto-reload, word (32 bits), TX count  
  132.             vm_pDMAreg->DCON2  = (  HANDSHAKE_MODE | GENERATE_INTERRUPT | MMC_DMA0 | DMA_TRIGGERED_BY_HARDWARE   
  133.                                             | NO_DMA_AUTO_RELOAD | TRANSFER_WORD | ((pRequest->BlockSize / sizeof(DWORD)) * pRequest->NumBlocks));  
  134.             break;  
  135.   
  136.         case 3:  
  137.             //----- 4b. Initialize the DMA channel for output mode -----  
  138.             vm_pDMAreg->DISRC3 = (int)m_pDMABufferPhys.LowPart;   
  139.             vm_pDMAreg->DISRCC3    &= ~(SOURCE_PERIPHERAL_BUS | FIXED_SOURCE_ADDRESS);             // Source is periperal bus, fixed addr  
  140.   
  141.             vm_pDMAreg->DIDST3 = (int)MMCFIF_PHYS;   
  142.             vm_pDMAreg->DIDSTC3 |= (DESTINATION_PERIPHERAL_BUS | FIXED_DESTINATION_ADDRESS);       // Destination is system bus, increment addr  
  143.   
  144.             //----- 4c. Configure the DMA channel's transfer characteristics: handshake, sync PCLK, interrupt, -----  
  145.             //          single TX, single service, MMC request, no auto-reload, word (32 bits), TX count  
  146.             vm_pDMAreg->DCON3  = (  HANDSHAKE_MODE | GENERATE_INTERRUPT | MMC_DMA0 | DMA_TRIGGERED_BY_HARDWARE   
  147.                                             | NO_DMA_AUTO_RELOAD | TRANSFER_WORD | ((pRequest->BlockSize / sizeof(DWORD)) * pRequest->NumBlocks));  
  148.             break;  
  149.   
  150.         default:  
  151.             ASSERT(0); // invalid DMA Channel... we should never get here  
  152.         }  
  153.   
  154.         //----- 4d. Setup the controller and DMA channel appropriately -----  
  155.         vm_pSDIReg->SDIDCON  = TRANSMIT_AFTER_RESPONSE | TRANSFER_BLOCK_MODE | Get_SDI_Bus_Width() | DMA_ENABLE | DATA_TRANSMIT_START | pRequest->NumBlocks;  
  156.   
  157.         break;  
  158.   
  159.   
  160.     case SD_COMMAND:  
  161.   
  162.         //----- 5. SPECIAL CASE: The SD_CMD_STOP_TRANSMISSION command requires that BUSY_AFTER_COMMAND be setup. -----  
  163.         if( ( m_fHandleBusyCheckOnCommand38 && pRequest->CommandCode == SD_CMD_ERASE ) ||  
  164.             ( ( pRequest->CommandCode == SD_CMD_STOP_TRANSMISSION ) && ( m_dwLastTypeOfTransfer == SD_WRITE ) ) )  
  165.         {  
  166.             vm_pSDIReg->SDIDCON = BUSY_AFTER_COMMAND | TRANSFER_BLOCK_MODE | DATA_BUSY | pRequest->NumBlocks;  
  167.         }  
  168.         break;  
  169.   
  170.     default:  
  171.         DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SetupDmaXfer(): Unrecognized transfer mode!/r/n")));  
  172.         return FALSE;  
  173.     }  
  174.   
  175.     return TRUE;  
  176. }  

15.IsCardBusy
检查Card是否处在Busy状态.检查SDICSTA和SDIDSTA状态寄存器,COMMAND_IN_PROGRESS,DATA_TRANSMIT_IN_PROGRESS,DATA_RECIEVE_IN_PROGRESS,READ_WAIT_REQUEST_OCCURE状态发生时,Card处于Busy状态.
[c-sharp]  view plain copy
  1. BOOL CSDIOControllerBase::IsCardBusy(UINT16 inData)  
  2. {  
  3.     //----- 1. Is there a command currently in progress? -----  
  4.     if(vm_pSDIReg->SDICSTA & COMMAND_IN_PROGRESS)  
  5.         return TRUE;  
  6.   
  7.     //----- 2. Is there a transfer in progress? -----  
  8.     if((vm_pSDIReg->SDIDSTA & DATA_TRANSMIT_IN_PROGRESS) ||   
  9.        (vm_pSDIReg->SDIDSTA & DATA_RECIEVE_IN_PROGRESS))  
  10.        return TRUE;  
  11.   
  12.     //----- 3. Is there a READ-WAIT request in progress? -----  
  13.     if(vm_pSDIReg->SDIDSTA & READ_WAIT_REQUEST_OCCURED)  
  14.         return TRUE;  
  15.   
  16.     return FALSE;  
  17. }  

16.SetClockRate
设置SDI clock时钟频率.首先检查参数正确性,频率最大为25MHz.如果输入MMC全速频率20MHz,由于2410在20MHz会有问题,所以设置成20MHz,然后计算分频值prescale = ((PCLK / (2*baud_rate)) - 1,然后确保SDI时钟处于停止状态,最后设置SDIPRE寄存器设置分配值,并启动SDI时钟.
[c-sharp]  view plain copy
  1. DWORD CSDIOControllerBase::SetClockRate(DWORD dwClockRate)  
  2. {  
  3.     if((dwClockRate < 0) || (dwClockRate > SD_FULL_SPEED_RATE))  
  4.     {  
  5.         DEBUGMSG(ZONE_ENABLE_ERROR, (TEXT("SDHCDriver:SetClockRate() - invalid clock rate %d !/r/n"), dwClockRate));  
  6.         goto DONE;  
  7.     }  
  8.   
  9.     //----- BUGBUG -----  
  10.     // HARDWARE BUG WORKAROUND  
  11.     //  
  12.     // The newest datasheet for the S3C2410X states that the maximum reliable speed for MMC cards is 10Mhz.  
  13.     // Some limited testing has shown 20Mhz to still be reliable, but for extra caution let's use 10Mhz.  
  14.     if(dwClockRate == MMC_FULL_SPEED_RATE)  
  15.     {  
  16.         dwClockRate = 10000000;  
  17.     }  
  18.   
  19.     //----- 2. Calculate the clock rate  -----  
  20.     //         NOTE: Using the prescale value, the clock's baud rate is  
  21.     //               determined as follows: baud_rate = (PCLK / 2 / (prescale + 1))  
  22.     //  
  23.     //               Hence, the prescale value can be computed as follows:  
  24.     //               prescale = ((PCLK / (2*baud_rate)) - 1  
  25.   
  26.     DWORD dwPrescale = dwClockRate ? ( (PCLK / (2*dwClockRate)) - 1 ) : 0xff;  
  27.     DWORD dwActualRate = PCLK / 2 / ( dwPrescale + 1 );  
  28.   
  29.     // adjust the rate if too high  
  30.     if( dwActualRate > dwClockRate )  
  31.     {  
  32.         dwPrescale++; // set to next supported lower rate  
  33.       
  34.         // recalculate the actual rate  
  35.         dwActualRate = PCLK / 2 / ( dwPrescale + 1 );  
  36.     }  
  37.   
  38.     // adjust the rate if too low  
  39.     if( dwPrescale > 0xff )  
  40.     {  
  41.         dwPrescale = 0xff; // set to slowest supported rate  
  42.       
  43.         // recalculate the actual rate  
  44.         dwActualRate = PCLK / 2 / ( dwPrescale + 1 );  
  45.     }  
  46.   
  47.     BOOL fClockIsRunning = Is_SDI_Clock_Running();  
  48.   
  49.     //----- 2. Make sure the clock is stopped -----  
  50.     if( fClockIsRunning )  
  51.     {  
  52.         Stop_SDI_Clock();  
  53.     }  
  54.   
  55.     //----- 3. Set the clock rate  -----  
  56.     vm_pSDIReg->SDIPRE = dwPrescale;  
  57.   
  58.     DEBUGMSG(SDHC_CLOCK_ZONE, (TEXT("SDHCD:SetClockRate() - Clock rate set to %d Hz/n"), dwActualRate));  
  59.   
  60.     if( fClockIsRunning )  
  61.     {  
  62.         Start_SDI_Clock();  
  63.     }  
  64.   
  65.     // remember the current clock rate  
  66.     m_dwClockRate = dwActualRate;  
  67.   
  68. DONE:  
  69.     return m_dwClockRate;  
  70. }  

17.PollingTransmit
用来轮询发送数据.首先判断一些错误状态是否发生,如卡不再插槽,FIFO Fail,CRC error等就返回false.状态正常则读取SDIFSTA看FIFO能否接收更多数据.可以就向SDIDAT写数据.直至FIFO满为止.然后监测数据是否写完,并设置DATA_TRANSMIT_FINISHED.
[c-sharp]  view plain copy
  1. BOOL CSDIOControllerBase::PollingTransmit(PSD_BUS_REQUEST pRequest, DWORD dwLen)  
  2. {  
  3.     BOOL fRetVal = TRUE;  
  4.     PBYTE pBuff = pRequest->pBlockBuffer;  
  5.    
  6.     SD_SET_PROC_PERMISSIONS_FROM_REQUEST( pRequest ) {                 
  7.         __try {   
  8.             //----- 1. Send the data to the FIFO -----  
  9.             while(dwLen > 0)  
  10.             {  
  11.                 if( !m_fCardInTheSlot )  
  12.                 {  
  13.                     DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:PollingTransmit() - Card ejected!/r/n")));  
  14.                     fRetVal = FALSE;  
  15.                     break;  
  16.                 }  
  17.                 if((vm_pSDIReg->SDIDSTA & FIFO_FAIL_ERROR))  
  18.                 {  
  19.                     DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:PollingTransmit() - FIFO Error!/r/n")));  
  20.                     fRetVal = FALSE;  
  21.                     break;  
  22.                 }  
  23.                 if((vm_pSDIReg->SDIDSTA & DATA_TRANSMIT_CRC_ERROR))  
  24.                 {  
  25.                     DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:PollingTransmit() - Transmit CRC Error!/r/n")));  
  26.                     fRetVal = FALSE;  
  27.                     break;  
  28.                 }  
  29.                 if((vm_pSDIReg->SDIDSTA & DATA_TIME_OUT))  
  30.                 {  
  31.                     DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:PollingTransmit() - Data timeout!/r/n")));  
  32.                     fRetVal = FALSE;  
  33.                     break;  
  34.                 }  
  35.                 //----- 2. Is the FIFO ready to accept more data? -----  
  36.                 if((vm_pSDIReg->SDIFSTA & FIFO_AVAIL_FOR_TX))  
  37.                 {  
  38.                     *(PBYTE)&(vm_pSDIReg->SDIDAT) = *pBuff++;  
  39.                     dwLen--;  
  40.                 }  
  41.             }  
  42.         } __except (SDProcessException(GetExceptionInformation())) {  
  43.             DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("--- SDHC Driver: Exception caught in PollingTransmit/n")));  
  44.             fRetVal = FALSE;  
  45.         }  
  46.     } SD_RESTORE_PROC_PERMISSIONS();  
  47.   
  48.     if( fRetVal )  
  49.     {  
  50.         DWORD dwWaitCount = 0;  
  51.         //----- 4. Make sure the transmit completes! -----  
  52.         while(!(vm_pSDIReg->SDIDSTA & DATA_TRANSMIT_FINISHED))  
  53.         {  
  54.             dwWaitCount++;  
  55.             if( dwWaitCount > WAIT_TIME )  
  56.             {  
  57.                 DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:PollingTransmit() - timeout waiting for DATA_TRANSMIT_FINISHED!/r/n")));  
  58.                 return SD_API_STATUS_RESPONSE_TIMEOUT;  
  59.             }  
  60.   
  61.             if( !IsCardPresent() )  
  62.             {  
  63.                 DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:PollingTransmit() - Card ejected!/r/n")));  
  64.                 fRetVal = FALSE;  
  65.                 break;  
  66.             }  
  67.             if((vm_pSDIReg->SDIDSTA & FIFO_FAIL_ERROR))  
  68.             {  
  69.                 DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:PollingTransmit() - FIFO Error waiting for DATA_TRANSMIT_FINISHED!/r/n")));  
  70.                 fRetVal = FALSE;  
  71.                 break;  
  72.             }  
  73.             if((vm_pSDIReg->SDIDSTA & DATA_TRANSMIT_CRC_ERROR))  
  74.             {  
  75.                 DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:PollingTransmit() - Transmit CRC Error waiting for DATA_TRANSMIT_FINISHED!/r/n")));  
  76.                 fRetVal = FALSE;  
  77.                 break;  
  78.             }  
  79.             if((vm_pSDIReg->SDIDSTA & DATA_TIME_OUT))  
  80.             {  
  81.                 DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:PollingTransmit() - Data timeout waiting for DATA_TRANSMIT_FINISHED!/r/n")));  
  82.                 fRetVal = FALSE;  
  83.                 break;  
  84.             }  
  85.         }  
  86.         vm_pSDIReg->SDIDSTA = DATA_TRANSMIT_FINISHED;  
  87.     }  
  88.   
  89.     return fRetVal;  
  90. }  

18.PollingReceive
轮询接收数据.首先判断一些错误状态是否发生,没有的话读SDIFSTA寄存器看是否有数据,有的话读取数据到缓冲区中.
[c-sharp]  view plain copy
  1. BOOL CSDIOControllerBase::PollingReceive(PSD_BUS_REQUEST pRequest, DWORD dwLen)  
  2. {  
  3.     BOOL fRetVal = TRUE;  
  4.     DEBUGCHK(m_dwNumBytesToTransfer <= MAXIMUM_DMA_TRANSFER_SIZE);  
  5.     PBYTE pBuff = pRequest->pBlockBuffer;  
  6.    
  7.     SD_SET_PROC_PERMISSIONS_FROM_REQUEST( pRequest ) {                 
  8.         __try {   
  9.             //----- 1. Read the data from the FIFO -----  
  10.             while(dwLen > 0)  
  11.             {  
  12.                 if( !m_fCardInTheSlot )  
  13.                 {  
  14.                     DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDIPollingReceive() - Card ejected!/r/n")));  
  15.                     fRetVal = FALSE;  
  16.                     break;  
  17.                 }  
  18.                 if((vm_pSDIReg->SDIDSTA & DATA_TIME_OUT))  
  19.                 {  
  20.                     DEBUGMSG(ZONE_ENABLE_ERROR, (TEXT("SDHCD:SDIPollingReceive() - Data receive time out!/r/n")));  
  21.                     fRetVal = FALSE;  
  22.                     break;  
  23.                 }  
  24.                 if((vm_pSDIReg->SDIDSTA & FIFO_FAIL_ERROR))  
  25.                 {  
  26.                     DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDIPollingReceive() - FIFO Error!/r/n")));  
  27.                     fRetVal = FALSE;  
  28.                     break;  
  29.                 }  
  30.                 if((vm_pSDIReg->SDIDSTA & DATA_RECEIVE_CRC_ERROR))  
  31.                 {  
  32.                     DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDIPollingReceive() - Receive CRC Error!/r/n")));  
  33.                     fRetVal = FALSE;  
  34.                     break;  
  35.                 }  
  36.                 if((vm_pSDIReg->SDIDSTA & DATA_TIME_OUT))  
  37.                 {  
  38.                     DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDIPollingReceive() - Data timeout!/r/n")));  
  39.                     fRetVal = FALSE;  
  40.                     break;  
  41.                 }  
  42.   
  43.                 //----- 2. Does the FIFO have more data ready? -----  
  44.                 if((vm_pSDIReg->SDIFSTA & FIFO_AVAIL_FOR_RX))  
  45.                 {  
  46.   
  47.                     *pBuff++ = *(PBYTE)&(vm_pSDIReg->SDIDAT);  
  48.                     dwLen--;  
  49.                 }  
  50.             }  
  51.         } __except (SDProcessException(GetExceptionInformation())) {  
  52.             DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("--- SDHC Driver: Exception caught in PollingTransmit/n")));  
  53.             fRetVal = FALSE;  
  54.         }  
  55.     } SD_RESTORE_PROC_PERMISSIONS();  
  56.   
  57.     return fRetVal;     
  58. }  

19.SetupPollingXfer
设置IO端口来初始化轮询.检查参数,Reset FIFO,然后根据传输类型(SD_READ,SD_WRITE,SD_COMMAND)来设置SDIBSIZE和SDIDCON寄存器.
[c-sharp]  view plain copy
  1. BOOL CSDIOControllerBase::SetupPollingXfer(PSD_BUS_REQUEST pRequest)  
  2. {  
  3.     //----- 1. Check the parameters -----  
  4.     if(!pRequest)  
  5.     {  
  6.         DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SetupSDIXfer() - Invalid parameters!/r/n")));  
  7.         return FALSE;  
  8.     }  
  9.   
  10.     //----- 2. Reset the FIFO -----  
  11.     vm_pSDIReg->SDICON   |= RESET_FIFO;      
  12.     vm_pSDIReg->SDIDSTA  |= FIFO_FAIL_ERROR;  
  13.   
  14.     //----- 3. Setup the SDI controller according to the type of transfer -----  
  15.     switch(pRequest->TransferClass)  
  16.     {  
  17.   
  18.     case SD_READ:  
  19.         vm_pSDIReg->SDIBSIZE       = pRequest->BlockSize;  
  20.         vm_pSDIReg->SDIDCON  = RECEIVE_AFTER_COMMAND | TRANSFER_BLOCK_MODE | Get_SDI_Bus_Width() | DATA_RECEIVE_START | pRequest->NumBlocks;  
  21.         break;  
  22.           
  23.   
  24.     case SD_WRITE:  
  25.         vm_pSDIReg->SDIBSIZE   = pRequest->BlockSize;  
  26.         vm_pSDIReg->SDIDCON  = TRANSMIT_AFTER_RESPONSE | TRANSFER_BLOCK_MODE | Get_SDI_Bus_Width() | DATA_TRANSMIT_START | pRequest->NumBlocks;  
  27.         break;  
  28.   
  29.     case SD_COMMAND:  
  30.         //----- 4. SPECIAL CASE: The SD_CMD_STOP_TRANSMISSION command requires that BUSY_AFTER_COMMAND be setup. -----  
  31.         if((pRequest->CommandCode == SD_CMD_STOP_TRANSMISSION) && (m_dwLastTypeOfTransfer == SD_WRITE))  
  32.         {  
  33.             vm_pSDIReg->SDIBSIZE  = pRequest->BlockSize;  
  34.             vm_pSDIReg->SDIDCON = BUSY_AFTER_COMMAND | TRANSFER_BLOCK_MODE | DATA_BUSY | pRequest->NumBlocks;  
  35.         }  
  36.         break;  
  37.   
  38.     default:  
  39.         DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SetupPollingXfer(): Unrecognized transfer mode!/r/n")));  
  40.         return FALSE;  
  41.     }  
  42.     return TRUE;  
  43. }  

20.SD_CardDetectThread,SD_IOInterruptIstThread,SD_TransferIstThread
分别对应于CardDetectThread,SD_IOInterruptIstThread,SD_TransferIstThread
[c-sharp]  view plain copy
  1. DWORD CSDIOControllerBase::SD_CardDetectThread(CSDIOControllerBase *pController)  
  2. {  
  3.     return pController->CardDetectThread();  
  4. }  
  5.   
  6. DWORD CSDIOControllerBase::SD_IOInterruptIstThread(CSDIOControllerBase *pController)  
  7. {  
  8.     return pController->IOInterruptIstThread();  
  9. }  
  10.   
  11. DWORD CSDIOControllerBase::SD_TransferIstThread(CSDIOControllerBase *pController)  
  12. {  
  13.     return pController->TransferIstThread();  
  14. }  

21.SDHCDInitialize,SDHCDDeinitialize,SDHCDCancelIoHandler,SDHCDBusRequestHandler,SDHCDSlotOptionHandler分别对应于Initialize,Deinitialize,CancelIoHandler,BusRequestHandler,SlotOptionHandler,这几个SDHCD handler在InterpretCapabilities被SDHCDSetControllerInitHandler,SDHCDSetControllerDeinitHandler,,SDHCDSetCancelIOHandler,SDHCDSetBusRequestHandler,SDHCDSetSlotOonHandler注册.实际上就是将这几个函数指针赋值给pHCContext对应的函数指针成员.
[c-sharp]  view plain copy
  1. SD_API_STATUS CSDIOControllerBase::SDHCDInitialize(PSDCARD_HC_CONTEXT pHCContext)  
  2. {  
  3.     // get our extension   
  4.     CSDIOControllerBase *pController = GET_PCONTROLLER_FROM_HCD(pHCContext);  
  5.     return pController->Initialize();  
  6. }  
  7.   
  8. SD_API_STATUS CSDIOControllerBase::SDHCDDeinitialize(PSDCARD_HC_CONTEXT pHCContext)  
  9. {  
  10.     // get our extension   
  11.     CSDIOControllerBase *pController = GET_PCONTROLLER_FROM_HCD(pHCContext);  
  12.     return pController->Deinitialize();  
  13. }  
  14.   
  15. BOOLEAN CSDIOControllerBase::SDHCDCancelIoHandler(PSDCARD_HC_CONTEXT pHCContext, DWORD dwSlot, PSD_BUS_REQUEST pRequest)  
  16. {  
  17.     // get our extension   
  18.     CSDIOControllerBase *pController = GET_PCONTROLLER_FROM_HCD(pHCContext);  
  19.     return pController->CancelIoHandler(dwSlot, pRequest);  
  20. }  
  21.   
  22. SD_API_STATUS CSDIOControllerBase::SDHCDBusRequestHandler(PSDCARD_HC_CONTEXT pHCContext, DWORD dwSlot, PSD_BUS_REQUEST pRequest)  
  23. {  
  24.     // get our extension   
  25.     CSDIOControllerBase *pController = GET_PCONTROLLER_FROM_HCD(pHCContext);  
  26.     return pController->BusRequestHandler(dwSlot, pRequest);  
  27. }  
  28.   
  29. SD_API_STATUS CSDIOControllerBase::SDHCDSlotOptionHandler(PSDCARD_HC_CONTEXT pHCContext, DWORD dwSlot,  
  30.                                        SD_SLOT_OPTION_CODE Option, PVOID pData, ULONG OptionSize)  
  31. {  
  32.     // get our extension   
  33.     CSDIOControllerBase *pController = GET_PCONTROLLER_FROM_HCD(pHCContext);  
  34.     return pController->SlotOptionHandler(dwSlot, Option, pData, OptionSize);  
  35. }  

22.InterpretCapabilities
在SDH_Init中调用,从注册表中读取配置信息.首先打开注册表,读取SD IRQ("SDIOIrq"=dword:15),然后向系统申请逻辑中断号.接着读取SDIO IST优先级("SDIO_IST_Priority"=dword:97),DMA通道号("DMAChannel"=dword:0).DMA IRQ("DMAIrq"=dword:11)并申请对应的逻辑中断号,接着读取DMA IST优先级,SD卡监测线程的轮询周期,HandleBusyFinishOnCommand39,DMA的一些信息等.调用CustomSetup(实现在sdiocontroller.cpp,CSDIOControllerBase的继承类CSDIOController)来进行和实际平台相关的初始化工作.
最后调用SDHCDSetHCName,SDHCDSetControllerInitHandler等进行m_pHCContext的成员赋值.
[c-sharp]  view plain copy
  1. BOOL CSDIOControllerBase::InterpretCapabilities( LPCTSTR pszRegistryPath )  
  2. {  
  3.     BOOL fRetVal = TRUE;  
  4.     CReg regDevice; // encapsulated device key  
  5.     HKEY hKeyDevice = OpenDeviceKey(pszRegistryPath);  
  6.     if ( (hKeyDevice == NULL) || !regDevice.Open(hKeyDevice, NULL) ) {  
  7.         DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("CSDIOControllerBase::InterpretCapabilities: Failed to open device key/n")));  
  8.         fRetVal = FALSE;  
  9.         goto FUNCTION_EXIT;  
  10.     }  
  11.   
  12.     // read registry settings  
  13.   
  14.     // read the SDIO SYSINTR value  
  15.     m_dwSDIOIrq = regDevice.ValueDW( SDIO_IRQ_TEXT, 0xffffffff );  
  16.     if( m_dwSDIOIrq == 0xffffffff )  
  17.     {  
  18.         // invalid SDIO IRQ value!  
  19.         DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("invalid SDIO IRQ value!/n")));  
  20.         fRetVal = FALSE;  
  21.         goto FUNCTION_EXIT;  
  22.     }  
  23.   
  24.     // convert the SDI hardware IRQ into a logical SYSINTR value  
  25.     if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &m_dwSDIOIrq, sizeof(DWORD), &m_dwSDIOSysIntr, sizeof(DWORD), NULL))  
  26.     {  
  27.         // invalid SDIO SYSINTR value!  
  28.         DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("invalid SDIO SYSINTR value!/n")));  
  29.         m_dwSDIOSysIntr = SYSINTR_UNDEFINED;  
  30.         fRetVal = FALSE;  
  31.         goto FUNCTION_EXIT;  
  32.     }   
  33.   
  34.     // read the SDIO IST priority  
  35.     m_nSDIOIstThreadPriority = regDevice.ValueDW( SDIO_IST_PRIORITY_TEXT, 0xffffffff );  
  36.   
  37.     // read the DMA channel number  
  38.     m_dwDMAChannel = regDevice.ValueDW( DMA_CHANNEL_TEXT, 0xffffffff );  
  39.   
  40.     // read the DMA IRQ value  
  41.     m_dwDMAIrq = regDevice.ValueDW( DMA_IRQ_TEXT, 0xffffffff );  
  42.     if( m_dwDMAIrq == 0xffffffff )  
  43.     {  
  44.         // invalid DMA IRQ value!  
  45.         m_dwDMAChannel = 0xffffffff; // disable DMA  
  46.     }  
  47.   
  48.     // convert the DMA hardware IRQ into a logical SYSINTR value.  
  49.     if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &m_dwDMAIrq, sizeof(DWORD), &m_dwDMASysIntr, sizeof(DWORD), NULL))  
  50.     {  
  51.         // invalid DMA IRQ value!  
  52.         m_dwDMAChannel = 0xffffffff; // disable DMA  
  53.     }   
  54.   
  55.     // read the DMA IST priority  
  56.     m_DMAIstThreadPriority = regDevice.ValueDW( DMA_IST_PRIORITY_TEXT, 0xffffffff );  
  57.   
  58.   
  59.     // read the card detect thread polling timeout (default 100 ms)  
  60.     m_dwPollingTimeout = regDevice.ValueDW( POLLING_TIMEOUT_TEXT, 150 );  
  61.   
  62.     // read the card detect thread priority  
  63.     m_nCardDetectIstThreadPriority = regDevice.ValueDW( CARD_DETECT_THREAD_PRIORITY_TEXT, 0xffffffff );  
  64.   
  65.     // read the HandleBusyFinishOnCommand38  
  66.     m_fHandleBusyCheckOnCommand38 = regDevice.ValueDW( HANDLE_BUSY_FINISH_ON_COMMAND38_TEXT, 0 ) ? TRUE : FALSE;  
  67.   
  68.     // read the DMA transfer timeout factor  
  69.     m_dwDMATransferTimeoutFactor = regDevice.ValueDW( DMA_TRANSFER_TIMEOUT_FACTOR_TEXT, 8 );  
  70.   
  71.     // read the DMA transfer timeout constant  
  72.     m_dwDMATransferTimeoutConstant = regDevice.ValueDW( DMA_TRANSFER_TIMEOUT_CONSTANT_TEXT, 3000 );  
  73.    
  74.     // call the custom (overrideable) routine for custom, hardware specific settings  
  75.     if( !CustomSetup( pszRegistryPath ) )  
  76.     {  
  77.         fRetVal = FALSE;  
  78.         goto FUNCTION_EXIT;  
  79.     }  
  80. /* 
  81.     // set the slot capabilities 
  82.     SDHCDSetSlotCapabilities(m_pHCContext, SD_SLOT_SD_1BIT_CAPABLE | SD_SLOT_SD_4BIT_CAPABLE |  
  83.                        SD_SLOT_SDIO_CAPABLE | SD_SLOT_SDIO_INT_DETECT_4BIT_MULTI_BLOCK); 
  84.  
  85.     // this platform has 3.3V tied directly to the slot   
  86.     SDHCDSetVoltageWindowMask(m_pHCContext, (SD_VDD_WINDOW_3_2_TO_3_3 | SD_VDD_WINDOW_3_3_TO_3_4));  
  87.  
  88.     // set on the low side  
  89.     SDHCDSetDesiredSlotVoltage(m_pHCContext, SD_VDD_WINDOW_3_2_TO_3_3);      
  90.  
  91.     // the SD/MMC controller tops out at MAX_SDI_BUS_TRANSFER_SPEED 
  92.     SDHCDSetMaxClockRate(m_pHCContext, MAX_SDI_BUS_TRANSFER_SPEED); 
  93.  
  94.     // power up settling time (estimated) 
  95.     SDHCDSetPowerUpDelay(m_pHCContext, 300);  
  96. */      
  97.     // set the name  
  98.     SDHCDSetHCName(m_pHCContext, TEXT("SDH"));  
  99.   
  100.     // set init handler  
  101.     SDHCDSetControllerInitHandler(m_pHCContext, CSDIOControllerBase::SDHCDInitialize);    
  102.           
  103.     // set deinit handler      
  104.     SDHCDSetControllerDeinitHandler(m_pHCContext, CSDIOControllerBase::SDHCDDeinitialize);  
  105.           
  106.     // set the Send packet handler  
  107.     SDHCDSetBusRequestHandler(m_pHCContext, CSDIOControllerBase::SDHCDBusRequestHandler);     
  108.           
  109.     // set the cancel I/O handler  
  110.     SDHCDSetCancelIOHandler(m_pHCContext, CSDIOControllerBase::SDHCDCancelIoHandler);     
  111.           
  112.     // set the slot option handler  
  113.     SDHCDSetSlotOptionHandler(m_pHCContext, CSDIOControllerBase::SDHCDSlotOptionHandler);   
  114.   
  115. FUNCTION_EXIT:  
  116.     if (hKeyDevice) RegCloseKey(hKeyDevice);  
  117.     return fRetVal;  
  118. }  

23.GetHostContext
返回m_pHCContext
[c-sharp]  view plain copy
  1. PSDCARD_HC_CONTEXT CSDIOControllerBase::GetHostContext() const  
  2. {  
  3.     return m_pHCContext;  
  4. }  

24.MMC_Hardware_PowerUp,MMC_Hardware_PowerDown
启动禁止SDI时钟,设置CLKON寄存器bit9(Control PCLK into SDI interface block)
[c-sharp]  view plain copy
  1. void CSDIOControllerBase::MMC_Hardware_PowerUp()  
  2. {  
  3.     vm_pCLKPWR->CLKCON |= (1 << 9);  
  4. }  
  5.   
  6. void CSDIOControllerBase::MMC_Hardware_PowerDown()  
  7. {  
  8.     vm_pCLKPWR->CLKCON &= ~(1 << 9);  
  9. }  

25.Stop_SDI_Hardware
停止数据传输,设置SDIDCON bit14强制停止数据传输(Determine whether data transfer stop by force or not)
[c-sharp]  view plain copy
  1. void CSDIOControllerBase::Stop_SDI_Hardware()  
  2. {   
  3.     vm_pSDIReg->SDIDCON |= STOP_BY_FORCE;  
  4. }  

26.Set_SDI_Bus_Width_1Bit,Set_SDI_Bus_Width_4Bit,Get_SDI_Bus_Width
设置和获取bus位宽(1bit或4bit)
[c-sharp]  view plain copy
  1. void CSDIOControllerBase::Set_SDI_Bus_Width_1Bit()  
  2. {   
  3.     m_dwSDIBusWidth = 0;  
  4. }  
  5.   
  6. void CSDIOControllerBase::Set_SDI_Bus_Width_4Bit()  
  7. {  
  8.     m_dwSDIBusWidth = WIDE_BUS_ENABLE;  
  9. }  
  10.   
  11. DWORD CSDIOControllerBase::Get_SDI_Bus_Width()  
  12. {  
  13.     return m_dwSDIBusWidth;  
  14. }  

27.Wait_80_SDI_Clock_Cycles
延时,这里调用sleep(1)延时约1ms

[c-sharp]  view plain copy
  1. void CSDIOControllerBase::Wait_80_SDI_Clock_Cycles()  
  2. {  
  3.     // delay 80 clock cycles... we may need a better way to do this  
  4.     Sleep(1); // sleep 1 ms  
  5. }  

28.Start_SDI_Clock,Stop_SDI_Clock,Is_SDI_Clock_Running
设置SDICON bit0(Determine whether SDCLK Out enable or not)使能或禁止SDCLK输出.Is_SDI_Clock_Running用来获取clock状态.
[c-sharp]  view plain copy
  1. void CSDIOControllerBase::Start_SDI_Clock()  
  2. {  
  3.     vm_pSDIReg->SDICON |= CLOCK_ENABLE;    
  4.     DEBUGMSG(SDHC_CLOCK_ZONE, (TEXT("SDHCD: Clock started.../n")));  
  5. }  
  6.   
  7. void CSDIOControllerBase::Stop_SDI_Clock()  
  8. {   
  9.     vm_pSDIReg->SDICON &= ~CLOCK_ENABLE;   
  10.     DEBUGMSG(SDHC_CLOCK_ZONE, (TEXT("SDHCD: Clock stopped.../n")));  
  11. }  
  12.   
  13. BOOL CSDIOControllerBase::Is_SDI_Clock_Running()  
  14. {  
  15.     if( vm_pSDIReg->SDICON & CLOCK_ENABLE )  
  16.         return TRUE;  
  17.     else  
  18.         return FALSE;  
  19. }  

29.Enable_SDIO_Interrupts,Disable_SDIO_Interrupts,Is_SDIO_Interrupt_Enabled,Is_SDIO_Interrupt_Enabled作用分别为使能/禁止SDIO中断,返回SDIO中断状态,清除中断标志.
[c-sharp]  view plain copy
  1. void CSDIOControllerBase::Enable_SDIO_Interrupts()  
  2. {   
  3.     vm_pSDIReg->SDICON   |= SDIO_INTERRUPT_ENABLE;  
  4.     vm_pSDIReg->SDIIMSK  |= SDIO_HOST_IO_INT;  
  5. }  
  6.   
  7. void CSDIOControllerBase::Disable_SDIO_Interrupts()  
  8. {  
  9.     vm_pSDIReg->SDICON   &= ~SDIO_INTERRUPT_ENABLE;  
  10.     vm_pSDIReg->SDIIMSK  &= ~SDIO_HOST_IO_INT;  
  11. }  
  12.   
  13. BOOL CSDIOControllerBase::Is_SDIO_Interrupt_Enabled()  
  14. {  
  15.     if( vm_pSDIReg->SDICON & SDIO_INTERRUPT_ENABLE )  
  16.         return TRUE;  
  17.     else  
  18.         return FALSE;  
  19. }  
  20.   
  21. void CSDIOControllerBase::Ack_SDIO_Interrupts()  
  22. {  
  23.     vm_pSDIReg->SDIDSTA = SDIO_INTERRUPT_DETECTED;  
  24. }  

30.Enable_SDIO_DMA_Channel,Disable_SDIO_DMA_Channel
使能/禁止对应DMA通道(m_dwDMAChannel)
[c-sharp]  view plain copy
  1. void CSDIOControllerBase::Enable_SDIO_Interrupts()  
  2. {   
  3.     vm_pSDIReg->SDICON   |= SDIO_INTERRUPT_ENABLE;  
  4.     vm_pSDIReg->SDIIMSK  |= SDIO_HOST_IO_INT;  
  5. }  
  6.   
  7. void CSDIOControllerBase::Disable_SDIO_Interrupts()  
  8. {  
  9.     vm_pSDIReg->SDICON   &= ~SDIO_INTERRUPT_ENABLE;  
  10.     vm_pSDIReg->SDIIMSK  &= ~SDIO_HOST_IO_INT;  
  11. }  
  12.   
  13. BOOL CSDIOControllerBase::Is_SDIO_Interrupt_Enabled()  
  14. {  
  15.     if( vm_pSDIReg->SDICON & SDIO_INTERRUPT_ENABLE )  
  16.         return TRUE;  
  17.     else  
  18.         return FALSE;  
  19. }  
  20.   
  21. void CSDIOControllerBase::Ack_SDIO_Interrupts()  
  22. {  
  23.     vm_pSDIReg->SDIDSTA = SDIO_INTERRUPT_DETECTED;  
  24. }  

31.OnPowerUp,OnPowerDown
这两个函数被流接口函数SDH_PowerUp和SDH_PowerDown调用.
OnPowerUp:
首先调用MMC_Hardware_PowerUp使能SDI时钟,配置GPIO进入SDI模式,设置SDI时钟默认频率(100KHz),配置SDI相关寄存器,如LITTLE_ENDIAN_BYTE_ORDER,RESET_FIFO,BYTES_PER_SECTOR(512)等,调用继承类的InitializeHardware函数进行硬件初始化(这个函数后面在介绍),启动SDI时钟,调用SDHCDPowerUpDown通知SD总线驱动PowerUp事件发生,设置事件m_hCardInsertInterruptEvent.
[c-sharp]  view plain copy
  1. void CSDIOControllerBase::OnPowerUp()  
  2. {  
  3.     //  Supply the clock to the SDI controller  
  4.     MMC_Hardware_PowerUp();  
  5.   
  6.     // Reconfigure the GPIO lines for SDI mode and enable the pullup resistor -----  
  7.     vm_pIOPreg->GPEUP  &= 0xF83F;  
  8.     vm_pIOPreg->GPECON |= 0x2AA800;  
  9.   
  10.     // Reset the SD/SDI controller to some reasonable default values -----  
  11.     SetClockRate(SD_DEFAULT_CARD_ID_CLOCK_RATE);        // 100Khz  
  12.   
  13.     vm_pSDIReg->SDICON     |= LITTLE_ENDIAN_BYTE_ORDER;    // Windows CE is always Little Endian.  
  14.     vm_pSDIReg->SDICON     |= RESET_FIFO;                  // Reset the FIFO  
  15.     vm_pSDIReg->SDIBSIZE    = BYTES_PER_SECTOR;   
  16.     vm_pSDIReg->SDIDTIMER   = MAX_DATABUSY_TIMEOUT;        // Data/busy timeout  
  17.   
  18.     // reinitialize the hardware  
  19.     InitializeHardware( TRUE );  
  20.   
  21.     // Start the SDI Clock  
  22.     Start_SDI_Clock();  
  23.   
  24.     // Notify the SD Bus driver of the PowerUp event  
  25.     SDHCDPowerUpDown(m_pHCContext, TRUE, FALSE, 0);  
  26.   
  27.     // simulate a card ejection/insertion  
  28.     m_bReinsertTheCard = TRUE;  
  29.     SetEvent( m_hCardInsertInterruptEvent );  
  30. }  

OnPowerDown:
首先调用SDHCDPowerUpDown通知SD总线驱动PowerDown事件,停止SDI时钟,调用DeinitializeHardware(继承类实现)进行硬件资源的释放.
[c-sharp]  view plain copy
  1. void CSDIOControllerBase::OnPowerDown()  
  2. {  
  3.     // Notify the SD Bus driver of the PowerDown event  
  4.     SDHCDPowerUpDown(m_pHCContext, FALSE, FALSE, 0);  
  5.   
  6.     // Stop the SDI Clock  
  7.     Stop_SDI_Clock();  
  8.   
  9.     // Call DeinitializeHardware (By default, it does nothing, but OEM's may overwrite   
  10.     // this function to provide hardware specific configuration changes on PowerDown event)  
  11.     DeinitializeHardware( TRUE );  
  12. }  

CSDIOControllerBase类就简单分析到这里,接下来来看看其继承类CSDIOController,里面实现了CSDIOControllerBase没有实现的几个纯虚函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值