📄 sdhcenum.cpp
字号:
}
DEBUGCHK(pHCContext->dwSig == VALID_HC_CONTEXT_SIG);
return DoDeregisterHostController(pHCContext, TRUE);
}
///////////////////////////////////////////////////////////////////////////////
// SDHCDIndicateSlotStateChange - indicate a change in the SD Slot
//
// Input: pExternalHCContext - Host controller context that was previously registered
// SlotNumber - Slot Number
// Event - new event
// Output:
// Return: SD_API_STATUS
// Notes:
// A host controller driver calls this api when the slot changes state (i.e.
// device insertion/deletion).
///////////////////////////////////////////////////////////////////////////////
VOID SDHCDIndicateSlotStateChange__X(PSDCARD_HC_CONTEXT pExternalHCContext,
DWORD SlotNumber,
SD_SLOT_EVENT Event)
{
PSDBUS_HC_CONTEXT pHCContext = (PSDBUS_HC_CONTEXT) pExternalHCContext;
PSDBUS_HC_SLOT_CONTEXT pSlotContext; // the slot context
CSDBusDriver *pBusDriver; // the bus driver
if (pHCContext == NULL) {
RETAILMSG(1, (TEXT("SDBusDriver: Passed invalid SDCARD_HC_CONTEXT \n")));
DEBUGCHK(FALSE);
return;
}
DEBUGCHK(pHCContext->dwSig == VALID_HC_CONTEXT_SIG);
if (SlotNumber > pHCContext->NumberOfSlots) {
DEBUG_CHECK(FALSE, (TEXT("SDHCDIndicateSlotStateChange, Slot number exceeds number of slots! \n")));
return;
}
// get the slot context for this slot number and host controller
pSlotContext = SDHCGetSlotContext(pHCContext, SlotNumber);
if (DeviceEjected == Event) {
// immediately mark the slot for ejection
pSlotContext->SlotState = SlotDeviceEjected;
if (NULL == pSlotContext->hDevice) {
// This can happen on very fast suspend-resume-suspend sequence because
// the DeviceInserted message is still in the WorkItem queue.
DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("Host Controller:%s indicated device eject on an empty slot \n"),
SDHCDGetHCName(pHCContext)));
return;
}
} else if (DeviceInterrupting == Event) {
if (NULL == pSlotContext->hDevice) {
DEBUG_CHECK(FALSE,(TEXT("Host Controller:%s indicated an interrupt on an empty slot \n"),
SDHCDGetHCName(pHCContext)));
return;
}
}
// get the bus driver object
pBusDriver = GetSDBusDriver(pHCContext);
PREFAST_DEBUGCHK(pBusDriver != NULL);
switch (Event) {
case DeviceInserted:
case DeviceEjected:
case DeviceInterrupting:
DEBUGCHK(pSlotContext->pWorkItem != NULL);
// post this message to the work item for each slot
pBusDriver->PostSlotEvent(Event, pSlotContext, (CSDWorkItem *)pSlotContext->pWorkItem);
break;
case BusRequestComplete:
// wake up bus request complete dispatcher
pBusDriver->WakeUpBusRequestCompleteDispatcher();
break;
default:
DEBUGCHK(FALSE);
}
}
///////////////////////////////////////////////////////////////////////////////
// SDHCDIndicateBusRequestComplete - indicate to the bus driver that
// the request is complete
// Input: pExternalHCContext - host controller context
// pRequest - the request to indicate
// Status - the ending status of the request
// Output:
// Return:
// Notes:
//
//
///////////////////////////////////////////////////////////////////////////////
VOID SDHCDIndicateBusRequestComplete__X(PSDCARD_HC_CONTEXT pExternalHCContext,
HBUS_REQUEST hRequest,
SD_API_STATUS Status)
{
PSDBUS_HC_SLOT_CONTEXT pSlot; // the slot
PSDBUS_BUS_REQUEST pNextRequest; // the next request
SD_API_STATUS submitStatus; // intermediate status
CSDBusDriver *pBusDriver;
PSDBUS_BUS_REQUEST pRequest = (PSDBUS_BUS_REQUEST) hRequest;
PSDBUS_HC_CONTEXT pHCContext = (PSDBUS_HC_CONTEXT) pExternalHCContext;
DEBUGCHK(pHCContext->dwSig == VALID_HC_CONTEXT_SIG);
// get the slot
PREFAST_DEBUGCHK(pRequest);
DEBUGCHK(pRequest->dwSig == VALID_BUS_REQUEST_SIG);
PSDCARD_DEVICE_CONTEXT pDevice = SDDCGetClientDeviceFromHandle(pRequest->hDevice);
PREFAST_DEBUGCHK(pDevice);
pSlot = pDevice->pSlot;
PREFAST_DEBUGCHK(pSlot);
pBusDriver = (CSDBusDriver *) pDevice->pSystemContext;
// acquire the HC lock
SDHCDAcquireHCLock(pHCContext);
// mark that the request is non-cancelable
SD_REQUEST_MARK_NON_CANCELABLE(pRequest);
if (!SD_API_SUCCESS(Status)) {
// check for retry
if ((SD_API_STATUS_RESPONSE_TIMEOUT == Status) ||
(SD_API_STATUS_DATA_TIMEOUT == Status) ||
(SD_API_STATUS_CRC_ERROR == Status)) {
// issue a retry only if the client doesn't handle them
if (!(CLIENT_HANDLES_RETRY(pDevice))) {
// only retry if the slot is still ready
// a device ejection may have caused the timeout error
if (SD_API_SUCCESS(CheckSlotReady(pSlot))) {
// check retry count
if (SDRequestGetRetryCount(pRequest) != 0) {
DEBUGMSG(SDCARD_ZONE_WARN,
(TEXT("SDBusDriver: Retrying request 0x%08X, Current retry count: %d \n"),
pRequest,SDRequestGetRetryCount(pRequest)));
// decrement retry count
SDDecrementRetryCount(pRequest);
pRequest->HCParam = 0;
// release the lock
SDHCDReleaseHCLock(pHCContext);
// resubmit
if (SD_API_SUCCESS(pBusDriver->SubmitToHC(pHCContext,
pSlot->SlotIndex, pRequest))) {
return;
}
// acquire the HC lock
SDHCDAcquireHCLock(pHCContext);
// re-submission failed, let it fall through to completion
DEBUGMSG(SDCARD_ZONE_WARN,
(TEXT("SDBusDriver: Could not start retry attempt for request 0x%08X\n"),
pRequest));
}
}
}
}
}
// mark that the request is completing
SD_REQUEST_MARK_COMPLETING(pRequest);
// set the completion status
pRequest->Status = Status;
// dequeue the current request
if ((SDDequeueBusRequest(&pSlot->RequestQueue)) != pRequest) {
// the request we are completing should be the first request in the queue
DEBUG_CHECK(FALSE,(TEXT("SDHCDCompleteRequest- the HC is completing a request that is not the current request! \n")));
// release the lock
SDHCDReleaseHCLock(pHCContext);
return;
}
// queue the request to the bus driver's completion queue
pBusDriver->QueueCompletedRequest(pRequest);
// start up the next request(s) in the queue
while (1) {
// get the next request
pNextRequest = (PSDBUS_BUS_REQUEST) SDGetCurrentRequest(&pSlot->RequestQueue);
// release the lock
SDHCDReleaseHCLock(pHCContext);
if (NULL != pNextRequest) {
// check the slot, we might have gotten a removal
submitStatus = CheckSlotReady(pSlot);
if (SD_API_SUCCESS(submitStatus)) {
// submit the next request
submitStatus = pBusDriver->SubmitToHC(pHCContext, pSlot->SlotIndex, pNextRequest);
}
// DO NOT USE pRequest after this line since it could have
// been freed in the above call. (Especially if the above call
// caused an AutoCmd12 to be issued to the standard host
// controller, since it is completed immediately.)
if (!SD_API_SUCCESS(submitStatus)) {
// set the status
pNextRequest->Status = submitStatus;
// re-acquire the HC lock
SDHCDAcquireHCLock(pHCContext);
// remove this one from the queue because it failed
SDDequeueBusRequest(&pSlot->RequestQueue);
// queue the request for completion
pBusDriver->QueueCompletedRequest(pNextRequest);
// we stay in this loop
} else {
// break out of the loop, we've already submitted one
break;
}
} else {
// nothing to start up
break;
}
}
// indicate a slot state change
// this will signal the dispatcher to examine the slot and
// complete the request from the completed request queue
SDHCDIndicateSlotStateChange__X(pHCContext,
pSlot->SlotIndex,
BusRequestComplete);
}
///////////////////////////////////////////////////////////////////////////////
// SDHCDGetAndLockCurrentRequest - get the current request in the host controller
// slot and lock it to keep it from being cancelable
// Input: pExternalHCContext - host controller context
// SlotIndex - the slot number
// Output:
// Return: current bus request
// Notes:
// This function retrieves the current request and marks the
// request as NON-cancelable. To return the request back to the
// cancelable state the caller must call SDHCDUnlockRequest()
// This function returns the current request which can be NULL if
// the request was previously marked cancelable and the host controller's
// cancelIo Handler completed the request
///////////////////////////////////////////////////////////////////////////////
HBUS_REQUEST SDHCDGetAndLockCurrentRequest__X(PSDCARD_HC_CONTEXT pExternalHCContext, DWORD SlotIndex)
{
PSDBUS_BUS_REQUEST pRequest; // the current request
PSDBUS_HC_CONTEXT pHCContext = (PSDBUS_HC_CONTEXT) pExternalHCContext;
if (pHCContext == NULL) {
RETAILMSG(1, (TEXT("SDBusDriver: Passed invalid SDCARD_HC_CONTEXT \n")));
DEBUGCHK(FALSE);
return NULL;
}
DEBUGCHK(pHCContext->dwSig == VALID_HC_CONTEXT_SIG);
SDHCDAcquireHCLock(pHCContext);
// get the current request
PSDBUS_HC_SLOT_CONTEXT pSlot = SDHCGetSlotContext(pHCContext, SlotIndex);
pRequest = (PSDBUS_BUS_REQUEST) SDGetCurrentRequest(&pSlot->RequestQueue);
if (NULL == pRequest) {
SDHCDReleaseHCLock(pHCContext);
return NULL;
}
if (IS_REQUEST_COMPLETING(pRequest)) {
DEBUGCHK(FALSE);
// the current request is completing in the dispatcher, this shouldn't happen
SDHCDReleaseHCLock(pHCContext);
return NULL;
}
// mark the request as non-cancelable
SD_REQUEST_MARK_NON_CANCELABLE(pRequest);
SDHCDReleaseHCLock(pHCContext);
return (HBUS_REQUEST) pRequest;
}
///////////////////////////////////////////////////////////////////////////////
// SDHCDUnlockRequest - Unlock a request that was previous locked
//
// Input: pHCContext - host controller context
// pRequest - the request to lock
// Output:
// Return:
// Notes: This function unlocks the request that was returned from the
// function SDHCDGetAndLockCurrentRequest()
//
// This request can now be cancelled from any thread context
///////////////////////////////////////////////////////////////////////////////
VOID SDHCDUnlockRequest__X(PSDCARD_HC_CONTEXT pExternalHCContext,
HBUS_REQUEST hRequest)
{
PSDBUS_HC_CONTEXT pHCContext = (PSDBUS_HC_CONTEXT) pExternalHCContext;
PSDBUS_BUS_REQUEST pRequest = (PSDBUS_BUS_REQUEST) hRequest;
if (pHCContext == NULL) {
RETAILMSG(1, (TEXT("SDBusDriver: Passed invalid SDCARD_HC_CONTEXT \n")));
DEBUGCHK(FALSE);
return;
}
DEBUGCHK(pHCContext->dwSig == VALID_HC_CONTEXT_SIG);
if (pRequest == NULL) {
RETAILMSG(1, (TEXT("SDBusDriver: Passed invalid SD_BUS_REQUEST \n")));
DEBUGCHK(FALSE);
return;
}
SDHCDAcquireHCLock(pHCContext);
// mark the request as cancelable
SD_REQUEST_MARK_CANCELABLE(pRequest);
SDHCDReleaseHCLock(pHCContext);
}
///////////////////////////////////////////////////////////////////////////////
// SDHCDPowerUpDown - Indicate a power up/down event
//
// Input: pHCContext - host controller context
// PowerUp - set to TRUE if powering up
// SlotKeepPower - set to TRUE if the slot maintains power to the
// slot during power down
// Output:
// Return:
// Notes: This function notifies the bus driver of a power up/down event.
// The host controller driver can indicate to the bus driver that power
// can be maintained for the slot. If power is removed, the bus driver
// will unload the device driver on the next power up event.
// This function can only be called from the host controller's XXX_PowerOn
// and XXX_PowerOff function.
///////////////////////////////////////////////////////////////////////////////
VOID SDHCDPowerUpDown__X(PSDCARD_HC_CONTEXT pExternalHCContext,
BOOL PowerUp,
BOOL SlotKeepPower,
DWORD SlotIndex)
{
PSDBUS_HC_CONTEXT pHCContext = (PSDBUS_HC_CONTEXT) pExternalHCContext;
if (pHCContext == NULL) {
RETAILMSG(1, (TEXT("SDBusDriver: Passed invalid SDCARD_HC_CONTEXT \n")));
DEBUGCHK(FALSE);
return;
}
DEBUGCHK(pHCContext->dwSig == VALID_HC_CONTEXT_SIG);
DEBUGCHK(SlotIndex < pHCContext->NumberOfSlots);
CSDBusDriver *pBusDriver = GetSDBusDriver(pHCContext);
PSDBUS_HC_SLOT_CONTEXT pSlot = SDHCGetSlotContext(pHCContext, SlotIndex);
if (PowerUp){
pBusDriver->PowerUp(pSlot);
} else {
pBusDriver->PowerDown(pSlot, SlotKeepPower);
}
}
// DO NOT REMOVE --- END EXTERNALLY DEVELOPED SOURCE CODE ID --- DO NOT REMOVE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -