void HIFShutDownDevice(HIF_DEVICE *device) { SD_API_STATUS sdStatus; //SDCONFIG_BUS_MODE_DATA busSettings; UCHAR buffer; if (device == NULL) { HIF_DEBUG_PRINTF(ATH_LOG_ERR, "Invalid Handle passed\n"); return; } /* Remove the allocated current if any */ /* * There is no equivalent for this one in WINCE status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_FREE_SLOT_CURRENT, NULL, 0); DBG_ASSERT(SDIO_SUCCESS(status)); */ /* Disable the card */ SDIODisconnectInterrupt(device->handle); sdStatus = SDSetCardFeature(device->handle, SD_IO_FUNCTION_DISABLE, NULL, 0); AR_DEBUG_ASSERT(SD_API_SUCCESS(sdStatus)); /* Perform a soft I/O reset */ sdStatus = SDReadWriteRegistersDirect(device->handle, SD_IO_WRITE, 0, SD_IO_REG_IO_ABORT, 1, &buffer, 0); AR_DEBUG_ASSERT(SD_API_SUCCESS(sdStatus)); /* * WAR - Codetelligence driver does not seem to shutdown correctly in 1 * bit mode. By default it configures the HC in the 4 bit. Its later in * our driver that we switch to 1 bit mode. If we try to shutdown, the * driver hangs so we revert to 4 bit mode, to be transparent to the * underlying bus driver. */ /* * Not sure whether this is required for WINCE hence commenting */ /* if (sdio1bitmode) { ZERO_OBJECT(busSettings); busSettings.BusModeFlags = device->handle->pHcd->CardProperties.BusMode; SDCONFIG_SET_BUS_WIDTH(busSettings.BusModeFlags, SDCONFIG_BUS_WIDTH_4_BIT); // Issue config request to change the bus width to 4 bit status = SDLIB_IssueConfig(device->handle, SDCONFIG_BUS_MODE_CTRL, &busSettings, sizeof(SDCONFIG_BUS_MODE_DATA)); DBG_ASSERT(SDIO_SUCCESS(status)); } */ /* Unregister with bus driver core */ sdStatus = SDIOUnregisterFunction(&sdFunction); AR_DEBUG_ASSERT(SD_API_SUCCESS(sdStatus)); return; }
SD_API_STATUS CSDHCBase::Start() { SD_API_STATUS status = SD_API_STATUS_INSUFFICIENT_RESOURCES; m_fDriverShutdown = FALSE; // allocate the interrupt event m_hevInterrupt = CreateEvent(NULL, FALSE, FALSE,NULL); if (NULL == m_hevInterrupt) { goto EXIT; } // initialize the interrupt event RETAILMSG(0,(_T("CSDHCBase::Start() m_dwSysIntr = %x\r\n"), m_dwSysIntr)); // jylee if (!InterruptInitialize (m_dwSysIntr, m_hevInterrupt, NULL, 0)) { goto EXIT; } m_fInterruptInitialized = TRUE; // create the interrupt thread for controller interrupts m_htIST = CreateThread(NULL, 0, ISTStub, this, 0, NULL); if (NULL == m_htIST) { goto EXIT; } for (DWORD dwSlot = 0; dwSlot < m_cSlots; ++dwSlot) { PCSDHCSlotBase pSlot = GetSlot(dwSlot); status = pSlot->Start(); if (!SD_API_SUCCESS(status)) { goto EXIT; } } // wake up the interrupt thread to check the slot ::SetInterruptEvent(m_dwSysIntr); status = SD_API_STATUS_SUCCESS; EXIT: if (!SD_API_SUCCESS(status)) { // Clean up Stop(); } RETAILMSG(0,(_T("CSDHCBase::-Start() status = %x\r\n"), status)); // jylee return status; }
/////////////////////////////////////////////////////////////////////////////// // CardDllEntry - the main dll entry point // Input: hInstance - the instance that is attaching // Reason - the reason for attaching // pReserved - // Output: // Return: TRUE // Notes: this is only used to initialize the zones /////////////////////////////////////////////////////////////////////////////// BOOL DllEntry(HINSTANCE hInstance, ULONG Reason, LPVOID pReserved) { if ( Reason == DLL_PROCESS_ATTACH ) { SD_DEBUG_ZONE_REGISTER(hInstance, SDH_REGISTRY_BASE_PATH); DisableThreadLibraryCalls( (HMODULE) hInstance ); if( !SDInitializeCardLib() ) { return FALSE; } else if( !SD_API_SUCCESS( SDHCDInitializeHCLib() ) ) { SDDeinitializeCardLib(); return FALSE; } } if ( Reason == DLL_PROCESS_DETACH ) { SDHCDDeinitializeHCLib(); SDDeinitializeCardLib(); } return(TRUE); }
void hifRWCompletionHandler(SD_DEVICE_HANDLE hDevice, PSD_BUS_REQUEST pRequest, PVOID notUsed, DWORD dwParam) { PVOID htcContext = (void *)dwParam; A_STATUS status = A_OK; if(SD_API_SUCCESS(pRequest->Status)) { status = A_OK; } else { status = A_ERROR; } if(htcContext != NULL) { htcCallbacks.rwCompletionHandler(htcContext, A_OK); } SDFreeBusRequest(pRequest); NDIS_DEBUG_PRINTF(DBG_TRACE, "%s() : - Exit \r\n", __FUNCTION__); }
A_STATUS HIFInit(OSDRV_CALLBACKS *callbacks) { SD_API_STATUS sdStatus; AR_DEBUG_ASSERT(callbacks != NULL); /* store the callback handlers */ osdrvCallbacks = *callbacks; /* Register with bus driver core */ NDIS_DEBUG_PRINTF(DBG_LEVEL_HIF, "AR6000: HIFInit registering \r\n"); registered = 1; #if defined(CONFIG_PM) // TODO about power management. #endif /* CONFIG_PM */ /* Register with bus driver core */ sdFunction.pName = "sdio_wlan"; sdFunction.pProbe = hifDeviceInserted; sdFunction.pRemove = hifDeviceRemoved; A_MUTEX_INIT(&hif_lock); NdisAllocateSpinLock(&sLock); sdStatus = SDIORegisterFunction(&sdFunction); AR_DEBUG_ASSERT(SD_API_SUCCESS(sdStatus)); return A_OK; }
void HIFUnMaskInterrupt(HIF_DEVICE *device) { SD_API_STATUS sdStatus; /* Register the IRQ Handler */ sdStatus = SDIOConnectInterrupt(device->handle, hifIRQHandler); AR_DEBUG_ASSERT(SD_API_SUCCESS(sdStatus)); return; }
/////////////////////////////////////////////////////////////////////////////// // SDMemCalcDataAccessClocks - Calculate the data access clocks // Input: pMemCard - the memcard // Output: pReadAccessClocks - Pointer to ULONG for read access clocks // pWriteAccessClocks - Pointer to ULONG for write access clocks // Return: TRUE or FALSE to indicate function success/failure // Notes: Calculate data access times for memory devices. This calculation // is to fine tune the data delay time /////////////////////////////////////////////////////////////////////////////// BOOL SDMemCalcDataAccessClocks(PSD_MEMCARD_INFO pMemCard, PULONG pReadAccessClocks, PULONG pWriteAccessClocks) { SD_CARD_INTERFACE cardInterface; // current card interface SD_API_STATUS status; // intermediate status DOUBLE clockPeriodNs; // clock period in nano seconds ULONG asyncClocks; // clocks required for the async portion // fetch the card clock rate status = SDCardInfoQuery(pMemCard->hDevice, SD_INFO_CARD_INTERFACE, &cardInterface, sizeof(cardInterface)); if(!SD_API_SUCCESS(status)) { DEBUGMSG(SDCARD_ZONE_ERROR,(TEXT("SDMemCalcDataAccessClocks: Can't get card interface info\r\n"))); return FALSE; } if(0 == cardInterface.ClockRate) { DEBUGCHK(FALSE); return FALSE; } // if the clock rate is greater than 1 Ghz, this won't work if(cardInterface.ClockRate > 1000000000) { DEBUGCHK(FALSE); return FALSE; } // calculate the clock period in nano seconds, clock rate is in Hz clockPeriodNs = 1000000000 / cardInterface.ClockRate; // calculate the async portion now that we know the clock rate // make asyncClock an integer asyncClocks = (ULONG)(pMemCard->CSDRegister.DataAccessTime.TAAC / clockPeriodNs); // add the async and synchronous portions together for the read access *pReadAccessClocks = asyncClocks + pMemCard->CSDRegister.DataAccessTime.NSAC; // for the write access the clocks area multiple of the read clocks *pWriteAccessClocks = (*pReadAccessClocks) * pMemCard->CSDRegister.WriteSpeedFactor; DEBUGMSG(SDCARD_ZONE_INIT, (TEXT("SDMemCalcDataAccessClocks: Tpd:%f ns, Asynch: %f ns, AsyncClocks:%d , SyncClocks: %d, ReadTotal: %d, Write Factor: %d WriteTotal: %d \n"), clockPeriodNs, pMemCard->CSDRegister.DataAccessTime.TAAC, asyncClocks, pMemCard->CSDRegister.DataAccessTime.NSAC, *pReadAccessClocks, pMemCard->CSDRegister.WriteSpeedFactor, *pWriteAccessClocks)); return TRUE; }
extern DWORD WINAPI DRG_Init(DWORD dwContext) { PWCHAR* pRegPath = NULL; SDCARD_CLIENT_REGISTRATION_INFO ClientInfo; // client into SD_API_STATUS Status; // intermediate status HANDLE hThread; NDIS_DEBUG_PRINTF(DBG_TRACE, "AR6K_SDIO: +DRG_Init by DiskImage !!! \r\n"); // get the device handle from the bus driver hClientHandle = SDGetDeviceHandle(dwContext, pRegPath); if (NULL == hClientHandle) { NDIS_DEBUG_PRINTF(DBG_ERR, "-DRG_Init: Failed to get client handle \r\n"); return 0; } memset(&ClientInfo, 0, sizeof(ClientInfo)); // set client options and register as a client device _tcscpy(ClientInfo.ClientName, TEXT("Atheros AR6K SDIO Wifi Card")); // set the callback ClientInfo.pSlotEventCallBack = SlotEventCallBack; Status = SDRegisterClient(hClientHandle, NULL, &ClientInfo); if (!SD_API_SUCCESS(Status)) { NDIS_DEBUG_PRINTF(DBG_ERR, "-DRG_Init: Failed to register client : 0x%08X \r\n", Status); return 0; } drvInit(); if (!createRegKeyValues()) { NDIS_DEBUG_PRINTF(DBG_ERR, "-DRG_Init: Failed to create ndis registryentries \r\n"); return 0; } // Perform NDIS register adapter on a separate thread to avoid // blocking the SDIO bus driver hThread = CreateThread(NULL, 0, NdisRegisterAdapterThread, NULL, 0, NULL); CeSetThreadPriority(hThread, 200); CloseHandle(hThread); NDIS_DEBUG_PRINTF(DBG_TRACE, "DRG_Init : Exit\r\n"); return 1; }
/////////////////////////////////////////////////////////////////////////////// // IdleThread - idle thread // Input: pMemCard - memory card instance // Output: // Return: thread exit code // Notes: // This thread is created if power management is enabled. // Normally the thread lays dormant until signalled to perform // the idle timeout. When an idle timeout occurs, if the // timer was not cancelled, the thread deselects the memory card // to reduce power consumption. /////////////////////////////////////////////////////////////////////////////// DWORD IdleThread(PSD_MEMCARD_INFO pMemCard) { while(1) { // wait for event WaitForSingleObject(pMemCard->hWakeUpIdleThread, INFINITE); if (pMemCard->ShutDownIdleThread) { return 0; } // while low power polling is enabled while (pMemCard->EnableLowPower) { // wait with a timeout WaitForSingleObject(pMemCard->hWakeUpIdleThread, pMemCard->IdleTimeout); if (pMemCard->EnableLowPower) { DEBUGMSG(SDMEM_ZONE_POWER, (TEXT("SDMemory: Idle Timeout Wakeup after %d MS \n"),pMemCard->IdleTimeout)); AcquireLock(pMemCard); // check for cancel if (!pMemCard->CancelIdleTimeout){ // make sure we haven't already deselected the card if (!pMemCard->CardDeSelected) { DEBUGMSG(SDMEM_ZONE_POWER, (TEXT("SDMemory: Idle Timout, De-Selecting Card \n"))); // we haven't been canceled, so issue the card de-select if (SD_API_SUCCESS(IssueCardSelectDeSelect(pMemCard, FALSE))) { pMemCard->CardDeSelected = TRUE; } } } else { DEBUGMSG(SDMEM_ZONE_POWER, (TEXT("SDMemory: Idle Timout, Cancelled! \n"))); } // clear the cancel flag // SMC_IOControl() will clear pMemCard->CancelIdleTimeout once ioctl request is end ReleaseLock(pMemCard); } } if (pMemCard->ShutDownIdleThread) { return 0; } } }
/////////////////////////////////////////////////////////////////////////////// // SDGetCardStatus - Get the current card status // Input: pMemCard - SD memory card structure // // Output: pCardStatus - card status // Return: win32 status code // Notes: /////////////////////////////////////////////////////////////////////////////// DWORD SDGetCardStatus(PSD_MEMCARD_INFO pMemCard , SD_CARD_STATUS *pCardStatus) { SD_API_STATUS status; // api status status = SDCardInfoQuery(pMemCard->hDevice, SD_INFO_CARD_STATUS, pCardStatus, sizeof(SD_CARD_STATUS)); if (!SD_API_SUCCESS(status)){ return SDAPIStatusToErrorCode(status); } return ERROR_SUCCESS; }
static A_BOOL IssueSDCommand(SD_DEVICE_HANDLE hDevice, A_UINT8 Cmd, A_UINT32 Argument, SD_RESPONSE_TYPE ResponseType, SD_COMMAND_RESPONSE *pResponse) { SD_API_STATUS sdStatus; sdStatus = SDSynchronousBusRequest(hDevice, Cmd, Argument, SD_COMMAND, ResponseType, pResponse, 0, 0, NULL, 0); return SD_API_SUCCESS(sdStatus) ? TRUE : FALSE; }
//++dralee_20060327 NDIS_STATUS SendNullPacket(IN PMRVDRV_ADAPTER Adapter,UCHAR pwmgr ) { NDIS_STATUS sdstatus; SDIO_TX_PKT downloadPkt; downloadPkt.Len = ADD_SDIO_PKT_HDR_LENGTH(sizeof(WCB)); downloadPkt.Type = IF_DATA_PKT; NdisZeroMemory(&downloadPkt.Buf.TxDataBuf.Wcb, sizeof(WCB)); downloadPkt.Buf.TxDataBuf.Wcb.PktPtr = sizeof(WCB); downloadPkt.Buf.TxDataBuf.Wcb.PowerMgmt = pwmgr; sdstatus = If_DownloadPkt(Adapter, &downloadPkt); if (!SD_API_SUCCESS(sdstatus)) { DBGPRINT(DBG_ERROR,(L"Send Null Pkt Fail\r\n")); return NDIS_STATUS_FAILURE; } return sdstatus; }
/////////////////////////////////////////////////////////////////////////////// // RequestPrologue - pre-tasks before handling the ioctl // Input: pMemCard - memory card instance // DeviceIoControl - device iocontrol to filter // Output: // Return: SD_API_STATUS code // Notes: // This function should be called from the Ioctl dispatch function /////////////////////////////////////////////////////////////////////////////// SD_API_STATUS RequestPrologue(PSD_MEMCARD_INFO pMemCard, DWORD DeviceIoControl) { SD_API_STATUS status = SD_API_STATUS_SUCCESS; // intermediate status if (pMemCard->CardEjected) { return SD_API_STATUS_DEVICE_REMOVED; } // check and see if we need to do power management tasks if (!pMemCard->EnablePowerManagement) { return SD_API_STATUS_SUCCESS; } // pass power Ioctls through without issuing card re-select if ((IOCTL_POWER_CAPABILITIES == DeviceIoControl) || (IOCTL_POWER_QUERY == DeviceIoControl) || (IOCTL_POWER_SET == DeviceIoControl)) { return SD_API_STATUS_SUCCESS; } // for all other ioctls, re-select the card AcquireLock(pMemCard); // cancel the idle timer pMemCard->CancelIdleTimeout= TRUE; // check to see if the card was deselected due to power // management if (pMemCard->CardDeSelected) { DEBUGMSG(SDMEM_ZONE_POWER, (TEXT("SDMemory: Re-Selecting Card \n"))); status = IssueCardSelectDeSelect(pMemCard, TRUE); if (SD_API_SUCCESS(status)) { pMemCard->CardDeSelected = FALSE; } } ReleaseLock(pMemCard); return status; }
void hifRWCompletionHandler(SD_DEVICE_HANDLE hDevice, PSD_BUS_REQUEST pRequest, PVOID notUsed, DWORD dwParam) { A_STATUS status; PVOID htcContext; if (SD_API_SUCCESS(pRequest->Status)) { status = A_OK; } else { status = A_ERROR; } htcContext = (void *)dwParam; htcCallbacks.rwCompletionHandler(htcContext, status); AR_DEBUG_ASSERT(status == A_OK); SDFreeBusRequest(pRequest); return; }
/////////////////////////////////////////////////////////////////////////////// // SDMemDoBusRequest - Perform a bus request, returns Windows Status // Input: pMemCard - SD memory card structure // Command - SD command to send over bus // Argument - 32 bit argument specific to the command // TransferClass - Command only, or associated with read/write data // ResponseType - Response Type for the command // NumBlocks - Number of data blocks in pBlockArray, can be zero // if transfer class is not read or write // BlockSize - Size of data blocks in pBlockArray. All blocks // must be same size. // pBuffer - Pointer to buffer containing BlockSize*NumBlocks bytes // Flags // Output: // Return: standard win32 status code // Notes: This function performs an SD Bus Request and converts the SD status // of that transaction into a standard windows status code. /////////////////////////////////////////////////////////////////////////////// DWORD SDMemDoBusRequest( PSD_MEMCARD_INFO pMemcard, UCHAR Command, DWORD Argument, SD_TRANSFER_CLASS TransferClass, SD_RESPONSE_TYPE ResponseType, ULONG NumBlocks, ULONG BlockSize, PUCHAR pBuffer, DWORD Flags) { SD_API_STATUS RequestStatus; // intermediate status DEBUGMSG( SDMEM_ZONE_BUS_REQS, (TEXT("SDMemDoBusRequest: CMD%d Arg 0x%08X TransferClass %d NumBlocks %d BlockSize %d\r\n"), Command,Argument,TransferClass,NumBlocks,BlockSize)); // initiate the bus transaction RequestStatus = SDSynchronousBusRequest( pMemcard->hDevice, Command, Argument, TransferClass, ResponseType, NULL, NumBlocks, BlockSize, pBuffer, Flags); // get the status and convert if necessary if (!SD_API_SUCCESS(RequestStatus)) { DEBUGMSG( SDCARD_ZONE_ERROR, (TEXT("SDMemDoBusRequest Failed: CMD%d returned API status 0x%X\r\n"), Command,RequestStatus)); return SDAPIStatusToErrorCode(RequestStatus); } // everything was OK, return success return ERROR_SUCCESS; }
/* ------ Functions ------ */ void HIFRegisterCallbacks(HTC_CALLBACKS *callbacks) { SD_API_STATUS sdStatus; /* Store the callback and event handlers */ htcCallbacks.deviceInsertedHandler = callbacks->deviceInsertedHandler; htcCallbacks.deviceRemovedHandler = callbacks->deviceRemovedHandler; htcCallbacks.deviceSuspendHandler = callbacks->deviceSuspendHandler; htcCallbacks.deviceResumeHandler = callbacks->deviceResumeHandler; htcCallbacks.deviceWakeupHandler = callbacks->deviceWakeupHandler; htcCallbacks.rwCompletionHandler = callbacks->rwCompletionHandler; htcCallbacks.deviceInterruptDisabler = callbacks->deviceInterruptDisabler; htcCallbacks.deviceInterruptEnabler = callbacks->deviceInterruptEnabler; htcCallbacks.dsrHandler = callbacks->dsrHandler; /* Register with bus driver core */ sdFunction.pName = "sdio_wlan"; sdFunction.pProbe = hifDeviceInserted; sdFunction.pRemove = hifDeviceRemoved; sdStatus = SDIORegisterFunction(&sdFunction); AR_DEBUG_ASSERT(SD_API_SUCCESS(sdStatus)); }
/////////////////////////////////////////////////////////////////////////////// // SMC_Init - the init entry point for the memory driver // Input: dwContext - the context for this init // Output: // Return: non-zero context // Notes: /////////////////////////////////////////////////////////////////////////////// extern "C" DWORD WINAPI SMC_Init(DWORD dwContext) { SD_DEVICE_HANDLE hClientHandle; // client handle PSD_MEMCARD_INFO pDevice; // this instance of the device SDCARD_CLIENT_REGISTRATION_INFO ClientInfo; // client into ULONG BufferSize; // size of buffer HKEY hSubKey; // registry key SD_API_STATUS Status; // intermediate status DWORD data; // registry data DWORD dataLength; // registry data length DEBUGMSG(SDCARD_ZONE_INIT, (TEXT("SDMemory: +SMC_Init\r\n"))); pDevice = (PSD_MEMCARD_INFO)SDAllocateMemoryWithTag( sizeof(SD_MEMCARD_INFO), SD_MEMORY_TAG); if (pDevice == NULL) { DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDMemory: Failed to allocate device info\r\n"))); DEBUGMSG(SDCARD_ZONE_INIT, (TEXT("SDMemory: -SMC_Init\r\n"))); return 0; } // initialize sterile I/O request to NULL pDevice->pSterileIoRequest = NULL; InitializeCriticalSection(&pDevice->CriticalSection); InitializeCriticalSection(&pDevice->RemovalLock); // get the device handle from the bus driver hClientHandle = SDGetDeviceHandle(dwContext, &pDevice->pRegPath); // store device handle in local context pDevice->hDevice = hClientHandle; if (NULL == hClientHandle) { DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDMemory: Failed to get client handle\r\n"))); CleanUpDevice(pDevice); DEBUGMSG(SDCARD_ZONE_INIT, (TEXT("SDMemory: -SMC_Init\r\n"))); return 0; } // allocate sterile I/O request pDevice->pSterileIoRequest = (PSG_REQ)LocalAlloc( LPTR, (sizeof(SG_REQ) + ((MAX_SG_BUF - 1) * sizeof(SG_BUF))) ); if (NULL == pDevice->pSterileIoRequest) { DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDMemory: Failed to allocate sterile I/O request\r\n"))); CleanUpDevice(pDevice); DEBUGMSG(SDCARD_ZONE_INIT, (TEXT("SDMemory: -SMC_Init\r\n"))); return 0; } // register our debug zones SDRegisterDebugZones(hClientHandle, pDevice->pRegPath); memset(&ClientInfo, 0, sizeof(ClientInfo)); // set client options and register as a client device _tcscpy(ClientInfo.ClientName, TEXT("Memory Card")); // set the callback ClientInfo.pSlotEventCallBack = SlotEventCallBack; Status = SDRegisterClient(hClientHandle, pDevice, &ClientInfo); if (!SD_API_SUCCESS(Status)) { DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDMemory: Failed to register client : 0x%08X\r\n"), Status)); CleanUpDevice(pDevice); DEBUGMSG(SDCARD_ZONE_INIT, (TEXT("SDMemory: -SMC_Init\r\n"))); return 0; } #ifdef _FOR_MOVI_NAND_ /** * Description : There is no way to distinguish between HSMMC and moviNAND. * So, We assume A HSMMC card is a moviNAND. Default value is false; */ pDevice->IsHSMMC = FALSE; #endif // configure card and retrieve disk size/format information if( SDMemCardConfig( pDevice ) != ERROR_SUCCESS ) { CleanUpDevice(pDevice); DEBUGMSG( SDCARD_ZONE_ERROR, (TEXT("SDMemory: Error initializing MemCard structure and card\r\n"))); return 0; } // aet a default block transfer size pDevice->BlockTransferSize = DEFAULT_BLOCK_TRANSFER_SIZE; // read configuration from registry // open the reg path if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, pDevice->pRegPath, 0, KEY_ALL_ACCESS, &hSubKey) == ERROR_SUCCESS ) { // read "BlockTransferSize" dataLength = sizeof(pDevice->BlockTransferSize); RegQueryValueEx( hSubKey, BLOCK_TRANSFER_SIZE_KEY, NULL, NULL, (PUCHAR)&(pDevice->BlockTransferSize), &dataLength); if (pDevice->BlockTransferSize != DEFAULT_BLOCK_TRANSFER_SIZE) { DEBUGMSG(SDCARD_ZONE_INIT, (TEXT("SDMemory: Initialize: Using block transfer size of %d blocks\r\n"), pDevice->BlockTransferSize)); } // read "SingleBlockWrites" // default to using mulitple block writes pDevice->SingleBlockWrites = FALSE; dataLength = sizeof(DWORD); data = 0; if (RegQueryValueEx( hSubKey, SINGLE_BLOCK_WRITES_KEY, NULL, NULL, (PUCHAR)&data, &dataLength) == ERROR_SUCCESS ) { // key is present pDevice->SingleBlockWrites = TRUE; DEBUGMSG(SDCARD_ZONE_INIT, (TEXT("SDMemory: Initialize: Using single block write commands only\r\n"))); } // read "DisablePowerManagement" // on by default unless key is present pDevice->EnablePowerManagement = TRUE; dataLength = sizeof(DWORD); data = 0; if (RegQueryValueEx( hSubKey, DISABLE_POWER_MANAGEMENT, NULL, NULL, (PUCHAR)&data, &dataLength) == ERROR_SUCCESS ) { // key is present DEBUGMSG(SDCARD_ZONE_INIT, (TEXT("SDMemory: Initialize: Disabled power management\r\n"))); pDevice->EnablePowerManagement = FALSE; } // read "IdleTimeout" pDevice->IdleTimeout = DEFAULT_IDLE_TIMEOUT; dataLength = sizeof(pDevice->IdleTimeout); if (RegQueryValueEx( hSubKey, IDLE_TIMEOUT, NULL, NULL, (PUCHAR)&pDevice->IdleTimeout, &dataLength) == ERROR_SUCCESS ) { // key is present DEBUGMSG(SDCARD_ZONE_INIT, (TEXT("SDMemory: Initialize: Using idle timeout of %u milliseconds\r\n"), pDevice->IdleTimeout)); } // read "IdlePowerState" // default power state for idle // if the power state is greater than D2, we do idle checking pDevice->PowerStateForIdle = D2; dataLength = sizeof(DWORD); data = 0; if (RegQueryValueEx( hSubKey, IDLE_POWER_STATE, NULL, NULL, (PUCHAR)&data, &dataLength) == ERROR_SUCCESS ) { if (data <= (ULONG)D4) { pDevice->PowerStateForIdle = (CEDEVICE_POWER_STATE)data; } } DEBUGMSG(SDCARD_ZONE_INIT, (TEXT("SDMemory: Idle Timeout: %d Idle Power State: %d\r\n"), pDevice->IdleTimeout, pDevice->PowerStateForIdle)); RegCloseKey(hSubKey); } // allocate our buffer list; we need 2 buffers: 1 for read and 1 for write data BufferSize = (ULONG)(pDevice->BlockTransferSize * SD_BLOCK_SIZE); // create the data buffer memory list pDevice->hBufferList = SDCreateMemoryList(SD_MEMORY_TAG, 2, BufferSize); if (pDevice->hBufferList == NULL) { DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDMemory: Initialize: Failed to allocate buffer list\r\n"))); CleanUpDevice(pDevice); return 0; } pDevice->fPreDeinitCalled = FALSE; InitializePowerManagement(pDevice); DEBUGMSG(SDCARD_ZONE_INIT, (TEXT("SDMemory: -SMC_Init\r\n"))); return (DWORD)pDevice; }
BOOL hifDeviceInserted(SD_DEVICE_HANDLE *handle) { HIF_DEVICE *device; SD_API_STATUS sdStatus; SDIO_CARD_INFO sdioInfo; SD_HOST_BLOCK_CAPABILITY blockCap; SD_CARD_RCA cardRCA; A_UCHAR rgucTuple[SD_CISTPLE_MAX_BODY_SIZE]; PSD_CISTPL_FUNCE_FUNCTION pFunce = (PSD_CISTPL_FUNCE_FUNCTION) rgucTuple; A_UINT32 ulLength = 0; A_UCHAR ucRegVal; A_BOOL blockMode; SD_CARD_INTERFACE ci; SD_IO_FUNCTION_ENABLE_INFO fData; DWORD bData; //SDCONFIG_FUNC_SLOT_CURRENT_DATA slotCurrent; #ifdef CEPC HANDLE hThread; #endif //CEPC device = addHifDevice(handle); HIF_DEBUG_PRINTF(ATH_LOG_TRC, "hifDeviceInserted: Enter\n"); /* Enable SDIO [dragon] function */ fData.Interval = DEFAULT_SDIO_FUNCTION_RETRY_TIMEOUT; fData.ReadyRetryCount = DEFAULT_SDIO_FUNCTION_RETRIES; sdStatus = SDSetCardFeature (handle, SD_IO_FUNCTION_ENABLE, &fData, sizeof(fData)); if (!SD_API_SUCCESS(sdStatus)) { return FALSE; } /* * Issue commands to get the manufacturer ID and stuff and compare it * against the rev Id derived from the ID registered during the * initialization process. Report the device only in the case there * is a match. */ sdStatus = SDCardInfoQuery(handle, SD_INFO_SDIO, &sdioInfo, sizeof(sdioInfo)); if (!SD_API_SUCCESS(sdStatus)) { return FALSE; } funcNo = sdioInfo.FunctionNumber; sdStatus = SDCardInfoQuery(handle, SD_INFO_REGISTER_RCA, &cardRCA, sizeof(cardRCA)); HIF_DEBUG_PRINTF(ATH_LOG_INF, "Card RCA is 0x%x\n", cardRCA); /* Configure the SDIO Bus Width */ memset(&ci, 0, sizeof(ci)); if (sdio1bitmode) { ci.InterfaceMode = SD_INTERFACE_SD_MMC_1BIT; } else { ci.InterfaceMode = SD_INTERFACE_SD_4BIT; } if (sdiobusspeedlow) { ci.ClockRate = SDIO_CLOCK_FREQUENCY_REDUCED; } else { ci.ClockRate = SDIO_CLOCK_FREQUENCY_DEFAULT; } sdStatus = SDSetCardFeature(handle, SD_SET_CARD_INTERFACE, &ci, sizeof(ci)); if (!SD_API_SUCCESS(sdStatus)) { return FALSE; } /* Check if the target supports block mode */ sdStatus = SDReadWriteRegistersDirect(handle, SD_IO_READ, 0, 0x08, FALSE, &ucRegVal, 1); if (!SD_API_SUCCESS(sdStatus)) { return FALSE; } blockMode = (ucRegVal & 0x2) >> 1; // SMB is bit 1 if (!blockMode) { HIF_DEBUG_PRINTF(ATH_LOG_ERR, "Function does not support block mode\n"); return FALSE; } else { HIF_DEBUG_PRINTF(ATH_LOG_TRC, "Function supports block mode\n"); blockCap.ReadBlocks = blockCap.WriteBlocks = 8; blockCap.ReadBlockSize = blockCap.WriteBlockSize = HIF_MBOX_BLOCK_SIZE; sdStatus = SDCardInfoQuery(handle, SD_INFO_HOST_BLOCK_CAPABILITY, &blockCap, sizeof(blockCap)); if (blockCap.ReadBlockSize < blockCap.WriteBlockSize) { maxBlockSize = blockCap.ReadBlockSize; } else { maxBlockSize = blockCap.WriteBlockSize; } if (blockCap.ReadBlocks < blockCap.WriteBlocks) { maxBlocks = blockCap.ReadBlocks; } else { maxBlocks = blockCap.WriteBlocks; } sdStatus = SDGetTuple(handle, SD_CISTPL_FUNCE, NULL, &ulLength, FALSE); if ((!SD_API_SUCCESS(sdStatus)) || (ulLength > sizeof(rgucTuple)) ) { return FALSE; } sdStatus = SDGetTuple(handle, SD_CISTPL_FUNCE, rgucTuple, &ulLength, FALSE); if ((!SD_API_SUCCESS(sdStatus)) || (pFunce->bType != SD_CISTPL_FUNCE_FUNCTION_TYPE) ) { return FALSE; } if (maxBlockSize > pFunce->wMaxBlkSize) { maxBlockSize = pFunce->wMaxBlkSize; } bData = (DWORD)maxBlockSize; sdStatus = SDSetCardFeature(handle, SD_IO_FUNCTION_SET_BLOCK_SIZE, &bData, sizeof(bData)); } HIF_DEBUG_PRINTF(ATH_LOG_TRC, "Bytes Per Block: %d bytes, Block Count:%d \n", maxBlockSize, maxBlocks); /* Allocate the slot current */ /* Kowsalya : commenting as there is no equivalent for this in WINCE */ /* status = SDLIB_GetDefaultOpCurrent(handle, &slotCurrent.SlotCurrent); if (SDIO_SUCCESS(status)) { HIF_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Allocating Slot current: %d mA\n", slotCurrent.SlotCurrent)); status = SDLIB_IssueConfig(handle, SDCONFIG_FUNC_ALLOC_SLOT_CURRENT, &slotCurrent, sizeof(slotCurrent)); if (!SDIO_SUCCESS(status)) { HIF_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Failed to allocate slot current %d\n", status)); return FALSE; } } */ /* Inform HTC */ if ((htcCallbacks.deviceInsertedHandler(device)) != A_OK) { HIF_DEBUG_PRINTF(ATH_LOG_TRC, "Device rejected\n"); return FALSE; } #ifdef CEPC NdisInitializeEvent(&hifIRQEvent); hThread = CreateThread(NULL, 0, hifIRQThread, (LPVOID)handle, 0, NULL); CeSetThreadPriority(hThread, 200); CloseHandle(hThread); #endif //CEPC return TRUE; }
static A_STATUS __HIFReadWrite(HIF_DEVICE *device, A_UINT32 address, A_UCHAR *buffer, A_UINT32 length, A_UINT32 request, void *context) { A_UINT8 rw; A_UINT8 mode; A_UINT8 opcode; A_UINT32 blockLen, blockCount, count; PSD_BUS_REQUEST busRequest=NULL; A_STATUS status = A_OK; SD_TRANSFER_CLASS transferClass; DWORD dwArg; A_UCHAR command; SD_API_STATUS sdStatus; SD_COMMAND_RESPONSE response; NDIS_DEBUG_PRINTF(0, "%s() : Enter \r\n",__FUNCTION__); if(context != NULL) NDIS_DEBUG_PRINTF(0, "%s() : context = 0x%08x \r\n", __FUNCTION__,context); if ((request & HIF_BLOCK_BASIS) && (!(request & HIF_EXTENDED_IO))) { NDIS_DEBUG_PRINTF(DBG_ERR, "Block mode not allowed for this type of command\r\n"); return A_ERROR; } if (request & HIF_BLOCK_BASIS) { mode = SD_IO_BLOCK_MODE; blockLen = HIF_MBOX_BLOCK_SIZE; blockCount = length / HIF_MBOX_BLOCK_SIZE; count = blockCount; } else if (request & HIF_BYTE_BASIS) { mode = SD_IO_BYTE_MODE; blockLen = length; blockCount = 1; count = blockLen; } else { NDIS_DEBUG_PRINTF(DBG_ERR, "Invalid data mode: %08x\r\n", request); return A_ERROR; } if (request & HIF_FIXED_ADDRESS) { opcode = SD_IO_FIXED_ADDRESS; NDIS_DEBUG_PRINTF(DBG_TRACE, "Fixed "); } else if (request & HIF_INCREMENTAL_ADDRESS) { opcode = SD_IO_INCREMENT_ADDRESS; NDIS_DEBUG_PRINTF(0, "Incremental "); } else { NDIS_DEBUG_PRINTF(DBG_ERR, "Invalid address mode: %08x\r\n", request); return A_ERROR; } if (request & HIF_WRITE) { transferClass = SD_WRITE; rw = SD_IO_OP_WRITE; if ((address >= HIF_MBOX_START_ADDR(0)) && (address <= HIF_MBOX_END_ADDR(3))) { /* Mailbox write. Adjust the address so that the last byte falls on the EOM address */ address = address + HIF_MBOX_WIDTH - length; } NDIS_DEBUG_PRINTF(0, "[Write]"); } else { transferClass = SD_READ; rw = SD_IO_OP_READ; NDIS_DEBUG_PRINTF(0, "[Read ] \r\n"); } if (request & HIF_EXTENDED_IO) { dwArg = BUILD_IO_RW_EXTENDED_ARG(rw, mode, funcNo, address, opcode, count); command = SD_IO_RW_EXTENDED; } else if (request & HIF_BASIC_IO) { dwArg = BUILD_IO_RW_DIRECT_ARG(rw, SD_IO_RW_NORMAL, funcNo, address, 0); command = SD_IO_RW_NORMAL; } else { NDIS_DEBUG_PRINTF(DBG_ERR, "Invalid command type: %08x\r\n", request); return A_ERROR; } if((request & HIF_READ) && (dwArg > 0x14000000)) { NDIS_DEBUG_PRINTF(DBG_TRACE, "Synchronous, command = %d, dwArg = 0x%08x, funcNo=%d \r\n", command, dwArg,funcNo); NDIS_DEBUG_PRINTF(0, "blockCount=%d,blockLen=%d \r\n", blockCount, blockLen); } sdStatus = SDSynchronousBusRequest(device->handle, command, dwArg, transferClass, ResponseR5, &response, blockCount, blockLen, buffer, 0); if (!SD_API_SUCCESS(sdStatus)) { NDIS_DEBUG_PRINTF(DBG_ERR, "SDBusRequest failed 0x%x, device->handle = 0x%x, buffer = 0x%x\r\n", sdStatus, device->handle, buffer); NDIS_DEBUG_PRINTF(DBG_ERR, "1[%d]2[%d]3[%d]4[%d]5[%d]6[%d] \r\n",buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],buffer[5]); status = A_ERROR; } if(status != A_OK) NDIS_DEBUG_PRINTF(DBG_ERR, "%s() : Status = %d - Exit \r\n",__FUNCTION__, status); return status; }
static BOOL SetupSDIOInterface(HIF_DEVICE *device) { SD_API_STATUS sdStatus; SDIO_CARD_INFO sdioInfo; SD_HOST_BLOCK_CAPABILITY blockCap; SD_CARD_RCA cardRCA; A_UCHAR rgucTuple[SD_CISTPLE_MAX_BODY_SIZE]; PSD_CISTPL_FUNCE_FUNCTION pFunce = (PSD_CISTPL_FUNCE_FUNCTION) rgucTuple; A_UINT32 ulLength = 0; A_UCHAR ucRegVal; A_BOOL blockMode; SD_CARD_INTERFACE ci; SD_IO_FUNCTION_ENABLE_INFO fData; DWORD bData; BOOL doInterfaceChange = FALSE; SD_DEVICE_HANDLE handle; int count; handle = device->handle; NDIS_DEBUG_PRINTF(1, "%s() : Enter + \r\n",__FUNCTION__); /* Enable SDIO [dragon] function */ fData.Interval = DEFAULT_SDIO_FUNCTION_RETRY_TIMEOUT; fData.ReadyRetryCount = DEFAULT_SDIO_FUNCTION_RETRIES; sdStatus = SDSetCardFeature (handle, SD_IO_FUNCTION_ENABLE, &fData, sizeof(fData)); if (!SD_API_SUCCESS(sdStatus)) { NDIS_DEBUG_PRINTF(DBG_ERR, "SDSetCardFeature (0x%x)\n", sdStatus); return FALSE; } /* * Issue commands to get the manufacturer ID and stuff and compare it * against the rev Id derived from the ID registered during the * initialization process. Report the device only in the case there * is a match. */ sdStatus = SDCardInfoQuery(handle, SD_INFO_SDIO, &sdioInfo, sizeof(sdioInfo)); if (!SD_API_SUCCESS(sdStatus)) { NDIS_DEBUG_PRINTF(DBG_ERR, "SDCardInfoQuery (0x%x) \r\n", sdStatus); return FALSE; } funcNo = sdioInfo.FunctionNumber; sdStatus = SDCardInfoQuery(handle, SD_INFO_REGISTER_RCA, &cardRCA, sizeof(cardRCA)); NDIS_DEBUG_PRINTF(1, "Card RCA is 0x%x \r\n", cardRCA); /* Configure the SDIO Bus Width */ memset(&ci, 0, sizeof(ci)); /* get current interface settings */ sdStatus = SDCardInfoQuery(handle, SD_INFO_CARD_INTERFACE, &ci, sizeof(ci)); if (!SD_API_SUCCESS(sdStatus)) { NDIS_DEBUG_PRINTF(DBG_ERR, "%s() : ERR, SDCardInfoQuery Fail !!\r\n",__FUNCTION__); return FALSE; } //DebugBreak(); #ifdef HIF_SDIO_1BIT /* force to 1 bit mode */ sdio1bitmode = 1; #endif if (sdio1bitmode && (ci.InterfaceMode != SD_INTERFACE_SD_MMC_1BIT)) { /* force to 1 bit mode */ ci.InterfaceMode = SD_INTERFACE_SD_MMC_1BIT; doInterfaceChange = TRUE; } /* check for forced low speed operation */ if (sdiobusspeedlow) { /* only set the lower of our current rate and our desired reduced rate, * otherwise we run at a clock rate that the bus driver setup for us */ ci.ClockRate = min(ci.ClockRate, SDIO_CLOCK_FREQUENCY_REDUCED); doInterfaceChange = TRUE; } if (doInterfaceChange) { sdStatus = SDSetCardFeature(handle, SD_SET_CARD_INTERFACE, &ci, sizeof(ci)); if (!SD_API_SUCCESS(sdStatus)) { NDIS_DEBUG_PRINTF(DBG_ERR, "%s() : SDSetCardFeature Fail !!\r\n",__FUNCTION__); return FALSE; } } NDIS_DEBUG_PRINTF(DBG_TRACE, ("** SDIO Interface : %s : %d (%s)\r\n", doInterfaceChange ? "Overridden to" : "Set by busdriver", ci.ClockRate, (ci.InterfaceMode == SD_INTERFACE_SD_MMC_1BIT) ? "1-bit" : "4-bit")); /* save card interface mode to restore later */ A_MEMCPY(&device->CardInterface, &ci, sizeof(ci)); /* Check if the target supports block mode */ sdStatus = SDReadWriteRegistersDirect(handle, SD_IO_READ, 0, 0x08, FALSE, &ucRegVal, 1); if (!SD_API_SUCCESS(sdStatus)) { NDIS_DEBUG_PRINTF(DBG_ERR, "%s() : SDReadWriteRegistersDirect Fail !!\r\n",__FUNCTION__); return FALSE; } blockMode = (ucRegVal & 0x2) >> 1; // SMB is bit 1 if (!blockMode) { NDIS_DEBUG_PRINTF(DBG_ERR, ("Function does not support block mode\n")); return FALSE; } else { NDIS_DEBUG_PRINTF(DBG_TRACE, ("Function supports block mode \r\n")); blockCap.ReadBlocks = blockCap.WriteBlocks = 8; blockCap.ReadBlockSize = blockCap.WriteBlockSize = HIF_MBOX_BLOCK_SIZE; sdStatus = SDCardInfoQuery(handle, SD_INFO_HOST_BLOCK_CAPABILITY, &blockCap, sizeof(blockCap)); if (blockCap.ReadBlockSize < blockCap.WriteBlockSize) { maxBlockSize = blockCap.ReadBlockSize; } else { maxBlockSize = blockCap.WriteBlockSize; } if (blockCap.ReadBlocks < blockCap.WriteBlocks) { maxBlocks = blockCap.ReadBlocks; } else { maxBlocks = blockCap.WriteBlocks; } sdStatus = SDGetTuple(handle, SD_CISTPL_FUNCE, NULL, &ulLength, FALSE); if ((!SD_API_SUCCESS(sdStatus)) || (ulLength > sizeof(rgucTuple)) ) { return FALSE; } sdStatus = SDGetTuple(handle, SD_CISTPL_FUNCE, rgucTuple, &ulLength, FALSE); if ((!SD_API_SUCCESS(sdStatus)) || (pFunce->bType != SD_CISTPL_FUNCE_FUNCTION_TYPE) ) { return FALSE; } if (maxBlockSize > pFunce->wMaxBlkSize) { maxBlockSize = pFunce->wMaxBlkSize; } bData = (DWORD)maxBlockSize; sdStatus = SDSetCardFeature(handle, SD_IO_FUNCTION_SET_BLOCK_SIZE, &bData, sizeof(bData)); } NDIS_DEBUG_PRINTF(DBG_TRACE, "Bytes Per Block: %d bytes, Block Count:%d \r\n", maxBlockSize, maxBlocks); /* Initialize the bus requests to be used later */ A_MEMZERO(device->busRequest, sizeof(device->busRequest)); for (count = 0; count < BUS_REQUEST_MAX_NUM; count ++) { NdisInitializeEvent(&device->busRequest[count].sem_req); hifFreeBusRequest(device, &device->busRequest[count]); } return TRUE; }
BOOL CSDHCBase::Init( LPCTSTR pszActiveKey ) { BOOL fRet = FALSE; SD_API_STATUS status; HKEY hkDevice = NULL; hkDevice = OpenDeviceKey(pszActiveKey); if (!hkDevice || !m_regDevice.Open(hkDevice, _T(""))) { DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHC: Failed to open device key\n"))); goto EXIT; } // Get a handle to our parent bus. m_hBusAccess = CreateBusAccessHandle(pszActiveKey); if (m_hBusAccess == NULL) { DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHC: Could not get handle to parent\n"))); goto EXIT; } m_cSlots = DetermineSlotCount(); if (m_cSlots == 0) { goto EXIT; } ValidateSlotCount(); RETAILMSG(0,(TEXT("CSDHCBase::Init m_cSlots=%d\n"),m_cSlots)); // jylee m_pSlotInfos = (PSDHC_SLOT_INFO) LocalAlloc(LPTR, sizeof(SDHC_SLOT_INFO) * m_cSlots); if (m_pSlotInfos == NULL) { DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHC Failed to allocate slot info objects\n"))); goto EXIT; } status = SDHCDAllocateContext(m_cSlots, &m_pHCDContext); if (!SD_API_SUCCESS(status)) { DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHC Failed to allocate context : 0x%08X \n"), status)); goto EXIT; } // Set our extension m_pHCDContext->pHCSpecificContext = this; if (!InitializeHardware()) { goto EXIT; } RETAILMSG(0,(TEXT("AllocateSlotObjects\n"))); // Allocate slot objects m_pSlots = AllocateSlotObjects(m_cSlots); if (m_pSlots == NULL) { DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHC Failed to allocate slot objects\n"))); goto EXIT; } // Initialize the slots for (DWORD dwSlot = 0; dwSlot < m_cSlots; ++dwSlot) { PSDHC_SLOT_INFO pSlotInfo = &m_pSlotInfos[dwSlot]; PCSDHCSlotBase pSlot = GetSlot(dwSlot); RETAILMSG(0,(TEXT("pSlot->Init\n"))); RETAILMSG(0,(TEXT("pSlotInfo->pucRegisters : 0x%x\r\n"),pSlotInfo->pucRegisters)); if (!pSlot->Init(dwSlot, pSlotInfo->pucRegisters, m_pHCDContext, m_dwSysIntr, m_hBusAccess, m_interfaceType, m_dwBusNumber, &m_regDevice)) { goto EXIT; } } // set the host controller name SDHCDSetHCName(m_pHCDContext, TEXT("HSMMC")); // set init handler SDHCDSetControllerInitHandler(m_pHCDContext, CSDHCBase::SDHCInitialize); // set deinit handler SDHCDSetControllerDeinitHandler(m_pHCDContext, CSDHCBase::SDHCDeinitialize); // set the Send packet handler SDHCDSetBusRequestHandler(m_pHCDContext, CSDHCBase::SDHCBusRequestHandler); // set the cancel I/O handler SDHCDSetCancelIOHandler(m_pHCDContext, CSDHCBase::SDHCCancelIoHandler); // set the slot option handler SDHCDSetSlotOptionHandler(m_pHCDContext, CSDHCBase::SDHCSlotOptionHandler); // These values must be set before calling SDHCDRegisterHostController() // because they are used during that call. m_dwPriority = m_regDevice.ValueDW(SDHC_PRIORITY_KEY, SDHC_CARD_CONTROLLER_PRIORITY); RETAILMSG(0,(TEXT("SDHCDRegisterHostController\n"))); // jylee // now register the host controller status = SDHCDRegisterHostController(m_pHCDContext); if (!SD_API_SUCCESS(status)) { DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHC Failed to register host controller: %0x08X \n"), status)); goto EXIT; } m_fRegisteredWithBusDriver = TRUE; fRet = TRUE; RETAILMSG(0,(TEXT("CSDHCBase::Init Finished.\n"))); // jylee EXIT: if (hkDevice) RegCloseKey(hkDevice); return fRet; }
SD_API_STATUS CSDHCBase::SlotOptionHandler( DWORD dwSlot, SD_SLOT_OPTION_CODE sdOption, PVOID pData, DWORD cbData ) { SD_API_STATUS status = SD_API_STATUS_SUCCESS; BOOL fCallSlotsHandler = TRUE; Lock(); Validate(); PCSDHCSlotBase pSlot = GetSlot(dwSlot); DEBUGCHK(sdOption < dim(sc_rgpszOptions)); DEBUGCHK(sc_rgpszOptions[sdOption] != NULL); DEBUGMSG(SDCARD_ZONE_INFO, (_T("CSDHCBase::SlotOptionHandler(%u, %s)\n"), dwSlot, sc_rgpszOptions[sdOption])); switch (sdOption) { case SDHCDSetSlotPower: { if (cbData != sizeof(DWORD)) { status = SD_API_STATUS_INVALID_PARAMETER; } break; } case SDHCDSetSlotInterface: { if (cbData != sizeof(SD_CARD_INTERFACE)) { status = SD_API_STATUS_INVALID_PARAMETER; } break; } case SDHCDEnableSDIOInterrupts: case SDHCDDisableSDIOInterrupts: case SDHCDAckSDIOInterrupt: if (pData || cbData != 0) { status = SD_API_STATUS_INVALID_PARAMETER; } break; case SDHCDGetWriteProtectStatus: { if (cbData != sizeof(SD_CARD_INTERFACE)) { status = SD_API_STATUS_INVALID_PARAMETER; } break; } case SDHCDQueryBlockCapability: { if (cbData != sizeof(SD_HOST_BLOCK_CAPABILITY)) { status = SD_API_STATUS_INVALID_PARAMETER; } break; } case SDHCDSetSlotPowerState: { if (cbData != sizeof(CEDEVICE_POWER_STATE)) { status = SD_API_STATUS_INVALID_PARAMETER; } PCEDEVICE_POWER_STATE pcps = (PCEDEVICE_POWER_STATE) pData; if (*pcps < m_cpsCurrent) { // Move controller to higher power state initially since // it will need to be powered for the slot to access // registers. SetControllerPowerState(*pcps); } status = pSlot->SlotOptionHandler(sdOption, pData, cbData); // Set the power state based on current conditions. Note that // the slot may have gone to a state different from what was // requested. CEDEVICE_POWER_STATE cps = DetermineRequiredControllerPowerState(); SetControllerPowerState(cps); fCallSlotsHandler = FALSE; break; } case SDHCDGetSlotPowerState: { if (cbData != sizeof(CEDEVICE_POWER_STATE)) { status = SD_API_STATUS_INVALID_PARAMETER; } break; } case SDHCDWakeOnSDIOInterrupts: { if (cbData != sizeof(BOOL)) { status = SD_API_STATUS_INVALID_PARAMETER; } break; } case SDHCDGetSlotInfo: { if (cbData != sizeof(SDCARD_HC_SLOT_INFO)) { status = SD_API_STATUS_INVALID_PARAMETER; } break; } default: break; } if (SD_API_SUCCESS(status) && fCallSlotsHandler) { // Call the slots handler to do the real work. status = pSlot->SlotOptionHandler(sdOption, pData, cbData); } Unlock(); return status; }
BOOL hifDeviceInserted(SD_DEVICE_HANDLE *handle) { HIF_DEVICE *device; #if 0 SD_API_STATUS sdStatus; SDIO_CARD_INFO sdioInfo; SD_HOST_BLOCK_CAPABILITY blockCap; SD_CARD_RCA cardRCA; A_UCHAR rgucTuple[SD_CISTPLE_MAX_BODY_SIZE]; PSD_CISTPL_FUNCE_FUNCTION pFunce = (PSD_CISTPL_FUNCE_FUNCTION) rgucTuple; A_UINT32 ulLength = 0; A_UCHAR ucRegVal; A_BOOL blockMode; SD_CARD_INTERFACE ci; SD_IO_FUNCTION_ENABLE_INFO fData; DWORD bData; //SDCONFIG_FUNC_SLOT_CURRENT_DATA slotCurrent; //HANDLE hIrqThread; #endif HANDLE hThread; device = addHifDevice(handle); NDIS_DEBUG_PRINTF(1, "hifDeviceInserted: Enter\r\n"); #if 0 /* Enable SDIO [dragon] function */ fData.Interval = DEFAULT_SDIO_FUNCTION_RETRY_TIMEOUT; fData.ReadyRetryCount = DEFAULT_SDIO_FUNCTION_RETRIES; sdStatus = SDSetCardFeature (handle, SD_IO_FUNCTION_ENABLE, &fData, sizeof(fData)); if (!SD_API_SUCCESS(sdStatus)) { return FALSE; } /* * Issue commands to get the manufacturer ID and stuff and compare it * against the rev Id derived from the ID registered during the * initialization process. Report the device only in the case there * is a match. */ sdStatus = SDCardInfoQuery(handle, SD_INFO_SDIO, &sdioInfo, sizeof(sdioInfo)); if (!SD_API_SUCCESS(sdStatus)) { return FALSE; } funcNo = sdioInfo.FunctionNumber; sdStatus = SDCardInfoQuery(handle, SD_INFO_REGISTER_RCA, &cardRCA, sizeof(cardRCA)); NDIS_DEBUG_PRINTF(1, " Card RCA is 0x%x \r\n", cardRCA); /* Configure the SDIO Bus Width */ memset(&ci, 0, sizeof(ci)); if (sdio1bitmode) { ci.InterfaceMode = SD_INTERFACE_SD_MMC_1BIT; } else { ci.InterfaceMode = SD_INTERFACE_SD_4BIT; } if (sdiobusspeedlow) { ci.ClockRate = SDIO_CLOCK_FREQUENCY_REDUCED; } else { ci.ClockRate = SDIO_CLOCK_FREQUENCY_DEFAULT; } sdStatus = SDSetCardFeature(handle, SD_SET_CARD_INTERFACE, &ci, sizeof(ci)); if (!SD_API_SUCCESS(sdStatus)) { return FALSE; } /* Check if the target supports block mode */ sdStatus = SDReadWriteRegistersDirect(handle, SD_IO_READ, 0, 0x08, FALSE, &ucRegVal, 1); if (!SD_API_SUCCESS(sdStatus)) { return FALSE; } blockMode = (ucRegVal & 0x2) >> 1; // SMB is bit 1 if (!blockMode) { NDIS_DEBUG_PRINTF(DBG_ERR, "[HIF] Function does not support block mode \r\n"); return FALSE; } else { NDIS_DEBUG_PRINTF(DBG_LEVEL_HIF, "[HIF] Function supports block mode \r\n"); blockCap.ReadBlocks = blockCap.WriteBlocks = 8; blockCap.ReadBlockSize = blockCap.WriteBlockSize = HIF_MBOX_BLOCK_SIZE; sdStatus = SDCardInfoQuery(handle, SD_INFO_HOST_BLOCK_CAPABILITY, &blockCap, sizeof(blockCap)); if (blockCap.ReadBlockSize < blockCap.WriteBlockSize) { maxBlockSize = blockCap.ReadBlockSize; } else { maxBlockSize = blockCap.WriteBlockSize; } if (blockCap.ReadBlocks < blockCap.WriteBlocks) { maxBlocks = blockCap.ReadBlocks; } else { maxBlocks = blockCap.WriteBlocks; } sdStatus = SDGetTuple(handle, SD_CISTPL_FUNCE, NULL, &ulLength, FALSE); if ((!SD_API_SUCCESS(sdStatus)) || (ulLength > sizeof(rgucTuple)) ) { return FALSE; } sdStatus = SDGetTuple(handle, SD_CISTPL_FUNCE, rgucTuple, &ulLength, FALSE); if ((!SD_API_SUCCESS(sdStatus)) || (pFunce->bType != SD_CISTPL_FUNCE_FUNCTION_TYPE) ) { return FALSE; } if (maxBlockSize > pFunce->wMaxBlkSize) { maxBlockSize = pFunce->wMaxBlkSize; } bData = (DWORD)maxBlockSize; sdStatus = SDSetCardFeature(handle, SD_IO_FUNCTION_SET_BLOCK_SIZE, &bData, sizeof(bData)); } NDIS_DEBUG_PRINTF(DBG_LEVEL_HIF, "Bytes Per Block: %d bytes, Block Count:%d \r\n", maxBlockSize, maxBlocks); /* Allocate the slot current */ /* Kowsalya : commenting as there is no equivalent for this in WINCE */ /* status = SDLIB_GetDefaultOpCurrent(handle, &slotCurrent.SlotCurrent); if (SDIO_SUCCESS(status)) { HIF_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Allocating Slot current: %d mA\n", slotCurrent.SlotCurrent)); status = SDLIB_IssueConfig(handle, SDCONFIG_FUNC_ALLOC_SLOT_CURRENT, &slotCurrent, sizeof(slotCurrent)); if (!SDIO_SUCCESS(status)) { HIF_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Failed to allocate slot current %d\n", status)); return FALSE; } } */ /* Initialize the bus requests to be used later */ A_MEMZERO(device->busRequest, sizeof(device->busRequest)); for (count = 0; count < BUS_REQUEST_MAX_NUM; count ++) { NdisInitializeEvent(&device->busRequest[count].sem_req); hifFreeBusRequest(device, &device->busRequest[count]); } #else SetupSlotPowerControl(device); if (!SetupSDIOInterface(device)) { return FALSE; } #endif InitializeCriticalSection(&gCriticalSection); //ÃʱâÈ device->async_shutdown = 0; hThread = CreateThread(NULL, 0, async_task, (void *)device, 0, NULL); CeSetThreadPriority(hThread, 200); CloseHandle(hThread); NdisInitializeEvent(&device->sem_async); #if USE_IRQ_THREAD hThread = CreateThread(NULL, 0, hifIRQThread, (void *)device, 0, NULL); CeSetThreadPriority(hThread, 200); CloseHandle(hThread); NdisInitializeEvent(&hifIRQEvent); #endif /* start up inform DRV layer */ if ((osdrvCallbacks.deviceInsertedHandler(osdrvCallbacks.context,device)) != A_OK) { NDIS_DEBUG_PRINTF(DBG_ERR, "[HIF] AR6000: Device rejected \r\n"); } NDIS_DEBUG_PRINTF(DBG_LEVEL_HIF, " %s() -Exit \r\n",__FUNCTION__); return TRUE; }
SD_API_STATUS GetFirstFailedStatus() { if (SD_API_SUCCESS(Status) && m_pChildListNext!=NULL ) return m_pChildListNext->GetFirstFailedStatus(); else return Status; }
// New Start function for Card detect of HSMMC ch1 on SMDK6410. SD_API_STATUS CSDHControllerCh1::Start() { SD_API_STATUS status = SD_API_STATUS_INSUFFICIENT_RESOURCES; m_fDriverShutdown = FALSE; // allocate the interrupt event m_hevInterrupt = CreateEvent(NULL, FALSE, FALSE,NULL); if (NULL == m_hevInterrupt) { goto EXIT; } // initialize the interrupt event if (!InterruptInitialize (m_dwSysIntr, m_hevInterrupt, NULL, 0)) { goto EXIT; } m_fInterruptInitialized = TRUE; // create the interrupt thread for controller interrupts m_htIST = CreateThread(NULL, 0, ISTStub, this, 0, NULL); if (NULL == m_htIST) { goto EXIT; } // allocate the card detect event m_hevCardDetectEvent = CreateEvent(NULL, FALSE, FALSE,NULL); if (NULL == m_hevCardDetectEvent) { goto EXIT; } // initialize the interrupt event if (!InterruptInitialize (m_dwSDDetectSysIntr, m_hevCardDetectEvent, NULL, 0)) { goto EXIT; } // create the card detect interrupt thread m_htCardDetectThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)SD_CardDetectThread, this, 0, NULL); if (NULL == m_htCardDetectThread) { goto EXIT; } for (DWORD dwSlot = 0; dwSlot < m_cSlots; ++dwSlot) { PCSDHCSlotBase pSlot = GetSlot(dwSlot); status = pSlot->Start(); if (!SD_API_SUCCESS(status)) { goto EXIT; } } // wake up the interrupt thread to check the slot ::SetInterruptEvent(m_dwSDDetectSysIntr); status = SD_API_STATUS_SUCCESS; EXIT: if (!SD_API_SUCCESS(status)) { // Clean up Stop(); } return status; }
BOOL CSDBusRequest::CheckForCompletion() { if (m_pParentBus!=NULL) { return m_pParentBus->CheckForCompletion(); } else if (IsComplete()) { // This one is completed. if (SD_API_SUCCESS(Status) && m_pChildListNext!=NULL) { Status = m_pChildListNext->GetFirstFailedStatus(); } #ifdef DEBUG SD_CARD_STATUS cardStatus; if (SDBUS_ZONE_REQUEST) { DEBUGMSG(SDBUS_ZONE_REQUEST, (TEXT("--- SDBusDriver: CMD%d CMDArg: 0x%08X TransferClass:%d ResponseType: %s Complete\n"), CommandCode, CommandArgument,TransferClass, SDCardResponseTypeLookUp[CommandResponse.ResponseType & 0x7])); if (SD_API_SUCCESS(Status)) { if ( (ResponseR1 == CommandResponse.ResponseType) || (ResponseR1b == CommandResponse.ResponseType)) { SDGetCardStatusFromResponse(&CommandResponse, &cardStatus); DEBUGMSG(SDBUS_ZONE_REQUEST, (TEXT("--- SDBusDriver: R1,R1b Response, Card Status: 0x%08X, Last State: %s \n"), cardStatus, SDCardStateStringLookUp[((CommandResponse.ResponseBuffer[2] >> 1) & 0x0F)])); } if (NoResponse != CommandResponse.ResponseType) { DEBUGMSG(SDBUS_ZONE_REQUEST, (TEXT("--- SDBusDriver: Response Dump: \n"))); if (ResponseR2 == CommandResponse.ResponseType) { SDOutputBuffer(CommandResponse.ResponseBuffer, 17); } else { SDOutputBuffer(CommandResponse.ResponseBuffer, 6); } } if (NULL != pBlockBuffer) { if (SD_READ == TransferClass) { DEBUGMSG(SDBUS_ZONE_REQUEST, (TEXT("--- SDBusDriver: Read Data Transfered : NumBlocks:%d BytesPerBlock:%d \n"), NumBlocks, BlockSize)); if (SDBUS_ZONE_BUFFER) { DEBUGMSG(SDBUS_ZONE_BUFFER, (TEXT("--- SDBusDriver: Read Data Dump: \n"))); SDOutputBuffer(pBlockBuffer, NumBlocks * BlockSize); } } else { DEBUGMSG(SDBUS_ZONE_REQUEST, (TEXT("--- SDBusDriver: Write Transfer Complete: NumBlocks:%d BytesPerBlock:%d\n"), NumBlocks, BlockSize)); } } } } #endif PSD_BUS_REQUEST_CALLBACK pCallbackPtr = (PSD_BUS_REQUEST_CALLBACK)InterlockedExchange( (LPLONG)&pCallback, NULL); // Make sure only call once. if (pCallbackPtr) { __try { /* For Windows CE 6.0 if (m_hCallback) { IO_BUS_SD_REQUEST_CALLBACK busSdRequestCallback = { pCallbackPtr, m_sdDevice.GetDeviceHandle().hValue,m_ExternalHandle, m_sdDevice.GetDeviceContext(), RequestParam }; CeDriverPerformCallback( m_hCallback, IOCTL_BUS_SD_REQUEST_CALLBACK,&busSdRequestCallback,sizeof(busSdRequestCallback), NULL,0,NULL,NULL); } else */ { pCallbackPtr(m_sdDevice.GetDeviceHandle().hValue, // device handle (PSD_BUS_REQUEST)m_ExternalHandle, // the request m_sdDevice.GetDeviceContext(), // device context RequestParam); // request argument } } __except (SDProcessException(GetExceptionInformation())) { DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("--- SDBusDriver: Exception caught in CompleteRequest when calling callback in device %s \n"), m_sdDevice.GetClientName())); } } }
/////////////////////////////////////////////////////////////////////////////// // SDMemCardConfig - Initialise the memcard structure and card itself // Input: pMemCard - SD memory card structure // Output: // Return: win32 status code // Notes: /////////////////////////////////////////////////////////////////////////////// DWORD SDMemCardConfig( PSD_MEMCARD_INFO pMemCard ) { DWORD status = ERROR_SUCCESS; // intermediate win32 status DWORD dwSDHC; // high capacity value SD_API_STATUS apiStatus; // intermediate SD API status SD_CARD_INTERFACE cardInterface; // card interface SD_DATA_TRANSFER_CLOCKS dataTransferClocks; // data transfer clocks // retrieve CID Register contents apiStatus = SDCardInfoQuery( pMemCard->hDevice, SD_INFO_REGISTER_CID, &(pMemCard->CIDRegister), sizeof(SD_PARSED_REGISTER_CID) ); if(!SD_API_SUCCESS(apiStatus)) { DEBUGMSG(SDCARD_ZONE_ERROR,(TEXT("SDMemCardConfig: Can't read CID Register\r\n"))); return ERROR_GEN_FAILURE; } // Retrieve CSD Register contents apiStatus = SDCardInfoQuery( pMemCard->hDevice, SD_INFO_REGISTER_CSD, &(pMemCard->CSDRegister), sizeof(SD_PARSED_REGISTER_CSD) ); if(!SD_API_SUCCESS(apiStatus)) { DEBUGMSG(SDCARD_ZONE_ERROR,(TEXT("SDMemCardConfig: Can't read CSD Register\r\n"))); return ERROR_GEN_FAILURE; } // retreive the card's RCA apiStatus = SDCardInfoQuery(pMemCard->hDevice, SD_INFO_REGISTER_RCA, &(pMemCard->RCA), sizeof(pMemCard->RCA)); if(!SD_API_SUCCESS(apiStatus)) { DEBUGMSG(SDCARD_ZONE_ERROR,(TEXT("SDMemCardConfig: Can't read RCA \r\n"))); return ERROR_GEN_FAILURE; } // get write protect state apiStatus = SDCardInfoQuery( pMemCard->hDevice, SD_INFO_CARD_INTERFACE, &cardInterface, sizeof(cardInterface)); if(!SD_API_SUCCESS(apiStatus)) { DEBUGMSG(SDCARD_ZONE_ERROR,(TEXT("SDMemCardConfig: Can't read Card Interface\r\n"))); return ERROR_GEN_FAILURE; } // Get write protect state from Card Interface structure pMemCard->WriteProtected = cardInterface.WriteProtected; if( pMemCard->WriteProtected ) { DEBUGMSG(SDCARD_ZONE_INIT, (TEXT("SDMemCardConfig: Card is write protected\r\n"))); } // get capacity information apiStatus = SDCardInfoQuery( pMemCard->hDevice, SD_INFO_HIGH_CAPACITY_SUPPORT, &dwSDHC, sizeof(dwSDHC)); if(!SD_API_SUCCESS(apiStatus)) { pMemCard->HighCapacity = FALSE; } else { pMemCard->HighCapacity = dwSDHC != 0; } if( pMemCard->HighCapacity ) { DEBUGMSG(SDCARD_ZONE_INIT, (TEXT("SDMemCardConfig: Card is high capacity (2.0+)\r\n"))); } // If the card doesn't support block reads, then fail if (!(pMemCard->CSDRegister.CardCommandClasses & SD_CSD_CCC_BLOCK_READ)) { DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDMemCardConfig: Card does not support block read\r\n"))); return ERROR_BAD_DEVICE; } // If the card doesn't support block writes, then mark the card as // write protected if (!(pMemCard->CSDRegister.CardCommandClasses & SD_CSD_CCC_BLOCK_WRITE)) { DEBUGMSG(SDCARD_ZONE_INIT || SDCARD_ZONE_WARN, (TEXT("SDMemCardConfig: Card does not support block write; mark as WP\r\n"))); pMemCard->WriteProtected = TRUE; } // Calculate read and write data access clocks to fine tune access times if( !SDMemCalcDataAccessClocks( pMemCard, &dataTransferClocks.ReadClocks, &dataTransferClocks.WriteClocks) ) { DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDMemCardConfig: Unable to calculate data access clocks\r\n"))); return ERROR_GEN_FAILURE; } // Call API to set the read and write data access clocks apiStatus = SDSetCardFeature( pMemCard->hDevice, SD_SET_DATA_TRANSFER_CLOCKS, &dataTransferClocks, sizeof(dataTransferClocks)); if(!SD_API_SUCCESS(apiStatus)) { DEBUGMSG(SDCARD_ZONE_ERROR,(TEXT("SDMemCardConfig: Can't set data access clocks\r\n"))); return ERROR_GEN_FAILURE; } // FATFS only supports 512 bytes per sector so set that pMemCard->DiskInfo.di_bytes_per_sect = SD_BLOCK_SIZE; // indicate that we aren't using Cylinder/Head/Sector addressing, // and that reads and writes are synchronous. pMemCard->DiskInfo.di_flags = DISK_INFO_FLAG_CHS_UNCERTAIN | DISK_INFO_FLAG_PAGEABLE; // since we aren't using C/H/S addressing we can set the counts of these // items to zero pMemCard->DiskInfo.di_cylinders = 0; pMemCard->DiskInfo.di_heads = 0; pMemCard->DiskInfo.di_sectors = 0; // Work out whether we have a Master Boot Record switch( pMemCard->CSDRegister.FileSystem ) { case SD_FS_FAT_PARTITION_TABLE: // yes, we have a MBR pMemCard->DiskInfo.di_flags |= DISK_INFO_FLAG_MBR; break; case SD_FS_FAT_NO_PARTITION_TABLE: // no, we don't have a MBR break; default: // ee don't do "Other" file systems DEBUGMSG( SDCARD_ZONE_ERROR, (TEXT("SDMemCardConfig: Card indicates unsupported file system (non FAT)\r\n"))); return ERROR_GEN_FAILURE; } // calculate total number of sectors on the card // // NOTE:The bus is only using BLOCK units instead of BYTE units if // the device type is SD (not MMC) and if the CSDVersion is SD_CSD_VERSION_CODE_2_0. // Since we don't have access to the device type, we are checking to see if it is // a high definition card. This should work for most cases. // if( pMemCard->CSDRegister.CSDVersion == SD_CSD_VERSION_CODE_2_0 && pMemCard->HighCapacity ) { pMemCard->DiskInfo.di_total_sectors = pMemCard->CSDRegister.DeviceSize; #ifdef _MMC_SPEC_42_ // Date : 07.05.14 // Developer : HS.JANG // Description : If MMC card is on SPEC42 } else if (pMemCard->CSDRegister.SpecVersion >= HSMMC_CSD_SPEC_VERSION_CODE_SUPPORTED ) { #ifdef _FOR_MOVI_NAND_ // Date : 07.05.28 // Developer : HS.JANG // Description : There is no way to distinguish between HSMMC // and moviNAND. So, We assume that All HSMMC // card is the moviNAND pMemCard->IsHSMMC = TRUE; #endif if( (signed)(pMemCard->CSDRegister.SectorCount) > 0) { RETAILMSG(1,(TEXT("[HSMMC] This MMC card is on SPEC42.\n"))); pMemCard->DiskInfo.di_total_sectors = pMemCard->CSDRegister.SectorCount; pMemCard->HighCapacity = TRUE; } else { pMemCard->DiskInfo.di_total_sectors = pMemCard->CSDRegister.DeviceSize/SD_BLOCK_SIZE; } #endif } else { pMemCard->DiskInfo.di_total_sectors = pMemCard->CSDRegister.DeviceSize/SD_BLOCK_SIZE; } // FATFS and the SD Memory file spec only supports 512 byte sectors. An SD Memory // card will ALWAYS allow us to read and write in 512 byte blocks - but it might // be configured for a larger size initially. We set the size to 512 bytes here if needed. if( pMemCard->CSDRegister.MaxReadBlockLength != SD_BLOCK_SIZE ) { // Set block length to 512 bytes status = SDMemSetBlockLen( pMemCard, SD_BLOCK_SIZE ); } return status; }
/////////////////////////////////////////////////////////////////////////////// // IssueCardSelectDeSelect - issue card select // Input: pMemCard - memory card instance // Select - select the card // Output: // Return: SD_API_STATUS code // Notes: /////////////////////////////////////////////////////////////////////////////// SD_API_STATUS IssueCardSelectDeSelect(PSD_MEMCARD_INFO pMemCard, BOOL Select) { USHORT relativeAddress; // relative address SD_RESPONSE_TYPE responseType; // expected response SD_API_STATUS status; // intermediate status int retryCount; // retryCount; SD_CARD_STATUS cardStatus; // card status if (Select) { // using the cards original address selects the card again relativeAddress = pMemCard->RCA; DEBUG_CHECK((relativeAddress != 0), (TEXT("IssueCardSelectDeSelect - Relative address is zero! \n"))); // the selected card should return a response responseType = ResponseR1b; } else { // address of zero deselects the card relativeAddress = 0; // according to the spec no response will be returned responseType = NoResponse; } retryCount = DEFAULT_DESELECT_RETRY_COUNT; while (retryCount) { status = SDSynchronousBusRequest(pMemCard->hDevice, SD_CMD_SELECT_DESELECT_CARD, ((DWORD)relativeAddress) << 16, SD_COMMAND, responseType, NULL, 0, 0, NULL, 0); if (!SD_API_SUCCESS(status)) { break; } if (!Select) { // if we deselected, get the card status and check for // standby state status = SDCardInfoQuery(pMemCard->hDevice, SD_INFO_CARD_STATUS, &cardStatus, sizeof(SD_CARD_STATUS)); if (!SD_API_SUCCESS(status)){ break; } if (SD_STATUS_CURRENT_STATE(cardStatus) == SD_STATUS_CURRENT_STATE_STDBY) { DEBUGMSG(SDMEM_ZONE_POWER, (TEXT("SDMemory: Card now in Standby \n"))); break; } else { DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDMemory: Card not in standby! Card Status: 0x%08X \n") , cardStatus)); // set unusuccessful for retry status = SD_API_STATUS_UNSUCCESSFUL; } retryCount--; } else { DEBUGMSG(SDMEM_ZONE_POWER, (TEXT("SDMemory: Card now in Transfer state \n"))); break; } } return status; }
A_STATUS HIFReadWrite(HIF_DEVICE *device, A_UINT32 address, A_UCHAR *buffer, A_UINT32 length, HIF_REQUEST *request, void *context) { A_UINT8 rw; A_UINT8 mode; A_UINT8 opcode; A_UINT32 blockLen, blockCount, count; PSD_BUS_REQUEST busRequest; A_STATUS status = A_OK; SD_TRANSFER_CLASS transferClass; DWORD dwArg; A_UCHAR command; SD_API_STATUS sdStatus; SD_COMMAND_RESPONSE response; HIF_DEBUG_PRINTF(ATH_LOG_TRC, "HIFReadWrite:Enter\n"); HIF_DEBUG_PRINTF(ATH_LOG_TRC, "Address 0x%x\n", address); if (request->dmode == HIF_BLOCK_BASIS && request->type != HIF_EXTENDED_IO) { HIF_DEBUG_PRINTF(ATH_LOG_ERR, "Block mode not allowed for this type of command\n"); return A_ERROR; } if (request->dmode == HIF_BLOCK_BASIS) { mode = SD_IO_BLOCK_MODE; blockLen = HIF_MBOX_BLOCK_SIZE; blockCount = length / HIF_MBOX_BLOCK_SIZE; count = blockCount; HIF_DEBUG_PRINTF(ATH_LOG_TRC, "Block mode (BlockLen: %d, BlockCount: %d)\n", blockLen, blockCount); } else if (request->dmode == HIF_BYTE_BASIS) { mode = SD_IO_BYTE_MODE; blockLen = length; blockCount = 1; count = blockLen; HIF_DEBUG_PRINTF(ATH_LOG_TRC, "Byte mode (BlockLen: %d, BlockCount: %d)\n", blockLen, blockCount); } else { HIF_DEBUG_PRINTF(ATH_LOG_ERR, "Invalid data mode: %d\n", request->dmode); return A_ERROR; } if (request->amode == HIF_FIXED_ADDRESS) { opcode = SD_IO_FIXED_ADDRESS; HIF_DEBUG_PRINTF(ATH_LOG_TRC, "Fixed "); } else if (request->amode == HIF_INCREMENTAL_ADDRESS) { opcode = SD_IO_INCREMENT_ADDRESS; HIF_DEBUG_PRINTF(ATH_LOG_TRC, "Incremental "); } else { HIF_DEBUG_PRINTF(ATH_LOG_ERR, "Invalid address mode: %d\n", request->amode); return A_ERROR; } if (request->direction == HIF_WRITE) { transferClass = SD_WRITE; rw = SD_IO_OP_WRITE; if ((address >= HIF_MBOX_START_ADDR(0)) && (address <= HIF_MBOX_END_ADDR(3))) { /* Mailbox write. Adjust the address so that the last byte falls on the EOM address */ address = address + HIF_MBOX_WIDTH - length; } HIF_DEBUG_PRINTF(ATH_LOG_TRC, "[Write]"); } else { transferClass = SD_READ; rw = SD_IO_OP_READ; HIF_DEBUG_PRINTF(ATH_LOG_TRC, "[Read ]"); } if (request->type == HIF_EXTENDED_IO) { dwArg = BUILD_IO_RW_EXTENDED_ARG(rw, mode, funcNo, address, opcode, count); command = SD_IO_RW_EXTENDED; } else if (request->type == HIF_BASIC_IO) { dwArg = BUILD_IO_RW_DIRECT_ARG(rw, SD_IO_RW_NORMAL, funcNo, address, 0); command = SD_IO_RW_NORMAL; } else { HIF_DEBUG_PRINTF(ATH_LOG_ERR, "Invalid command type: %d\n", request->type); return A_ERROR; } if (request->emode == HIF_SYNCHRONOUS) { HIF_DEBUG_PRINTF(ATH_LOG_TRC, "Synchronous\n"); sdStatus = SDSynchronousBusRequest(device->handle, command, dwArg, transferClass, ResponseR5, &response, blockCount, blockLen, buffer, 0); if (!SD_API_SUCCESS(sdStatus)) { HIF_DEBUG_PRINTF(ATH_LOG_ERR, "SDBusRequest failed 0x%x\n", sdStatus); status = A_ERROR; } } else { HIF_DEBUG_PRINTF(ATH_LOG_TRC, "Asynchronous\n"); sdStatus = SDBusRequest(device->handle, command, dwArg, transferClass, ResponseR5, blockCount, blockLen, buffer, hifRWCompletionHandler, (DWORD) context, &busRequest, 0); if (!SD_API_SUCCESS(sdStatus)) { status = A_ERROR; } } return status; }
/////////////////////////////////////////////////////////////////////////////// // SMC_IOControl - the I/O control entry point for the memory driver // Input: Handle - the context returned from SMC_Open // IoctlCode - the ioctl code // pInBuf - the input buffer from the user // InBufSize - the length of the input buffer // pOutBuf - the output buffer from the user // InBufSize - the length of the output buffer // pBytesReturned - the size of the transfer // Output: // Return: TRUE if ioctl was handled // Notes: /////////////////////////////////////////////////////////////////////////////// extern "C" BOOL WINAPI SMC_IOControl( DWORD Handle, DWORD IoctlCode, PBYTE pInBuf, DWORD InBufSize, PBYTE pOutBuf, DWORD OutBufSize, PDWORD pBytesReturned ) { DWORD Status = ERROR_SUCCESS; // win32 status PSD_MEMCARD_INFO pHandle = (PSD_MEMCARD_INFO)Handle; // memcard info PSG_REQ pSG; // scatter gather buffer SD_API_STATUS sdStatus; // SD API status DWORD SafeBytesReturned = 0; // safe copy of pBytesReturned DWORD dwStartTicks = 0; DEBUGMSG(SDCARD_ZONE_FUNC, (TEXT("SDMemory: +SMC_IOControl\r\n"))); // any of these IOCTLs can access the device instance or card handle so we // must protect it from being freed from XXX_Deinit; Windows CE does not // synchronize the callback from Deinit AcquireRemovalLock(pHandle); if (pHandle->fPreDeinitCalled) { Status = ERROR_INVALID_HANDLE; goto ErrorStatusReturn; } sdStatus = RequestPrologue(pHandle, IoctlCode); if (!SD_API_SUCCESS(sdStatus)) { ReleaseRemovalLock(pHandle); SetLastError(SDAPIStatusToErrorCode(sdStatus)); return FALSE; } DEBUGMSG(SDCARD_ZONE_INFO, (TEXT("SMC_IOControl: Recevied IOCTL %d ="), IoctlCode)); switch(IoctlCode) { case IOCTL_DISK_READ: DEBUGMSG(SDCARD_ZONE_INFO, (TEXT("IOCTL_DISK_READ\r\n"))); break; case DISK_IOCTL_READ: DEBUGMSG(SDCARD_ZONE_INFO, (TEXT("DISK_IOCTL_READ\r\n"))); break; case IOCTL_DISK_WRITE: DEBUGMSG(SDCARD_ZONE_INFO, (TEXT("IOCTL_DISK_WRITE\r\n"))); break; case DISK_IOCTL_WRITE: DEBUGMSG(SDCARD_ZONE_INFO, (TEXT("DISK_IOCTL_WRITE\r\n"))); break; case IOCTL_DISK_GETINFO: DEBUGMSG(SDCARD_ZONE_INFO, (TEXT("IOCTL_DISK_GETINFO\r\n"))); break; case DISK_IOCTL_GETINFO: DEBUGMSG(SDCARD_ZONE_INFO, (TEXT("DISK_IOCTL_GETINFO\r\n"))); break; case IOCTL_DISK_SETINFO: DEBUGMSG(SDCARD_ZONE_INFO, (TEXT("IOCTL_DISK_SETINFO\r\n"))); break; case DISK_IOCTL_INITIALIZED: DEBUGMSG(SDCARD_ZONE_INFO, (TEXT("DISK_IOCTL_INITIALIZED\r\n"))); break; case IOCTL_DISK_INITIALIZED: DEBUGMSG(SDCARD_ZONE_INFO, (TEXT("IOCTL_DISK_INITIALIZED\r\n"))); break; case IOCTL_DISK_GETNAME: DEBUGMSG(SDCARD_ZONE_INFO, (TEXT("IOCTL_DISK_GETNAME\r\n"))); break; case DISK_IOCTL_GETNAME: DEBUGMSG(SDCARD_ZONE_INFO, (TEXT("DISK_IOCTL_GETNAME\r\n"))); break; case IOCTL_DISK_GET_STORAGEID: DEBUGMSG(SDCARD_ZONE_INFO, (TEXT("IOCTL_DISK_GET_STORAGEID\r\n"))); break; case IOCTL_DISK_FORMAT_MEDIA: case DISK_IOCTL_FORMAT_MEDIA: DEBUGMSG(SDCARD_ZONE_INFO, (TEXT("IOCTL_DISK_FORMAT_MEDIA\r\n"))); break; case IOCTL_DISK_DEVICE_INFO: DEBUGMSG(SDCARD_ZONE_INFO, (TEXT("IOCTL_DISK_DEVICE_INFO\r\n"))); break; case IOCTL_DISK_DELETE_SECTORS: DEBUGMSG(SDCARD_ZONE_INFO, (TEXT("IOCTL_DISK_DELETE_SECTORS\r\n"))); break; default: DEBUGMSG(SDCARD_ZONE_INFO, (TEXT("**UNKNOWN**\r\n"))); break; } // validate parameters switch(IoctlCode) { case IOCTL_DISK_READ: case DISK_IOCTL_READ: case IOCTL_DISK_WRITE: case DISK_IOCTL_WRITE: if (pInBuf == NULL || InBufSize < sizeof(SG_REQ) || InBufSize > (sizeof(SG_REQ) + ((MAX_SG_BUF - 1) * sizeof(SG_BUF)))) { Status = ERROR_INVALID_PARAMETER; } break; case DISK_IOCTL_GETINFO: case IOCTL_DISK_SETINFO: if (NULL == pInBuf || InBufSize != sizeof(DISK_INFO)) { Status = ERROR_INVALID_PARAMETER; } break; case IOCTL_DISK_DELETE_SECTORS: if (pInBuf == NULL || InBufSize != sizeof(DELETE_SECTOR_INFO)) { Status = ERROR_INVALID_PARAMETER; } break; case IOCTL_DISK_GETINFO: if (pOutBuf == NULL || OutBufSize != sizeof(DISK_INFO)) { Status = ERROR_INVALID_PARAMETER; } break; case IOCTL_DISK_GET_STORAGEID: // the identification data is stored after the struct, so the out // buffer must be at least the size of the struct. if (pOutBuf == NULL || OutBufSize < sizeof(STORAGE_IDENTIFICATION)) { Status = ERROR_INVALID_PARAMETER; } break; case IOCTL_DISK_FORMAT_MEDIA: case DISK_IOCTL_FORMAT_MEDIA: break; case IOCTL_DISK_DEVICE_INFO: if (NULL == pInBuf || (InBufSize != sizeof(STORAGEDEVICEINFO))) { Status = ERROR_INVALID_PARAMETER; } break; case IOCTL_POWER_CAPABILITIES: if (!pOutBuf || OutBufSize < sizeof(POWER_CAPABILITIES) || !pBytesReturned) { Status = ERROR_INVALID_PARAMETER; } break; case IOCTL_POWER_SET: if (!pOutBuf || OutBufSize < sizeof(CEDEVICE_POWER_STATE) || !pBytesReturned) { Status = ERROR_INVALID_PARAMETER; } break; default: Status = ERROR_INVALID_PARAMETER; } if (Status != ERROR_SUCCESS) { goto ErrorStatusReturn; } // execute the IOCTL switch(IoctlCode) { case IOCTL_DISK_READ: case DISK_IOCTL_READ: pSG = (PSG_REQ)pInBuf; if (0 == CeSafeCopyMemory((LPVOID)pHandle->pSterileIoRequest, (LPVOID)pSG, InBufSize)) { Status = ERROR_INVALID_PARAMETER; break; } Status = SDMemRead(pHandle, pHandle->pSterileIoRequest); __try { pSG->sr_status = Status; if (pBytesReturned && (ERROR_SUCCESS == Status)) { *pBytesReturned = (pHandle->pSterileIoRequest->sr_num_sec * SD_BLOCK_SIZE); } } __except(EXCEPTION_EXECUTE_HANDLER) { Status = ERROR_INVALID_PARAMETER; } break; case IOCTL_DISK_WRITE: case DISK_IOCTL_WRITE: pSG = (PSG_REQ)pInBuf; if (0 == CeSafeCopyMemory((LPVOID)pHandle->pSterileIoRequest, (LPVOID)pSG, InBufSize)) { Status = ERROR_INVALID_PARAMETER; break; } Status = SDMemWrite(pHandle, pHandle->pSterileIoRequest); __try { pSG->sr_status = Status; if (pBytesReturned && (ERROR_SUCCESS == Status)) { *pBytesReturned = (pHandle->pSterileIoRequest->sr_num_sec * SD_BLOCK_SIZE); } } __except(EXCEPTION_EXECUTE_HANDLER) { Status = ERROR_INVALID_PARAMETER; } break; case IOCTL_DISK_GETINFO: { DISK_INFO SafeDiskInfo = {0}; SafeBytesReturned = sizeof(DISK_INFO); Status = GetDiskInfo(pHandle, &SafeDiskInfo); if (0 == CeSafeCopyMemory((LPVOID)pOutBuf, (LPVOID)&SafeDiskInfo, sizeof(DISK_INFO))) { Status = ERROR_INVALID_PARAMETER; break; } if (pBytesReturned) { if (0 == CeSafeCopyMemory((LPVOID)pBytesReturned, (LPVOID)&SafeBytesReturned, sizeof(DWORD))) { Status = ERROR_INVALID_PARAMETER; break; } } } break; case DISK_IOCTL_GETINFO: { DISK_INFO SafeDiskInfo = {0}; SafeBytesReturned = sizeof(DISK_INFO); Status = GetDiskInfo(pHandle, &SafeDiskInfo); if (0 == CeSafeCopyMemory((LPVOID)pInBuf, (LPVOID)&SafeDiskInfo, sizeof(DISK_INFO))) { Status = ERROR_INVALID_PARAMETER; break; } if (pBytesReturned) { if (0 == CeSafeCopyMemory((LPVOID)pBytesReturned, (LPVOID)&SafeBytesReturned, sizeof(DWORD))) { Status = ERROR_INVALID_PARAMETER; break; } } } break; case IOCTL_DISK_SETINFO: { DISK_INFO SafeDiskInfo = {0}; if (0 == CeSafeCopyMemory((LPVOID)&SafeDiskInfo, (LPVOID)pInBuf, sizeof(DISK_INFO))) { Status = ERROR_INVALID_PARAMETER; break; } Status = SetDiskInfo(pHandle, &SafeDiskInfo); } break; case IOCTL_DISK_FORMAT_MEDIA: case DISK_IOCTL_FORMAT_MEDIA: Status = ERROR_SUCCESS; break; case IOCTL_DISK_GET_STORAGEID: { __try { Status = GetStorageID( pHandle, (PSTORAGE_IDENTIFICATION)pOutBuf, OutBufSize, pBytesReturned); } __except(EXCEPTION_EXECUTE_HANDLER) { Status = ERROR_INVALID_PARAMETER; } } break; case IOCTL_DISK_DEVICE_INFO: { STORAGEDEVICEINFO SafeStorageDeviceInfo = {0}; SafeBytesReturned = sizeof(STORAGEDEVICEINFO); if (!GetDeviceInfo(pHandle, &SafeStorageDeviceInfo)) { Status = ERROR_GEN_FAILURE; break; } if (0 == CeSafeCopyMemory((LPVOID)pInBuf, (LPVOID)&SafeStorageDeviceInfo, sizeof(STORAGEDEVICEINFO))) { Status = ERROR_INVALID_PARAMETER; break; } Status = ERROR_SUCCESS; if (pBytesReturned) { if (0 == CeSafeCopyMemory((LPVOID)pBytesReturned, (LPVOID)&SafeBytesReturned, sizeof(DWORD))) { Status = ERROR_INVALID_PARAMETER; } } } break; case IOCTL_DISK_DELETE_SECTORS: { DELETE_SECTOR_INFO SafeDeleteSectorInfo = {0}; if (0 == CeSafeCopyMemory((LPVOID)&SafeDeleteSectorInfo, (LPVOID)pInBuf, sizeof(DELETE_SECTOR_INFO))) { Status = ERROR_INVALID_PARAMETER; break; } Status = SDMemErase(pHandle, &SafeDeleteSectorInfo); } break; case IOCTL_POWER_CAPABILITIES: { POWER_CAPABILITIES SafePowerCapabilities = {0}; SafeBytesReturned = sizeof(POWER_CAPABILITIES); // support D0 + PowerStateForIdle (D2, by default) SafePowerCapabilities.DeviceDx = DX_MASK(D0) | DX_MASK(pHandle->PowerStateForIdle); SafePowerCapabilities.Power[D0] = PwrDeviceUnspecified; SafePowerCapabilities.Power[D1] = PwrDeviceUnspecified; SafePowerCapabilities.Power[D2] = PwrDeviceUnspecified; SafePowerCapabilities.Power[D3] = PwrDeviceUnspecified; SafePowerCapabilities.Power[D4] = PwrDeviceUnspecified; SafePowerCapabilities.Latency[D0] = 0; SafePowerCapabilities.Latency[D1] = 0; SafePowerCapabilities.Latency[D2] = 0; SafePowerCapabilities.Latency[D3] = 0; SafePowerCapabilities.Latency[D4] = 1000; // no device wake SafePowerCapabilities.WakeFromDx = 0; // no inrush SafePowerCapabilities.InrushDx = 0; if (0 == CeSafeCopyMemory((LPVOID)pOutBuf, (LPVOID)&SafePowerCapabilities, sizeof(POWER_CAPABILITIES))) { Status = ERROR_INVALID_PARAMETER; break; } Status = ERROR_SUCCESS; if (pBytesReturned) { if (0 == CeSafeCopyMemory((LPVOID)pBytesReturned, (LPVOID)&SafeBytesReturned, sizeof(DWORD))) { Status = ERROR_INVALID_PARAMETER; } } } break; case IOCTL_POWER_SET: { // pOutBuf is a pointer to CEDEVICE_POWER_STATE; this is the device // state incd .. which to put the device; if the driver does not support // the requested power state, then we return the adjusted power // state CEDEVICE_POWER_STATE SafeCeDevicePowerState; SafeBytesReturned = sizeof(CEDEVICE_POWER_STATE); if (0 == CeSafeCopyMemory((LPVOID)&SafeCeDevicePowerState, (LPVOID)pOutBuf, sizeof(CEDEVICE_POWER_STATE))) { Status = ERROR_INVALID_PARAMETER; break; } Status = ERROR_SUCCESS; HandleIoctlPowerSet(pHandle, &SafeCeDevicePowerState); // return the adjusted power state if (0 == CeSafeCopyMemory((LPVOID)pOutBuf, (LPVOID)&SafeCeDevicePowerState, sizeof(CEDEVICE_POWER_STATE))) { Status = ERROR_INVALID_PARAMETER; break; } if (pBytesReturned) { if (0 == CeSafeCopyMemory((LPVOID)pBytesReturned, (LPVOID)&SafeBytesReturned, sizeof(DWORD))) { Status = ERROR_INVALID_PARAMETER; } } } break; default: Status = ERROR_INVALID_PARAMETER; break; } RequestEnd(pHandle); ErrorStatusReturn: ReleaseRemovalLock(pHandle); DEBUGMSG(SDCARD_ZONE_FUNC, (TEXT("SDMemory: -SMC_IOControl returning %d\n"),Status == ERROR_SUCCESS)); if (Status != ERROR_SUCCESS) { SetLastError(Status); } return (ERROR_SUCCESS == Status); }