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

📄 promise.cpp

📁 这是运行在windows ce 4.2 版本下的关于硬盘加载的驱动程序
💻 CPP
字号:
//
// 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 "promise.h"
#include <giisr.h>
#include <ceddk.h>

void CPromise::DumpAllRegs(DWORD dwZone)
{
    DEBUGMSG( dwZone, (L"The status is %02x\r\n", GetAltStatus()));
    DEBUGMSG( dwZone, (L"The reason is %02x\r\n", GetReason()));
    DEBUGMSG( dwZone, (L"The error is  %02x\r\n", GetError()));
    DEBUGMSG( dwZone, (L"The system control register is %08x\r\n", ReadSystemCtrlReg()));
    DEBUGMSG( dwZone, (L"The UDMA register is %02x\r\n", ReadUDMAReg()));
    DEBUGMSG( dwZone, (L"The Mode control register is %02X\r\n", ReadModeCtrlReg()));
    DEBUGMSG( dwZone, (L"The subsystem register is %02X\r\n", ReadSubSystemReg()));
}

DWORD InterruptThread(LPVOID lParam)
{
    CPort *pPort = (CPort *)lParam;
    HANDLE hEvent;
    BOOL bStatus;
    if (pPort->m_pDisk[0]) {
        hEvent = ((CPromise *)(pPort->m_pDisk[0]))->m_hEvent;
    } else {
        hEvent = ((CPromise *)(pPort->m_pDisk[1]))->m_hEvent;
    }
    while(TRUE) {
        WaitForSingleObject( pPort->m_hIRQEvent, INFINITE);
        bStatus = ATA_READ_BYTE((LPBYTE)(pPort->m_dwRegBase+ATA_REG_STATUS));
        if (pPort->m_pDisk[0]) {
            ((CPromise *)pPort->m_pDisk[0])->m_bStatus = bStatus;
        }
        if (pPort->m_pDisk[1]) {
            ((CPromise *)pPort->m_pDisk[1])->m_bStatus = bStatus;
        }
        SetEvent( hEvent);
        InterruptDone(pPort->m_dwSysIntr);
    }    
    return 0;
}

BOOL CPromise::WaitForInterrupt(DWORD dwTimeOut) 
{
    BOOL fRet = TRUE;
    DWORD dwRet;
    dwRet = WaitForSingleObject( m_hEvent, dwTimeOut);
    if (dwRet == WAIT_TIMEOUT) {
        fRet = FALSE;
    } else
    if (dwRet != WAIT_OBJECT_0) {
        if (!WaitForDisc( WAIT_TYPE_DRQ,  dwTimeOut, 10)) {
            fRet = FALSE;
        }   
    }
    
    if (m_bStatus & ATA_STATUS_ERROR) {
        m_bStatus = GetError();
        fRet = FALSE;
    }    

    return fRet;
}

BOOL CPromise::Init(HKEY hActiveKey)
{
    BOOL bRet = CPCIDisk::Init(hActiveKey);
    if (!IsAtapiDevice()) {
       WriteAtapiTransferReg(0);
       SetTransferMode(0x20);
    }  
    GetBaseStatus();
    if (!AtaGetRegistryValue(m_hDevKey, L"DMADelay0",&m_dwDelay)) {
        m_dwDelay = 0;
    }   
    return bRet;
}

//--------------------------------------------------------------------------
BOOL CPromise::ConfigPort()
{
    extern CPort      *g_PortTable;
    BOOL bRet = TRUE;
    CPort *pPort = &g_PortTable[m_dwDeviceId>>1];
    if (pPort->m_hIRQEvent) {
        bRet = CPCIDisk::ConfigPort();
        if (pPort->m_pDisk[0]) {
            m_hEvent = ((CPromise *)(pPort->m_pDisk[0]))->m_hEvent;
        }   
        pPort->m_pDisk[1] = (HANDLE)this;
    } else {
        bRet = CPCIDisk::ConfigPort();
        // Install ISR handler
        if (bRet) {
            m_hEvent = CreateEvent( NULL, FALSE, FALSE, NULL);
            pPort->m_pDisk[0] = (HANDLE)this;
            TCHAR *szISRDll;
            TCHAR *szISRHandler;
            if (AtaGetRegistryString(m_hDevKey, L"IsrDll", &szISRDll) &&  AtaGetRegistryString(m_hDevKey, L"IsrHandler", &szISRHandler)) {
                m_hIsr = LoadIntChainHandler(szISRDll, szISRHandler, (BYTE)m_pPort->m_dwIrq);
                DEBUGMSG( ZONE_INIT, (L"PROMISE: ConfigPort - Loaded ISR Handler\r\n"));
                if (!m_hIsr) {
                    DEBUGMSG(ZONE_ERROR, (L"PROMISE: Couldn't install ISR handler\r\n"));
                    bRet = FALSE;
                } else {
                    GIISR_INFO Info;
                
                    // Set up ISR handler
                    Info.SysIntr = m_pPort->m_dwSysIntr;
                    Info.CheckPort = TRUE;
                    Info.PortIsIO = TRUE;
                    Info.UseMaskReg = FALSE;
                    Info.PortAddr = pPort->m_dwBMRStatic+PROMISE_SYSTEM_CTRL;
                    Info.PortSize = sizeof(DWORD);
                    Info.Mask = 0x400;
                    if (!KernelLibIoControl(m_hIsr, IOCTL_GIISR_INFO, &Info, sizeof(Info), NULL, 0, NULL)) {
                        DEBUGMSG(ZONE_ERROR, (L"PROMISE: KernelLibIoControl call failed.\r\n"));
                        bRet = FALSE;
                    } else {
                        DEBUGMSG( ZONE_INIT, (L"PROMISE: ConfigPort - Installed ISR Handler\r\n"));
                    }   
                }
            }  
            DWORD dwThreadId;
            HANDLE hThread;
            DWORD dwThreadPri;
            hThread = ::CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)InterruptThread, pPort, 0, &dwThreadId);
            if (AtaGetRegistryValue (m_hDevKey, L"IstPriority256", &dwThreadPri))
                ::CeSetThreadPriority (hThread, dwThreadPri);
            CloseHandle(hThread);
        }    
    }
    return bRet;
}   

#if 0
//--------------------------------------------------------------------------
BOOL CPromise::SetupDMA( PSG_BUF pSgBuf, DWORD dwSgCount, BOOL fRead)
{
    BOOL bRet =  CPCIDisk::SetupDMA( pSgBuf, dwSgCount, fRead);
    return bRet;
}
//--------------------------------------------------------------------------
BOOL CPromise::BeginDMA(BOOL fRead)
{
    BOOL bRet = CPCIDisk::BeginDMA(fRead);
    return bRet;
}
//--------------------------------------------------------------------------
BOOL CPromise::EndDMA()
{
    BOOL bRet = CPCIDisk::EndDMA();
    return bRet;
}
//--------------------------------------------------------------------------
BOOL CPromise::AbortDMA()
{
    BOOL bRet = CPCIDisk::AbortDMA();
    return bRet;
}
//--------------------------------------------------------------------------
BOOL CPromise::CompleteDMA(PSG_BUF pSgBuf, DWORD dwSgCount, BOOL fRead)
{
    BOOL bRet = CPCIDisk::CompleteDMA(pSgBuf, dwSgCount, fRead);
    return bRet;
}
#endif

DWORD CPromise::ReadCdRomDMA(DWORD dwLBAAddr, DWORD dwTransferLength, WORD wSectorSize, DWORD dwSgCount, SGX_BUF *pSgBuf)
{
    ATAPI_COMMAND_PACKET    CmdPkt;
    DWORD                   dwError=ERROR_SUCCESS;
    DWORD               dwSectorsToTransfer;
    SG_BUF              CurBuffer[MAX_SG_BUF];
    DWORD                   dwValue = 0;
    WORD                    wCount;

    if (m_fInterruptSupported)
        GetBaseStatus();
//      WaitForInterrupt(0);

    WaitForDisc(WAIT_TYPE_NOT_BUSY, 50);
    WaitForDisc(WAIT_TYPE_NOT_DRQ, 50);
    if (ERROR_SUCCESS != WaitForDisc( WAIT_TYPE_NOT_BUSY, 1000)) {
        DumpAllRegs(1);
    }
    if (ERROR_SUCCESS != WaitForDisc( WAIT_TYPE_NOT_DRQ, 1000)) {
        DumpAllRegs(1);
    }
    
    DEBUGMSG( ZONE_IO | ZONE_CDROM, (TEXT("ATAPI:ReadCdRomDMA Address=%ld TransferLen=%02X SectorSize=%ld SgCount=%02X\r\n"), dwLBAAddr, dwTransferLength, wSectorSize, dwSgCount));

    DWORD dwStartBufferNum = 0, dwEndBufferNum = 0, dwEndBufferOffset = 0;
    DWORD dwNumSectors = dwTransferLength;
    DWORD dwStartSector = dwLBAAddr;

    // Process the SG buffers in blocks of MAX_CD_SECT_PER_COMMAND.  Each DMA request will have a new SG_BUF array 
    // which will be a subset of the original request, and may start/stop in the middle of the original buffer.
    while (dwNumSectors) {

        dwSectorsToTransfer = (dwNumSectors > MAX_CD_SECT_PER_COMMAND) ? MAX_CD_SECT_PER_COMMAND : dwNumSectors;
    
        DWORD dwBufferLeft = dwSectorsToTransfer * wSectorSize;
        DWORD dwNumSg = 0;

        while (dwBufferLeft) {
            DWORD dwCurBufferLen = pSgBuf[dwEndBufferNum].sb_len - dwEndBufferOffset;

            if (dwBufferLeft < dwCurBufferLen) {
                // The buffer left for this block is less than the current SG buffer length
                CurBuffer[dwEndBufferNum - dwStartBufferNum].sb_buf = pSgBuf[dwEndBufferNum].sb_buf + dwEndBufferOffset;
                CurBuffer[dwEndBufferNum - dwStartBufferNum].sb_len = dwBufferLeft;
                dwEndBufferOffset += dwBufferLeft;
                dwBufferLeft = 0;
            } else {
                // The buffer left for this block is greater than or equal to the current SG buffer length.  Move on to the next SG buffer.
                CurBuffer[dwEndBufferNum - dwStartBufferNum].sb_buf = pSgBuf[dwEndBufferNum].sb_buf + dwEndBufferOffset;
                CurBuffer[dwEndBufferNum - dwStartBufferNum].sb_len = dwCurBufferLen;
                dwEndBufferOffset = 0;
                dwEndBufferNum++;
                dwBufferLeft -= dwCurBufferLen;
            }    
            dwNumSg++;
        }
     
        if (!SetupDMA(CurBuffer, dwNumSg, TRUE)) {
            dwError = ERROR_READ_FAULT;
            goto ExitFailure;
        }    


        SetupCdRomRead( wSectorSize == CDROM_RAW_SECTOR_SIZE ? TRUE : FALSE, dwStartSector, dwSectorsToTransfer, &CmdPkt);

        wCount = (SHORT)((dwSectorsToTransfer * wSectorSize) >> 1);

        if (AtapiSendCommand(&CmdPkt, wCount, IsDMASupported())) {
            if (m_dwDelay) {
                StallExecution(m_dwDelay);
            }   
            if (ERROR_SUCCESS != WaitForDisc( WAIT_TYPE_READY, 5000, 100)) {
                DEBUGMSG( ZONE_IO, (L"WaitforDisc before WriteTransferReg failed\r\n"));
                WriteAtapiTransferReg(0);
                dwError = ERROR_GEN_FAILURE;
                goto ExitFailure;
            }   
            if (GetAltStatus() & ATA_STATUS_ERROR) {
                dwError = ERROR_GEN_FAILURE;
                goto ExitFailure;
            }   
            WriteAtapiTransferReg(0);
            dwValue = ReadAtapiTransferReg();
            WriteAtapiTransferReg((1 << 24) | wCount);
            if (ERROR_SUCCESS != WaitForDisc( WAIT_TYPE_READY, 5000, 100)) {
                DEBUGMSG( ZONE_IO, (L"WaitforDisc before DMAStart failed\r\n"));
                WriteAtapiTransferReg(0);
                dwError = ERROR_READ_FAULT;
                goto ExitFailure;
            }   
            BeginDMA(TRUE);
            if (m_fInterruptSupported) {
                if (!WaitForInterrupt(DISK_IO_TIME_OUT)) {  
                    DEBUGMSG( ZONE_IO, (TEXT("ATAPI:ReadCdRom- WaitforInterrupt failed (DevId %x) \r\n"),m_dwDeviceId));
                    WriteAtapiTransferReg(0);
                    dwError = ERROR_READ_FAULT;
                    goto ExitFailure;
                }
                WaitForDisc(WAIT_TYPE_NOT_BUSY, 5000, 100);
            }    
            WriteAtapiTransferReg(0);
            if (EndDMA()) {
                WaitOnBusy(FALSE);
                CompleteDMA( (PSG_BUF)pSgBuf, dwSgCount, TRUE);
            } else {
                dwError = ERROR_READ_FAULT;
                goto ExitFailure;
            }    
        }


        dwStartSector += dwSectorsToTransfer;
        dwStartBufferNum = dwEndBufferNum;
        dwNumSectors -= dwSectorsToTransfer;        
    }    


ExitFailure:
    if (dwError != ERROR_SUCCESS) {
        AbortDMA();
    }    
    return dwError;
}

⌨️ 快捷键说明

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