?? sdio.c
字號:
pController->hGPIO = GPIO_Init();
if (INVALID_HANDLE_VALUE == pController->hGPIO) {
DEBUGMSG(SDCARD_ZONE_ERROR,(TEXT("SDIO: Unable to opne GPIO device\r\n")));
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto exitInit;
}
status = SDIOPlatInit(pController);
if (SD_API_STATUS_SUCCESS != status) {
goto exitInit;
}
// allocate the controller interrupt event
pController->hControllerInterruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (NULL == pController->hControllerInterruptEvent) {
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto exitInit;
}
// initialize the controller interrupt event
if (!InterruptInitialize (pController->SysIntr,
pController->hControllerInterruptEvent,
NULL,
0)) {
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto exitInit;
}
pController->ControllerIstThreadPriority = SDIO_CARD_CONTROLLER_IST_PRIORITY;
// create the interrupt thread for controller interrupts
pController->hControllerInterruptThread = CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)SDIOControllerIstThread,
pController,
0,
&threadID);
if (NULL == pController->hControllerInterruptThread) {
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto exitInit;
}
// initialize the slots
for (i=0;i<SDIOPlatNumSlots();i++) {
status = SDIOInitializeSlot(&pController->Slots[i]);
if (SD_API_STATUS_SUCCESS != status) {
goto exitInit;
}
}
pController->Initialized = TRUE;
// wake up the interrupt thread to check the slot
SetEvent(pController->hControllerInterruptEvent);
// initialize the slots
for (i=0;i<SDIOPlatNumSlots();i++) {
SetEvent(pController->Slots[i].hInsertionInterruptEvent);
}
exitInit:
if (!SD_API_SUCCESS(status)) {
// just call the deinit handler directly to cleanup
SDIODeinitialize(pHCContext);
}
DumpController(pController);
return status;
}
///////////////////////////////////////////////////////////////////////////////
// SDIODeInitialize - De-Initialize the SDIO Controller
// Input: pHCContext - HC context
// Output:
// Return: SD_API_STATUS
// Notes:
///////////////////////////////////////////////////////////////////////////////
SD_API_STATUS SDIODeinitialize(PSDCARD_HC_CONTEXT pHCContext)
{
PSDIO_HW_CONTEXT pController; // the controller
int i;
pController = GetExtensionFromHCDContext(PSDIO_HW_CONTEXT, pHCContext);
#ifdef DEBUG
DumpController(pController);
#endif
// mark for shutdown
// this will cause all IST to terminate when signalled
pController->DriverShutdown = TRUE;
if (pController->Initialized) {
// disable interrupts
InterruptDisable(pController->SysIntr);
// clean up controller IST
if (NULL != pController->hControllerInterruptThread) {
// wake up the IST
SetEvent(pController->hControllerInterruptEvent);
// wait for the thread to exit
WaitForSingleObject(pController->hControllerInterruptThread, INFINITE);
CloseHandle(pController->hControllerInterruptThread);
pController->hControllerInterruptThread = NULL;
}
// free controller interrupt event
if (NULL != pController->hControllerInterruptEvent) {
CloseHandle(pController->hControllerInterruptEvent);
pController->hControllerInterruptEvent = NULL;
}
// close GPIO handle
CloseHandle(pController->hGPIO);
// delete the critical sections
DeleteCriticalSection(&(pController->CriticalSection));
SDIOPlatDeinit(pController);
// deinitialize each slot
for (i=0;i<SDIOPlatNumSlots();i++) {
SDIODeinitializeSlot(&pController->Slots[i]);
}
}
return SD_API_STATUS_SUCCESS;
}
///////////////////////////////////////////////////////////////////////////////
// SDIOBusRequestHandler - bus request handler
// Input: pHostContext - host controller context
// Slot - slot the request is going on
// pRequest - the request
// Output:
// Return: SD_API_STATUS
// Notes: The request passed in is marked as uncancelable, this function
// has the option of making the outstanding request cancelable
// returns status pending if request submitted successfully
///////////////////////////////////////////////////////////////////////////////
SD_API_STATUS SDIOBusRequestHandler(PSDCARD_HC_CONTEXT pHCContext, DWORD Slot, PSD_BUS_REQUEST pRequest) {
PSDIO_HW_CONTEXT pController; // the controller
PSDIO_SLOT pSlot; // the slot
ULONG commandRegister; // SD_CMD register control value
ULONG blkSizeRegister; // SD_BLKSIZE register value
BOOL IOAbort = FALSE; // request is an IO Abort
static BOOL lastCmd53 = FALSE;
ULONG tmp;
// check slot number is in range
if (Slot >= (DWORD)SDIOPlatNumSlots()) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDIOSDSendHandler - Slot %d outside valid range 0-%d\n"),
Slot,
SDIOPlatNumSlots()));
return SD_API_STATUS_INVALID_PARAMETER;
}
DEBUGMSG(SDIO_SEND_ZONE,(TEXT("SDIOBusRequestHandler: Sending CMD%d (%d blocks) Size %d Arg=%08X Read=%d\r\n"),pRequest->CommandCode,pRequest->NumBlocks,pRequest->BlockSize,pRequest->CommandArgument,TRANSFER_IS_READ(pRequest)));
// get our extension
pController = GetExtensionFromHCDContext(PSDIO_HW_CONTEXT, pHCContext);
// get pointer to slot context
pSlot = &pController->Slots[Slot];
pSlot->pCurrentRequest = pRequest;
// set block/byte count to zero
pRequest->HCParam = (DWORD)&HCParams;
HCParams.BytesCopied = 0;
HCParams.BlocksCopied = 0;
HCParams.BuffersOutstanding = 0;
// initialize command register with command code
commandRegister = SD_CMD_CI_N(pRequest->CommandCode);
// set GO bit
commandRegister |= SD_CMD_GO;
// setup for response type
switch (pRequest->CommandResponse.ResponseType) {
case NoResponse: commandRegister |= SD_CMD_RT_NONE; break;
case ResponseR1: commandRegister |= SD_CMD_RT_R1; break;
case ResponseR1b: commandRegister |= SD_CMD_RT_R1b; break;
case ResponseR2: commandRegister |= SD_CMD_RT_R2; break;
case ResponseR3: commandRegister |= SD_CMD_RT_R3; break;
case ResponseR4: commandRegister |= SD_CMD_RT_R4; break;
case ResponseR5: commandRegister |= SD_CMD_RT_R5; break;
case ResponseR6: commandRegister |= SD_CMD_RT_R6; break;
default: return SD_API_STATUS_INVALID_PARAMETER;
}
// set the command type field of the command register
if (TRANSFER_HAS_DATA_PHASE(pRequest)) {
// check for various flavours of IO_RW_EXTENDED
if (SD_CMD_IO_RW_EXTENDED == pRequest->CommandCode) {
// are we in block mode ?
if (IO_RW_EXTENDED_BLOCK_MODE(pRequest->CommandArgument)) {
// is the block count infinite ?
if (0 == IO_RW_EXTENDED_COUNT(pRequest->CommandArgument)) {
if (TRANSFER_IS_READ(pRequest)) {
commandRegister |= SD_CMD_CT_MBR;
} else {
commandRegister |= SD_CMD_CT_MBW;
}
} else {
if (TRANSFER_IS_READ(pRequest)) {
commandRegister |= SD_CMD_CT_MBIOR;
} else {
commandRegister |= SD_CMD_CT_MBIOW;
}
}
} else {
if (TRANSFER_IS_READ(pRequest)) {
commandRegister |= SD_CMD_CT_SBR;
} else {
commandRegister |= SD_CMD_CT_SBW;
}
}
} else {
if (TRANSFER_IS_READ(pRequest)) {
if (SD_CMD_READ_MULTIPLE_BLOCK == pRequest->CommandCode) {
commandRegister |= SD_CMD_CT_MBR;
} else {
commandRegister |= SD_CMD_CT_SBR;
}
} else {
if (SD_CMD_WRITE_MULTIPLE_BLOCK == pRequest->CommandCode) {
commandRegister |= SD_CMD_CT_MBW;
} else {
commandRegister |= SD_CMD_CT_SBW;
}
}
}
// check for Stop Transmission command
} else if (SD_CMD_STOP_TRANSMISSION == pRequest->CommandCode) {
// set for CMD12 stop transmission
commandRegister |= SD_CMD_CT_TERM;
// check for an IO Abort
} else if ((SD_CMD_IO_RW_DIRECT == pRequest->CommandCode) &&
(SD_IO_REG_IO_ABORT == IO_RW_DIRECT_ADDR_ARG(pRequest->CommandArgument))) {
commandRegister |= SD_CMD_CT_TERMIO;
IOAbort = TRUE;
}
if (!pSlot->CardInitialised) {
// Send at least 80 clocks to the card before 1st command is sent
Sleep(2);
pSlot->CardInitialised = TRUE;
}
// wait for data busy bit to be clear, unless this
// is a STOP TRANSMISSION or IO ABORT
if (SD_CMD_STOP_TRANSMISSION != pRequest->CommandCode && !IOAbort) {
// if the previous command is command 53 and the data busy bit is on,
// there is a chance that the clock may be frozen. Set DF to 1 to get
// the clock back.
if (lastCmd53 && (READ_REGISTER_ULONG((PULONG)&pSlot->pSD->status) & SD_STATUS_DB )) {
tmp = READ_REGISTER_ULONG((PULONG)&pSlot->pSD->config2);
tmp |= SD_CONFIG2_DF;
WRITE_REGISTER_ULONG((PULONG)&pSlot->pSD->config2, tmp);
}
while( READ_REGISTER_ULONG((PULONG)&pSlot->pSD->status) & SD_STATUS_DB) {
; // do nothing
}
}
// handle setting for data transfers
if (TRANSFER_HAS_DATA_PHASE(pRequest)) {
// Ensure the block count & block size are both within the range.
if (pRequest->NumBlocks > SD_MAX_BLOCK_COUNT ||
pRequest->BlockSize > SD_MAX_BLOCK_SIZE) {
return SD_API_STATUS_INVALID_PARAMETER;
}
// Set block size and count
blkSizeRegister = SD_BLKSIZE_BC_N(pRequest->NumBlocks); // Macro does -1 for us
blkSizeRegister |= SD_BLKSIZE_BS_N(pRequest->BlockSize); // Macro does -1 for us
WRITE_REGISTER_ULONG((PULONG)&pSlot->pSD->blksize, blkSizeRegister);
// enable clock freezing
tmp = READ_REGISTER_ULONG((PULONG)&pSlot->pSD->config2);
tmp &= ~SD_CONFIG2_DF;
tmp |= SD_CONFIG2_FF;
WRITE_REGISTER_ULONG((PULONG)&pSlot->pSD->config2, tmp);
}
// work out if we want to fall back to PIO rather than DMA
// right now we can only handle DMA for transfer that are a multiple
// of four bytes
if (pSlot->UsingDma) {
if ( TRANSFER_HAS_DATA_PHASE(pRequest) && (pRequest->BlockSize & 0x3)) {
pSlot->UsingDmaThisCmd = FALSE;
} else {
pSlot->UsingDmaThisCmd = TRUE;
}
} else {
pSlot->UsingDmaThisCmd = FALSE;
}
#ifdef USE_DMA
// handle data phase transfer, we actually start the DMA
// transfers in HandleResponseDone
if (pSlot->UsingDmaThisCmd && TRANSFER_HAS_DATA_PHASE(pRequest)) {
if (TRANSFER_IS_READ(pRequest)) {
PULONG pDmaBuffer;
ULONG bufferSize;
bufferSize = min((pRequest->NumBlocks*pRequest->BlockSize),pSlot->DmaBufferSize);
// enable both buffers
HalStopDMA(pSlot->RxDmaChannel);
pDmaBuffer = HalGetNextDMABuffer(pSlot->RxDmaChannel);
HalActivateDMABuffer(pSlot->RxDmaChannel,pDmaBuffer,bufferSize);
pDmaBuffer = HalGetNextDMABuffer(pSlot->RxDmaChannel);
HalActivateDMABuffer(pSlot->RxDmaChannel,pDmaBuffer,bufferSize);
} else if (TRANSFER_IS_WRITE(pRequest)) {
PULONG pDmaBuffer;
ULONG copySize;
HalStopDMA(pSlot->TxDmaChannel);
// fill next buffer
pDmaBuffer = HalGetNextDMABuffer(pSlot->TxDmaChannel);
copySize = CopyToDmaBuffer(pRequest,pDmaBuffer);
HalActivateDMABuffer(pSlot->TxDmaChannel,pDmaBuffer,copySize);
// fill other buffer if more than 1 block to write
if (pRequest->NumBlocks > ((PHC_PARAMS)pRequest->HCParam)->BlocksCopied) {
pDmaBuffer = HalGetNextDMABuffer(pSlot->TxDmaChannel);
copySize = CopyToDmaBuffer(pRequest,pDmaBuffer);
HalActivateDMABuffer(pSlot->TxDmaChannel,pDmaBuffer,copySize);
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -