📄 sdcontrol.c
字号:
// Configure GPIO_92 as Alternate Function 1 (MMC_DAT0)
// assume that the MMC_CLK is active-high signal driven
dwRegVal = pHardwareContext->pGPIORegisters->GPSR2;
dwRegVal |= 0x10000000;
pHardwareContext->pGPIORegisters->GPSR2 = dwRegVal;
// change the direction to OUT
dwRegVal = pHardwareContext->pGPIORegisters->GPDR2;
dwRegVal |= 0x10000000;
pHardwareContext->pGPIORegisters->GPDR2 = dwRegVal;
// change to Alternate Function 1
dwRegVal = pHardwareContext->pGPIORegisters->GAFR2_U;
dwRegVal = ( dwRegVal & 0xfcffffff ) | 0x01000000;
pHardwareContext->pGPIORegisters->GAFR2_U = dwRegVal;
//////////////////////////////////////////////////////////
// Configure GPIO_109-GPIO_111 as Alternate Function 1 (MMC_DAT1-MMC_DAT3)
// assume that the MMC_CLK is active-high signal driven
dwRegVal = pHardwareContext->pGPIORegisters->GPSR3;
dwRegVal |= 0x0000e000;
pHardwareContext->pGPIORegisters->GPSR3 = dwRegVal;
// change the direction to OUT
dwRegVal = pHardwareContext->pGPIORegisters->GPDR3;
dwRegVal |= 0x0000e000;
pHardwareContext->pGPIORegisters->GPDR3 = dwRegVal;
// change to Alternate Function 1
dwRegVal = pHardwareContext->pGPIORegisters->GAFR3_L;
dwRegVal = ( dwRegVal & 0x03ffffff ) | 0x54000000;
pHardwareContext->pGPIORegisters->GAFR3_L = dwRegVal;
#ifdef DEBUG
DumpRegisters( pHardwareContext );
DumpGPIORegisters( pHardwareContext );
#endif
// allocate the interrupt event
pHardwareContext->hControllerInterruptEvent = CreateEvent(NULL, FALSE, FALSE,NULL);
if (NULL == pHardwareContext->hControllerInterruptEvent) {
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto exitInit;
}
// convert the hardware SD/MMC controller interrupt IRQ into a logical SYSINTR value
dwSDIOIrq = pHardwareContext->dwSDMMCIrq;
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &dwSDIOIrq, sizeof(DWORD), &(pHardwareContext->dwSysintrSDMMC), sizeof(DWORD), NULL))
{
// invalid SDIO SYSINTR value!
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("Error obtaining SDIO SYSINTR value!\n")));
pHardwareContext->dwSysintrSDMMC = SYSINTR_UNDEFINED;
goto exitInit;
}
// initialize the interrupt event
if (!InterruptInitialize (pHardwareContext->dwSysintrSDMMC,
pHardwareContext->hControllerInterruptEvent,
NULL,
0)) {
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
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
IndicateBusRequestComplete(pHCContext,
pRequest,
SD_API_STATUS_CANCELED);
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
// SDBusIssueRequest - 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 SDBusIssueRequest(PSDCARD_HC_CONTEXT pHCContext,
DWORD Slot,
PSD_BUS_REQUEST pRequest)
{
BOOL fExtraDelay = FALSE;
PSDH_HARDWARE_CONTEXT pController; // our controller
DWORD cmdatRegister; // CMDAT register
// get our extension
pController = GetExtensionFromHCDContext(PSDH_HARDWARE_CONTEXT, pHCContext);
DbgPrintZo(SDH_SDBUS_INTERACTION_ZONE, (TEXT("SDBusIssueRequest - pRequest = %x, CMD: 0x%02X DATA: 0x%08X, TC: %d\n"),
pRequest,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("SDBusIssueRequest 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)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -