?? sdio.c
字號:
&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()) {
DbgPrintZo(SDCARD_ZONE_ERROR, (TEXT("SDIOSDSendHandler - Slot %d outside valid range 0-%d\n"),
Slot,
SDIOPlatNumSlots()));
return SD_API_STATUS_INVALID_PARAMETER;
}
DbgPrintZo(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 = 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);
blkSizeRegister |= SD_BLKSIZE_BS_N(pRequest->BlockSize-1);
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
if (pSlot->UsingDmaThisCmd && TRANSFER_HAS_DATA_PHASE(pRequest)) {
if (TRANSFER_IS_READ(pRequest)) {
PULONG pDmaBuffer;
// enable both buffers
// IMR, is this necessary ?
HalStopDMA(pSlot->RxDmaChannel);
pDmaBuffer = HalGetNextDMABuffer(pSlot->RxDmaChannel);
HalActivateDMABuffer(pSlot->RxDmaChannel,pDmaBuffer,pRequest->BlockSize);
pDmaBuffer = HalGetNextDMABuffer(pSlot->RxDmaChannel);
HalActivateDMABuffer(pSlot->RxDmaChannel,pDmaBuffer,pRequest->BlockSize);
HalStartDMA(pSlot->RxDmaChannel);
} else if (TRANSFER_IS_WRITE(pRequest)) {
PULONG pDmaBuffer;
HalStopDMA(pSlot->TxDmaChannel);
// fill next buffer
pDmaBuffer = HalGetNextDMABuffer(pSlot->TxDmaChannel);
CopyToDmaBuffer(pRequest,pDmaBuffer);
HalActivateDMABuffer(pSlot->TxDmaChannel,pDmaBuffer,pRequest->BlockSize);
// fill other buffer if more than 1 block to write
if (pRequest->NumBlocks > 1) {
pDmaBuffer = HalGetNextDMABuffer(pSlot->TxDmaChannel);
CopyToDmaBuffer(pRequest,pDmaBuffer);
HalActivateDMABuffer(pSlot->TxDmaChannel,pDmaBuffer,pRequest->BlockSize);
}
HalStartDMA(pSlot->TxDmaChannel);
}
}
#endif //#ifdef USE_DMA
// turn on the clock
// SDIOClockOn(pSlot);
SD_INTERRUPTS_CLEAR(pSlot,SD_Int_CRC_Errors |
SD_Int_Response_Timeout |
SD_Int_Response_Done );
// enable response done and response timeout interrupts
SD_INTERRUPTS_ENABLE(pSlot, SD_Int_Response_Done | SD_Int_Response_Timeout );
// for Stop Transmission and IO Abort disable clock freezing to
// get the state machine running again to send command
if ((SD_CMD_STOP_TRANSMISSION == pRequest->CommandCode) ||
(SD_CMD_IO_RW_DIRECT == pRequest->CommandCode && SD_IO_REG_IO_ABORT == IO_RW_DIRECT_ADDR_ARG(pRequest->CommandArgument))) {
tmp = READ_REGISTER_ULONG((PULONG)&pSlot->pSD->config2);
tmp |= SD_CONFIG2_DF;
WRITE_REGISTER_ULONG((PULONG)&pSlot->pSD->config2, tmp);
}
// remember whether the last command is CMD53 or not.
lastCmd53 = ( SD_CMD_IO_RW_EXTENDED == pRequest->CommandCode );
// write the 32 bit command argument
WRITE_REGISTER_ULONG((PULONG)&pSlot->pSD->cmdarg, pRequest->CommandArgument );
// write the completed command register - this will issue the command
WRITE_REGISTER_ULONG((PULONG)&pSlot->pSD->cmd, commandRegister );
DbgPrintZo(SDIO_SEND_ZONE,(TEXT("Send Command - CMD register = 0x%08X\r\n"),commandRegister));
return SD_API_STATUS_PENDING;
}
///////////////////////////////////////////////////////////////////////////////
// SDIOSDCancelIoHandler - io cancel handler
// Input: pHostContext - host controller context
// Slot - slot the request is going on
// pRequest - the request to be cancelled
// Output:
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -