📄 sdcontrol.c
字号:
if (NoResponse != pRequest->CommandResponse.ResponseType) {
// read in the response words from the response fifo.
for (ii = startingOffset; ii >= 0; ii--) {
// read from the fifo
responseBuffer[ii] = (USHORT)(pController->pSDMMCRegisters->RES);
}
if (ResponseR2 == pRequest->CommandResponse.ResponseType) {
// since the response Fifo is only 16 bytes, the R2 response which is normally 17 bytes
// gets crammed into 16 bits, this offset the whole R2 response by 1 byte so when
// copy the data to the response buffer, bump over the place holder for the CRC
memcpy(&pRequest->CommandResponse.ResponseBuffer[1],
responseBuffer,
(sizeof(USHORT)) * (startingOffset + 1));
} else {
// all other responses are nicely aligned to 6 bytes, the CRC value in the last
// dword is not set, but we copy it anyways to the response buffer
memcpy(pRequest->CommandResponse.ResponseBuffer,
responseBuffer,
(sizeof(USHORT)) * (startingOffset + 1));
}
}
// check for command/response only
if (SD_COMMAND == pRequest->TransferClass) {
// check to see if this request was a response with busy
if (ResponseR1b == pRequest->CommandResponse.ResponseType) {
while( ( !( statRegister & MMC_STAT_PROGRAM_DONE ) ) &&
( !( pController->DriverShutdown ) ) &&
IsCardPresent() )
{
statRegister = pController->pSDMMCRegisters->STAT;
}
}
if( !( pController->fClockAlwaysOn ||
( pController->fClockOnIfInterruptsEnabled && pController->fSDIOEnabled ) ) )
{
// complete the current request here, there's no data phase
// turn off the clock
SDClockOff(pController);
}
SetCurrentState(pController, CommandComplete);
DbgPrintZo(SDH_SDBUS_INTERACTION_ZONE, (TEXT("HandleEndCommandInterrupt reports Bus Request Completed\n")));
SDHCDIndicateBusRequestComplete(pController->pHCContext,
pRequest ,
SD_API_STATUS_SUCCESS);
} else {
if (TRANSFER_IS_READ(pRequest)){
DbgPrintZo(SDH_SDBUS_INTERACTION_ZONE, (TEXT("HandleEndCommandInterrupt starting READ TRANSFER of %d blocks of %d bytes\n"), pRequest->NumBlocks, pRequest->BlockSize ));
// turn on RX Fifo interrupts
RX_FIFO_INTERRUPT_ON(pController);
SetCurrentState(pController, ReadDataTransfer);
// turn on the transfer done interrupt to check for timeout on reads
// the receive handler will turn this off after getting the first byte
TRANSFER_DONE_INTERRUPT_ON(pController);
} else {
DbgPrintZo(SDH_SDBUS_INTERACTION_ZONE, (TEXT("HandleEndCommandInterrupt starting WRITE TRANSFER of %d blocks of %d bytes\n"), pRequest->NumBlocks, pRequest->BlockSize ));
DbgPrintZo(SDH_SDBUS_INTERACTION_ZONE, (TEXT("Bytes wrtn: [%S]\n"), HexDisplay( pRequest->pBlockBuffer, TRANSFER_SIZE(pRequest) )) );
SetCurrentState(pController, WriteDataTransfer);
// turn on Fifo interrupts
TX_FIFO_INTERRUPT_ON(pController);
// turn on transfer interrupts
TRANSFER_DONE_INTERRUPT_ON(pController);
SDLoadXmitFifo(pController, pRequest);
}
}
}
///////////////////////////////////////////////////////////////////////////////
// GetMMCInterrupts - Get MMC interrupts
// Input: pHCDevice - the controller
// Output:
// Return: bit mask of the interrupts
// Notes:
///////////////////////////////////////////////////////////////////////////////
DWORD GetMMCInterrupts(PSDH_HARDWARE_CONTEXT pHCDevice)
{
DWORD intr;
DWORD interrupts; // current interrupts
DWORD interruptMask; // interrupt mask
DWORD stat;
// get interrupts
intr = pHCDevice->pSDMMCRegisters->IREG & MMC_IREG_INTERRUPTS;
// get the interrupt masks so we know which ones we don't care about
// the handlers will turn off (mask) interrupts
interruptMask = (~(pHCDevice->pSDMMCRegisters->IMASK)) & MMC_IREG_INTERRUPTS;
// mask it
interrupts = intr & interruptMask;
stat = pHCDevice->pSDMMCRegisters->STAT;
if( pHCDevice->fSDIOEnabled )
{
DbgPrintZo(SDH_INTERRUPT_ZONE,
(TEXT("S=%04X I=%04X M=%04X R=%04X\n"),
stat, intr, interruptMask, interrupts));
}
return interrupts;
}
///////////////////////////////////////////////////////////////////////////////
// SDControllerIstThread - IST thread for MMC Controller driver
// Input: pHCDevice - the controller instance
// Output:
// Return: Thread exit code
// Notes:
///////////////////////////////////////////////////////////////////////////////
DWORD SDControllerIstThread(PSDH_HARDWARE_CONTEXT pHCDevice)
{
DWORD waitStatus; // wait status
DWORD interrupts; // current interrupts
if (!CeSetThreadPriority(GetCurrentThread(),
pHCDevice->ControllerIstThreadPriority)) {
DbgPrintZo(SDCARD_ZONE_WARN,
(TEXT("SDControllerIstThread: warning, failed to set CEThreadPriority \n")));
}
while(1) {
waitStatus = WaitForSingleObject(pHCDevice->hControllerInterruptEvent, INFINITE);
if (WAIT_OBJECT_0 != waitStatus) {
DbgPrintZo(SDCARD_ZONE_WARN,
(TEXT("SDControllerIstThread: Wait Failed! 0x%08X \n"), waitStatus));
// bail out
return 0;
}
if (pHCDevice->DriverShutdown) {
DbgPrintZo(1, (TEXT("SDControllerIstThread: Thread Exiting\n")));
return 0;
}
DbgPrintZo(SDH_INTERRUPT_ZONE, (TEXT("SDIst+++++++++++++ \n")));
// loop until all interrupts are serviced
while (interrupts = GetMMCInterrupts(pHCDevice)) {
DbgPrintZo(SDH_INTERRUPT_ZONE,
(TEXT("SDControllerIstThread: Controller Interrupt: 0x%08X \n"),interrupts));
if (interrupts & MMC_IREG_CLOCK_IS_OFF) {
// no one should be turning this on
DEBUG_ASSERT(FALSE);
// mask the interrupt
CLOCK_OFF_INTERRUPT_OFF(pHCDevice);
}
if (interrupts & MMC_IREG_END_CMD) {
DbgPrintZo(SDH_INTERRUPT_ZONE,
(TEXT("SDControllerIstThread: MMC_IREG_END_CMD \n")));
HandleEndCommandInterrupt(pHCDevice);
}
if (interrupts & MMC_IREG_STOP_CMD) {
DbgPrintZo(SDH_INTERRUPT_ZONE,
(TEXT("SDControllerIstThread: MMC_IREG_STOP_CMD \n")));
DEBUG_ASSERT(FALSE);
}
if (interrupts & MMC_IREG_RXFIFO_REQ ) {
DbgPrintZo(SDH_INTERRUPT_ZONE,
(TEXT("SDControllerIstThread: MMC_IREG_RXFIFO_REQ \n")));
HandleReceiveInterrupt(pHCDevice);
}
if (interrupts & MMC_IREG_TXFIFO_REQ) {
DbgPrintZo(SDH_INTERRUPT_ZONE,
(TEXT("SDControllerIstThread: MMC_IREG_TXFIFO_REQ \n")));
HandleXmitInterrupt(pHCDevice);
}
if (interrupts & MMC_IREG_PROG_DONE) {
DbgPrintZo(SDH_INTERRUPT_ZONE,
(TEXT("SDControllerIstThread: MMC_IREG_PROG_DONE \n")));
HandleProgramDone(pHCDevice);
}
// DATA transfer done should be checked last so that the
// HandleReceive and HandleTransmit
// have a chance to finish copying from the fifos
if (interrupts & MMC_IREG_DATA_TRAN_DONE) {
DbgPrintZo(SDH_INTERRUPT_ZONE,
(TEXT("SDControllerIstThread: MMC_IREG_DATA_TRAN_DONE \n")));
HandleTransferDone(pHCDevice);
}
}
#if 0
if( pHCDevice->CurrentState == ReadDataTransfer )
{
if (!CLOCK_IS_ON(pHCDevice))
{
//DbgPrintZo(SDCARD_ZONE_WARN, (TEXT("CLOCK IS OFF during transfer!\n")));
SDClockOn(pHCDevice);
}
}
#endif
DbgPrintZo(SDH_INTERRUPT_ZONE, (TEXT("SDIst-------------- \n")));
InterruptDone(pHCDevice->dwSysintrSDMMC);
}
}
void ProcessCardInsertion( void *pContext )
{
DWORD initializationClock = SD_DEFAULT_CARD_ID_CLOCK_RATE;
PSDH_HARDWARE_CONTEXT pHCDevice = (PSDH_HARDWARE_CONTEXT)pContext;
if (!pHCDevice->DevicePresent) {
// if we have stable insertion and there wasn't a device mark it
DbgPrintZo(SDH_INTERRUPT_ZONE,
(TEXT("CardDetectIstThread: Device Fully Inserted ! \n")));
// mark that the card is in the slot
pHCDevice->DevicePresent = TRUE;
// flag that this is the first command sent
pHCDevice->SendInitClocks = TRUE;
// turn the Multimedia Card power on
MMCPowerControl( TRUE );
// reset the clock to the ID rate
// shut off clock first
SDClockOff(pHCDevice);
// set rate
SDSetRate(pHCDevice, &initializationClock);
// give the card some time for initialization
Sleep(100);
// indicate the slot change
SDHCDIndicateSlotStateChange(pHCDevice->pHCContext,
0,
DeviceInserted);
}
}
void ProcessCardRemoval( void *pContext )
{
PSDH_HARDWARE_CONTEXT pHCDevice = (PSDH_HARDWARE_CONTEXT)pContext;
if( pHCDevice->DevicePresent )
{
DbgPrintZo(SDH_INTERRUPT_ZONE,
(TEXT("CardDetectIstThread: Card Removal Detected! \n")));
// mark that the card has been removed
pHCDevice->DevicePresent = FALSE;
// indicate the slot change
SDHCDIndicateSlotStateChange(pHCDevice->pHCContext,
0,
DeviceEjected);
// shut off clock first
SDClockOff(pHCDevice);
// turn the Multimedia Card power on
MMCPowerControl( FALSE );
}
}
BOOL DriverShutdown(void *pContext)
{
PSDH_HARDWARE_CONTEXT pHCDevice = (PSDH_HARDWARE_CONTEXT)pContext;
return pHCDevice->DriverShutdown;
}
#ifdef DEBUG
void DumpRegisters(PSDH_HARDWARE_CONTEXT pController)
{
BOOL fQuit = TRUE;
#ifdef EXTENSIVE_DEBUGGING
fQuit = FALSE;
#endif
if( !fQuit )
{
DbgPrintZo(SDCARD_ZONE_WARN, (TEXT("SD/MMC Registers Dump Begin\r\n")));
DbgPrintZo(SDCARD_ZONE_WARN, (TEXT("STRPC =0x%08X\n"), pController->pSDMMCRegisters->STRPC));
DbgPrintZo(SDCARD_ZONE_WARN, (TEXT("STAT =0x%08X\n"), pController->pSDMMCRegisters->STAT));
DbgPrintZo(SDCARD_ZONE_WARN, (TEXT("CLKRT =0x%08X\n"), pController->pSDMMCRegisters->CLKRT));
DbgPrintZo(SDCARD_ZONE_WARN, (TEXT("SPI =0x%08X\n"), pController->pSDMMCRegisters->SPI));
DbgPrintZo(SDCARD_ZONE_WARN, (TEXT("CMDAT =0x%08X\n"), pController->pSDMMCRegisters->CMDAT));
DbgPrintZo(SDCARD_ZONE_WARN, (TEXT("RESTO =0x%08X\n"), pController->pSDMMCRegisters->RESTO));
DbgPrintZo(SDCARD_ZONE_WARN, (TEXT("RDTO =0x%08X\n"), pController->pSDMMCRegisters->RDTO));
DbgPrintZo(SDCARD_ZONE_WARN, (TEXT("BLKLE =0x%08X\n"), pController->pSDMMCRegisters->BLKLE));
DbgPrintZo(SDCARD_ZONE_WARN, (TEXT("NOB =0x%08X\n"), pController->pSDMMCRegisters->NOB));
DbgPrintZo(SDCARD_ZONE_WARN, (TEXT("PRTBU =0x%08X\n"), pController->pSDMMCRegisters->PRTBUF));
DbgPrintZo(SDCARD_ZONE_WARN, (TEXT("IMASK =0x%08X\n"), pController->pSDMMCRegisters->IMASK));
DbgPrintZo(SDCARD_ZONE_WARN, (TEXT("IREG =0x%08X\n"), pController->pSDMMCRegisters->IREG));
DbgPrintZo(SDCARD_ZONE_WARN, (TEXT("CMD =0x%08X\n"), pController->pSDMMCRegisters->CMD));
DbgPrintZo(SDCARD_ZONE_WARN, (TEXT("ARGH =0x%08X\n"), pController->pSDMMCRegisters->ARGH));
DbgPrintZo(SDCARD_ZONE_WARN, (TEXT("ARGL =0x%08X\n"), pController->pSDMMCRegisters->ARGL));
DbgPrintZo(SDCARD_ZONE_WARN, (TEXT("RES =0x%08X\n"), pController->pSDMMCRegisters->RES));
DbgPrintZo(SDCARD_ZONE_WARN, (TEXT("RXFIFO=----------\n")/*, pController->pSDMMCRegisters->RXFIFO*/));
DbgPrintZo(SDCARD_ZONE_WARN, (TEXT("TXFIFO=----------\n")/*, pController->pSDMMCRegisters->TXFIFO*/));
DbgPrintZo(SDCARD_ZONE_WARN, (TEXT("SD/MMC Registers Dump End\r\n")));
}
}
#endif
// DO NOT REMOVE --- END EXTERNALLY DEVELOPED SOURCE CODE ID --- DO NOT REMOVE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -