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

📄 sdcontrol.c

📁 老外的一个开源项目
💻 C
📖 第 1 页 / 共 5 页
字号:
            SDClockOff(pController);
        }
        DbgPrintZo(SDH_SDBUS_INTERACTION_ZONE, (TEXT("HandleTransferDone reports CRC ERROR\n")));
        SDHCDIndicateBusRequestComplete(pController->pHCContext,
                                        pRequest ,
                                        SD_API_STATUS_CRC_ERROR);
        return;
    }

    
    if (TRANSFER_IS_READ(pRequest)) {
            // why are we doing this here? If the remaining read data is less than a Fifo's worth (32)
            // we won't get the RX Fifo Read Request interrupt because the fifo won't be full.
            // also even if it is full or if this isn't the case the TRANSFER_DONE bit seems to mask it out
            // anyways this prevents the problem where there are bytes stuck in the Fifo
        maxBytes = pRequest->NumBlocks * pRequest->BlockSize;

        if (pRequest->HCParam < maxBytes) {
            DbgPrintZo(SDH_RECEIVE_ZONE, (TEXT("HandleTransferDoneInterrupt: Fifo contains remaining data, Max: %d, current count %d  \n"),
                maxBytes, pRequest->HCParam));
                // get the remaining bytes out of the FIFO
            EmptyReceiveFifo(pController, 
                             pRequest, 
                             (maxBytes - pRequest->HCParam), 
                             maxBytes);
        }

        SetCurrentState(pController, ReadDataDone);

        if( !( pController->fClockAlwaysOn || 
               ( pController->fClockOnIfInterruptsEnabled && pController->fSDIOEnabled ) ) )
        {
                // now it is safe to turn off the clock
            SDClockOff(pController);
        }

        DbgPrintZo(SDH_SDBUS_INTERACTION_ZONE, (TEXT("Bytes read: [%S]\n"), HexDisplay( pRequest->pBlockBuffer, TRANSFER_SIZE(pRequest) ) ) );
    }


    if (TRANSFER_IS_WRITE(pRequest)) {

        if (!IS_PROGRAM_DONE(pController)) {
            SetCurrentState(pController, ProgramWait);
            
                // turn on programming done interrupt
            PROGRAM_DONE_INTERRUPT_ON(pController); 
            //Sleep(500);

                // check to see if programming is finished
            if (!IS_PROGRAM_DONE(pController)) {
                DbgPrintZo(SDH_TRANSMIT_ZONE, (TEXT("HandleTransferDoneInterrupt: Programming Not Complete \n")));   
            }

            // if we wait on the programming done interrupt this could
            // go on forever because now it is up to the memory card, 
            // we may have to make this request cancelable at this point
            
            return;
        }
    } 

    DEBUG_ASSERT((pRequest->HCParam >= (pRequest->NumBlocks * pRequest->BlockSize)));
        // complete the request
    DbgPrintZo(SDH_SDBUS_INTERACTION_ZONE, (TEXT("HandleTransferDone reports Data Transfer Completed\n")));
    if (TRANSFER_IS_READ(pRequest)) {
		DbgPrintZo(SDH_SDBUS_INTERACTION_ZONE, (TEXT("Bytes read: [%S]\n"), HexDisplay( pRequest->pBlockBuffer, TRANSFER_SIZE(pRequest) ) ) );
	}

    SDHCDIndicateBusRequestComplete(pController->pHCContext,
                                    pRequest ,
                                    SD_API_STATUS_SUCCESS);
}


///////////////////////////////////////////////////////////////////////////////
//  SDLoadXmitFifo - load the transmit fifo
//  Input:  pController - the controler
//          pRequest    - the request 
//  Output: 
//  Return:  returns TRUE if the request has been fullfilled
//  Notes:  
///////////////////////////////////////////////////////////////////////////////
BOOL SDLoadXmitFifo(PSDH_HARDWARE_CONTEXT pController, PSD_BUS_REQUEST pRequest)
{
    DWORD           maxBytes;       // max bytes
    ULONG           ii = 0;         // loop variable
    ULONG           remainingBytes; // remaining bytes in the transfer
    volatile UCHAR *pMMC_TX_Fifo = (volatile UCHAR *)&(pController->pSDMMCRegisters->TXFIFO);


        // precalc
    maxBytes = pRequest->NumBlocks * pRequest->BlockSize;

    DbgPrintZo(SDH_TRANSMIT_ZONE, (TEXT("SDLoadXmitFifo: Current %d \n"),pRequest->HCParam));

        // make sure the partial full flag is cleared
    pController->pSDMMCRegisters->PRTBUF = 0;

        // according to the spec the TX Fifo Empty interrupt asserts once when the fifo is
        // empty 
    if ((maxBytes - pRequest->HCParam) >= (LONG)MMC_TXFIFO_SIZE) {
            // because the remaining bytes is greater than or equal to the fifo size,
            // the Tx Fifo better be empty according to Intel's spec!
        // DEBUG_ASSERT(TX_FIFO_EMPTY(pController)); @todo
    }

            // figure out how much to prefetch from the user
            // buffer safely
        remainingBytes = maxBytes - pRequest->HCParam;

        if (remainingBytes > MMC_TXFIFO_SIZE) {
                // fix it
            remainingBytes = MMC_TXFIFO_SIZE;
        } 

            // perform the safe copy
        SDPerformSafeCopy(pController->XmitBuffer,
                          &pRequest->pBlockBuffer[pRequest->HCParam],
                          remainingBytes);            

            // according to the spec (15.2.8.3) the TX Fifo interrupt asserts for every empty fifo
            // (32 bytes)
            // so we write a Fifo's worth, as per spec 
        for (ii = 0; ii < remainingBytes; ii++) {
            
            if( !IsCardPresent() )
            {
                DbgPrintZo(SDCARD_ZONE_ERROR, (TEXT("SDLoadXmitFifo: Card ejected!\n")));     
                break;
            }

                // transfer bytes to the fifo from the safe buffer
            *pMMC_TX_Fifo = pController->XmitBuffer[ii];

            pRequest->HCParam++;

                // check to see if we've read enough
            if (pRequest->HCParam >= maxBytes) {
                break;
            }
        }
        // check for a partial buffer
    if (ii < MMC_TXFIFO_SIZE) {
        pController->pSDMMCRegisters->PRTBUF = MMC_PRTBUF_BUFFER_PARTIAL_FULL;
    }

    DbgPrintZo(SDH_TRANSMIT_ZONE, (TEXT("SDLoadXmitFifo: New Current %d  \n"),pRequest->HCParam));
    
        // see if we are done
    if (pRequest->HCParam >= maxBytes) {
        return TRUE;
    } 

    return FALSE;
}


///////////////////////////////////////////////////////////////////////////////
//  HandleXmitInterrupt - handle the Xmit Fifo Empty interrupt
//  Input:  pController - the controler
//  Output: 
//  Return:
//  Notes:   
///////////////////////////////////////////////////////////////////////////////
VOID HandleXmitInterrupt(PSDH_HARDWARE_CONTEXT pController)
{
    PSD_BUS_REQUEST pRequest;       // current request
  
        // get the current request  
    pRequest = SDHCDGetAndLockCurrentRequest(pController->pHCContext, 0);

        // this should never happen because we mark the request as un-cancelable
    DEBUG_ASSERT(NULL != pRequest);

    if (SDLoadXmitFifo(pController, pRequest)) {
            // the request is complete  
            // turn off the Fifo Interrupts
        TX_FIFO_INTERRUPT_OFF(pController);
        SetCurrentState(pController, WriteDataTransferDone);
    }

    // now we need to wait for the controller to transmit (transfer done) and the card 
    // to complete programming (program done)
    // if the transfer is done or programming is done before we go back into the interrupt wait
    // the interrupt bit will be set and the IST loop will handle the transfer done in this same thread     

}

///////////////////////////////////////////////////////////////////////////////
//  HandleReceiveInterrupt - Handle recieve data interrupt
//  Input:  pController - the controller that is interrupting
//  Output: 
//  Return:
//  Notes:  
///////////////////////////////////////////////////////////////////////////////
VOID HandleReceiveInterrupt(PSDH_HARDWARE_CONTEXT pController)
{
    PSD_BUS_REQUEST pRequest;       // current request
    DWORD           maxBytes;       // max bytes
    ULONG           ii = 0;         // loop variable

        // get the current request  
    pRequest = SDHCDGetAndLockCurrentRequest(pController->pHCContext, 0);

        // this should never happen because we mark the request as un-cancelable
    DEBUG_ASSERT(NULL != pRequest);

    maxBytes = pRequest->NumBlocks * pRequest->BlockSize;
    
    DbgPrintZo(SDH_RECEIVE_ZONE, (TEXT("HandleReceiveInterrupt: Max: %d, Current %d \n"),
        maxBytes, pRequest->HCParam));
 
        // according to the spec (15.2.8.2) the RX Fifo interrupt asserts for every 32 bytes and
        // remains asserted until the RX fifo is empty, once it is empty 
        // the interrupt req resets and won't assert until 32 more bytes are received
        // or until the transfer is complete and their is a partial Fifo
    if ((maxBytes - pRequest->HCParam) >= (LONG)MMC_RXFIFO_SIZE) {
            // because the remaining bytes is greater than or equal to the fifo size,
            // the fifo better be full as per Intel spec!
        // DEBUG_ASSERT(RX_FIFO_FULL(pController)); @todo
    }

        // read a Fifo's worth, as per spec 
    EmptyReceiveFifo(pController, pRequest, MMC_RXFIFO_SIZE, maxBytes);

    DbgPrintZo(SDH_RECEIVE_ZONE, (TEXT("HandleReceiveInterrupt: New Current %d  \n"),pRequest->HCParam));
    
        // see if we are done
    if (pRequest->HCParam >= maxBytes) {
        DbgPrintZo(SDH_RECEIVE_ZONE, (TEXT("HandleReceiveInterrupt: Data Transfer Completing waiting for TRANS_DONE..\n")));    
            // if we are finished, turn off the RX Fifo request interrupt
        RX_FIFO_INTERRUPT_OFF(pController);  
        SetCurrentState(pController, ReadDataTransferDone);
        // now we need to wait for the controller to perform the CRC check and issue trailing clocks (transfer done)
        // if the transfer is done, the interrupt bit will be set and the IST loop will 
        // handle the transfer done in this same thread      
    }  

        // we could mark the request as cancelable again...
}

///////////////////////////////////////////////////////////////////////////////
//  HandleEndCommandInterrupt - Handle End of Command Interrupt
//  Input:  pController - the controller that is interrupting
//  Output: 
//  Notes:  
///////////////////////////////////////////////////////////////////////////////
VOID HandleEndCommandInterrupt(PSDH_HARDWARE_CONTEXT pController)
{
    DWORD               statRegister;   // status register
    PSD_BUS_REQUEST     pRequest;       // the request to complete
    DWORD               regValue;       // intermediate reg value
    LONG                ii;             // loop variable  
    LONG                startingOffset;     // starting offset in response buffer
    USHORT              responseBuffer[SDH_RESPONSE_FIFO_DEPTH]; // response buffer

        // get the current request  
    pRequest = SDHCDGetAndLockCurrentRequest(pController->pHCContext, 0);

        // this should never happen because we mark the request as un-cancelable
    DEBUG_ASSERT(NULL != pRequest);

        // get the stat register
    statRegister = pController->pSDMMCRegisters->STAT;

        // mask the END_CMD interrupt, the command is complete , however
        // reading the STAT register doesn't clear the interrupt
        // we need to just mask this interrupt out
    END_CMD_INTERRUPT_OFF(pController);
       
    if (statRegister & MMC_STAT_RESPONSE_TIMEOUT) {
        regValue = pController->pSDMMCRegisters->CMD;
        regValue &= 0x3F;
        DbgPrintZo(SDCARD_ZONE_WARN, (TEXT("HandleEndCommandInterrupt: response for command %d , timed - out \n"),regValue));

        if( !( pController->fClockAlwaysOn || 
               ( pController->fClockOnIfInterruptsEnabled && pController->fSDIOEnabled ) ) )
        {
                // turn off the clock
            SDClockOff(pController);
        }
            // complete the current request with a timeout
        DbgPrintZo(SDH_SDBUS_INTERACTION_ZONE, (TEXT("HandleEndCommandInterrupt reports RESPONSE TIMEOUT\n")));
        SDHCDIndicateBusRequestComplete(pController->pHCContext,
                                        pRequest ,
                                        SD_API_STATUS_RESPONSE_TIMEOUT);
        return;
    }

    if (statRegister & MMC_STAT_RESPONSE_CRC_ERROR) {
        regValue = pController->pSDMMCRegisters->CMD;
        regValue &= 0x3F;

        if( !( pController->fClockAlwaysOn || 
               ( pController->fClockOnIfInterruptsEnabled && pController->fSDIOEnabled ) ) )
        {
                // turn off the clock
            SDClockOff(pController);
        }
        DbgPrintZo(SDCARD_ZONE_ERROR, (TEXT("HandleEndCommandInterrupt: response for command %d , contains a CRC error \n"), regValue));
            // complete the current request with a CRC error status
        DbgPrintZo(SDH_SDBUS_INTERACTION_ZONE, (TEXT("HandleEndCommandInterrupt reports CRC ERROR\n")));
        SDHCDIndicateBusRequestComplete(pController->pHCContext,
                                        pRequest ,
                                        SD_API_STATUS_CRC_ERROR);
        return;
    }

   
    if (NoResponse == pRequest->CommandResponse.ResponseType) {
        startingOffset = -1;
    } else if (ResponseR2 == pRequest->CommandResponse.ResponseType) {
            // 8 words - 128 bits
        startingOffset = SDH_RESPONSE_FIFO_DEPTH - 1;
    } else {
            // 3 WORDS - 48 bits
        startingOffset = 2;
    }

  

⌨️ 快捷键说明

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