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

📄 atamain.cpp

📁 Microsoft WinCE 6.0 BSP FINAL release source code for use with the i.MX27ADS TO2 WCE600_FINAL_MX27_S
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//------------------------------------------------------------------------------
//
// Copyright (C) 2006, Freescale Semiconductor, Inc. All Rights Reserved.
// THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS
// AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT 
//
//------------------------------------------------------------------------------
//
//  File:  atamain.cpp
//
//       IDE/ATA and ATA/ATAPI are stream interface drivers.
//
//------------------------------------------------------------------------------

#include <windows.h>
#include <atamx27.h>

// DLL instance handle; differentiate this driver from other ATAPI instances
// (what other buses?)
HINSTANCE g_hInstance;

// List of active devices/disks
CDisk *g_pDiskRoot = NULL;

// Protect global variables
CRITICAL_SECTION g_csMain;

// Debug
extern "C" BOOL RegisterDbgZones(HMODULE hMod, LPDBGPARAM lpdbgparam);

// Definitions
typedef CDisk *(* POBJECTFUNCTION)(HKEY hKey);

//------------------------------------------------------------------------------
//
//    Function : CPort
//           CPort Constructor
//    Parameters:
//           void
//    Return:
//           void
//
//------------------------------------------------------------------------------

CPort::CPort()
{
    InitializeCriticalSection(&m_csPort);
    // initialize flags
    m_fInitialized = 0;
    m_dwFlag = 0;
    // initialize I/O ports
    m_dwRegBase = 0;
    m_dwRegAlt = 0;
    m_dwBMR = 0;
    m_dwBMRStatic = 0;
    // initialize interrupt data
    m_hIRQEvent = NULL;
    m_hThread = NULL;
    m_dwSysIntr = SYSINTR_NOP;
    m_dwSysIntrRX = SYSINTR_NOP;
    m_dwSysIntrTX = SYSINTR_NOP;
    m_dwIrq = IRQ_ATA;
}

//------------------------------------------------------------------------------
//
//    Function : ~CPort
//           CPort Destructor
//    Parameters:
//           void
//    Return:
//           void
//
//------------------------------------------------------------------------------

CPort::~CPort(
    )
{
    DeleteCriticalSection(&m_csPort);
    // unmap ATA channel's I/O windows
    if (m_dwRegBase) {
        MmUnmapIoSpace((LPVOID)m_dwRegBase, ATA_REG_LENGTH);
    }
    if (m_dwRegAlt) {
        MmUnmapIoSpace((LPVOID)m_dwRegAlt, ATA_REG_LENGTH);
    }
    if (m_dwBMR) {
        MmUnmapIoSpace((LPVOID)m_dwBMR, 16);
    }
    // close interrupt event handle
    if (m_hIRQEvent) {
        CloseHandle(m_hIRQEvent);
    }
    // close interrupt thread
    if (m_hThread) {
        CloseHandle(m_hThread);
    }
    // disable interrupt
    if (m_dwSysIntr != SYSINTR_NOP) {
        InterruptDisable(m_dwSysIntr);
    }
    // disable interrupt
    if (m_dwSysIntrRX != SYSINTR_NOP) {
        InterruptDisable(m_dwSysIntrRX);
    }
    // disable interrupt
    if (m_dwSysIntrTX != SYSINTR_NOP) {
        InterruptDisable(m_dwSysIntrTX);
    }
    // free DSK_ registry value set
    if (m_pDskReg[0]) {
        LocalFree(m_pDskReg[0]);
    }
    if (m_pDskReg[1]) {
        LocalFree(m_pDskReg[1]);
    }
}

//------------------------------------------------------------------------------
//
//    Function : TakeCS
//           Acquire exclusive access to IDE/ATA channel's I/O window
//    Parameters:
//           void
//    Return:
//           void
//
//------------------------------------------------------------------------------

VOID
CPort::TakeCS(
    )
{
    EnterCriticalSection(&m_csPort);
}

//------------------------------------------------------------------------------
//
//    Function : ReleaseCS
//          Release exclusive access to IDE/ATA channel's I/O window
//    Parameters:
//          void
//    Return:
//          void
//
//------------------------------------------------------------------------------

VOID
CPort::ReleaseCS(
    )
{
    LeaveCriticalSection(&m_csPort);
}

//------------------------------------------------------------------------------
//
//    Function : AtaLoadRegKey
//           Write I/O window and interrupt data to debug output
//
//    Parameters:
//           void
//    Return:
//           void
//
//------------------------------------------------------------------------------

VOID
CPort::PrintInfo(
    )
{
    DEBUGMSG(ZONE_INIT, (TEXT("dwRegBase   = %08X\r\n"), m_dwRegBase));
    DEBUGMSG(ZONE_INIT, (TEXT("dwRegAlt    = %08X\r\n"), m_dwRegAlt));
    DEBUGMSG(ZONE_INIT, (TEXT("dwSysIntr   = %08X\r\n"), m_dwSysIntr));
    DEBUGMSG(ZONE_INIT, (TEXT("dwIrq       = %08X\r\n"), m_dwIrq));
}

//------------------------------------------------------------------------------
//
//    Function : AtaLoadRegKey
//          This function is used by an Xxx_Init function to fetch the name of
//          and return a handle to the instance/device ("Key") key from an
//          Active key
//    Parameters:
//          hActiveKey : handle to DSK active Key
//          pszDevKey  : pointer to device key
//    Return:
//          return handle to DSK active key, otherwise return NULL handle.
//
//------------------------------------------------------------------------------

HKEY
AtaLoadRegKey(
    HKEY hActiveKey,
    TCHAR **pszDevKey
    )
{
    DWORD dwValueType;        // registry value type
    DWORD dwValueLength = 0;  // registry value length
    PTSTR szDeviceKey = NULL; // name of device key; value associated with "Key"
    HKEY hDeviceKey = NULL;   // handle to device key; handle to "Key"

    // query the value of "Key" with @dwValueLength=0, to determine the actual
    // length of the value (so as to allocate the exact amount of memory)

    if (ERROR_SUCCESS == RegQueryValueEx(hActiveKey, DEVLOAD_DEVKEY_VALNAME, NULL, &dwValueType, NULL, &dwValueLength)) {

        // allocate just enough memory to store the value of "Key"
        szDeviceKey = (PTSTR)LocalAlloc(LPTR, dwValueLength);
        if (szDeviceKey) {

            // read the actual value of "Key" and null terminate the target buffer
            RegQueryValueEx(hActiveKey, DEVLOAD_DEVKEY_VALNAME, NULL, &dwValueType, (PBYTE)szDeviceKey, &dwValueLength);
            DEBUGCHK(dwValueLength != 0);
            szDeviceKey[(dwValueLength / sizeof(TCHAR)) - 1] = 0;

            // open the device key
            if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, szDeviceKey, 0, 0, &hDeviceKey)) {
                DEBUGMSG(ZONE_INIT, (_T(
                    "AtaLoadRegyKey> Failed to open %s\r\n"
                    ), szDeviceKey));
                hDeviceKey = NULL;
            }
        }
    }
    if (!hDeviceKey) {
        if (szDeviceKey) {
            LocalFree(szDeviceKey);
        }
        *pszDevKey = NULL;
    }
    else {
        *pszDevKey = szDeviceKey;
    }
    return hDeviceKey;
}

//------------------------------------------------------------------------------
//
//    Function : AtaIsValidDisk
//          This function is used to determine whether a target disk instance
//          is valid
//    Parameters:
//          pDisk : Pointer Cdisk object
//
//    Return:
//          On success return true, Otherwise return flase.
//
//------------------------------------------------------------------------------

BOOL
AtaIsValidDisk(
    CDisk *pDisk
    )
{
    CDisk *pTemp = g_pDiskRoot;
    while (pTemp) {
        if (pTemp == pDisk) {
            return TRUE;
        }
        pTemp = pTemp->m_pNextDisk;
    }
    return FALSE;
}

//------------------------------------------------------------------------------
//
//    Function : AtaGetRegistryResources
//          This function is used to fetch an IDE/ATA channel's I/O window from
//          its instance key; this function recovers gracefully if an OEM has a
//          proprietary registry configuration that doesn't specify bus type or
//          bus number
//    Parameters:
//          hDevKey : Handle to active device key
//          pdwi : Pointer to window info
//
//    Return:
//          On success return true, Otherwise return flase.
//
//------------------------------------------------------------------------------

BOOL
AtaGetRegistryResources(
    HKEY hDevKey,
    PDDKWINDOWINFO pdwi
    )
{
    DEBUGCHK(pdwi != NULL);

    if (!pdwi) {
        return FALSE;
    }

    // fetch I/O window information
    pdwi->cbSize = sizeof(*pdwi);
    if (ERROR_SUCCESS != ::DDKReg_GetWindowInfo(hDevKey, pdwi)) {
        return FALSE;
    }

    // if interface not specified, then assume PCI
    if (pdwi->dwInterfaceType == InterfaceTypeUndefined) {
        DEBUGMSG(ZONE_WARNING, (_T(
            "Ata!AtaGetRegistryResources> bus type not specified, using PCI as default\r\n"
            )));
        pdwi->dwInterfaceType = PCIBus;
    }

    return TRUE;
}

//------------------------------------------------------------------------------
//
//    Function : GetDSKRegistryValueSet
//         This function reads the DSK registry value set from the IDE/ATA
//         controller's registry key
//
//    Parameters:
//         hDSKInstanceKey : Active registry instance key
//         pDskReg : Pointer to registry value structure.
//
//    Return:
//       On success return true, Otherwise return flase.
//
//------------------------------------------------------------------------------

BOOL
GetDSKRegistryValueSet(
    HKEY hDSKInstanceKey,
    PDSKREG pDskReg
    )
{
    BOOL fRet;

    // fetch device ID
    fRet = AtaGetRegistryValue(hDSKInstanceKey, REG_VAL_DSK_DEVICEID, &pDskReg->dwDeviceId);
    if (!fRet) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
            "Ata!GetDSKRegistryValueSet> Failed to read %s from DSK instance key\r\n"
            ), REG_VAL_DSK_DEVICEID));
        return FALSE;
    }
    if (!((0 <= pDskReg->dwDeviceId) && (pDskReg->dwDeviceId <= 3))) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
            "Ata!GetDSKRegistryValueSet> Bad value(%d) for %s in DSK instance key; valid: {0, 1, 2, 3}\r\n"
            ), pDskReg->dwDeviceId, REG_VAL_DSK_DEVICEID));
        return FALSE;
    }

    // fetch interrupt driven I/O boolean
    fRet = AtaGetRegistryValue(hDSKInstanceKey, REG_VAL_DSK_INTERRUPTDRIVEN, &pDskReg->dwInterruptDriven);
    if (!fRet) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
            "Ata!GetDSKRegistryValueSet> Failed to read %s from DSK instance key\r\n"
            ), REG_VAL_DSK_INTERRUPTDRIVEN));
        return FALSE;
    }
    if (pDskReg->dwInterruptDriven >= 2) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
            "Ata!GetDSKRegistryValueSet> Bad value(%d) for %s in DSK instance key; valid: {0, 1}\r\n"
            ), pDskReg->dwInterruptDriven, REG_VAL_DSK_INTERRUPTDRIVEN));
        return FALSE;
    }

    // fetch DMA triple
    fRet = AtaGetRegistryValue(hDSKInstanceKey, REG_VAL_DSK_DMA, &pDskReg->dwDMA);
    if (!fRet) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
            "Ata!GetDSKRegistryValueSet> Failed to read %s from DSK instance key\r\n"
            ), REG_VAL_DSK_DMA));
        return FALSE;
    }
    if (pDskReg->dwDMA >= 0x03) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
            "Ata!GetDSKRegistryValueSet> Bad value(%d) for %s in DSK instance key; valid: {0=no DMA, 1 or 2=MDMA/UDMA}\r\n"
            ), pDskReg->dwDMA, REG_VAL_DSK_DMA));
        return FALSE;
    }

    // fetch double buffer size
    fRet = AtaGetRegistryValue(hDSKInstanceKey, REG_VAL_DSK_DOUBLEBUFFERSIZE, &pDskReg->dwDoubleBufferSize);
    if (!fRet) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
            "Ata!GetDSKRegistryValueSet> Failed to read %s from DSK instance key\r\n"
            ), REG_VAL_DSK_DOUBLEBUFFERSIZE));
        return FALSE;
    }
    if (
        (pDskReg->dwDoubleBufferSize < REG_VAL_DSK_DOUBLEBUFFERSIZE_MIN) ||
        (pDskReg->dwDoubleBufferSize > REG_VAL_DSK_DOUBLEBUFFERSIZE_MAX)
    ) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
            "Ata!GetDSKRegistryValueSet> Bad value(%d) for %s in DSK instance key; valid: {%d, ..., %d}\r\n"
            ), pDskReg->dwDoubleBufferSize, REG_VAL_DSK_DOUBLEBUFFERSIZE, REG_VAL_DSK_DOUBLEBUFFERSIZE_MIN, REG_VAL_DSK_DOUBLEBUFFERSIZE_MAX));
        return FALSE;
    }

    // fetch DRQ data block size; this has to be validated by a sub-class
    fRet = AtaGetRegistryValue(hDSKInstanceKey, REG_VAL_DSK_DRQDATABLOCKSIZE, &pDskReg->dwDrqDataBlockSize);
    if (!fRet) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
            "Ata!GetDSKRegistryValueSet> Failed to read %s from DSK instance key\r\n"
            ), REG_VAL_DSK_DRQDATABLOCKSIZE));
        return FALSE;
    }

    // fetch write cache boolean
    fRet = AtaGetRegistryValue(hDSKInstanceKey, REG_VAL_DSK_WRITECACHE, &pDskReg->dwWriteCache);
    if (!fRet) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
            "Ata!GetDSKRegistryValueSet> Failed to read %s from DSK instance key\r\n"
            ), REG_VAL_DSK_WRITECACHE));
        return FALSE;
    }
    if (pDskReg->dwWriteCache >= 2) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
            "Ata!GetDSKRegistryValueSet> Bad value(%d) for %s in DSK instance key; valid: {0, 1}\r\n"
            ), pDskReg->dwWriteCache, REG_VAL_DSK_WRITECACHE));
        return FALSE;
    }

    // fetch look-ahead boolean
    fRet = AtaGetRegistryValue(hDSKInstanceKey, REG_VAL_DSK_LOOKAHEAD, &pDskReg->dwLookAhead);
    if (!fRet) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
            "Ata!GetDSKRegistryValueSet> Failed to read %s from DSK instance key\r\n"
            ), REG_VAL_DSK_LOOKAHEAD));
        return FALSE;
    }
    if (pDskReg->dwLookAhead >= 2) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
            "Ata!GetDSKRegistryValueSet> Bad value(%d) for %s in DSK instance key; valid: {0, 1}\r\n"
            ), pDskReg->dwLookAhead, REG_VAL_DSK_LOOKAHEAD));
        return FALSE;
    }

    // fetch transfer mode
    fRet = AtaGetRegistryValue(hDSKInstanceKey, REG_VAL_DSK_TRANSFERMODE, &pDskReg->dwTransferMode);
    if (!fRet) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
            "Ata!GetDSKRegistryValueSet> Failed to read %s from DSK instance key\r\n"
            ), REG_VAL_DSK_TRANSFERMODE));
        return FALSE;
    }

    // fetch IORDY Enable
    fRet = AtaGetRegistryValue(hDSKInstanceKey, REG_VAL_DSK_IORDYENABLE, &pDskReg->dwIORDYEnable);
    if (!fRet) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
            "Ata!GetDSKRegistryValueSet> Failed to read %s from DSK instance key\r\n"
            ), REG_VAL_DSK_IORDYENABLE));
        return FALSE;
    }

    return TRUE;
}

//------------------------------------------------------------------------------
//
//    Function : DSK_Init
//       This function is called as a result of IDE_Init calling ActivateDevice on
//       HKLM\Drivers\@BUS\@IDEAdapter\DeviceX, to initialize a master or slave
//       device on a particular IDE/ATA channel of a particular IDE/ATA controller.
//       That is, an "IDE" driver is a bus driver for devices to one its IDE/ATA
//       controller's channels.
//
//       This function is responsible for creating a CDisk instance to associate
//       with a device.  This function reads the "Object" value from its instance
//       key to determine which CDisk (sub)type to instantiate and calls Init on the
//       CDisk instance to initialize the device.  If the device is not present, then
//       Init will fail.  The "Object" value maps to a function that creates an
//       instance of the target CDisk (sub)type.
//
//       Note that this driver model is convoluted.  A CDisk (sub)type instance
//       corresponds to both an IDE/ATA controller and an ATA/ATAPI device.
//
//    Parameters:
//       dwContext - pointer to string containing the registry path to the active key
//       of the associated device; the active key contains a key to the device's instance
//       key, which stores all of the device's configuration information
//
//    Return:
//       On success, return handle to device (to identify device); this handle is
//       passed to all subsequent DSK_Xxx calls.  Otherwise, return null.
//
//------------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -