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

📄 sdio.c

📁 wince 5.0下SDIO驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
///////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2002,2004-2005 BSQUARE Corporation.  All rights reserved.
//
// Module Name:
//
//    SDIO.c
//
// Abstract:
//
//    Au1100 SDIO controller driver implementation
//
// Notes:
//
///////////////////////////////////////////////////////////////////////////////

#include <windows.h>	// For min() macro
#include <sdcardddk.h>
#include <sdhcd.h>
#include "sdio.h"
#include "gpio.h"

typedef struct {
	ULONG	BlocksCopied;
	ULONG   BytesCopied;
	ULONG   BuffersOutstanding;
} HC_PARAMS, *PHC_PARAMS;

static HC_PARAMS HCParams;

    // clock rate table structure
typedef struct _CLOCK_RATE_ENTRY {
    DWORD  Frequency;
    USHORT ControlValue;
} CLOCK_RATE_ENTRY, *PCLOCK_RATE_ENTRY;

    // lookup table of some of the more useful SD clock frequencies
CLOCK_RATE_ENTRY SDIOClockTable[] = 
    
{       // FREQ                         Divisor    Rate assuming 50MHz MCLK
    {CONTROLLER_CLOCK_FREQUENCY/512,    511},   // 98 Khz 
    {CONTROLLER_CLOCK_FREQUENCY/256,    255},   // 195 Khz
    {CONTROLLER_CLOCK_FREQUENCY/128,    127},   // 391 Khz
    {CONTROLLER_CLOCK_FREQUENCY/64,     63},    // 781 Khz
    {CONTROLLER_CLOCK_FREQUENCY/32,     31},    // 1.5 Mhz
    {CONTROLLER_CLOCK_FREQUENCY/16,     15},    // 3.13 Mhz
    {CONTROLLER_CLOCK_FREQUENCY/8,      7},     // 6.25 Mhz
    {CONTROLLER_CLOCK_FREQUENCY/4,      3},     // 12.5 Mhz
    {CONTROLLER_CLOCK_FREQUENCY/3,      2},     // 16.6 Mhz
    {CONTROLLER_CLOCK_FREQUENCY/2,      1},     // 25 Mhz
};

#define NUM_CLOCK_ENTRIES sizeof(SDIOClockTable)/sizeof(CLOCK_RATE_ENTRY)

// structure containing configuration information for each slot
typedef struct {
	ULONG SDPhysAddr;
	ULONG TxDmaDeviceId;
	ULONG RxDmaDeviceId;
} AUSDIO_CONFIG;

AUSDIO_CONFIG AuSdConfig[] = {
	{ SD0_PHYS_ADDR, DMA_SD0_TX, DMA_SD0_RX },
	{ SD1_PHYS_ADDR, DMA_SD1_TX, DMA_SD1_RX }
};



///////////////////////////////////////////////////////////////////////////////
//  ResetSlot - reset the slot to its initial state
//  Input:  pSlot -   slot context
//  Output: 
//  Return: 
///////////////////////////////////////////////////////////////////////////////
VOID ResetSlot(PSDIO_SLOT pSlot, BOOL IsInitPath)
{
	ULONG divisor = 0;
	ULONG config2 = 0;

	if (!IsInitPath)
    {
		config2 = READ_REGISTER_ULONG((PULONG)&pSlot->pSD->config2);
		divisor = READ_REGISTER_ULONG((PULONG)&pSlot->pSD->config);
		divisor &= SD_CONFIG_DIV;
	}

		// reset the controller
	WRITE_REGISTER_ULONG((PULONG)&pSlot->pSD->enable, 0);
	WRITE_REGISTER_ULONG((PULONG)&pSlot->pSD->enable, SD_ENABLE_CE);
	WRITE_REGISTER_ULONG((PULONG)&pSlot->pSD->enable, SD_ENABLE_R | SD_ENABLE_CE);

		// enable the state machines
	WRITE_REGISTER_ULONG((PULONG)&pSlot->pSD->config2, config2 | SD_CONFIG2_EN );
		// set the timeout to max
	WRITE_REGISTER_ULONG((PULONG)&pSlot->pSD->timeout, SD_TIMEOUT_MAX );
   
		// write clock
	WRITE_REGISTER_ULONG((PULONG)&pSlot->pSD->config, divisor | SD_CONFIG_DE);

		// Disable all interrupts
	SD_INTERRUPTS_DISABLE(pSlot,0xFFFFFFFF);
		// Clear interrupt status
	SD_INTERRUPTS_CLEAR(pSlot,0xFFFFFFFF);
		// Enable master inerrupt
	SD_INTERRUPTS_ENABLE(pSlot, SD_Int_Master );
}     

///////////////////////////////////////////////////////////////////////////////
//  DumpSlot - dump the states of the slot 
//  Input:  pSlot -   slot context
//  Output: 
//  Return: 
///////////////////////////////////////////////////////////////////////////////
VOID DumpSlot( PSDIO_SLOT pSlot )
{
    RETAILMSG(1,(TEXT("SDIO SLOT %d\r\n"),pSlot->SlotNumber));
    RETAILMSG(1,(TEXT("SD_CONFIG = 0x%08X\r\n"),READ_REGISTER_ULONG((PULONG)&pSlot->pSD->config)));
    RETAILMSG(1,(TEXT("SD_ENABLE = 0x%08X\r\n"),READ_REGISTER_ULONG((PULONG)&pSlot->pSD->enable)));
    RETAILMSG(1,(TEXT("SD_CONFIG2 = 0x%08X\r\n"),READ_REGISTER_ULONG((PULONG)&pSlot->pSD->config2)));
    RETAILMSG(1,(TEXT("SD_BLKSIZE = 0x%08X\r\n"),READ_REGISTER_ULONG((PULONG)&pSlot->pSD->blksize)));
    RETAILMSG(1,(TEXT("SD_STATUS = 0x%08X\r\n"),READ_REGISTER_ULONG((PULONG)&pSlot->pSD->status)));
    RETAILMSG(1,(TEXT("SD_DEBUG = 0x%08X\r\n"),READ_REGISTER_ULONG((PULONG)&pSlot->pSD->debug)));
    RETAILMSG(1,(TEXT("SD_CMD = 0x%08X\r\n"),READ_REGISTER_ULONG((PULONG)&pSlot->pSD->cmd)));
    RETAILMSG(1,(TEXT("SD_CMDARG = 0x%08X\r\n"),READ_REGISTER_ULONG((PULONG)&pSlot->pSD->cmdarg)));
    RETAILMSG(1,(TEXT("SD_TIMEOUT = 0x%08X\r\n"),READ_REGISTER_ULONG((PULONG)&pSlot->pSD->timeout)));

    if (NULL!=pSlot->pCurrentRequest) {
        RETAILMSG(1, (TEXT("pCurrentRequest->CommandCode = %d\r\n"),pSlot->pCurrentRequest->CommandCode));
        RETAILMSG(1, (TEXT("pCurrentRequest->NumBlocks = %d\r\n"),pSlot->pCurrentRequest->NumBlocks));
        RETAILMSG(1, (TEXT("pCurrentRequest->BlockSize = %d\r\n"),pSlot->pCurrentRequest->BlockSize));
        RETAILMSG(1, (TEXT("pCurrentRequest->HCParam = %d\r\n"),pSlot->pCurrentRequest->HCParam));
    }

    RETAILMSG(1,(TEXT("InterruptMask = 0x%08X\r\n"),pSlot->InterruptMask));
    RETAILMSG(1,(TEXT("CardPresent   = %d\r\n"),pSlot->CardPresent));
    RETAILMSG(1,(TEXT("CheckSlotOnStartUp = %d\r\n"),pSlot->CheckSlotOnStartUp));
    RETAILMSG(1,(TEXT("CardInitialised = %d\r\n"),pSlot->CardInitialised));
}

///////////////////////////////////////////////////////////////////////////////
//  DumpController - dump the states of the controller 
//  Input:  pController -   controller context
//  Output: 
//  Return: 
///////////////////////////////////////////////////////////////////////////////
VOID DumpController( PSDIO_HW_CONTEXT pController )
{
	int i;
	
	for (i=0;i<SDIOPlatNumSlots();i++) {
		DumpSlot(&pController->Slots[i]);
	}
}

///////////////////////////////////////////////////////////////////////////////
//  SDIOClockOff - turn off the SD clock
//  Input:  pSlot -   slot context
//  Output: 
//  Return: 
//  Notes:  Currently simply leave the clock along for now.
///////////////////////////////////////////////////////////////////////////////
VOID SDIOClockOff(PSDIO_SLOT pSlot)
{
	ULONG tmp;

	    // turn off the clock
	tmp = READ_REGISTER_ULONG((PULONG)&pSlot->pSD->enable);
	tmp &= ~SD_ENABLE_CE;
//	WRITE_REGISTER_ULONG((PULONG)&pSlot->pSD->enable,tmp);

    DEBUGMSG(SDIO_CLOCK_ZONE, (TEXT("SDIOClockOff - Clock is now off \n")));
}

///////////////////////////////////////////////////////////////////////////////
//  SDIOClockOn - turn on the MMC Clock
//  Input:  pSlot -   slot context
//  Output: 
//  Return: 
//  Notes:  
///////////////////////////////////////////////////////////////////////////////
VOID SDIOClockOn(PSDIO_SLOT pSlot)
{
	ULONG tmp;

	    // turn on the clock
	tmp = READ_REGISTER_ULONG((PULONG)&pSlot->pSD->enable);
	tmp |= SD_ENABLE_CE;
	WRITE_REGISTER_ULONG((PULONG)&pSlot->pSD->enable,tmp);

    DEBUGMSG(SDIO_CLOCK_ZONE, (TEXT("SDIOClockOn  - Clock is now on \n")));
}

///////////////////////////////////////////////////////////////////////////////
//  SDIOSetRate - sets rate of SD Clock
//  Input:  pSlot -   slot context
//          pRate - desired clock rate in Hz
//  Output: pRate - the clock rate now in use
//  Return: 
//  Notes:  Divisor could easily be calculated
///////////////////////////////////////////////////////////////////////////////
VOID SDIOSetRate(PSDIO_SLOT pSlot, PDWORD pRate)
{
    ULONG ii;           // table index variable
	ULONG regValue;		// temp register value

        // check to see if the rate is below the first entry in the table
    if (*pRate <= SDIOClockTable[0].Frequency) {
        ii = 0;
    } else {
            // scan through the table looking for a frequency that
            // is close to the requested rate
        for (ii = 0; ii < (NUM_CLOCK_ENTRIES - 1); ii++) {
            if ((*pRate >= SDIOClockTable[ii].Frequency) &&
                (*pRate < SDIOClockTable[ii+1].Frequency)) {
                break;
            } 
        }
    }

    DEBUGMSG(SDIO_CLOCK_ZONE, (TEXT("SDIOSetRate - Requested Rate: %d, Setting clock rate to %d Hz \n"),
           *pRate, SDIOClockTable[ii].Frequency ));

        // return the actual frequency
    *pRate = SDIOClockTable[ii].Frequency;
		// update the divisor setting
	regValue = READ_REGISTER_ULONG((PULONG)&pSlot->pSD->config );
        // clear old divisor
	regValue &= ~SD_CONFIG_DIV;
        // set new divisot
	regValue |= SDIOClockTable[ii].ControlValue;
	regValue |= SD_CONFIG_DE;
        // write new value back
	WRITE_REGISTER_ULONG((PULONG)&pSlot->pSD->config, regValue );
}

#ifdef USE_DMA
///////////////////////////////////////////////////////////////////////////////
//  CopyFromDmaBuffer - Copy data from a DMA buffer into a requests data buffer
//  Input:  pRequest   - the request that this data belongs to
//          pDmaBuffer - which buffer to copy from
//  Output: 
//  Return:
//  Notes:  
///////////////////////////////////////////////////////////////////////////////
VOID CopyFromDmaBuffer(PSD_BUS_REQUEST pRequest,
                       PULONG          pDmaBuffer)
{
	ULONG blocksToCopy;
	ULONG blocksRemaining;
	
	blocksRemaining = pRequest->NumBlocks - ((PHC_PARAMS)pRequest->HCParam)->BlocksCopied;

	if (blocksRemaining > (DMA_BUFFER_SIZE / pRequest->BlockSize)) {
		blocksToCopy = (DMA_BUFFER_SIZE / pRequest->BlockSize);
	} else {
		blocksToCopy = blocksRemaining;
	}

        // we are touching the block buffer, set the process permissions
    SD_SET_PROC_PERMISSIONS_FROM_REQUEST(pRequest) {
            // safe copy data into block buffer
        SDPerformSafeCopy(pRequest->pBlockBuffer+(((PHC_PARAMS)pRequest->HCParam)->BlocksCopied*pRequest->BlockSize),
                          pDmaBuffer, 
                          pRequest->BlockSize * blocksToCopy);
    } SD_RESTORE_PROC_PERMISSIONS();

	((PHC_PARAMS)pRequest->HCParam)->BlocksCopied += blocksToCopy;
	((PHC_PARAMS)pRequest->HCParam)->BuffersOutstanding--;
}

///////////////////////////////////////////////////////////////////////////////
//  CopyToDmaBuffer - Copy data to a DMA buffer from a requests data buffer
//  Input:  pRequest   - the request that this data belongs to
//          pDmaBuffer - which buffer to copy to
//  Output: 
//  Return:
//  Notes:  
///////////////////////////////////////////////////////////////////////////////
ULONG CopyToDmaBuffer(PSD_BUS_REQUEST pRequest,
                      PULONG          pDmaBuffer)
{
	ULONG blocksToCopy;
	ULONG blocksRemaining;
	
	blocksRemaining = pRequest->NumBlocks - ((PHC_PARAMS)pRequest->HCParam)->BlocksCopied;

	if (blocksRemaining > (DMA_BUFFER_SIZE / pRequest->BlockSize)) {
		blocksToCopy = (DMA_BUFFER_SIZE / pRequest->BlockSize);
	} else {
		blocksToCopy = blocksRemaining;
	}

        // we are touching the block buffer, set the process permissions
    SD_SET_PROC_PERMISSIONS_FROM_REQUEST(pRequest) {
            // safe copy data into block buffer
        SDPerformSafeCopy(pDmaBuffer,
                          pRequest->pBlockBuffer+(((PHC_PARAMS)pRequest->HCParam)->BlocksCopied*pRequest->BlockSize),
                          pRequest->BlockSize * blocksToCopy);
    } SD_RESTORE_PROC_PERMISSIONS();

	((PHC_PARAMS)pRequest->HCParam)->BlocksCopied += blocksToCopy;

	// Incrementing count of outstanding blocks
	// IST will decrement this when a block has been transmitted
	((PHC_PARAMS)pRequest->HCParam)->BuffersOutstanding++;

	return (blocksToCopy*pRequest->BlockSize);
}

///////////////////////////////////////////////////////////////////////////////
//  SDIOInitializeDMA - Initialize DMA resources for an SD slot
//  Input:  pSlot        - slot context
//  Output: 
//  Return:
//  Notes:  
///////////////////////////////////////////////////////////////////////////////
BOOL SDIOInitializeDMA(PSDIO_SLOT pSlot)
{
    ULONG hwIntr;
    DWORD threadID;                         // thread ID

	// Allocate Tx DMA Channel
	pSlot->TxDmaChannel = HalAllocateDMAChannel();

	if (pSlot->TxDmaChannel==NULL) {
        DEBUGMSG(SDCARD_ZONE_ERROR,(TEXT("SDIO[%d]: Can't allocate Tx DMA Channel\r\n"),
                   pSlot->SlotNumber));
		goto ErrorReturn;
	}

	// Allocate Rx DMA Channel
	pSlot->RxDmaChannel = HalAllocateDMAChannel();

	if (pSlot->RxDmaChannel==NULL) {
        DEBUGMSG(SDCARD_ZONE_ERROR,(TEXT("SDIO[%d]: Can't allocate Rx DMA Channel\r\n"),
                   pSlot->SlotNumber));
		goto ErrorReturn;
	}

    pSlot->UsingDma = TRUE;

⌨️ 快捷键说明

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