📄 cdio.cpp
字号:
WriteSectorCount(0);
WriteSectorNumber(0);
// Set the byte tranfer count
if (wCount) {
WriteLowCount((BYTE)(0xff & wCount));
WriteHighCount((BYTE)(0xff & (wCount >> 8)));
} else {
WriteLowCount(0xFE);
WriteHighCount(0xFF);
}
//
// Set PIO or DMA Mode as specified in bFlags. 0 = PIO, 1 = DMA
//
WriteFeature(fDMA ? 0x1 : 0x0);
WaitForDisc( WAIT_TYPE_NOT_BUSY, 20);
// Write ATAPI into command register
SelectDevice();
WriteCommand(ATAPI_CMD_COMMAND);
WaitForDisc( WAIT_TYPE_NOT_BUSY, 20);
//
// Check how device is reporting CPU attention: DRQ or INTRQ?
// INTRQ within 10 ms!!!
//
if (m_fInterruptSupported && IsDRQTypeIRQ())
{
// ATA_INTR_CMD is expected
//
if (WaitForInterrupt(DISK_IO_TIME_OUT))
{
DEBUGMSG( ZONE_IO | ZONE_CDROM, (TEXT("ATAPI:AtapiSendCommand - Wait for ATA_INTR_CMD Interrupt (DevId %x) \r\n"), m_dwDeviceId));
return FALSE;
}
}
//
// Device will assert DRQ within (50us or 3ms) if no interrupt id used
// Wait for not BSY and DRQ
if (!WaitForDRQ())
{
DEBUGMSG( ZONE_IO | ZONE_CDROM, (TEXT("ATAPIPCI:AtapiSendCommand 1 - ATAWaitForDisc failed with: %x (DevId %x)\r\n"), GetError(), m_dwDeviceId));
return FALSE;
}
// Write the ATAPI Command Packet.
WriteWordBuffer( (LPWORD)pCmdPkt,GetPacketSize()/sizeof(WORD));
return TRUE;
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
BOOL CDisk::AtapiReceiveData(PSGX_BUF pSgBuf, DWORD dwSgCount,LPDWORD pdwBytesRead)
{
DWORD dwSgLeft = dwSgCount;
DWORD dwTransferCount;
PSGX_BUF pCurrentSegment;
DWORD dwReadCount = 0;
DWORD dwThisCount;
BYTE *pCurrentBuffer = NULL;
DWORD dwLen;
DEBUGMSG( ZONE_IO | ZONE_CDROM, (TEXT("ATAPI:AtapiReceiveData - Entered SgCount=%ld.\r\n"), dwSgCount));
if (ERROR_SUCCESS != WaitForDisc( WAIT_TYPE_READY, 5000, 100))
return FALSE;
pCurrentSegment = pSgBuf;
if (pCurrentSegment) {
dwLen = pCurrentSegment->sb_len;
pCurrentBuffer = (LPBYTE)MapPtrToProcess(pCurrentSegment->sb_buf, GetCallerProcess());
}
m_wNextByte = 0xFFFF; // There is no byte left from the previous transaction.
for(;;) {
if (m_fInterruptSupported) {
//
// Waiting for ATA_INTR_READ or ATA_INTR_WRITE or ATA_INTR_READY
//
if (!WaitForInterrupt(DISK_IO_TIME_OUT)) {
DEBUGMSG( ZONE_CDROM | ZONE_ERROR, (TEXT("ATAPI:AtapiReceiveData - Wait for ATA_INTR_READ failed (DevId %x) \r\n"), m_dwDeviceId));
return FALSE;
}
WORD wState = CheckIntrState();
//
// Return Error if not IO Interrupt
//
if ((wState == ATA_INTR_ERROR) || (GetAltStatus() & ATA_STATUS_ERROR))
{
DEBUGMSG( ZONE_IO | ZONE_ERROR | ZONE_CDROM, (TEXT("ATAPI:AtapiReceiveData - Wait for ATA_INTR_READ failed (DevId %x) \r\n"), m_dwDeviceId));
return FALSE;
}
if (wState == ATA_INTR_READY)
{
DEBUGMSG( ZONE_IO | ZONE_CDROM, (TEXT("ATAPI:AtapiReceiveData - Exiting with Interrupt Ready signal Device=%ld\r\n"), m_dwDeviceId));
return TRUE;
}
};
//
// Wait until device is ready for data transfer.
//
if (!WaitForDRQ())
{
DEBUGMSG( ZONE_IO | ZONE_ERROR | ZONE_CDROM, (TEXT("ATAPI:AtapiReceiveData Failed at WaitForDRQ Status=%02X Error=%02X Deivce=%ld\r\n"), GetAltStatus(), GetError(), m_dwDeviceId));
return(FALSE);
}
//
// Read Transfer Counter set by Device.
//
dwTransferCount = GetCount();
DEBUGMSG (ZONE_CDROM | ZONE_IO, (TEXT(">>>Read Transfer Count : %x SG=%x \r\n"),dwTransferCount,dwSgLeft));
while ((dwSgLeft>0) && (dwTransferCount>0))
{
dwThisCount = min(dwTransferCount, dwLen);
if (pCurrentBuffer) {
ReadBuffer(pCurrentBuffer,dwThisCount);
dwTransferCount -= dwThisCount;
dwReadCount += dwThisCount;
}
pCurrentBuffer += dwThisCount;
dwLen -= dwThisCount;
if (dwLen == 0) {
// Go to the next SG
dwSgLeft--;
pCurrentSegment++;
if (pCurrentSegment) {
dwLen = pCurrentSegment->sb_len;
pCurrentBuffer = (LPBYTE)MapPtrToProcess(pCurrentSegment->sb_buf, GetCallerProcess());
}
}
} // End of while loop
// Discard the rest of data if left.
while (dwTransferCount > 0)
{
(void) ReadWord();
dwTransferCount-=2 ;
}
if (pdwBytesRead)
*pdwBytesRead = dwReadCount;
if (!dwSgLeft)
break;
}
return TRUE;
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
BOOL CDisk::AtapiSendData(PSGX_BUF pSgBuf, DWORD dwSgCount,LPDWORD pdwBytesWrite)
{
DWORD dwSgLeft = dwSgCount;
DWORD dwTransferCount;
PSGX_BUF pCurrentSegment;
DWORD dwWriteCount = 0;
DWORD dwThisCount;
BYTE *pCurrentBuffer=NULL;
DEBUGMSG( ZONE_IO | ZONE_CDROM, (TEXT("ATAPI:AtapiReceiveData - Entered SgCount=%ld.\r\n"), dwSgCount));
pCurrentSegment = pSgBuf;
m_wNextByte = 0xFFFF; // There is no byte left from the previous transaction.
for(;;) {
if (m_fInterruptSupported) {
//
// Waiting for ATA_INTR_READ or ATA_INTR_WRITE or ATA_INTR_READY
//
if (!WaitForInterrupt(DISK_IO_TIME_OUT)) {
DEBUGMSG( ZONE_CDROM | ZONE_ERROR, (TEXT("ATAPI:AtapiReceiveData - Wait for ATA_INTR_READ failed (DevId %x) \r\n"), m_dwDeviceId));
return FALSE;
}
WORD wState = CheckIntrState();
//
// Return Error if not IO Interrupt
//
if (wState == ATA_INTR_ERROR)
{
DEBUGMSG( ZONE_IO | ZONE_ERROR | ZONE_CDROM, (TEXT("ATAPI:AtapiReceiveData - Wait for ATA_INTR_READ failed (DevId %x) \r\n"), m_dwDeviceId));
return FALSE;
}
if (wState == ATA_INTR_READY)
{
DEBUGMSG( ZONE_IO | ZONE_CDROM, (TEXT("ATAPI:AtapiReceiveData - Exiting with Interrupt Ready signal Device=%ld\r\n"), m_dwDeviceId));
return TRUE;
}
};
//
// Wait until device is ready for data transfer.
//
if (!WaitForDRQ())
{
DEBUGMSG( ZONE_IO | ZONE_ERROR | ZONE_CDROM, (TEXT("ATAPI:AtapiReceiveData Failed at WaitForDRQ Status=%02X Error=%02X Deivce=%ld\r\n"), GetAltStatus(), GetError(), m_dwDeviceId));
return(FALSE);
}
//
// Read Transfer Counter set by Device.
//
dwTransferCount = GetCount();
DEBUGMSG (ZONE_CDROM | ZONE_IO, (TEXT(">>>Read Transfer Count : %x SG=%x \r\n"),dwTransferCount,dwSgLeft));
while ((dwSgLeft>0) && (dwTransferCount>0))
{
dwThisCount = min(dwTransferCount, pCurrentSegment->sb_len);
if (pCurrentSegment->sb_buf)
pCurrentBuffer = (LPBYTE)MapPtrToProcess(pCurrentSegment->sb_buf, GetCallerProcess());
if (pCurrentBuffer)
{
WriteBuffer(pCurrentBuffer,dwThisCount);
dwTransferCount -= dwThisCount;
dwWriteCount += dwThisCount;
}
pCurrentSegment->sb_len -=dwThisCount;
pCurrentSegment->sb_buf +=dwThisCount;
if (pCurrentSegment->sb_len == 0)
{
// Go to the next SG
dwSgLeft--;
pCurrentSegment++;
}
} // End of while loop
if (pdwBytesWrite)
*pdwBytesWrite = dwWriteCount;
if (!dwSgLeft)
break;
}
return TRUE;
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
BOOL CDisk::AtapiIsUnitReady(PIOREQ pIOReq)
{
ATAPI_COMMAND_PACKET CmdPkt;
DWORD dwRet;
BOOL fRet = TRUE;
if (!IsRemoveableDevice())
return(TRUE);
memset(&CmdPkt, 0, sizeof(ATAPI_COMMAND_PACKET));
CmdPkt.Opcode = ATAPI_PACKET_CMD_TEST_READY;
if (AtapiSendCommand(&CmdPkt)) {
if (!AtapiReceiveData( NULL, 0, &dwRet)) {
fRet = FALSE;
}
} else {
fRet = FALSE;
}
if ( pIOReq && pIOReq->pInBuf)
{
((CDROM_TESTUNITREADY *)pIOReq->pInBuf)->bUnitReady = fRet;
}
if ( pIOReq && pIOReq->pOutBuf)
{
((CDROM_TESTUNITREADY *)pIOReq->pOutBuf)->bUnitReady = fRet;
}
if (!fRet) {
DEBUGMSG( ZONE_ERROR |ZONE_CDROM, (TEXT("ATAPI:AtapiIsUnitReady Status=%02X Error=%02X Reason=%02X\r\n"), GetAltStatus(), GetError(), GetReason()));
}
return fRet;
}
//---------------------------------------------------------------------------
//
// function: AtaGetSenseInfo
//
// synopsis: Issue a request sense command to get additional error data
//
// ENTRY
//
// EXIT
//
// Failure
// Returns an extended error code.
//
//-----------------------------------------------------------------------------
BOOL CDisk::AtapiGetSenseInfo(CD_SENSE_DATA *pSenseData)
{
ATAPI_COMMAND_PACKET CmdPkt;
SGX_BUF SgBuf;
DWORD dwRet;
memset(&CmdPkt, 0, sizeof(ATAPI_COMMAND_PACKET));
CmdPkt.Opcode = ATAPI_PACKET_CMD_REQUEST_SENSE;
CmdPkt.Byte_4 = (BYTE)sizeof(CD_SENSE_DATA);
SgBuf.sb_len = sizeof(CD_SENSE_DATA);
SgBuf.sb_buf = (PBYTE) pSenseData;
if (AtapiSendCommand(&CmdPkt)) {
if (!AtapiReceiveData(&SgBuf, 1, &dwRet)) {
DEBUGMSG( ZONE_ERROR|ZONE_CDROM, (TEXT("AtaGetSenseInfo Failed!!!\r\n")));
return FALSE;
}
} else {
return FALSE;
}
// Issue the request sense command
DEBUGMSG( ZONE_CDROM | ZONE_IO, (TEXT("Sense Info\r\n")));
DEBUGMSG( ZONE_CDROM | ZONE_IO, (TEXT(" Error Code = 0x%2.2X, Segment Number = %d, Sense Key = 0x%2.2X\r\n"), pSenseData->sd_ErrCode, pSenseData->sd_SegNum, pSenseData->sd_ILI_Key));
DEBUGMSG( ZONE_CDROM | ZONE_IO, (TEXT(" Information = 0x%2.2X 0x%2.2X 0x%2.2X 0x%2.2X\r\n"), pSenseData->sd_Info[0], pSenseData->sd_Info[1], pSenseData->sd_Info[2], pSenseData->sd_Info[3]));
DEBUGMSG( ZONE_CDROM | ZONE_IO, (TEXT(" Additional Sense Length = %d\r\n"), pSenseData->sd_Length));
DEBUGMSG( ZONE_CDROM | ZONE_IO, (TEXT(" Command Specific Information = 0x%2.2X 0x%2.2X 0x%2.2X 0x%2.2X\r\n"),pSenseData->sd_CmdInfo[0], pSenseData->sd_CmdInfo[1], pSenseData->sd_CmdInfo[2], pSenseData->sd_CmdInfo[3]));
DEBUGMSG( ZONE_CDROM | ZONE_IO, (TEXT(" ASC = 0x%2.2X, ASCQ = 0x%2.2X, FRUC = 0x%2.2X\r\n"), pSenseData->sd_SenseCode, pSenseData->sd_Qualifier, pSenseData->sd_UnitCode));
DEBUGMSG( ZONE_CDROM | ZONE_IO, (TEXT(" Sense Key Specfic = 0x%2.2X 0x%2.2X 0x%2.2X\r\n"), pSenseData->sd_Key1, pSenseData->sd_Key2, pSenseData->sd_Key3));
return TRUE;
}
//
// This function send INQUIRY command to Atapi Device and
// process reply corresponding reply.
//
BOOL CDisk::AtapiIssueInquiry(INQUIRY_DATA *pInqData)
{
ATAPI_COMMAND_PACKET CmdPkt;
SGX_BUF SgBuf;
DWORD dwRet;
memset((void *)&CmdPkt, 0, sizeof(CmdPkt));
CmdPkt.Opcode = ATAPI_PACKET_CMD_INQUIRY;
CmdPkt.Byte_4 = sizeof(INQUIRY_DATA);
SgBuf.sb_len = sizeof(INQUIRY_DATA);
SgBuf.sb_buf = (PBYTE) pInqData;
if (AtapiSendCommand(&CmdPkt)) {
if (!AtapiReceiveData(&SgBuf, 1, &dwRet)) {
DEBUGMSG( ZONE_ERROR|ZONE_CDROM, (TEXT("AtapiIssueInquriy Failed\r\n")));
return FALSE;
}
} else {
return FALSE;
}
return TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -