?? promise.cpp
字號(hào):
//
// 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;
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -