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

📄 atapipci.cpp

📁 这是运行在windows ce 4.2 版本下的关于硬盘加载的驱动程序
💻 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.
//
#include "atamain.h"
#include "atapipci.h"
#include <ceddk.h>
#undef ZONE_INIT
#define ZONE_INIT 1
 
//BOOL      g_fControllerInitialized = FALSE;
//CController g_ControllerTable[4];
//CPort g_PortTable[4];
LONG CPCIDisk::m_lDeviceCount = 0;
static TCHAR *g_szPCICDRomDisk = TEXT("CDROM Drive");
static TCHAR *g_szPCIHardDisk = TEXT("Hard Disk");


CController *g_ControllerTable=NULL;
CPort      *g_PortTable=NULL;
DWORD      g_dwControllerIndex=0;
//
// The following table specifies the ports to be checked when searching for
// an IDE controller.  A zero entry terminates the search.
//

CONST ULONG g_AdapterAddresses[5] = {0xBD000000, 0x170, 0x0F0, 0x070, 0};

//
// The following table specifies interrupt levels corresponding to the
// port addresses in the previous table.
//

CONST ULONG g_InterruptLevels[5] = {14, 15, 11, 10, 0};


/*****************************************************************************************************/
// CPCIDisk Class
/*****************************************************************************************************/
CPCIDisk::~CPCIDisk()
{
    FreeDMABuffers();
    if (!InterlockedDecrement( &m_lDeviceCount)) {
    }
    DEBUGMSG( ZONE_INIT | ZONE_PCI, (TEXT("ATAPIPCI:~CPCIDisk DeviceCount = %ld\r\n"), m_lDeviceCount));
}

void CPCIDisk::FreeDMABuffers()
{
    if (m_pPRD) {
        FreePhysMem( m_pPRD);
        m_pPRDPhys = NULL;
        m_pPRD = NULL;
    }    
    if (m_pPhysList) {
        // Free the fixed pages.  The variable ones should already be free
        for (DWORD i = 0; i < MIN_PHYS_PAGES; i++) {
            FreePhysMem (m_pPhysList[i].pVirtualAddress);
        }
        VirtualFree( m_pPhysList, UserKInfo[KINX_PAGESIZE], MEM_DECOMMIT);
        m_pPhysList = NULL;
    }    
    if (m_pSGCopy) {
        VirtualFree( m_pSGCopy, UserKInfo[KINX_PAGESIZE], MEM_DECOMMIT);
        m_pSGCopy = NULL;
    }
    if (m_pPFNs) {
        VirtualFree( m_pPFNs, UserKInfo[KINX_PAGESIZE], MEM_DECOMMIT);
        m_pSGCopy = NULL;
    }    
    VirtualFree (m_pStartMemory, 0, MEM_RELEASE);
    m_pStartMemory = NULL;
    
    m_dwPhysCount = 0;
    m_dwSGCount = 0;
}

void CPCIDisk::CopyDiskInfoFromPort()
{
    // Set up the memory address
    ASSERT( m_pPort->m_dwRegBase != 0);
    m_pATAReg = (PBYTE)m_pPort->m_dwRegBase;
    m_pATARegAlt = (PBYTE)m_pPort->m_dwRegAlt;
    
    ASSERT( m_pPort->m_dwBMR != 0);
    m_pBMCommand = (LPBYTE)m_pPort->m_dwBMR;
}

BOOL CPCIDisk::WaitForInterrupt(DWORD dwTimeOut) 
{
    BYTE bStatus;
    BOOL fRet = TRUE;
    DWORD dwRet;
    dwRet = WaitForSingleObject( m_pPort->m_hIRQEvent, dwTimeOut);
    if (dwRet == WAIT_TIMEOUT) {
        fRet = FALSE;
    } else
    if (dwRet != WAIT_OBJECT_0) {
        if (!WaitForDisc( WAIT_TYPE_DRQ,  dwTimeOut, 10)) {
            fRet = FALSE;
        }   
    }
    
    bStatus = GetBaseStatus();// Ack interrupt!!!!!
    
    if (bStatus & ATA_STATUS_ERROR) {
        bStatus = GetError();
        fRet = FALSE;
    }    

    
    InterruptDone(m_pPort->m_dwSysIntr);
    return fRet;
}

void CPCIDisk::EnableInterrupt() 
{
    GetBaseStatus();// Ack interrupt!!!!!
    InterruptDone(m_pPort->m_dwSysIntr);        
}


BOOL CPCIDisk::Init(HKEY hActiveKey)
{
    BOOL bRet = FALSE;

    //  Retrieve DeviceID  Number from Registry (0,1,2,3,4,5,6,7).
    //   A Device is specified by three Bits:
    //      Bit 0 - Specify Device on the chanel/port. Master(0)/Slave(1)
    //      Bit 1 - Specify Port/Channel: 0- Primary, 1 - Secondary Port
    //      Bit 3 - Specify Ata Controller/Adapter.
    //
    if (!AtaGetRegistryValue(m_hDevKey, TEXT("DeviceId"), &m_dwDeviceId)) {
        DEBUGMSG( ZONE_INIT, (TEXT("ATAPIPCI:Init: Missing Device Number in Registry \r\n")));
        goto ExitFail;
    }

    // Verify that the DeviceID is in range
    if ((m_dwDeviceId <0) || (m_dwDeviceId >= MAX_ATA_DEVICES))
    {
        DEBUGMSG( ZONE_INIT, (TEXT("ATAPIPCI:Init: Wrong DeviceID in the Registry DeviceId=% \r\n"),m_dwDeviceId));
        goto ExitFail;
    }
    
    if (DoesDeviceAlreadyExist()) {
        DEBUGMSG( ZONE_INIT, (TEXT("ATAPIPCI:AtaInitDevice: Device Initialized already!\r\n")));
        goto ExitFail;
    }
    //
    // Now can configure Port if not configure yet. 
    //
    m_dwPort = (m_dwDeviceId>>1) & 1;
    m_dwDevice = m_dwDeviceId & 1;

    DEBUGMSG( ZONE_INIT, (TEXT("Port configuration Port=%ld Device=%ld\r\n"), m_dwPort, m_dwDevice));

    if (!ConfigPort()) {
        DEBUGMSG( ZONE_INIT, (TEXT("ATAPIPCI:ConfigPort failed DeviceId=% \r\n"),m_dwDeviceId));
        goto ExitFail;
    }
    
    m_f16Bit = TRUE;    // PCI Is 16 access
    m_fInterruptSupported = TRUE;

    
    bRet = CDisk::Init(hActiveKey);
    if (IsCDRomDevice()) {
        m_szDiskName = g_szPCICDRomDisk;
    } else {
        m_szDiskName = g_szPCIHardDisk;
    }

    m_pStartMemory = (LPBYTE)VirtualAlloc (NULL, 0x10000, MEM_RESERVE, PAGE_READWRITE);
    if (!m_pStartMemory)
        bRet = FALSE;

ExitFail:
    return bRet;
}
//--------------------------------------------------------------------------
//
//  ConfigPort: Open the device key specified by the active key
//
//  Input:  dwPort  - Port Number 
//
//  Return: CPort *- ok.
//         NULL -   error.
//  
//  Notes:  Configure Controller Port. Each ATA Controller has two IO Ports.
//          This function is called for each device, but initialized only once.
//          The following procedure is used to configure IO Port:
//              1.) Check data received from PCI Config space
//              2.) Check Registry for required keys
//              3.) Use Default values if no value is found before.
//
//--------------------------------------------------------------------------
BOOL CPCIDisk::ConfigPort()
{
	g_ControllerTable=new CController[4];
	g_PortTable=new CPort[4];
    CController *pController= &g_ControllerTable[m_dwDeviceId>>1];
    CPort *pPort = &g_PortTable[m_dwDeviceId>>1];

    DEBUGMSG( ZONE_INIT, (TEXT("ATAPIPCI: ATAConfig  Device:%x\r\n"),m_dwDeviceId));

    // Configure Device only, if  the Port is already configured!!!

    if (pPort->m_hIRQEvent) {
        DEBUGMSG( ZONE_INIT, (TEXT("ATAPIPCI: ConfigPort - Port is already configured pPort=%08X\r\n"), pPort));
        m_pPort = pPort;
        m_dwDeviceFlags |= DFLAGS_DEVICE_INITIALIZED;
        CopyDiskInfoFromPort();
        return TRUE;
    }   

    DEBUGMSG( ZONE_INIT, (TEXT("ATAPIPCI: ConfigPort - Configuring pPort=%08X\r\n"), pPort));
    //
    //  Update Base Status Register.
    //  Check Registry if the Base Register was not found in the PCI Config Check Registry;
    //  Otrewise take default value.
    //
//	DWORD pPhyAdd = 0;
/*    if (!AtaGetRegistryValue(m_hDevKey, REG_VALUE_IOBASEADDRESS, &pPhyAdd)) {
        if (pController->m_dwRegBase)   {
            pPort->m_dwRegBase  = pController->m_dwRegBase ;
        } else {
            pPort->m_dwRegBase = g_AdapterAddresses[(m_dwDeviceId>>1) & 1];       // Othrewise take default value
            DEBUGMSG( ZONE_INIT | ZONE_PCI,  (TEXT(" ATAPIPCI: Using predefined IOBaseAddress = %08X\r\n"), pPort->m_dwRegBase));
        }
//		return FALSE;
    }
 */   //
    //  Update Alternative Status Register
    //
/*    if (pController->m_dwRegAlt) {
        pPort->m_dwRegAlt    = pController->m_dwRegAlt;
    } else {
        pPort->m_dwRegAlt = pPort->m_dwRegBase +0x204;
    } 
	*/
//IDE's CS0			->	CS0(0x11800000)
//IDE's CS1			->	CS1(0x12000000)
//IDE's A2			->	A3
//IDE's A1			->	A2
//IDE's A0			->	A1

/*
======================================================================================
|     | -CS0  | -CS1   |   HA2   |   HA1 |   HA0 |       RD    |      WR     | Offset|
|ADDR.----+-----+-----+----+----+----------------------------------------------------|
|     |  CS0  |   CS1  |  A3     |  A2   |   A1  |       Command Block       |       |
|----+----+-----+-----+----+-----+---------------------------------------------------|
| 1F0 |   0   |    1   |    0    |   0   |   0   |Data Reg.    |Data Reg.    | 0x000 |
| 1F1 |   0   |    1   |    0    |   0   |   1   |Error Reg.   |Features Reg.| 0x002 |
| 1F2 |   0   |    1   |    0    |   1   |   0   |SEC CNT Reg. |SEC CNT Reg. | 0x004 |
| 1F3 |   0   |    1   |    0    |   1   |   1   |SEC NUM Reg. |SEC NUM Reg. | 0x006 |
| 1F4 |   0   |    1   |    1    |   0   |   0   |CYL LOW Reg. |CYL LOW Reg. | 0x008 |
| 1F5 |   0   |    1   |    1    |   0   |   1   |CYL HIGH Reg.|CYL HIGH Reg.| 0x00A |
| 1F6 |   0   |    1   |    1    |   1   |   0   |Drv/Head Reg.|Drv/Head Reg.| 0x00C |
| 1F7 |   0   |    1   |    1    |   1   |   1   |Status Reg.  |Status Reg.  | 0x00E |
|------------------------------------------------------------------------------------|
|     |       |        |         |       |       |       Contorl Block       |       |
|----+----+----+------+----+-----+-----------------------------|-------------|-------|
| 3F6 |   1   |   0    |    1    |  1    |  0  |AltStatus Reg  |Dev Ctrl Reg | 0x00C |
| 3F7 |   1   |   0    |    1    |  1    |  1  |Drv Addr Reg.  |    ---      | 0x00E |
=====================================================================================|
*/
	DWORD pPhyAdd = 0;
	PVOID pVirtual=NULL;
    if (!AtaGetRegistryValue(m_hDevKey, REG_VALUE_BASEADD, &pPhyAdd)) {
		return FALSE;
    }
	DWORD IoSpace = 0;
	PHYSICAL_ADDRESS    ioPhysicalBase = {0, 0};
	ioPhysicalBase.LowPart = pPhyAdd;
	TransBusAddrToVirtual(PCIBus, 0, ioPhysicalBase, ATA_REG_LENGTH, &IoSpace, &pVirtual);
	pPort->m_dwRegBase = (ULONG)pVirtual;
    if (!AtaGetRegistryValue(m_hDevKey, REG_VALUE_ALTADD, &pPhyAdd)) {
		return FALSE;
    }
	ioPhysicalBase.LowPart = pPhyAdd;
	TransBusAddrToVirtual(PCIBus, 0, ioPhysicalBase, ATA_REG_LENGTH, &IoSpace, &pVirtual);
	pPort->m_dwRegAlt = ((ULONG)pVirtual+0xC);
    //
    //  Create an Interrupt Event. This event will be used by threads waiting 
    //  for an interrupt from Ata Device.
    //
    if ((pPort->m_hIRQEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL)
        return FALSE;
    //
    // Check DMA Bus Master Controller
    //
    if (!AtaGetRegistryValue(m_hDevKey, REG_VALUE_BMR, &pPort->m_dwBMR)) {
        pPort->m_dwBMR = pController->m_dwBMR ;
        pPort->m_dwBMRStatic = pController->m_dwBMRStatic;
    }   

/*    if (!AtaGetRegistryValue(m_hDevKey, REG_VALUE_INTERRUPT, &(pPort->m_dwIrq))) {
        if (pController->m_dwIrq) 
        {
            pPort->m_dwIrq = pController->m_dwIrq;
        }  else {
            pPort->m_dwIrq = g_InterruptLevels[(m_dwDeviceId>>1) & 1];
            DEBUGMSG( ZONE_INIT | ZONE_PCI,  (TEXT(" ATAPIPCI: Using predefined Interrupt = %08X\r\n"), pPort->m_dwIrq));
        }
    }   
*/

    if (!pController->m_dwSysIntr) {
        if (!AtaGetRegistryValue(m_hDevKey, REG_VALUE_SYSINTR, &(pController->m_dwSysIntr))) {
            //
            //  Update an Interrupt Level
            //

            DWORD dwReturned;
            if (!KernelIoControl( IOCTL_HAL_TRANSLATE_IRQ, 
                                  (LPVOID)&pPort->m_dwIrq, 
                                  sizeof(DWORD), 
                                  (LPVOID)&pController->m_dwSysIntr, 
                                  sizeof(DWORD), 
                                  &dwReturned))
            {
 #if defined(x86)
                 pController->m_dwSysIntr = pPort->m_dwIrq+SYSINTR_FIRMWARE;
#else            
                return FALSE;
#endif
            } else {
                DEBUGMSG( ZONE_INIT | ZONE_PCI, (TEXT("ATAPIPCI: Mapped IRQ %ld to SYSINTR %ld\r\n"), pController->m_dwSysIntr, pPort->m_dwIrq));
            }
        }    

⌨️ 快捷键说明

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