📄 sdio.c
字号:
DbgPrintZo(SDIO_RESPONSE_ZONE, (TEXT("HandleResponseDone SD_RESP0: 0x%08X \n"),response[0]));
DbgPrintZo(SDIO_RESPONSE_ZONE, (TEXT("HandleResponseDone SD_RESP1: 0x%08X \n"),response[1]));
DbgPrintZo(SDIO_RESPONSE_ZONE, (TEXT("HandleResponseDone SD_RESP2: 0x%08X \n"),response[2]));
DbgPrintZo(SDIO_RESPONSE_ZONE, (TEXT("HandleResponseDone SD_RESP3: 0x%08X \n"),response[3]));
if (NoResponse != pRequest->CommandResponse.ResponseType) {
// Copy response over to request structure
PUCHAR pResponseBuffer = &(pRequest->CommandResponse.ResponseBuffer[1]);
int ii;
for (ii=0; ii<4; ii++) {
*pResponseBuffer++ = (UCHAR)(response[ii]);
*pResponseBuffer++ = (UCHAR)(response[ii] >> 8);
*pResponseBuffer++ = (UCHAR)(response[ii] >> 16);
*pResponseBuffer++ = (UCHAR)(response[ii] >> 24);
}
}
// check for command/response only
if (SD_COMMAND == pRequest->TransferClass) {
// check for and handle errors
if (FALSE==HandleTransferErrors(pSlot,pRequest,SD_Int_Response_CRC_Error)) {
// no errors, complete request with success
CompleteRequest(pSlot, SD_API_STATUS_SUCCESS);
}
} else {
#ifdef USE_DMA
if (!pSlot->UsingDmaThisCmd) {
#endif // #ifdef USE_DMA
// handle data phase transfer
// set blocks transferred to 0
pRequest->HCParam = 0;
if (TRANSFER_IS_READ(pRequest)) {
// Enable buffer read enable interrupt
SD_INTERRUPTS_ENABLE(pSlot, SD_Int_Rx_FIFO_Not_Empty |
SD_Int_Data_Timeout);
} else {
// Enable buffer write enable interrupt
SD_INTERRUPTS_ENABLE(pSlot, SD_Int_Tx_Empty |
SD_Int_Data_Timeout);
}
#ifdef USE_DMA
}
#endif // #ifdef USE_DMA
}
}
///////////////////////////////////////////////////////////////////////////////
// HandleRxFifoNotEmpty - handle Rx FIFO not empty interrupt
// Input: pSlot - slot context
// Output:
// Return:
// Notes: Completes the following requests:
// Requests with a CRC/timeout error in the read data phase
///////////////////////////////////////////////////////////////////////////////
VOID HandleRxFifoNotEmpty(PSDIO_SLOT pSlot)
{
PSD_BUS_REQUEST pRequest; // current request
ULONG regValue; // reg value
// get the current request
pRequest = pSlot->pCurrentRequest;
if (NULL==pRequest) {
return;
}
if (pRequest->HCParam == (pRequest->BlockSize*pRequest->NumBlocks)) {
return;
}
// we are touching the block buffer, we must set the process permissions
SD_SET_PROC_PERMISSIONS_FROM_REQUEST(pRequest) {
// Get byte from fifo
regValue = READ_REGISTER_ULONG((PULONG)&pSlot->pSD->rxport);
pRequest->pBlockBuffer[pRequest->HCParam] = (UCHAR)(regValue&0xFF);
pRequest->HCParam++;
} SD_RESTORE_PROC_PERMISSIONS();
if (pRequest->HCParam == (pRequest->BlockSize*pRequest->NumBlocks)) {
SD_INTERRUPTS_DISABLE(pSlot,SD_Int_Rx_FIFO_Not_Empty);
DbgPrintZo(SDIO_INTERRUPT_ZONE,(TEXT("SDIO: RxFifoNotEmpty completing request, HCParam=%d\r\n"),pRequest->HCParam));
// check for and handle errors
if (FALSE==HandleTransferErrors(pSlot,pRequest,SD_Int_Read_CRC_Error)) {
// no errors, complete request with success
CompleteRequest(pSlot, SD_API_STATUS_SUCCESS);
}
}
}
///////////////////////////////////////////////////////////////////////////////
// HandleTxEmpty - handle Tx empty interrupt
// Input: pSlot - slot context
// Output:
// Return: TRUE if the request has been completed
// Notes: Completes the following requests:
// Requests with a CRC/timeout error in the read data phase
///////////////////////////////////////////////////////////////////////////////
VOID HandleTxEmpty(PSDIO_SLOT pSlot)
{
PSD_BUS_REQUEST pRequest; // current request
ULONG dataValue; // reg value
// get the current request
pRequest = pSlot->pCurrentRequest;
// check the request hasn't already been completed
if ((NULL==pRequest) || (pRequest->HCParam == (pRequest->BlockSize*pRequest->NumBlocks))) {
SD_INTERRUPTS_DISABLE(pSlot,SD_Int_Tx_Empty);
return;
}
// we are touching the block buffer, we must set the process permissions
SD_SET_PROC_PERMISSIONS_FROM_REQUEST(pRequest) {
// Get byte from buffer
dataValue = pRequest->pBlockBuffer[pRequest->HCParam];
WRITE_REGISTER_ULONG((PULONG)&pSlot->pSD->txport,dataValue);
pRequest->HCParam++;
} SD_RESTORE_PROC_PERMISSIONS();
if (pRequest->HCParam == (pRequest->BlockSize*pRequest->NumBlocks)) {
SD_INTERRUPTS_DISABLE(pSlot,SD_Int_Tx_Empty);
// check for and handle errors
if (FALSE==HandleTransferErrors(pSlot,pRequest,SD_Int_Write_CRC_Error)) {
// no errors, complete request with success
CompleteRequest(pSlot, SD_API_STATUS_SUCCESS);
}
}
}
///////////////////////////////////////////////////////////////////////////////
// GetInterrupts - get current pending interrupts
// Input: pSlot - slot context
// Output: pInterrupts - active, unmasked, controller interrupts
// Return: TRUE if there is an active unmasked interrupt
// Notes:
///////////////////////////////////////////////////////////////////////////////
BOOL GetInterrupts(PSDIO_SLOT pSlot,
PULONG pInterrupts)
{
ULONG interrupts; // controller interrupts
// read interrupts from hardware
interrupts = READ_REGISTER_ULONG((PULONG)&pSlot->pSD->status);
// the hardware masks interrupts sources from causing an interrupt,
// but not from showing up in the status register. Mask them here.
interrupts &= pSlot->InterruptMask;
*pInterrupts = interrupts;
// Return TRUE if any unmasked interrupts are active
return (0 != interrupts);
}
///////////////////////////////////////////////////////////////////////////////
// SDIOInsertionIstThread - IST thread for driver
// Input: pSlot - slot context
// Output:
// Notes:
///////////////////////////////////////////////////////////////////////////////
DWORD SDIOInsertionIstThread(PSDIO_SLOT pSlot)
{
DWORD waitStatus; // wait status
DWORD initRate = 200000;
int debounceCount;
BOOL cardInserted;
if (!CeSetThreadPriority(GetCurrentThread(), pSlot->InsertionIstThreadPriority)) {
DbgPrintZo(SDCARD_ZONE_WARN, (TEXT("SDIOInsertionIstThread[%d]: warning, failed to set CEThreadPriority \n"),pSlot->SlotNumber));
}
while(1) {
waitStatus = WaitForSingleObject(pSlot->hInsertionInterruptEvent, INFINITE);
if (WAIT_OBJECT_0 != waitStatus) {
DbgPrintZo(SDCARD_ZONE_WARN, (TEXT("SDIOInsertionIstThread[%d]: Wait Failed! 0x%08X \n"),pSlot->SlotNumber, waitStatus));
// bail out
return 0;
}
if (pSlot->pController->DriverShutdown) {
DbgPrintZo(1, (TEXT("SDIOInsertionIstThread[%d]: Thread Exiting\n"),pSlot->SlotNumber));
return 0;
}
// check slot on startup for inserted cards
if (pSlot->CheckSlotOnStartUp) {
DbgPrintZo(SDIO_INTERRUPT_ZONE,(TEXT("SDIOInsertionIstThread[%d]: Removing device after powerdown\r\n"),pSlot->SlotNumber));
// this case is hit when we suspend and resume while there is a
// card in the slot, because we remove power we have
// to indicate a device removal first
RemoveDevice(pSlot);
// Reset the slot
ResetSlot(pSlot, FALSE);
#ifdef DEBUG
// Dump the state of the slot
DumpSlot(pSlot);
#endif
// Now check to see if the card is still present, if so
// handle as per device insertion
if (SDIOPlatCardInserted(pSlot->pController,pSlot->SlotNumber)) {
pSlot->CardPresent = TRUE;
pSlot->CardInitialised = FALSE;
// indicate device arrival
SDHCDIndicateSlotStateChange(pSlot->pController->pHCContext,
pSlot->SlotNumber,
DeviceInserted );
} else {
pSlot->CardPresent = FALSE;
}
pSlot->CheckSlotOnStartUp = FALSE;
InterruptDone(pSlot->InsertionSysIntr);
continue;
}
DbgPrintZo(SDIO_INTERRUPT_ZONE, (TEXT("SDIOInsertionIstThread[%d]: interrupt!\n"),pSlot->SlotNumber));
// start debounce logic
debounceCount = 0;
cardInserted = FALSE;
// stay in this loop until the insertion state has been the same for
// ten consecutive debounce sampling intervals
while(debounceCount < SDIO_DEBOUNCE_COUNT) {
if (SDIOPlatCardInserted(pSlot->pController,pSlot->SlotNumber)) {
if (cardInserted) {
debounceCount++;
} else {
cardInserted = TRUE;
debounceCount = 0;
}
} else {
if (cardInserted) {
cardInserted = FALSE;
debounceCount = 0;
} else {
debounceCount++;
}
}
Sleep(SDIO_DEBOUNCE_INTERVAL);
}
if (cardInserted && !pSlot->CardPresent) {
// set clock to 100 kHz for card initialisation
SDIOSetRate(pSlot, &initRate);
pSlot->CardPresent = TRUE;
pSlot->CardInitialised = FALSE;
DbgPrintZo(SDIO_INTERRUPT_ZONE,(TEXT("SDIOInsertionIstThread[%d]: Card Insertion Interrupt\r\n"),pSlot->SlotNumber));
// indicate device arrival
SDHCDIndicateSlotStateChange(pSlot->pController->pHCContext,
pSlot->SlotNumber,
DeviceInserted );
} else if (!cardInserted && pSlot->CardPresent) {
DbgPrintZo(SDIO_INTERRUPT_ZONE,(TEXT("SDIOInsertionIstThread[%d]: Card Removal Interrupt\r\n"),pSlot->SlotNumber));
// remove device
RemoveDevice(pSlot);
pSlot->CardPresent = FALSE;
}
InterruptDone(pSlot->InsertionSysIntr);
}
}
///////////////////////////////////////////////////////////////////////////////
// SDIOControllerIstThread - IST thread for driver
// Input: pController - controller context
// Output:
// Notes:
///////////////////////////////////////////////////////////////////////////////
DWORD SDIOControllerIstThread(PSDIO_HW_CONTEXT pController)
{
DWORD waitStatus; // wait status
ULONG interrupts; // current interrupts
UCHAR slot; // slot number
PSDIO_SLOT pSlot; // the slot
if (!CeSetThreadPriority(GetCurrentThread(), pController->ControllerIstThreadPriority)) {
DbgPrintZo(SDCARD_ZONE_WARN, (TEXT("SDIOControllerIstThread: warning, failed to set CEThreadPriority \n")));
}
while(1) {
waitStatus = WaitForSingleObject(pController->hControllerInterruptEvent, INFINITE);
if (WAIT_OBJECT_0 != waitStatus) {
DbgPrintZo(SDCARD_ZONE_WARN, (TEXT("SDIOControllerIstThread: Wait Failed! 0x%08X \n"), waitStatus));
// bail out
return 0;
}
if (pController->DriverShutdown) {
// shut the thread down
DbgPrintZo(1, (TEXT("SDIOControllerIstThread: Thread Exiting\n")));
return 0;
}
// check each slot in turn
for (slot=0; slot<SDIOPlatNumSlots(); slot++) {
pSlot = &pController->Slots[slot];
// loop until all interrupts are serviced
while (GetInterrupts(pSlot,&interrupts)) {
DbgPrintZo(SDIO_INTERRUPT_ZONE,(TEXT("Int: %08X\r\n"),interrupts));
if (interrupts & SD_Int_Response_Timeout) {
// clear the interrupt
SD_INTERRUPTS_CLEAR(pSlot, SD_Int_Response_Timeout);
DbgPrintZo(SDCARD_ZONE_ERROR,(TEXT("SDIO - Response Timeout Interrupt\r\n")));
HandleResponseTimeout(pSlot);
}
if (interrupts & SD_Int_Data_Timeout) {
// clear the interrupt
SD_INTERRUPTS_CLEAR(pSlot, SD_Int_Data_Timeout);
DbgPrintZo(SDCARD_ZONE_ERROR,(TEXT("SDIO - Data Transfer Timeout Interrupt\r\n")));
HandleDataTimeout(pSlot);
}
if (interrupts & SD_Int_Response_Done) {
// clear the interrupt
SD_INTERRUPTS_CLEAR(pSlot, SD_Int_Response_Done);
DbgPrintZo(SDIO_INTERRUPT_ZONE,(TEXT("SDIO - Response Done Interrupt\r\n")));
HandleRespons
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -