// Aspi.cpp: implementation of the aspi methods // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "cdvd.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif #define MOVESCSIDWORD(pdwSrc,pdwDst) \ {\ ((PBYTE)(pdwDst))[0] = ((PBYTE)(pdwSrc))[3];\ ((PBYTE)(pdwDst))[1] = ((PBYTE)(pdwSrc))[2];\ ((PBYTE)(pdwDst))[2] = ((PBYTE)(pdwSrc))[1];\ ((PBYTE)(pdwDst))[3] = ((PBYTE)(pdwSrc))[0];\ } #define MOVESCSIWORD(pwSrc,pwDst) \ {\ ((PBYTE)(pwDst))[0] = ((PBYTE)(pwSrc))[1];\ ((PBYTE)(pwDst))[1] = ((PBYTE)(pwSrc))[0];\ } /***********************************************************/ /* ASPI Init/Shutdown related methods */ /***********************************************************/ // using MFC classes, no aspi in other systems. int CCdvd::Aspi_CheckValidInstallation() { int retval = CDVD_ERROR_FAIL; CFileStatus fstat; TCHAR szDir[MAX_PATH]; if(GetSystemDirectory(szDir,MAX_PATH)) { CString directory = szDir; WIN32OSTYPE ostype = GetWin32OSType(); if(ostype != WINNTNEW && ostype != WINNTOLD) { if(CFile::GetStatus(directory+_T("\\wnaspi32.dll"), fstat) && CFile::GetStatus(directory+_T("\\winaspi.dll"), fstat) && CFile::GetStatus(directory+_T("\\iosubsys\\apix.vxd"), fstat)) { retval = CDVD_ERROR_SUCCESS; } } else { if(CFile::GetStatus(directory+_T("\\wnaspi32.dll"), fstat) && CFile::GetStatus(directory+_T("\\drivers\\aspi32.sys"), fstat)) { retval = CDVD_ERROR_SUCCESS; } } } else { // are you crazy? o_O, no fucking windows directory? o_O retval = CDVD_ERROR_FAIL; } return retval; } // called once to init Aspi int CCdvd::Aspi_Init() { int retval = CDVD_ERROR_FAIL; if(m_bAspiInitialized) return CDVD_ERROR_SUCCESS; if(Aspi_CheckValidInstallation() == CDVD_ERROR_SUCCESS) { if((m_hAspi = AfxLoadLibrary("WNASPI32")) != NULL) { SendASPI32Command = (CDROMSendASPI32Command) GetProcAddress(m_hAspi,"SendASPI32Command"); GetASPI32SupportInfo = (CDROMGetASPI32SupportInfo) GetProcAddress(m_hAspi,"GetASPI32SupportInfo"); if(SendASPI32Command != NULL && GetASPI32SupportInfo != NULL) { UI32 support_info = GetASPI32SupportInfo(); if( HIBYTE(LOWORD(support_info)) != SS_COMP && HIBYTE(LOWORD(support_info)) != SS_NO_ADAPTERS ) { Aspi_Shutdown(); } else { if(InitializeBuffers() == CDVD_ERROR_SUCCESS) { if(Aspi_ScsiBusScan() == CDVD_ERROR_SUCCESS) { SetCurrentBuffer(0); m_bAspiInitialized = TRUE; retval = CDVD_ERROR_SUCCESS; GetNumSectors = Aspi_GetNumSectors; GetToc = Aspi_GetToc; // GetHeader = Aspi_GetHeader; SetSpeed = Aspi_SetSpeed; Stop = Aspi_Stop; SetSectorSize = Aspi_SetSectorSize; Play = Aspi_Play; TestReady = Aspi_TestReady; ReadSector = Dummy_T4; UpdateInterfaceObject(); } } } } else { Aspi_Shutdown(); } } } return retval; } // shuts down aspi int CCdvd::Aspi_Shutdown() { int retval = CDVD_ERROR_SUCCESS; // gota detect the read_mode first before i do this // but just reset to 2048 for now. Aspi_SetSectorSize(CDVD_SECTOR_SIZE_DVD); // the old ASPI drivers suck shit to hell and damnation, // freeing them up immediately after init will crash sometimes ::Sleep(200); if(m_hAspi != NULL) AfxFreeLibrary(m_hAspi); m_hAspi = NULL; SendASPI32Command = NULL; GetASPI32SupportInfo = NULL; GetNumSectors = Dummy_T1; GetToc = Dummy_T1; Stop = Dummy_T1; Play = Dummy_T3; TestReady = Dummy_T1; // GetHeader = Dummy_T1; SetSpeed = Dummy_T2; SetSectorSize = Dummy_T2; ReadSector = Dummy_T4; UpdateInterfaceObject(); ShutdownBuffers(); m_bAspiInitialized = FALSE; return retval; } // open a drive for reading int CCdvd::Aspi_OpenDrive(int drv_num) { int retval = CDVD_ERROR_SUCCESS; CloseDrive(); m_nCurrentDrive = drv_num; return retval; } // dummy for now int CCdvd::Aspi_CloseDrive() { int retval = CDVD_ERROR_SUCCESS; m_nCurrentDrive = -1; return retval; } // get srb status int CCdvd::Aspi_GetSrbStatus(int srb_num) { int retval = CDVD_SRB_ERROR; switch(m_nCurrentReadMode) { case CDVD_READ_MMC: retval = m_srbReadCd [srb_num].SRB_Status; break; case CDVD_READ_SCSI10: retval = m_srbRead10 [srb_num].SRB_Status; break; case CDVD_READ_D8: retval = m_srbReadMat [srb_num].SRB_Status; break; case CDVD_READ_D410: retval = m_srbReadSony[srb_num].SRB_Status; break; case CDVD_READ_D412: retval = m_srbReadNec [srb_num].SRB_Status; break; default: break; } if(retval == SS_COMP) retval = CDVD_SRB_COMPLETED; else if(retval == SS_PENDING) retval = CDVD_SRB_PENDING; else //if(retval == SS_ERR) retval = CDVD_SRB_ERROR; return retval; } // set read mode int CCdvd::Aspi_SetReadMode(CDVD_READ_MODE read_mode) { int retval = CDVD_ERROR_SUCCESS; switch(read_mode) { case CDVD_READ_MMC: ReadSector = Aspi_ReadSector_mmc; break; case CDVD_READ_SCSI10: TRACE("cdvdlib: setting scsi10 readmode.\n"); ReadSector = Aspi_ReadSector_scsi10; if(((this)->*(SetSectorSize))((m_nMmcDataMode == CDVD_MMC_DATAMODE_RAW) ? CDVD_SECTOR_SIZE_CD : CDVD_SECTOR_SIZE_DVD) != CDVD_ERROR_SUCCESS) { retval = CDVD_ERROR_FAIL; } break; case CDVD_READ_D8: ReadSector = Aspi_ReadSector_matsu; break; case CDVD_READ_D410: ReadSector = Aspi_ReadSector_sony; break; case CDVD_READ_D412: ReadSector = Aspi_ReadSector_nec; break; default: retval = CDVD_ERROR_FAIL; break; } UpdateInterfaceObject(); return retval; } // search for scsi adapters with c/dvd drives. int CCdvd::Aspi_ScsiBusScan() { int retval = CDVD_ERROR_SUCCESS; SRB_HAInquiry srbHAInquiry; m_nDrives = 0; memset(m_drvDetails, 0, CDVD_MAX_SUPPORTED_DRIVES * sizeof(ADAPTERINFO)); memset(&srbHAInquiry, 0, sizeof (SRB_HAInquiry) ); srbHAInquiry.SRB_Cmd = SC_HA_INQUIRY; srbHAInquiry.SRB_HaId = 0; SendASPI32Command ((LPSRB) &srbHAInquiry); if (srbHAInquiry.SRB_Status != SS_COMP) { return CDVD_ERROR_FAIL; } UI08 HA_Count = srbHAInquiry.HA_Count; srbHAInquiry.HA_ManagerId[16] = 0; for (UI08 HA_num = 0; HA_num < HA_Count; HA_num++) { char szHA_num[10]; itoa((int) HA_num, szHA_num, 10); memset(&srbHAInquiry, 0, sizeof(SRB_HAInquiry)); srbHAInquiry.SRB_Cmd = SC_HA_INQUIRY; srbHAInquiry.SRB_HaId = HA_num; SendASPI32Command ((LPSRB) &srbHAInquiry); if (srbHAInquiry.SRB_Status != SS_COMP) { return CDVD_ERROR_FAIL; } else { srbHAInquiry.HA_Identifier[16] = 0; for (UI08 SCSI_Id = 0; SCSI_Id < 8; SCSI_Id++) { char szSCSI_Id[10]; itoa ((int) SCSI_Id, szSCSI_Id, 10); for(UI08 SCSI_Lun = 0; SCSI_Lun < 8; SCSI_Lun++) { char szSCSI_Lun[10]; itoa ((int) SCSI_Lun, szSCSI_Lun, 10); SRB_GDEVBlock srbGDEVBlock; memset(&srbGDEVBlock, 0, sizeof(srbGDEVBlock)); srbGDEVBlock.SRB_Cmd = SC_GET_DEV_TYPE; srbGDEVBlock.SRB_HaId = HA_num; srbGDEVBlock.SRB_Target = SCSI_Id; srbGDEVBlock.SRB_Lun = SCSI_Lun; SendASPI32Command ((LPSRB) &srbGDEVBlock); if (srbGDEVBlock.SRB_Status != SS_COMP || srbGDEVBlock.SRB_DeviceType != DTYPE_CDROM) continue; char temp[40]; if(Aspi_ScsiInquiry(HA_num, SCSI_Id, SCSI_Lun, temp) == CDVD_ERROR_SUCCESS) { if(m_nDrives < CDVD_MAX_SUPPORTED_DRIVES) { TRACE("drive %ld: [%ld:%ld:%ld] - %s %s\n", m_nDrives, HA_num, SCSI_Id, SCSI_Lun, m_drvDetails[m_nDrives].hostname, temp); m_drvDetails[m_nDrives].ha = HA_num; m_drvDetails[m_nDrives].id = SCSI_Id; m_drvDetails[m_nDrives].lun = SCSI_Lun; strcpy(m_drvDetails[m_nDrives].hostname, (const char*) srbHAInquiry.HA_Identifier); strcpy(m_drvDetails[m_nDrives].name, temp); ++m_nDrives; } else { break; } } else { retval = CDVD_ERROR_FAIL; break; } } } } } return retval; } // retrieve ha info int CCdvd::Aspi_ScsiInquiry(UI08 ha, UI08 id, UI08 lun, char *destination) { int retval = CDVD_ERROR_SUCCESS; UI08 buffer[36]; SRB_ExecSCSICmd srb; memset(buffer, 0x20, sizeof(buffer)); memset(&srb, 0, sizeof(SRB_ExecSCSICmd)); srb.SRB_Cmd = SC_EXEC_SCSI_CMD; srb.SRB_HaId = ha; srb.SRB_Flags = SRB_DIR_IN; srb.SRB_Target = id; srb.SRB_Lun = lun; srb.SRB_BufLen = 36; srb.SRB_BufPointer = buffer; srb.SRB_SenseLen = SENSE_LEN; srb.SRB_CDBLen = 6; srb.CDBByte[0] = SCSI_INQUIRY; srb.CDBByte[4] = 36; // allocation length per buffer if (Aspi_ExecuteSrb(srb, NULL, 0) == CDVD_ERROR_SUCCESS) { memcpy(destination, buffer + 8, 27); destination[27] = '\0'; } else { destination[0] = '\0'; } return retval; } /***********************************************************/ /* ASPI Execute SRB */ /***********************************************************/ // if HANDLE = NULL, SRB is synchronous, else its asynchronous int CCdvd::Aspi_ExecuteSrb(SRB_ExecSCSICmd &srbExec, HANDLE *handle, int nretry) { int retval = CDVD_ERROR_SUCCESS; ++nretry; // lets do sync with handle == NULL if(handle == NULL) { TRACE("executing synchronous SRB.\n"); while(nretry) { HANDLE heventExec = CreateEvent( NULL, TRUE, FALSE, NULL ); if(heventExec) // do event based notification { srbExec.SRB_Flags |= SRB_EVENT_NOTIFY; srbExec.SRB_PostProc = (LPVOID)heventExec; DWORD dwASPIStatus = SendASPI32Command((LPSRB) &srbExec); if(dwASPIStatus == SS_ERR) { CloseHandle(heventExec); return CDVD_ERROR_FAIL; } if(dwASPIStatus == SS_PENDING) { WaitForSingleObject(heventExec, INFINITE); } CloseHandle(heventExec); } else // do shitty polling { SendASPI32Command((LPSRB)&srbExec); while(srbExec.SRB_Status == SS_PENDING); } TRACE("SRB_Status: %ld\n", srbExec.SRB_Status); if( srbExec.SRB_Status != SS_COMP ) { if(nretry-- && (srbExec.SRB_TargStat != STATUS_CHKCOND || (srbExec.SenseArea[2] & 0x0F) != KEY_UNITATT) ) { UI08 sense = srbExec.SenseArea[2] & 0x0F; UI08 asc = srbExec.SenseArea[12]; UI08 ascq = srbExec.SenseArea[13]; TRACE("sensekey: %02Xh, %02Xh, %02Xh\n", sense, asc, ascq); continue; } } else { // we're done. break; } } } else { TRACE("executing asynchronous SRB.\n"); ResetEvent(*handle); srbExec.SRB_Flags |= SRB_EVENT_NOTIFY; srbExec.SRB_PostProc = *handle; DWORD dwASPIStatus = SendASPI32Command((LPSRB) &srbExec); if(dwASPIStatus == SS_ERR) { SetEvent(*handle); TRACE("SRB unrecoverable error.\n"); return CDVD_ERROR_FAIL; } if(dwASPIStatus == SS_PENDING) { TRACE("SRB Pending completion.\n"); return CDVD_ERROR_PENDING; } TRACE("SRB completed immediately.\n"); } if(nretry == 0) retval = CDVD_ERROR_FAIL; return retval; } /***********************************************************/ /* ASPI C/DVD Methods */ /***********************************************************/ // read using mmc 0xbe command int CCdvd::Aspi_ReadSector_mmc(int sect, HANDLE *handle) { _ASSERT(m_bAspiInitialized == TRUE); m_srbReadCd[m_nCurrentBuffer].SRB_Cmd = SC_EXEC_SCSI_CMD; m_srbReadCd[m_nCurrentBuffer].SRB_HaId = m_drvDetails[m_nCurrentDrive].ha; m_srbReadCd[m_nCurrentBuffer].SRB_Flags = SRB_DIR_IN | SRB_ENABLE_RESIDUAL_COUNT; m_srbReadCd[m_nCurrentBuffer].SRB_Target = m_drvDetails[m_nCurrentDrive].id; m_srbReadCd[m_nCurrentBuffer].SRB_BufPointer = m_ReadBuffer[m_nCurrentBuffer].AB_BufPointer; m_srbReadCd[m_nCurrentBuffer].SRB_BufLen = m_ReadBuffer[m_nCurrentBuffer].AB_BufLen; m_srbReadCd[m_nCurrentBuffer].SRB_Lun = m_drvDetails[m_nCurrentDrive].lun; m_srbReadCd[m_nCurrentBuffer].SRB_SenseLen = SENSE_LEN; m_srbReadCd[m_nCurrentBuffer].SRB_CDBLen = 12; m_srbReadCd[m_nCurrentBuffer].CDBByte[0] = 0xBE; m_srbReadCd[m_nCurrentBuffer].CDBByte[1] = 0x00; m_srbReadCd[m_nCurrentBuffer].CDBByte[2] = HIBYTE(HIWORD(sect)); m_srbReadCd[m_nCurrentBuffer].CDBByte[3] = LOBYTE(HIWORD(sect)); m_srbReadCd[m_nCurrentBuffer].CDBByte[4] = HIBYTE(LOWORD(sect)); m_srbReadCd[m_nCurrentBuffer].CDBByte[5] = LOBYTE(LOWORD(sect)); m_srbReadCd[m_nCurrentBuffer].CDBByte[6] = 0x00; m_srbReadCd[m_nCurrentBuffer].CDBByte[7] = 0x00; m_srbReadCd[m_nCurrentBuffer].CDBByte[8] = CDVD_NUM_SECTORS_PER_BUFF; m_srbReadCd[m_nCurrentBuffer].CDBByte[9] = (UI08) m_nMmcDataMode; m_srbReadCd[m_nCurrentBuffer].CDBByte[10] = 0x00; m_srbReadCd[m_nCurrentBuffer].CDBByte[11] = 0x00; return Aspi_ExecuteSrb(m_srbReadCd[m_nCurrentBuffer], handle, CDVD_MAX_RETRY); } // read using scsi-10 (0x28) command, size is dependent on SetSectorSize int CCdvd::Aspi_ReadSector_scsi10(int sect, HANDLE *handle) { _ASSERT(m_bAspiInitialized == TRUE); m_srbRead10[m_nCurrentBuffer].SRB_Cmd = SC_EXEC_SCSI_CMD; m_srbRead10[m_nCurrentBuffer].SRB_HaId = m_drvDetails[m_nCurrentDrive].ha; m_srbRead10[m_nCurrentBuffer].SRB_Flags = SRB_DIR_IN;// | SRB_ENABLE_RESIDUAL_COUNT; m_srbRead10[m_nCurrentBuffer].SRB_Target = m_drvDetails[m_nCurrentDrive].id; m_srbRead10[m_nCurrentBuffer].SRB_BufPointer = m_ReadBuffer[m_nCurrentBuffer].AB_BufPointer; m_srbRead10[m_nCurrentBuffer].SRB_BufLen = m_ReadBuffer[m_nCurrentBuffer].AB_BufLen; m_srbRead10[m_nCurrentBuffer].SRB_Lun = m_drvDetails[m_nCurrentDrive].lun; m_srbRead10[m_nCurrentBuffer].SRB_SenseLen = SENSE_LEN; m_srbRead10[m_nCurrentBuffer].SRB_CDBLen = 10; m_srbRead10[m_nCurrentBuffer].CDBByte[0] = 0x28; m_srbRead10[m_nCurrentBuffer].CDBByte[1] = 0x00; m_srbRead10[m_nCurrentBuffer].CDBByte[2] = HIBYTE(HIWORD(sect)); m_srbRead10[m_nCurrentBuffer].CDBByte[3] = LOBYTE(HIWORD(sect)); m_srbRead10[m_nCurrentBuffer].CDBByte[4] = HIBYTE(LOWORD(sect)); m_srbRead10[m_nCurrentBuffer].CDBByte[5] = LOBYTE(LOWORD(sect)); m_srbRead10[m_nCurrentBuffer].CDBByte[6] = 0x00; m_srbRead10[m_nCurrentBuffer].CDBByte[7] = 0x00; m_srbRead10[m_nCurrentBuffer].CDBByte[8] = CDVD_NUM_SECTORS_PER_BUFF; m_srbRead10[m_nCurrentBuffer].CDBByte[9] = 0x00; return Aspi_ExecuteSrb(m_srbRead10[m_nCurrentBuffer], handle, CDVD_MAX_RETRY); } // read using proprietary matsushita command, heck if it works int CCdvd::Aspi_ReadSector_matsu(int sect, HANDLE *handle) { _ASSERT(m_bAspiInitialized == TRUE); m_srbReadMat[m_nCurrentBuffer].SRB_Cmd = SC_EXEC_SCSI_CMD; m_srbReadMat[m_nCurrentBuffer].SRB_HaId = m_drvDetails[m_nCurrentDrive].ha; m_srbReadMat[m_nCurrentBuffer].SRB_Flags = SRB_DIR_IN | SRB_ENABLE_RESIDUAL_COUNT; m_srbReadMat[m_nCurrentBuffer].SRB_Target = m_drvDetails[m_nCurrentDrive].id; m_srbReadMat[m_nCurrentBuffer].SRB_BufPointer = m_ReadBuffer[m_nCurrentBuffer].AB_BufPointer; m_srbReadMat[m_nCurrentBuffer].SRB_BufLen = m_ReadBuffer[m_nCurrentBuffer].AB_BufLen; m_srbReadMat[m_nCurrentBuffer].SRB_Lun = m_drvDetails[m_nCurrentDrive].lun; m_srbReadMat[m_nCurrentBuffer].SRB_SenseLen = SENSE_LEN; m_srbReadMat[m_nCurrentBuffer].SRB_CDBLen = 12; m_srbReadMat[m_nCurrentBuffer].CDBByte[0] = 0xd4; m_srbReadMat[m_nCurrentBuffer].CDBByte[1] = 0x00; m_srbReadMat[m_nCurrentBuffer].CDBByte[2] = HIBYTE(HIWORD(sect)); m_srbReadMat[m_nCurrentBuffer].CDBByte[3] = LOBYTE(HIWORD(sect)); m_srbReadMat[m_nCurrentBuffer].CDBByte[4] = HIBYTE(LOWORD(sect)); m_srbReadMat[m_nCurrentBuffer].CDBByte[5] = LOBYTE(LOWORD(sect)); m_srbReadMat[m_nCurrentBuffer].CDBByte[6] = 0x00; m_srbReadMat[m_nCurrentBuffer].CDBByte[7] = 0x00; m_srbReadMat[m_nCurrentBuffer].CDBByte[8] = CDVD_NUM_SECTORS_PER_BUFF; m_srbReadMat[m_nCurrentBuffer].CDBByte[9] = 0x00; m_srbReadMat[m_nCurrentBuffer].CDBByte[10] = 0x00; m_srbReadMat[m_nCurrentBuffer].CDBByte[11] = 0x00; return Aspi_ExecuteSrb(m_srbReadMat[m_nCurrentBuffer], handle, CDVD_MAX_RETRY); } // read using proprietary sony command, heck if it works int CCdvd::Aspi_ReadSector_sony(int sect, HANDLE *handle) { _ASSERT(m_bAspiInitialized == TRUE); m_srbReadSony[m_nCurrentBuffer].SRB_Cmd = SC_EXEC_SCSI_CMD; m_srbReadSony[m_nCurrentBuffer].SRB_HaId = m_drvDetails[m_nCurrentDrive].ha; m_srbReadSony[m_nCurrentBuffer].SRB_Flags = SRB_DIR_IN | SRB_ENABLE_RESIDUAL_COUNT; m_srbReadSony[m_nCurrentBuffer].SRB_Target = m_drvDetails[m_nCurrentDrive].id; m_srbReadSony[m_nCurrentBuffer].SRB_BufPointer = m_ReadBuffer[m_nCurrentBuffer].AB_BufPointer; m_srbReadSony[m_nCurrentBuffer].SRB_BufLen = m_ReadBuffer[m_nCurrentBuffer].AB_BufLen; m_srbReadSony[m_nCurrentBuffer].SRB_Lun = m_drvDetails[m_nCurrentDrive].lun; m_srbReadSony[m_nCurrentBuffer].SRB_SenseLen = SENSE_LEN; m_srbReadSony[m_nCurrentBuffer].SRB_CDBLen = 12; m_srbReadSony[m_nCurrentBuffer].CDBByte[0] = 0xd8; m_srbReadSony[m_nCurrentBuffer].CDBByte[1] = 0x00; m_srbReadSony[m_nCurrentBuffer].CDBByte[2] = HIBYTE(HIWORD(sect)); m_srbReadSony[m_nCurrentBuffer].CDBByte[3] = LOBYTE(HIWORD(sect)); m_srbReadSony[m_nCurrentBuffer].CDBByte[4] = HIBYTE(LOWORD(sect)); m_srbReadSony[m_nCurrentBuffer].CDBByte[5] = LOBYTE(LOWORD(sect)); m_srbReadSony[m_nCurrentBuffer].CDBByte[6] = 0x00; m_srbReadSony[m_nCurrentBuffer].CDBByte[7] = 0x00; m_srbReadSony[m_nCurrentBuffer].CDBByte[8] = CDVD_NUM_SECTORS_PER_BUFF; m_srbReadSony[m_nCurrentBuffer].CDBByte[9] = 0x00; m_srbReadSony[m_nCurrentBuffer].CDBByte[10] = 0x00; m_srbReadSony[m_nCurrentBuffer].CDBByte[11] = 0x00; return Aspi_ExecuteSrb(m_srbReadSony[m_nCurrentBuffer], handle, CDVD_MAX_RETRY); } // read using proprietary nec command, heck if it works int CCdvd::Aspi_ReadSector_nec(int sect, HANDLE *handle) { _ASSERT(m_bAspiInitialized == TRUE); m_srbReadNec[m_nCurrentBuffer].SRB_Cmd = SC_EXEC_SCSI_CMD; m_srbReadNec[m_nCurrentBuffer].SRB_HaId = m_drvDetails[m_nCurrentDrive].ha; m_srbReadNec[m_nCurrentBuffer].SRB_Flags = SRB_DIR_IN | SRB_ENABLE_RESIDUAL_COUNT; m_srbReadNec[m_nCurrentBuffer].SRB_Target = m_drvDetails[m_nCurrentDrive].id; m_srbReadNec[m_nCurrentBuffer].SRB_BufPointer = m_ReadBuffer[m_nCurrentBuffer].AB_BufPointer; m_srbReadNec[m_nCurrentBuffer].SRB_BufLen = m_ReadBuffer[m_nCurrentBuffer].AB_BufLen; m_srbReadNec[m_nCurrentBuffer].SRB_Lun = m_drvDetails[m_nCurrentDrive].lun; m_srbReadNec[m_nCurrentBuffer].SRB_SenseLen = SENSE_LEN; m_srbReadNec[m_nCurrentBuffer].SRB_CDBLen = 10; m_srbReadNec[m_nCurrentBuffer].CDBByte[0] = 0xd4; m_srbReadNec[m_nCurrentBuffer].CDBByte[1] = 0x00; m_srbReadNec[m_nCurrentBuffer].CDBByte[2] = HIBYTE(HIWORD(sect)); m_srbReadNec[m_nCurrentBuffer].CDBByte[3] = LOBYTE(HIWORD(sect)); m_srbReadNec[m_nCurrentBuffer].CDBByte[4] = HIBYTE(LOWORD(sect)); m_srbReadNec[m_nCurrentBuffer].CDBByte[5] = LOBYTE(LOWORD(sect)); m_srbReadNec[m_nCurrentBuffer].CDBByte[6] = 0x00; m_srbReadNec[m_nCurrentBuffer].CDBByte[7] = 0x00; m_srbReadNec[m_nCurrentBuffer].CDBByte[8] = CDVD_NUM_SECTORS_PER_BUFF; m_srbReadNec[m_nCurrentBuffer].CDBByte[9] = 0x00; return Aspi_ExecuteSrb(m_srbReadNec[m_nCurrentBuffer], handle, CDVD_MAX_RETRY); } // retrieve number of sectors present in c/dvd media int CCdvd::Aspi_GetNumSectors() { _ASSERT(m_bAspiInitialized == TRUE); SRB_ExecSCSICmd srb; UI08 capacity[8]; UI32 max_sector; memset(&srb, 0, sizeof(SRB_ExecSCSICmd)); srb.SRB_Cmd = SC_EXEC_SCSI_CMD; srb.SRB_HaId = m_drvDetails[m_nCurrentDrive].ha; srb.SRB_Flags = SRB_DIR_IN; srb.SRB_Target = m_drvDetails[m_nCurrentDrive].id; srb.SRB_Lun = m_drvDetails[m_nCurrentDrive].lun; srb.SRB_BufLen = 8; srb.SRB_BufPointer = capacity; srb.SRB_SenseLen = SENSE_LEN; srb.SRB_CDBLen = 10; srb.CDBByte[0] = SCSI_RD_CAPAC; if(Aspi_ExecuteSrb(srb, NULL, CDVD_MAX_RETRY) != CDVD_ERROR_SUCCESS) return 0; // no sectors found MOVESCSIDWORD(&capacity[0], &max_sector); return max_sector+1; } // retrieve TOC data int CCdvd::Aspi_GetToc() { _ASSERT(m_bAspiInitialized == TRUE); SRB_ExecSCSICmd srb; UI08 buff[804]; memset(buff, 0, sizeof(buff)); memset (&srb, 0, sizeof(SRB_ExecSCSICmd)); srb.SRB_Cmd = SC_EXEC_SCSI_CMD; srb.SRB_Flags = SRB_DIR_IN; srb.SRB_HaId = m_drvDetails[m_nCurrentDrive].ha; srb.SRB_Target = m_drvDetails[m_nCurrentDrive].id; srb.SRB_Lun = m_drvDetails[m_nCurrentDrive].lun; srb.SRB_SenseLen = SENSE_LEN; srb.SRB_BufPointer = buff; srb.SRB_BufLen = sizeof(buff); srb.SRB_CDBLen = 10; srb.CDBByte[0] = SCSI_READ_TOC; srb.CDBByte[6] = 0; srb.CDBByte[7] = 0x03; srb.CDBByte[8] = 0x24; if(Aspi_ExecuteSrb(srb, NULL, CDVD_MAX_RETRY) != CDVD_ERROR_SUCCESS) return CDVD_ERROR_FAIL; if(ExtractTocData(buff) != CDVD_ERROR_SUCCESS) return CDVD_ERROR_FAIL; return CDVD_ERROR_SUCCESS; } // set cdrom speed int CCdvd::Aspi_SetSpeed(int speed) { _ASSERT(m_bAspiInitialized == TRUE); SRB_ExecSCSICmd srb; UI16 kbSpeed = 0xFFFF; switch(speed) { case 0: kbSpeed = 0xFFFF; break; case 1: kbSpeed = 176; break; case 2: kbSpeed = 353; break; case 3: kbSpeed = 528; break; case 4: kbSpeed = 706; break; case 5: kbSpeed = 1400; break; case 6: kbSpeed = 2800; break; default: kbSpeed = 0xFFFF; break; // max } memset(&srb,0,sizeof(srb)); srb.SRB_Cmd = SC_EXEC_SCSI_CMD; srb.SRB_HaId = m_drvDetails[m_nCurrentDrive].ha; srb.SRB_Target = m_drvDetails[m_nCurrentDrive].id; srb.SRB_Lun = m_drvDetails[m_nCurrentDrive].lun; srb.SRB_Flags = SRB_DIR_OUT; //|SRB_ENABLE_RESIDUAL_COUNT; srb.SRB_SenseLen = SENSE_LEN; srb.SRB_CDBLen = 12; srb.CDBByte[0] = 0xBB; srb.CDBByte[2] = HIBYTE(kbSpeed); srb.CDBByte[3] = LOBYTE(kbSpeed); return Aspi_ExecuteSrb(srb, NULL, CDVD_MAX_RETRY); } // used for scsi only, sets sector size (i.e, 2352, 2048) int CCdvd::Aspi_SetSectorSize(int sect_size) { _ASSERT(m_bAspiInitialized == TRUE); TRACE("sectorsize: %ld\n", sect_size); MODESELHEADER mh; SRB_ExecSCSICmd srb; memset (&srb, 0, sizeof(SRB_ExecSCSICmd)); memset (&mh, 0, sizeof(MODESELHEADER)); mh.block_desc_length = 0x08; mh.block_length_med = HIBYTE(LOWORD(sect_size)); mh.block_length_lo = LOBYTE(LOWORD(sect_size)); srb.SRB_Cmd = SC_EXEC_SCSI_CMD; srb.SRB_HaId = m_drvDetails[m_nCurrentDrive].ha; srb.SRB_Target = m_drvDetails[m_nCurrentDrive].id; srb.SRB_Lun = m_drvDetails[m_nCurrentDrive].lun; srb.SRB_SenseLen = SENSE_LEN; srb.SRB_Flags = SRB_DIR_OUT; srb.SRB_BufLen = sizeof(mh); srb.SRB_BufPointer = (UI08 *) &mh; srb.SRB_CDBLen = 6; srb.CDBByte[0] = 0x15; srb.CDBByte[1] = 0x10; srb.CDBByte[4] = 0x0C; return Aspi_ExecuteSrb(srb, NULL, CDVD_MAX_RETRY); } // start cddda playback, dunno if it works right really.. :p int CCdvd::Aspi_Play(int sect_start, int sect_stop) { _ASSERT(m_bAspiInitialized == TRUE); SRB_ExecSCSICmd srb; memset( &srb, 0, sizeof(SRB_ExecSCSICmd) ); srb.SRB_Cmd = SC_EXEC_SCSI_CMD; srb.SRB_HaId = m_drvDetails[m_nCurrentDrive].ha; srb.SRB_Target = m_drvDetails[m_nCurrentDrive].id; srb.SRB_Lun = m_drvDetails[m_nCurrentDrive].lun; srb.SRB_Flags = SRB_DIR_IN; srb.SRB_SenseLen = SENSE_LEN; srb.SRB_CDBLen = 12; srb.CDBByte[0] = 0xa5; srb.CDBByte[2] = HIBYTE(HIWORD(sect_start)); srb.CDBByte[3] = LOBYTE(HIWORD(sect_start)); srb.CDBByte[4] = HIBYTE(LOWORD(sect_start)); srb.CDBByte[5] = LOBYTE(LOWORD(sect_start)); srb.CDBByte[6] = HIBYTE(HIWORD(sect_stop)); srb.CDBByte[7] = LOBYTE(HIWORD(sect_stop)); srb.CDBByte[8] = HIBYTE(LOWORD(sect_stop)); srb.CDBByte[9] = LOBYTE(LOWORD(sect_stop)); // srb.CDBByte[10] = 0x8F; return Aspi_ExecuteSrb(srb, NULL, CDVD_MAX_RETRY); } // stop cdda playback, dunno if it works right really.. :p int CCdvd::Aspi_Stop() { _ASSERT(m_bAspiInitialized == TRUE); SRB_ExecSCSICmd srb; memset(&srb, 0, sizeof(SRB_ExecSCSICmd)); srb.SRB_Cmd = SC_EXEC_SCSI_CMD; srb.SRB_HaId = m_drvDetails[m_nCurrentDrive].ha; srb.SRB_Target = m_drvDetails[m_nCurrentDrive].id; srb.SRB_Lun = m_drvDetails[m_nCurrentDrive].lun; srb.SRB_Flags = SRB_DIR_IN; srb.SRB_SenseLen = SENSE_LEN; srb.SRB_CDBLen = 10; srb.CDBByte[0] = 0x4E; return Aspi_ExecuteSrb(srb, NULL, CDVD_MAX_RETRY); } // detect if media/LUN is ready, legacy command, // can prolly be substituted with GetMediaType(), with some modifs int CCdvd::Aspi_TestReady() { SRB_ExecSCSICmd srb; memset (&srb, 0, sizeof(SRB_ExecSCSICmd)); srb.SRB_Cmd = SC_EXEC_SCSI_CMD; srb.SRB_HaId = m_drvDetails[m_nCurrentDrive].ha; srb.SRB_Target = m_drvDetails[m_nCurrentDrive].id; srb.SRB_Lun = m_drvDetails[m_nCurrentDrive].lun; srb.SRB_SenseLen = SENSE_LEN; srb.SRB_CDBLen = 6; srb.CDBByte[0] = SCSI_TST_U_RDY; return Aspi_ExecuteSrb(srb, NULL, CDVD_MAX_RETRY); } // retrieve feature details int CCdvd::Aspi_GetConfiguration(UI16 feature, UI08 *dest, UI32 dest_size) { _ASSERT(m_bAspiInitialized == TRUE); int retval = CDVD_ERROR_SUCCESS; SRB_ExecSCSICmd srb; memset(&srb, 0, sizeof(SRB_ExecSCSICmd)); memset(dest, 0, dest_size); srb.SRB_Cmd = SC_EXEC_SCSI_CMD; srb.SRB_HaId = m_drvDetails[m_nCurrentDrive].ha; srb.SRB_Target = m_drvDetails[m_nCurrentDrive].id; srb.SRB_Lun = m_drvDetails[m_nCurrentDrive].lun; srb.SRB_Flags = SRB_DIR_IN; srb.SRB_SenseLen = SENSE_LEN; srb.SRB_BufPointer = dest; srb.SRB_BufLen = dest_size; srb.SRB_CDBLen = 12; srb.CDBByte[0] = 0x46; srb.CDBByte[1] = 0x02; // return a single feature set ONLY. srb.CDBByte[2] = HIBYTE(feature); srb.CDBByte[3] = LOBYTE(feature); srb.CDBByte[7] = HIBYTE(dest_size); srb.CDBByte[8] = LOBYTE(dest_size); return Aspi_ExecuteSrb(srb, NULL, CDVD_MAX_RETRY); }