📄 ali.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 "ali.h"
#include <ceddk.h>
BOOL CAli::Init(HKEY hActiveKey)
{
BOOL bRet = CPCIDisk::Init(hActiveKey);
SetTransferMode(0x20);
GetBaseStatus();
return bRet;
}
//--------------------------------------------------------------------------
BOOL CAli::EndDMA()
{
BYTE bStatus = ReadBMStatus();
if ((bStatus & BM_STATUS_INTR) && (bStatus & BM_STATUS_ACTIVE))
DEBUGMSG( ZONE_DMA, (TEXT(" ATAPI:EndDMA This is an active state... status=%02x\n"), bStatus));
else if ((bStatus & BM_STATUS_INTR) && !(bStatus & BM_STATUS_ACTIVE))
{
DEBUGMSG( ZONE_DMA, (TEXT(" ATAPI:EndDMA This is an inactive state... status=%02x\n"), bStatus));
}
else if (!(bStatus & BM_STATUS_INTR) || (bStatus & BM_STATUS_ACTIVE))
{
DEBUGMSG( ZONE_ERROR | ZONE_DMA, (TEXT(" ATAPI:EndDMA Interrupt Delayed... status=%02x\n"), bStatus));
BOOL bCount = 0;
while (TRUE) {
StallExecution(100);
bCount++;
bStatus = ReadBMStatus();
if ((bStatus & BM_STATUS_INTR) && !(bStatus & BM_STATUS_ACTIVE)) {
DEBUGMSG( ZONE_DMA, (TEXT(" ATAPI:EndDMA DMA Done after wait... status=%02x\n"), bStatus));
break;
} else {
DEBUGMSG( ZONE_ERROR | ZONE_DMA, (TEXT(" ATAPI:EndDMA Interrupt still delayed... status=%02x\n"), bStatus));
if (bCount > 10) {
WriteBMCommand(0);
return FALSE;
}
}
}
}
else
{
if (bStatus & BM_STATUS_ERROR) {
DEBUGMSG( ZONE_ERROR | ZONE_DMA, (TEXT(" ATAPI:EndDMA Error... status=%02x\n"), bStatus));
ASSERT(0);
return FALSE;
}
}
WriteBMCommand(0);
return TRUE;
}
DWORD CAli::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;
DWORD dwRetry=0;
while(dwRetry++ < 5) {
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)) {
}
if (ERROR_SUCCESS != WaitForDisc( WAIT_TYPE_NOT_DRQ, 1000)) {
}
DEBUGMSG( ZONE_IO | ZONE_CDROM, (TEXT("ATAPI:Ali: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 (GetAltStatus() & ATA_STATUS_ERROR) {
dwError = ERROR_GEN_FAILURE;
goto ExitFailure;
}
BeginDMA(TRUE);
if (m_fInterruptSupported) {
if (!WaitForInterrupt(DISK_IO_TIME_OUT)) {
DEBUGMSG( ZONE_IO, (TEXT("ATAPI:Ali:ReadCdRom- WaitforInterrupt failed (DevId %x) \r\n"),m_dwDeviceId));
dwError = ERROR_READ_FAULT;
goto ExitFailure;
}
WaitForDisc(WAIT_TYPE_NOT_BUSY, 5000, 100);
}
if (ERROR_SUCCESS != WaitForDisc(WAIT_TYPE_READY, 1000)) {
}
if (EndDMA()) {
WaitOnBusy(FALSE);
CompleteDMA( (PSG_BUF)pSgBuf, dwSgCount, TRUE);
} else {
dwError = ERROR_READ_FAULT;
goto ExitFailure;
}
}
dwStartSector += dwSectorsToTransfer;
dwStartBufferNum = dwEndBufferNum;
dwNumSectors -= dwSectorsToTransfer;
}
break;
ExitFailure:
if (dwError != ERROR_SUCCESS) {
AbortDMA();
}
}
return dwError;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -