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

📄 atamain.cpp

📁 SMDK2450的BSP 有很多新的特性,记得升级PB啊.
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//
// 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.
//

#include <atamain.h>
#include "../atapiromi/atapiromi.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);

// IDE/ATA bus implementation

// Constructor
CIDEBUS::CIDEBUS(
    )
{
    // initialize device handle table and device registry key name table
    for (int i = 0; i < MAX_DEVICES_PER_CONTROLLER; i++) {
        m_hDevice[i] = NULL;
        m_szDevice[i] = NULL;
    }
    // initialize DDKREGWINDOW structure
    memset(&m_dwi, 0, sizeof(m_dwi));
    // initialize port structures
    m_pIdeReg = NULL;
    m_pPrimaryPort = NULL;
    m_pSecondaryPort = NULL;
}

// Destructor
CIDEBUS::~CIDEBUS(
    )
{
    // deinitialize device handle table and device registry key name table
    for (int i = 0; i < MAX_DEVICES_PER_CONTROLLER; i++) {
        if (m_hDevice[i]) {
            BOOL fOk = DeactivateDevice(m_hDevice[i]);
            DEBUGCHK(fOk);
            DEBUGCHK(m_szDevice[i] != NULL);
        }
        if (m_szDevice[i] != NULL) {
            delete m_szDevice[i];
        }
    }
    // delete IDE_ registry value set
    if (m_pIdeReg) {
        if (m_pIdeReg->pszSpawnFunction) {
            LocalFree(m_pIdeReg->pszSpawnFunction);
        }
        if (m_pIdeReg->pszIsrDll) {
            LocalFree(m_pIdeReg->pszIsrDll);
        }
        if (m_pIdeReg->pszIsrHandler) {
            LocalFree(m_pIdeReg->pszIsrHandler);
        }
        LocalFree(m_pIdeReg);
    }
    // deinitialize port structures
    if (m_pPrimaryPort) {
        delete m_pPrimaryPort;
    }
    if (m_pSecondaryPort) {
        delete m_pSecondaryPort;
    }
}

// IDE/ATA channel/port implementation

// Constructor
CPort::CPort(
    CIDEBUS *pParent
    )
{
    DEBUGCHK(pParent);
    InitializeCriticalSection(&m_csPort);
    // hook up bus
    m_pController = pParent;
    // 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_dwIrq = IRQ_UNSPECIFIED;
    // initialize master/slave registry value set
    m_pDskReg[0] = NULL;
    m_pDskReg[1] = NULL;
    // initialize master/slave stream interface handles
    m_pDisk[0] = NULL;
    m_pDisk[1] = NULL;
}

// Destructor
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);
    }
    // free DSK_ registry value set
    if (m_pDskReg[0]) {
        LocalFree(m_pDskReg[0]);
    }
    if (m_pDskReg[1]) {
        LocalFree(m_pDskReg[1]);
    }
}

// Acquire exclusive access to IDE/ATA channel's I/O window
VOID
CPort::TakeCS(
    )
{
    EnterCriticalSection(&m_csPort);
}

// Release exclusive access to IDE/ATA channel's I/O window
VOID
CPort::ReleaseCS(
    )
{
    LeaveCriticalSection(&m_csPort);
}

// Write I/O window and interrupt data to debug output
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("dwBMR       = %08X\r\n"), m_dwBMR));
    DEBUGMSG(ZONE_INIT, (TEXT("dwSysIntr   = %08X\r\n"), m_dwSysIntr));
    DEBUGMSG(ZONE_INIT, (TEXT("dwIrq       = %08X\r\n"), m_dwIrq));
    DEBUGMSG(ZONE_INIT, (TEXT("dwBMRStatic = %08X\r\n"), m_dwBMRStatic));
}

// Helper functions

// 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
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;
}

// This function is used to determine whether a target disk instance is valid
BOOL
AtaIsValidDisk(
    CDisk *pDisk
    )
{
    CDisk *pTemp = g_pDiskRoot;
    while (pTemp) {
        if (pTemp == pDisk) {
            return TRUE;
        }
        pTemp = pTemp->m_pNextDisk;
    }
    return FALSE;
}

// 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
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(
            "Atapi!AtaGetRegistryResources> bus type not specified, using PCI as default\r\n"
            )));
        pdwi->dwInterfaceType = PCIBus;
    }

    return TRUE;
}

// This function translates a bus address in an I/O window to a virtual address
DWORD
DoIoTranslation(
    PDDKWINDOWINFO pdwi,
    DWORD dwIoWindowIndex
    )
{
    PHYSICAL_ADDRESS PhysicalAddress; // bus address
    DWORD AddressSpace = 1;           // mark bus address as being in an I/O window
    LPVOID pAddress;                  // return

    DEBUGCHK(pdwi != NULL);
    DEBUGCHK(dwIoWindowIndex < MAX_DEVICE_WINDOWS);
    if (!pdwi) {
        return NULL;
    }

    // extract the target bus address
    PhysicalAddress.HighPart = 0;
    PhysicalAddress.LowPart = pdwi->ioWindows[dwIoWindowIndex].dwBase;

    // translate the target bus address to a virtual address
    if (!TransBusAddrToVirtual(
        (INTERFACE_TYPE)pdwi->dwInterfaceType,
        pdwi->dwBusNumber,
        PhysicalAddress,
        pdwi->ioWindows[dwIoWindowIndex].dwLen,
        &AddressSpace,
        &pAddress
     )) {
        return NULL;
    }

    return (DWORD)pAddress;
}

// This function translates a bus address to a statically physical address
DWORD
DoStaticTranslation(
    PDDKWINDOWINFO pdwi,
    DWORD dwIoWindowIndex
    )
{
    PHYSICAL_ADDRESS PhysicalAddress; // bus address
    DWORD AddressSpace = 1;           // mark bus address as being in an I/O window
    LPVOID pAddress;                  // return

    DEBUGCHK(pdwi != NULL);
    DEBUGCHK(dwIoWindowIndex < MAX_DEVICE_WINDOWS);

    if (!pdwi) {
        return NULL;
    }

    // extract bus address
    PhysicalAddress.HighPart = 0;
    PhysicalAddress.LowPart = pdwi->ioWindows[dwIoWindowIndex].dwBase;

    // translate the target bus address to a statically mapped physical address
    if (!TransBusAddrToStatic(
        (INTERFACE_TYPE)pdwi->dwInterfaceType,
        pdwi->dwBusNumber,
        PhysicalAddress,
        pdwi->ioWindows[dwIoWindowIndex].dwLen,
        &AddressSpace,
        &pAddress
    )) {
        return NULL;
    }

    return (DWORD)pAddress;
}

// This function reads the IDE registry value set from the IDE/ATA controller's
// registry key
BOOL
GetIDERegistryValueSet(
    HKEY hIDEInstanceKey,
    PIDEREG pIdeReg
    )
{
    BOOL fRet;

    DEBUGCHK(NULL != pIdeReg);

    // fetch legacy boolean
    fRet = AtaGetRegistryValue(hIDEInstanceKey, REG_VAL_IDE_LEGACY, &pIdeReg->dwLegacy);
    if (!fRet) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
            "Atapi!GetIDERegistryValueSet> Failed to read %s from IDE instance key\r\n"
            ), REG_VAL_IDE_LEGACY));
        return FALSE;
    }
    if (pIdeReg->dwLegacy >= 2) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
            "Atapi!GetIDERegistryValueSet> Bad value(%d) for %s in IDE instance key; valid: {0, 1}\r\n"
            ), pIdeReg->dwLegacy, REG_VAL_IDE_LEGACY));
        return FALSE;
    }

    // fetch IRQ; this value is not mandatory
    fRet = AtaGetRegistryValue(hIDEInstanceKey, REG_VAL_IDE_IRQ, &pIdeReg->dwIrq);
    if (!fRet) {
        pIdeReg->dwIrq = IRQ_UNSPECIFIED;
    }

    // fetch SysIntr; this is not mandatory
    fRet = AtaGetRegistryValue(hIDEInstanceKey, REG_VAL_IDE_SYSINTR, &pIdeReg->dwSysIntr);
    if (!fRet) {
        pIdeReg->dwSysIntr = SYSINTR_NOP;
    }

    // fetch vendor id; this is not mandatory
    fRet = AtaGetRegistryValue(hIDEInstanceKey, REG_VAL_IDE_VENDORID, &pIdeReg->dwVendorId);
    if (!fRet) {
        pIdeReg->dwVendorId = 0;
    }

    // fetch DMA alignment; this is not mandatory
    fRet = AtaGetRegistryValue(hIDEInstanceKey, REG_VAL_IDE_DMAALIGNMENT, &pIdeReg->dwDMAAlignment);
    if (!fRet) {
        pIdeReg->dwDMAAlignment = 0;
    }

    // fetch soft reset timeout
    fRet = AtaGetRegistryValue(hIDEInstanceKey, REG_VAL_IDE_SOFTRESETTIMEOUT, &pIdeReg->dwSoftResetTimeout);
    if (!fRet) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
            "Atapi!GetIDERegistryValueSet> Failed to read %s from IDE instance key\r\n"
            ), REG_VAL_IDE_SOFTRESETTIMEOUT));
        return FALSE;
    }

    // fetch Status register poll cycles
    fRet = AtaGetRegistryValue(hIDEInstanceKey, REG_VAL_IDE_STATUSPOLLCYCLES, &pIdeReg->dwStatusPollCycles);
    if (!fRet) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
            "Atapi!GetIDERegistryValueSet> Failed to read %s from IDE instance key\r\n"
            ), REG_VAL_IDE_STATUSPOLLCYCLES));
        return FALSE;
    }

    // fetch Status register polls per cycle
    fRet = AtaGetRegistryValue(hIDEInstanceKey, REG_VAL_IDE_STATUSPOLLSPERCYCLE, &pIdeReg->dwStatusPollsPerCycle);
    if (!fRet) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
            "Atapi!GetIDERegistryValueSet> Failed to read %s from IDE instance key\r\n"
            ), REG_VAL_IDE_STATUSPOLLSPERCYCLE));
        return FALSE;
    }

    // fetch Status register poll cycle pause
    fRet = AtaGetRegistryValue(hIDEInstanceKey, REG_VAL_IDE_STATUSPOLLCYCLEPAUSE, &pIdeReg->dwStatusPollCyclePause);
    if (!fRet) {

⌨️ 快捷键说明

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