sdcontrol.c

来自「该BSP是基于PXA270+WINCE的BSP」· C语言 代码 · 共 1,659 行 · 第 1/5 页

C
1,659
字号
        goto exitInit;
    }

    if( pHardwareContext->dwDmaChannel != 0xffffffff )
    {
        // allocate the DMA interrupt event
        pHardwareContext->hDMAInterruptEvent = CreateEvent(NULL, FALSE, FALSE,NULL);

        if( pHardwareContext->dwDmaSysIntr == SYSINTR_UNDEFINED )
        {
                // convert the hardware DMA controller interrupt IRQ into a logical SYSINTR value
            DWORD dwDMAIrq = pHardwareContext->dwDmaIRQ;
            if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &dwDMAIrq, sizeof(DWORD), &(pHardwareContext->dwDmaSysIntr), sizeof(DWORD), NULL))
            {
                // invalid SDIO SYSINTR value!
                DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("Error obtaining DMA SYSINTR value!\n")));
                pHardwareContext->dwDmaSysIntr = SYSINTR_UNDEFINED;
                status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
                goto exitInit;
            }
        }

        // allocate the DMA data & descriptors buffers
        if( pHardwareContext->dwDmaBufferSize )
        {
            DMA_ADAPTER_OBJECT dmaAdapter;
            dmaAdapter.ObjectSize = sizeof(dmaAdapter);
            dmaAdapter.InterfaceType = Internal;
            dmaAdapter.BusNumber = 0;
            pHardwareContext->pDMABuffer = (PBYTE)HalAllocateCommonBuffer( &dmaAdapter, 
                                                                           pHardwareContext->dwDmaBufferSize,
                                                                           &pHardwareContext->pDMABufferPhys,
                                                                           FALSE );
            if( pHardwareContext->pDMABuffer == NULL )
            {
                DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("SHCDriver: - Unable to allocate memory for DMA buffers!\r\n")));
                pHardwareContext->dwDmaBufferSize = 0;
            }
            else
            { // allocate DMA descriptors
                DWORD dwDescriptorsSize = pHardwareContext->dwDmaBufferSize / pHardwareContext->systemInfo.dwPageSize;
                if( pHardwareContext->dwDmaBufferSize % pHardwareContext->systemInfo.dwPageSize )
                {
                    dwDescriptorsSize++;
                }
                dwDescriptorsSize *= sizeof(DMADescriptorChannelType);
                
                pHardwareContext->pDMADescriptors = (volatile DMADescriptorChannelType*)HalAllocateCommonBuffer( &dmaAdapter, 
                                                                               dwDescriptorsSize,
                                                                               &pHardwareContext->pDMADescriptorsPhys,
                                                                               FALSE );
                if( pHardwareContext->pDMADescriptors == NULL )
                {
                    DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("SHCDriver: - Unable to allocate memory for DMA descriptors!\r\n")));
                    HalFreeCommonBuffer( &dmaAdapter, 
                                           pHardwareContext->dwDmaBufferSize,
                                           pHardwareContext->pDMABufferPhys,
                                           pHardwareContext->pDMABuffer,
                                           FALSE );
                    pHardwareContext->pDMABuffer = NULL;
                    pHardwareContext->dwDmaBufferSize = 0;
                }
            }
        }

            // install the DMA ISR handler
        if( pHardwareContext->wszDmaIsrDll[0] )
        {
            GIISR_INFO Info;
            PVOID PhysAddr;
            DWORD inIoSpace = 0;    // io space
            PHYSICAL_ADDRESS DmaRegisterAddress = {DMA_INTERRUPT_REGISTER, 0}; 
            
            pHardwareContext->hDMAIsrHandler = LoadIntChainHandler(pHardwareContext->wszDmaIsrDll, 
                                                                     pHardwareContext->wszDmaIsrHandler,
                                                                     (BYTE)pHardwareContext->dwDmaIRQ);
            if (pHardwareContext->hDMAIsrHandler == NULL) {
                DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("LoadIntChainHandler (%s, %s, %d) failed!\r\n"),
                                            pHardwareContext->wszDmaIsrDll, 
                                            pHardwareContext->wszDmaIsrHandler,
                                            (BYTE)pHardwareContext->dwDmaIRQ));
                status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
                goto exitInit;
            }

            if (!BusTransBusAddrToStatic(pHardwareContext->hBusAccessHandle, Internal, 0, DmaRegisterAddress, sizeof(DWORD), &inIoSpace, &PhysAddr)) {
                DEBUGMSG(SDCARD_ZONE_ERROR, (L"SDHC: Failed TransBusAddrToStatic\r\n"));
                status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
                goto exitInit;
            }
            
            DEBUGMSG(SDCARD_ZONE_INIT, (L"SDHC: Installed ISR handler, Dll = '%s', Handler = '%s', Irq = %d, PhysAddr = 0x%x\r\n", 
                pHardwareContext->wszDmaIsrDll, pHardwareContext->wszDmaIsrHandler, pHardwareContext->dwDmaIRQ, PhysAddr));

            // Set up ISR handler
            Info.SysIntr = pHardwareContext->dwDmaSysIntr;
            Info.CheckPort = TRUE;
            Info.PortIsIO = FALSE;
            Info.UseMaskReg = FALSE;
            Info.PortAddr = (DWORD)PhysAddr;
            Info.PortSize = sizeof(DWORD);
            Info.Mask = 1 << pHardwareContext->dwDmaChannel;
            
            if (!KernelLibIoControl(pHardwareContext->hDMAIsrHandler, IOCTL_GIISR_INFO, &Info, sizeof(Info), NULL, 0, NULL)) {
                DEBUGMSG(SDCARD_ZONE_ERROR, (L"SDHC: KernelLibIoControl call failed.\r\n"));
            }
        }

            // initialize the DMA interrupt event
        if (!InterruptInitialize (pHardwareContext->dwDmaSysIntr,
                                  pHardwareContext->hDMAInterruptEvent,
                                  NULL,
                                  0)) {
            status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
            goto exitInit;
        }

            // create the interrupt thread for controller interrupts
        pHardwareContext->hDmaInterruptThread = CreateThread(NULL,
                                                          0,
                                                          (LPTHREAD_START_ROUTINE)SDDMAIstThread,
                                                          pHardwareContext,
                                                          0,
                                                          &threadID);

        if (NULL == pHardwareContext->hDmaInterruptThread) {
            status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
            goto exitInit;
        }
    }

        // create the interrupt thread for controller interrupts
    pHardwareContext->hControllerInterruptThread = CreateThread(NULL,
                                                      0,
                                                      (LPTHREAD_START_ROUTINE)SDControllerIstThread,
                                                      pHardwareContext,
                                                      0,
                                                      &threadID);

    if (NULL == pHardwareContext->hControllerInterruptThread) {
        status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
        goto exitInit;
    }

    if (!SetupCardDetectIST(pHardwareContext))
    {
        status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
    }

exitInit:

    if (!SD_API_SUCCESS(status)) {
            // just call the deinit handler directly to cleanup
        SDDeinitialize(pHCContext);
    }

    return status;

}

///////////////////////////////////////////////////////////////////////////////
//  SDHCancelIoHandler - io cancel handler 
//  Input:  pHostContext - host controller context
//          Slot - slot the request is going on
//          pRequest - the request to be cancelled
//          
//  Output: 
//  Return: TRUE if the request was cancelled
//  Notes:  
//          
//
///////////////////////////////////////////////////////////////////////////////
BOOLEAN SDHCancelIoHandler(PSDCARD_HC_CONTEXT pHCContext, 
                             DWORD              Slot, 
                             PSD_BUS_REQUEST    pRequest)
{
    PSDH_HARDWARE_CONTEXT    pController;

        // for now, we should never get here because all requests are non-cancelable
        // the hardware supports timeouts so it is impossible for the controller to get stuck
    DEBUG_ASSERT(FALSE);

        // get our extension 
    pController = GetExtensionFromHCDContext(PSDH_HARDWARE_CONTEXT, pHCContext);

        // --- Stop hardware, cancel the request!

        // release the lock before we complete the request
    SDHCDReleaseHCLock(pHCContext);
 
        // complete the request with a cancelled status
    SDHCDIndicateBusRequestComplete(pHCContext,
                                    pRequest,
                                    SD_API_STATUS_CANCELED);

    return TRUE;
}

///////////////////////////////////////////////////////////////////////////////
//  SDHBusRequestHandler - bus request handler 
//  Input:  pHostContext - host controller context
//          Slot - slot the request is going on
//          pRequest - the request
//          
//  Output: 
//  Return: SD_API_STATUS Code
//  Notes:  The request passed in is marked as uncancelable, this function
//          has the option of making the outstanding request cancelable    
//          
///////////////////////////////////////////////////////////////////////////////
SD_API_STATUS SDHBusRequestHandler(PSDCARD_HC_CONTEXT pHCContext, 
                                     DWORD              Slot, 
                                     PSD_BUS_REQUEST    pRequest) 
{
    BOOL fExtraDelay = FALSE;
    PSDH_HARDWARE_CONTEXT    pController;     // our controller
    DWORD                      cmdatRegister;   // CMDAT register

    DbgPrintZo(SDCARD_ZONE_FUNC, (TEXT("SDHBusRequestHandler - CMD: 0x%02X DATA: 0x%08X, TC: %d\n"),
                pRequest->CommandCode, pRequest->CommandArgument, pRequest->TransferClass));

        // get our extension 
    pController = GetExtensionFromHCDContext(PSDH_HARDWARE_CONTEXT, pHCContext);

    DbgPrintZo(SDH_SDBUS_INTERACTION_ZONE, (TEXT("SDHBusRequestHandler - CMD: 0x%02X DATA: 0x%08X, TC: %d\n"),
            pRequest->CommandCode, pRequest->CommandArgument, pRequest->TransferClass));

        // stop the clock
    SDClockOff(pController);

        // set the command
    WRITE_MMC_REGISTER_DWORD(pController, MMC_CMD, pRequest->CommandCode);
        // set the argument,  high part
    WRITE_MMC_REGISTER_DWORD(pController, MMC_ARGH, (pRequest->CommandArgument >> 16));
        // set the argument,  high part
    WRITE_MMC_REGISTER_DWORD(pController, MMC_ARGL, (pRequest->CommandArgument & 0x0000FFFF));


    switch (pRequest->CommandResponse.ResponseType) {

        case NoResponse:
            cmdatRegister = MMC_CMDAT_RESPONSE_NONE;
            break;
        case ResponseR1b:
                // response1 with busy signalling
            cmdatRegister = MMC_CMDAT_RESPONSE_R1 | MMC_CMDAT_EXPECT_BUSY;
            break;
        case ResponseR1:
        case ResponseR5:
        case ResponseR6:
                // on an MMC controller R5 and R6 are really just an R1 response (CRC protected)
            cmdatRegister = MMC_CMDAT_RESPONSE_R1;
            break;
        case ResponseR2:    
            cmdatRegister = MMC_CMDAT_RESPONSE_R2;
            break;
        case ResponseR3:
        case ResponseR4:    
                // R4 is really same as an R3 response on an MMC controller (non-CRC)
            cmdatRegister = MMC_CMDAT_RESPONSE_R3;
            break;

        default:
            DbgPrintZo(SDH_SDBUS_INTERACTION_ZONE, (TEXT("SDHBusRequestHandler failed (Invalid parameter)\n")));
            return SD_API_STATUS_INVALID_PARAMETER;
    }

    pController->fDMATransfer = FALSE;
    pController->fDMATransferCancelled = FALSE;

        // check for Command Only
    if ((SD_COMMAND == pRequest->TransferClass)) {
       
            // set the length of the block
        WRITE_MMC_REGISTER_DWORD(pController, MMC_BLKLEN, 0);

            // set the number of blocks
        WRITE_MMC_REGISTER_DWORD(pController, MMC_NOB, 0);

    } else {
            // its a command with a data phase
        cmdatRegister |= MMC_CMDAT_DATA_EN;
        
            // set the buffer index to the end of the buffer
        pRequest->HCParam = 0;      

            // set the length of the block
        WRITE_MMC_REGISTER_DWORD(pController, MMC_BLKLEN, pRequest->BlockSize);

            // set the number of blocks
        WRITE_MMC_REGISTER_DWORD(pController, MMC_NOB, pRequest->NumBlocks);

            // check for write
        if (TRANSFER_IS_WRITE(pRequest)) {
            cmdatRegister |= MMC_CMDAT_DATA_WRITE;
        } 

        // check to see if we can use DMA for data transfer
        if( PrepareDmaTransfer( pController, pRequest ) )
        {
            cmdatRegister |= MMC_CMDAT_DMA_ENABLE;
            pController->fDMATransfer = TRUE;
        }
    }

        // check to see if we need to append the 80 clocks (i.e. this is the first transaction)
    if (pController->SendInitClocks) {
        pController->SendInitClocks = FALSE;
        cmdatRegister |= MMC_CMDAT_INIT;
        fExtraDelay = TRUE;
    }

        // check to see if we need to enable the SDIO interrupt checking
    if (pController->fSDIOEnabled) {
        cmdatRegister |= MMC_CMDAT_SDIO_INT_EN;
    }

        // check to see if we need to enable wide bus (4 bit) data transfer mode
    if (pController->f4BitMode) {
        cmdatRegister |= MMC_CMDAT_SD_4DAT;
    }

    

        // write the CMDAT register
    WRITE_MMC_REGISTER_DWORD(pController, MMC_CMDAT, cmdatRegister);
    DbgPrintZo(SDH_SEND_ZONE, (TEXT("SDHBusRequestHandler - CMDAT Reg: 0x%08X, CMD:%d \n"),
                cmdatRegister, pRequest->CommandCode));

        // set the the response timeout
    WRITE_MMC_REGISTER_DWORD(pController, MMC_RESTO, SDH_DEFAULT_RESPONSE_TIMEOUT_CLOCKS);
        // set the data receive timeout

⌨️ 快捷键说明

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