⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdslot.cpp

📁 6410BSP3
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
// 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 + -