📄 sdslot.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Module Name:
SDSlot.cpp
Abstract:
SDSlot Implementation.
Notes:
--*/
#include <windows.h>
#include <types.h>
#include "../HSMMCCh1/s3c6410_hsmmc_lib/sdhcd.h"
#include "sdbus.hpp"
#include "sdslot.hpp"
#include "sdbusreq.hpp"
#include "sddevice.hpp"
CSDBusReqAsyncQueue::CSDBusReqAsyncQueue()
{
m_pQueueListHead = m_pQueueListLast = NULL;
m_fAttached = FALSE;
}
CSDBusReqAsyncQueue::~CSDBusReqAsyncQueue()
{
Lock();
while (m_pQueueListHead) {
CSDBusRequest * pNext = m_pQueueListHead->GetAsyncQueueNext();
m_pQueueListHead->DeRef();
m_pQueueListHead = pNext;
}
Unlock();
}
BOOL CSDBusReqAsyncQueue::Init()
{
m_fAttached = TRUE;
return TRUE;
}
BOOL CSDBusReqAsyncQueue::Detach()
{
m_fAttached = FALSE;
RemoveAllRequest();
if (m_pQueueListHead!=NULL) { // I don't think HC are going to complete this one. So, let me do it here.
Lock();
CSDBusRequest * pCur = m_pQueueListHead;
while(pCur) {
CSDBusRequest *pNext = pCur->GetAsyncQueueNext();
pCur->SetAsyncQueueNext(NULL);
pCur->CompleteBusRequest(SD_API_STATUS_CANCELED);
pCur->DeRef();
pCur = pNext;
}
m_pQueueListLast = m_pQueueListHead = NULL ;;
Unlock();
}
return TRUE;
}
SD_API_STATUS CSDBusReqAsyncQueue::QueueBusRequest(CSDBusRequest * pRequest)
{
SD_API_STATUS status = SD_API_STATUS_UNSUCCESSFUL;
if (pRequest && m_fAttached) {
BOOL fHeader = FALSE;
Lock();
pRequest->SetAsyncQueueNext(NULL);
if (m_pQueueListHead!=NULL && m_pQueueListLast!=NULL) {
m_pQueueListLast->SetAsyncQueueNext(pRequest);
m_pQueueListLast = pRequest;
}
else {
ASSERT(m_pQueueListHead==m_pQueueListLast);
m_pQueueListHead = m_pQueueListLast = pRequest;
fHeader = TRUE;
}
pRequest->AddRef();
if (fHeader) {
BOOL fSync= ((pRequest->SystemFlags & SD_FAST_PATH_AVAILABLE)!=0);
status = SubmitRequestToHC(pRequest);
if (!SD_API_SUCCESS(status) || status == SD_API_STATUS_FAST_PATH_SUCCESS ) {
ASSERT(pRequest == m_pQueueListHead);
ASSERT( pRequest->GetAsyncQueueNext()==NULL);
// Failed or Fast pass completion, CompleteRequest is never happen.
if (fSync) {
m_pQueueListHead = pRequest->GetAsyncQueueNext();
if (m_pQueueListHead == NULL)
m_pQueueListLast = NULL;
pRequest->SetStatus(status);
pRequest->DeRef();
}
else
CompleteRequest(pRequest,fSync);
}
}
else { // Async any always.
pRequest->SystemFlags &= ~ SD_FAST_PATH_AVAILABLE;
status = SD_API_STATUS_PENDING ;
}
Unlock();
}
else
ASSERT(FALSE);
return status;
};
CSDBusRequest * CSDBusReqAsyncQueue::CompleteRequest(CSDBusRequest * pRequest,SD_API_STATUS Status)
{
CSDBusRequest * pReturn = NULL;
Lock();
if (m_pQueueListHead && m_pQueueListHead == pRequest) {
pRequest->SetStatus(Status);
if (!SD_API_SUCCESS(Status) && pRequest->IsRequestNeedRetry()) {
pRequest->SetStatus(SD_API_STATUS_PENDING);
pRequest->DecRetryCount();
SD_API_STATUS status = SubmitRequestToHC(pRequest);
if (!SD_API_SUCCESS(status) || status == SD_API_STATUS_FAST_PATH_SUCCESS ) {
// Failed or Fast pass completion, CompleteRequest is never happen.
pReturn = CompleteRequest(pRequest,status ); // Yes recursive. It will stop either succeeded or try count to zero.
}
}
else {
pRequest->CompleteBusRequest(Status);
pReturn = m_pQueueListHead;
ASSERT((m_pQueueListHead == m_pQueueListLast) == (m_pQueueListHead->GetAsyncQueueNext()==NULL));
CSDBusRequest * pNext = m_pQueueListHead->GetAsyncQueueNext();
m_pQueueListHead->DeRef();
m_pQueueListHead = pNext;
if (m_pQueueListHead == NULL) {
m_pQueueListLast = NULL;
}
else { // Submit Another one inside queue.
SD_API_STATUS status = SubmitRequestToHC(m_pQueueListHead);
if (!SD_API_SUCCESS(status) || status == SD_API_STATUS_FAST_PATH_SUCCESS ) {
// Failed or Fast pass completion, CompleteRequest is never happen.
CSDBusRequest * pReturn1 = CompleteRequest(m_pQueueListHead,status ); // Yes recursive. It will stop either succeeded or try count to zero.
}
}
}
}
else { // Why this happens?
ASSERT(FALSE);
}
Unlock();
return pReturn;
}
CSDBusRequest * CSDBusReqAsyncQueue::RemoveRequest(CSDBusRequest * pRequest)
{
CSDBusRequest * pReturn = NULL;
Lock();
CSDBusRequest * pPrev = NULL;
CSDBusRequest * pCur = m_pQueueListHead;
while (pCur!=NULL && pCur != pRequest) {
pPrev = pCur;
pCur = pCur->GetAsyncQueueNext();
}
if (pCur == pRequest) {
pReturn = pCur ;
if (pPrev!=NULL) {
pPrev->SetAsyncQueueNext(pCur->GetAsyncQueueNext());
if (pCur->GetAsyncQueueNext() == NULL) // Last one.
m_pQueueListLast = pPrev;
pCur->CompleteBusRequest(SD_API_STATUS_CANCELED);
pCur->SetAsyncQueueNext(NULL);
pCur->DeRef();
}
else {
// Delete from First?
// Queue header can not remove from this function because it is processing by SDHC.
CancelRequestFromHC(pRequest);
}
}
else
ASSERT(FALSE);
Unlock();
return pReturn;
}
BOOL CSDBusReqAsyncQueue::RemoveAllRequest()
{
Lock();
if (m_pQueueListHead) {
CSDBusRequest * pCur = m_pQueueListHead->GetAsyncQueueNext();
while(pCur) {
CSDBusRequest *pNext = pCur->GetAsyncQueueNext();
pCur->CompleteBusRequest(SD_API_STATUS_CANCELED);
pCur->DeRef();
pCur = pNext;
}
m_pQueueListHead->SetAsyncQueueNext(NULL);
m_pQueueListLast = m_pQueueListHead;
CancelRequestFromHC(m_pQueueListHead);
}
Unlock();
return TRUE;
}
CSDBusRequest * CSDBusReqAsyncQueue::GetRequestFromHead()
{
Lock();
CSDBusRequest * pReturn = m_pQueueListHead;
if (pReturn)
pReturn->AddRef();
Unlock();
return pReturn;
}
CSDSlot::CSDSlot(DWORD dwSlotIndex, CSDHost& sdHost)
: m_SdHost(sdHost)
, m_dwSlotIndex(dwSlotIndex)
, CSDWorkItem()
{
for (DWORD dwIndex = 0; dwIndex<SD_MAXIMUM_DEVICE_PER_SLOT; dwIndex++)
m_pFuncDevice[dwIndex] = NULL;
m_SlotState = SlotInactive;
m_curHCOwned = NULL;
m_lcurHCLockCount = NULL;
m_Flags = 0 ;
}
CSDSlot::~CSDSlot()
{
ASSERT(!(m_SdHost.m_fHostAttached));
RemoveAllDevice();
ASSERT(m_curHCOwned==NULL);
}
BOOL CSDSlot::Init()
{
// get the capabilities of this slot
memset((SDCARD_HC_SLOT_INFO *)this, 0, sizeof (SDCARD_HC_SLOT_INFO));
// ??Read Setting From Registry in future??
//by default enable power control at the slot
m_SlotState = SlotInactive;
m_fEnablePowerControl = TRUE;
m_AllocatedPower = 0;
DWORD dwThreadPrority = CSDHostContainer::RegValueDWORD(SDCARD_THREAD_PRIORITY_KEY,DEFAULT_THREAD_PRIORITY);
if (!CSDWorkItem::Init(dwThreadPrority + 1) || !CSDBusReqAsyncQueue::Init()) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("CSDSlot::Init: CSDWorkItem::Init or CSDBusReqAsyncQueue::Init Failed \n")));
return FALSE;
}
m_FastPathThreshHold = CSDHostContainer::RegValueDWORD(SDCARD_PASTPATH_THRESHOLD,DEFAULT_PASTPATH_THRESHOLD);
return TRUE;
};
SD_API_STATUS CSDSlot::SubmitRequestToHC(CSDBusRequest * pRequest)
{
SD_API_STATUS status = SD_API_STATUS_UNSUCCESSFUL;
m_SdHost.SDHCAccessLock();
DEBUGMSG(SDCARD_ZONE_0,(TEXT("SubmitRequestToHC(%x)\n"),pRequest));
if (m_fAttached && SD_API_SUCCESS(CheckSlotReady()) && m_SdHost.IsAttached() &&
m_curHCOwned==NULL && pRequest!=NULL) {
m_curHCOwned = pRequest;
m_lcurHCLockCount = 0 ;
status = m_SdHost.BusRequestHandler(m_dwSlotIndex,pRequest);
// Retry if needed.
while (!SD_API_SUCCESS(status)) {
if (SD_API_SUCCESS(CheckSlotReady()) && pRequest->IsRequestNeedRetry()) {
pRequest->DecRetryCount();
status = m_SdHost.BusRequestHandler(m_dwSlotIndex,pRequest);
}
else
break;
}
if (status!=SD_API_STATUS_PENDING) { // This is has been completed.
m_curHCOwned = NULL;
}
}
else {
ASSERT(FALSE);
}
m_SdHost.SDHCAccessUnlock();
return status;
}
DWORD CSDSlot::GetNumOfFunctionDevice()
{
DWORD dwReturn = 0;
m_SlotLock.Lock();
for (DWORD dwIndex = 0; dwIndex< SD_MAXIMUM_DEVICE_PER_SLOT; dwIndex ++) {
if (m_pFuncDevice[dwIndex]) {
dwReturn++;
}
};
m_SlotLock.Unlock();
return dwReturn;
}
CSDDevice * CSDSlot::RemoveDevice(DWORD dwIndex )
{
m_SlotLock.Lock();
CSDDevice* pReturn = NULL;
if( dwIndex < SD_MAXIMUM_DEVICE_PER_SLOT )
{
pReturn = m_pFuncDevice[dwIndex];
m_pFuncDevice[dwIndex] = NULL;
};
m_SlotLock.Unlock();
if( pReturn ) {
pReturn->Detach();
pReturn->DeRef();
}
return pReturn;
}
CSDDevice * CSDSlot::InsertDevice(DWORD dwIndex,CSDDevice * pObject)
{
CSDDevice* pReturn = NULL;
if( pObject )
{
m_SlotLock.Lock();
if( dwIndex < SD_MAXIMUM_DEVICE_PER_SLOT && m_pFuncDevice[dwIndex]==NULL ) {
pReturn = m_pFuncDevice[dwIndex] = pObject;
pReturn->AddRef();
}
m_SlotLock.Unlock();
}
return pReturn;
}
BOOL CSDSlot::RemoveAllDevice()
{
for (LONG lIndex=SD_MAXIMUM_DEVICE_PER_SLOT-1; lIndex>=0 ; lIndex--) {
if (m_pFuncDevice[lIndex]!=NULL)
RemoveDevice(lIndex);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -