pcsx2/plugins/CDVDpeops/Scsi.c
2010-04-25 00:31:27 +00:00

1135 lines
30 KiB
C

/***************************************************************************
scsi.c - description
-------------------
begin : Sun Nov 16 2003
copyright : (C) 2003 by Pete Bernert
email : BlackDove@addcom.de
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. See also the license.txt file for *
* additional informations. *
* *
***************************************************************************/
//*************************************************************************//
// History of changes:
//
// 2003/11/16 - Pete
// - generic cleanup for the Peops release
//
//*************************************************************************//
/////////////////////////////////////////////////////////
#include "stdafx.h"
#define _IN_SCSI
#include "externals.h"
/////////////////////////////////////////////////////////
SRB_ExecSCSICmd sx; // used with all (non-waiting) read funcs
BOOL bDoWaiting=FALSE; // flag for async reads
/////////////////////////////////////////////////////////
// returns device type
int GetSCSIDevice(int iA,int iT,int iL)
{
SRB_GDEVBlock s;DWORD dwStatus;
memset(&s,0,sizeof(SRB_GDEVBlock));
s.SRB_Cmd = SC_GET_DEV_TYPE;
s.SRB_HaID = iA;
s.SRB_Target = iT;
s.SRB_Lun = iL;
ResetEvent(hEvent);
dwStatus=pSendASPI32Command((LPSRB)&s);
if(dwStatus==SS_PENDING)
{WaitGenEvent(30000);dwStatus=s.SRB_Status;}
if(dwStatus==SS_COMP) return s.SRB_DeviceType;
return -1;
}
/////////////////////////////////////////////////////////
int GetSCSIStatus(int iA,int iT,int iL)
{
SRB_ExecSCSICmd s;DWORD dwStatus;
char ret[0x324];
memset(&s,0,sizeof(s));
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = iCD_AD;
s.SRB_Target = iCD_TA;
s.SRB_Lun = iCD_LU;
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.SRB_BufLen = 0x324;
s.SRB_BufPointer = (BYTE FAR *)ret;
s.SRB_SenseLen = 0x0E;
s.SRB_CDBLen = 0x0A;
s.SRB_PostProc = (LPVOID)hEvent;
s.CDBByte[0] = 0x00;
ResetEvent(hEvent);
dwStatus=pSendASPI32Command((LPSRB)&s);
if(dwStatus==SS_PENDING) WaitGenEvent(30000);
return s.SRB_Status;
}
/////////////////////////////////////////////////////////
// fills toc infos
DWORD GetSCSITOC(LPTOC toc)
{
SRB_ExecSCSICmd s;DWORD dwStatus;
memset(&s,0,sizeof(s));
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = iCD_AD;
s.SRB_Target = iCD_TA;
s.SRB_Lun = iCD_LU;
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.SRB_BufLen = 0x324;
s.SRB_BufPointer = (BYTE FAR *)toc;
s.SRB_SenseLen = 0x0E;
s.SRB_CDBLen = 0x0A;
s.SRB_PostProc = (LPVOID)hEvent;
s.CDBByte[0] = 0x43;
s.CDBByte[1] = 0x00; // 0x02 for MSF
s.CDBByte[7] = 0x03;
s.CDBByte[8] = 0x24;
ResetEvent(hEvent);
dwStatus=pSendASPI32Command((LPSRB)&s);
if(dwStatus==SS_PENDING) WaitGenEvent(30000);
if(s.SRB_Status!=SS_COMP) return SS_ERR;
return SS_COMP;
}
/////////////////////////////////////////////////////////
// enum all cd drives into 32k buffer, return num of drives
int GetSCSICDDrives(char * pDList)
{
int iCnt=0,iA,iT,iL;char * p=pDList;
SRB_HAInquiry si;SRB_GDEVBlock sd;
SRB_ExecSCSICmd s;int iNumA;char szBuf[100];
DWORD dw,dwStatus;
if(!pGetASPI32SupportInfo) return 0;
dw=pGetASPI32SupportInfo();
if(HIBYTE(LOWORD(dw))!=SS_COMP) return 0;
iNumA=(int)LOBYTE(LOWORD(dw));
for(iA=0;iA<iNumA;iA++)
{
memset(&si,0,sizeof(SRB_HAInquiry));
si.SRB_Cmd = SC_HA_INQUIRY;
si.SRB_HaId = iA;
pSendASPI32Command((LPSRB)&si);
if(si.SRB_Status!=SS_COMP) continue;
if(!si.HA_Unique[3]) si.HA_Unique[3]=8;
for(iT=0;iT<si.HA_Unique[3];iT++)
{
for(iL=0;iL<8;iL++)
{
memset(&sd,0,sizeof(SRB_GDEVBlock));
sd.SRB_Cmd = SC_GET_DEV_TYPE;
sd.SRB_HaID = iA;
sd.SRB_Target = iT;
sd.SRB_Lun = iL;
pSendASPI32Command((LPSRB)&sd);
if(sd.SRB_Status==SS_COMP &&
sd.SRB_DeviceType==DTYPE_CDROM)
{
memset(&s,0,sizeof(s));
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = iA;
s.SRB_Target = iT;
s.SRB_Lun = iL;
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.SRB_BufLen = 100;
s.SRB_BufPointer = szBuf;
s.SRB_SenseLen = SENSE_LEN;
s.SRB_CDBLen = 6;
s.SRB_PostProc = (LPVOID)hEvent;
s.CDBByte[0] = SCSI_INQUIRY;
s.CDBByte[4] = 100;
ResetEvent(hEvent);
dwStatus=pSendASPI32Command((LPSRB)&s);
if(dwStatus==SS_PENDING)
WaitGenEvent(WAITFOREVER);
if(s.SRB_Status==SS_COMP)
{
int i;
for(i=8 ;i<15;i++) if(szBuf[i]==' ') {szBuf[i]=0;break;}
szBuf[15]=0;
for(i=16;i<32;i++) if(szBuf[i]==' ') {szBuf[i]=0;break;}
szBuf[31]=0;
for(i=32;i<37;i++) if(szBuf[i]==' ') {szBuf[i]=0;break;}
szBuf[36]=0;
wsprintf(p,"[%d:%d:%d] %s %s V%s",
iA,iT,iL,&szBuf[8],&szBuf[16],&szBuf[32]);
iCnt++;
p+=strlen(p)+1;
}
}
}
}
}
return iCnt;
}
/////////////////////////////////////////////////////////
// play audio
DWORD PlaySCSIAudio(unsigned long start,unsigned long len)
{
SRB_ExecSCSICmd s;DWORD dwStatus;
memset(&s,0,sizeof(s));
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = iCD_AD;
s.SRB_Target = iCD_TA;
s.SRB_Lun = iCD_LU;
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.SRB_BufLen = 0;
s.SRB_BufPointer = 0;
s.SRB_SenseLen = SENSE_LEN;
s.SRB_CDBLen = 12;
s.SRB_PostProc = (LPVOID)hEvent;
if(start==0) // mmm... that stop doesn't seem to work on all drives... pfff
{
s.CDBByte[0] = 0x4b;
s.CDBByte[1] = (iCD_LU << 5) | 01;
s.CDBByte[2] = 0;
s.CDBByte[3] = 0;
s.CDBByte[4] = 0;
s.CDBByte[5] = 0;
s.CDBByte[6] = 0;
s.CDBByte[7] = 0;
s.CDBByte[8] = 0;
s.CDBByte[9] = 0;
}
else // start playing
{
s.CDBByte[0] = 0xa5;
s.CDBByte[1] = iCD_LU << 5;
s.CDBByte[2] = (unsigned char)((start >> 24) & 0xFF);
s.CDBByte[3] = (unsigned char)((start >> 16) & 0xFF);
s.CDBByte[4] = (unsigned char)((start >> 8) & 0xFF);
s.CDBByte[5] = (unsigned char)((start & 0xFF));
s.CDBByte[6] = (unsigned char)((len >> 24) & 0xFF);
s.CDBByte[7] = (unsigned char)((len >> 16) & 0xFF);
s.CDBByte[8] = (unsigned char)((len >> 8) & 0xFF);
s.CDBByte[9] = (unsigned char)(len & 0xFF);
}
ResetEvent(hEvent);
dwStatus = pSendASPI32Command((LPSRB)&s);
if(dwStatus==SS_PENDING) WaitGenEvent(10000);
return s.SRB_Status;
}
/////////////////////////////////////////////////////////
// do (unprecise) sub channel read on audio play
unsigned char * GetSCSIAudioSub(void)
{
SRB_ExecSCSICmd s;DWORD dwStatus;
unsigned char cB[20];
memset(cB,0,20);
memset(&s,0,sizeof(s));
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = iCD_AD;
s.SRB_Target = iCD_TA;
s.SRB_Lun = iCD_LU;
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.SRB_SenseLen = SENSE_LEN;
s.SRB_BufLen = 20;//44;
s.SRB_BufPointer = cB;
s.SRB_CDBLen = 10;
s.CDBByte[0] = 0x42;
s.CDBByte[1] = (iCD_LU<<5)|2; // lun & msf
s.CDBByte[2] = 0x40; // subq
s.CDBByte[3] = 0x01; // curr pos info
s.CDBByte[6] = 0; // track number (only in isrc mode, ignored)
s.CDBByte[7] = 0; // alloc len
s.CDBByte[8] = 20;//44;
ResetEvent(hEvent);
dwStatus = pSendASPI32Command((LPSRB)&s);
if(dwStatus==SS_PENDING) WaitGenEvent(WAITFOREVER);
if(s.SRB_Status!=SS_COMP) return NULL;
SubAData[12]=(cB[5]<<4)|(cB[5]>>4);
SubAData[13]=cB[6];
SubAData[14]=cB[7];
SubAData[15]=itob(cB[13]);
SubAData[16]=itob(cB[14]);
SubAData[17]=itob(cB[15]);
SubAData[18]=0;
SubAData[19]=itob(cB[9]);
SubAData[20]=itob(cB[10]);
SubAData[21]=itob(cB[11]);
return SubAData;
}
/////////////////////////////////////////////////////////
// test, if drive is ready (doesn't work on all drives)
BOOL TestSCSIUnitReady(void)
{
SRB_ExecSCSICmd s;DWORD dwStatus;
memset(&s,0,sizeof(s));
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = iCD_AD;
s.SRB_Target = iCD_TA;
s.SRB_Lun = iCD_LU;
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.SRB_BufLen = 0;
s.SRB_BufPointer = 0;
s.SRB_SenseLen = SENSE_LEN;
s.SRB_CDBLen = 6;
s.SRB_PostProc = (LPVOID)hEvent;
s.CDBByte[0] = 0x00;
s.CDBByte[1] = iCD_LU << 5;
ResetEvent(hEvent);
dwStatus = pSendASPI32Command((LPSRB)&s);
if(dwStatus==SS_PENDING)
WaitGenEvent(1000);
if(s.SRB_Status!=SS_COMP)
return FALSE;
if(s.SRB_TargStat==STATUS_GOOD) return TRUE; // will always be GOOD with ioctl, so no problem here
return FALSE;
}
/////////////////////////////////////////////////////////
// change the read speed (not supported on all drives)
DWORD SetSCSISpeed(DWORD dwSpeed)
{
SRB_ExecSCSICmd s;DWORD dwStatus;
memset(&s,0,sizeof(s));
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = iCD_AD;
s.SRB_Target = iCD_TA;
s.SRB_Lun = iCD_LU;
s.SRB_Flags = SRB_DIR_OUT | SRB_EVENT_NOTIFY;
s.SRB_SenseLen = SENSE_LEN;
s.SRB_CDBLen = 12;
s.SRB_PostProc = (LPVOID)hEvent;
s.CDBByte[0] = 0xBB;
s.CDBByte[2] = (BYTE)(dwSpeed >> 8);
s.CDBByte[3] = (BYTE)dwSpeed;
ResetEvent(hEvent);
dwStatus=pSendASPI32Command((LPSRB)&s);
if(dwStatus==SS_PENDING)
WaitGenEvent(WAITFOREVER);
if(s.SRB_Status!=SS_COMP) return SS_ERR;
return SS_COMP;
}
/////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////
// all the different SCSI read commands can be found here
// 'bWait' is a flag, if the command should wait until
// completed, or if the func can return as soon as possible
// (async reading). Attention: 'bWait' is not really used
// in the Sub-channel commands yet (sub is done always
// blocking, and just 'one sector' reads are done, caching=0)
/////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////
// BE: used by most ATAPI drives
/////////////////////////////////////////////////////////
DWORD ReadSCSI_BE(BOOL bWait,FRAMEBUF * f)
{
DWORD dwStatus;
memset(&sx,0,sizeof(sx));
sx.SRB_Cmd = SC_EXEC_SCSI_CMD;
sx.SRB_HaId = iCD_AD;
sx.SRB_Target = iCD_TA;
sx.SRB_Lun = iCD_LU;
sx.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
sx.SRB_BufLen = f->dwBufLen;
sx.SRB_BufPointer = &(f->BufData[0]);
sx.SRB_SenseLen = SENSE_LEN;
sx.SRB_CDBLen = 12;
sx.SRB_PostProc = (LPVOID)hEvent;
sx.CDBByte[0] = 0xBE;
//s.CDBByte[1] = 0x04;
sx.CDBByte[2] = (unsigned char)((f->dwFrame >> 24) & 0xFF);
sx.CDBByte[3] = (unsigned char)((f->dwFrame >> 16) & 0xFF);
sx.CDBByte[4] = (unsigned char)((f->dwFrame >> 8) & 0xFF);
sx.CDBByte[5] = (unsigned char)(f->dwFrame & 0xFF);
sx.CDBByte[8] = (unsigned char)(f->dwFrameCnt & 0xFF);
sx.CDBByte[9] = (iRType==MODE_BE_1)?0x10:0xF8;//F0!!!!!!!!!!!
ResetEvent(hEvent);
dwStatus=pSendASPI32Command((LPSRB)&sx);
if(dwStatus==SS_PENDING)
{
if(bWait) WaitGenEvent(WAITFOREVER);
else
{
bDoWaiting=TRUE;
return SS_COMP;
}
}
if(sx.SRB_Status!=SS_COMP)
return SS_ERR;
return SS_COMP;
}
/////////////////////////////////////////////////////////
DWORD ReadSCSI_BE_Sub(BOOL bWait,FRAMEBUF * f)
{
DWORD dwStatus;
memset(&sx,0,sizeof(sx));
sx.SRB_Cmd = SC_EXEC_SCSI_CMD;
sx.SRB_HaId = iCD_AD;
sx.SRB_Target = iCD_TA;
sx.SRB_Lun = iCD_LU;
sx.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
sx.SRB_BufLen = f->dwBufLen + 16;
sx.SRB_BufPointer = &(f->BufData[0]);
sx.SRB_SenseLen = SENSE_LEN;
sx.SRB_CDBLen = 12;
sx.SRB_PostProc = (LPVOID)hEvent;
sx.CDBByte[0] = 0xBE;
//s.CDBByte[1] = 0x04;
sx.CDBByte[2] = (unsigned char)((f->dwFrame >> 24) & 0xFF);
sx.CDBByte[3] = (unsigned char)((f->dwFrame >> 16) & 0xFF);
sx.CDBByte[4] = (unsigned char)((f->dwFrame >> 8) & 0xFF);
sx.CDBByte[5] = (unsigned char)(f->dwFrame & 0xFF);
sx.CDBByte[8] = (unsigned char)(f->dwFrameCnt & 0xFF);
sx.CDBByte[9] = (iRType==MODE_BE_1)?0x10:0xF8;//F0!!!!!!!!!!!
sx.CDBByte[10] = 0x2;
ResetEvent(hEvent );
dwStatus=pSendASPI32Command((LPSRB)&sx);
if(dwStatus==SS_PENDING)
WaitGenEvent(WAITSUB);
if(sx.SRB_Status!=SS_COMP)
return SS_ERR;
memcpy(&SubCData[12],&f->BufData[2352],16);
SubCData[15]=itob(SubCData[15]);
SubCData[16]=itob(SubCData[16]);
SubCData[17]=itob(SubCData[17]);
SubCData[19]=itob(SubCData[19]);
SubCData[20]=itob(SubCData[20]);
SubCData[21]=itob(SubCData[21]);
return SS_COMP;
}
/////////////////////////////////////////////////////////
// different sub reading for lite-on ltd163d...
// 16 bytes subc data is encoded in 96 bytes...
DWORD ReadSCSI_BE_Sub_1(BOOL bWait,FRAMEBUF * f)
{
DWORD dwStatus;
memset(&sx,0,sizeof(sx));
sx.SRB_Cmd = SC_EXEC_SCSI_CMD;
sx.SRB_HaId = iCD_AD;
sx.SRB_Target = iCD_TA;
sx.SRB_Lun = iCD_LU;
sx.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
sx.SRB_BufLen = f->dwBufLen + 96;
sx.SRB_BufPointer = &(f->BufData[0]);
sx.SRB_SenseLen = SENSE_LEN;
sx.SRB_CDBLen = 12;
sx.SRB_PostProc = (LPVOID)hEvent;
sx.CDBByte[0] = 0xBE;
sx.CDBByte[2] = (unsigned char)((f->dwFrame >> 24) & 0xFF);
sx.CDBByte[3] = (unsigned char)((f->dwFrame >> 16) & 0xFF);
sx.CDBByte[4] = (unsigned char)((f->dwFrame >> 8) & 0xFF);
sx.CDBByte[5] = (unsigned char)(f->dwFrame & 0xFF);
sx.CDBByte[8] = (unsigned char)(f->dwFrameCnt & 0xFF);
sx.CDBByte[9] = 0xF8;
sx.CDBByte[10] = 0x1;
ResetEvent(hEvent);
dwStatus=pSendASPI32Command((LPSRB)&sx);
if(dwStatus==SS_PENDING)
WaitGenEvent(WAITSUB);
if(sx.SRB_Status!=SS_COMP)
return SS_ERR;
DecodeSub_BE_2_1(&f->BufData[2352]);
memcpy(&SubCData[12],&f->BufData[2352],16);
return SS_COMP;
}
/////////////////////////////////////////////////////////
// 28: used by most SCSI drives
/////////////////////////////////////////////////////////
DWORD InitSCSI_28_2(void)
{
SRB_ExecSCSICmd s;DWORD dwStatus;
int i;
BYTE init1[] = { 0, 0, 0, 0x08, 0, 0, 0, 0, 0, 0, 0x09, 0x30, 0x23, 6, 0, 0, 0, 0, 0, 0x80 };
BYTE init2[] = { 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 9, 48, 1, 6, 32, 7, 0, 0, 0, 0 };
for(i=0;i<2;i++)
{
memset( &s, 0, sizeof( s ) );
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = iCD_AD;
s.SRB_Target = iCD_TA;
s.SRB_Lun = iCD_LU;
s.SRB_Flags = SRB_EVENT_NOTIFY;
s.SRB_BufLen = 0x14;
s.SRB_BufPointer = (i==0)?init1:init2;
s.SRB_SenseLen = SENSE_LEN;
s.SRB_CDBLen = 6;
s.SRB_PostProc = (LPVOID)hEvent;
s.CDBByte[0] = 0x15;
s.CDBByte[1] = 0x10;
s.CDBByte[4] = 0x14;
ResetEvent(hEvent);
dwStatus=pSendASPI32Command((LPSRB)&s);
if (dwStatus == SS_PENDING)
WaitGenEvent(WAITFOREVER);
if(s.SRB_Status!=SS_COMP)
return SS_ERR;
}
pDeInitFunc = DeInitSCSI_28;
return s.SRB_Status;
}
/////////////////////////////////////////////////////////
DWORD InitSCSI_28_1(void)
{
SRB_ExecSCSICmd s;DWORD dwStatus;
BYTE init1[] = { 0, 0, 0, 0x08, 0, 0, 0, 0, 0, 0, 0x09, 0x30 };
memset(&s,0,sizeof(s));
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = iCD_AD;
s.SRB_Target = iCD_TA;
s.SRB_Lun = iCD_LU;
s.SRB_Flags = SRB_EVENT_NOTIFY;
s.SRB_BufLen = 0x0C;
s.SRB_BufPointer = init1;
s.SRB_SenseLen = SENSE_LEN;
s.SRB_CDBLen = 6;
s.SRB_PostProc = (LPVOID)hEvent;
s.CDBByte[0] = 0x15;
s.CDBByte[4] = 0x0C;
ResetEvent(hEvent);
dwStatus=pSendASPI32Command((LPSRB)&s);
if(dwStatus==SS_PENDING)
WaitGenEvent(WAITFOREVER);
if(s.SRB_Status!=SS_COMP)
return SS_ERR;
pDeInitFunc = DeInitSCSI_28;
return s.SRB_Status;
}
/////////////////////////////////////////////////////////
DWORD InitSCSI_28_2048(void)
{
SRB_ExecSCSICmd s;DWORD dwStatus;
BYTE init1[] = { 0, 0, 0, 0x08, 0, 0, 0, 0, 0, 0, 0x08, 0x0 };
pDeInitFunc = DeInitSCSI_28;
memset(&s,0,sizeof(s));
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = iCD_AD;
s.SRB_Target = iCD_TA;
s.SRB_Lun = iCD_LU;
s.SRB_Flags = SRB_EVENT_NOTIFY;
s.SRB_BufLen = 0x0C;
s.SRB_BufPointer = init1;
s.SRB_SenseLen = SENSE_LEN;
s.SRB_CDBLen = 6;
s.SRB_PostProc = (LPVOID)hEvent;
s.CDBByte[0] = 0x15;
s.CDBByte[4] = 0x0C;
ResetEvent(hEvent);
dwStatus=pSendASPI32Command((LPSRB)&s);
if(dwStatus==SS_PENDING)
WaitGenEvent(WAITFOREVER);
if(s.SRB_Status!=SS_COMP)
return SS_ERR;
return s.SRB_Status;
}
/////////////////////////////////////////////////////////
DWORD DeInitSCSI_28(void)
{
SRB_ExecSCSICmd s;DWORD dwStatus;
BYTE init1[] = { 0, 0, 0, 8, 83, 0, 0, 0, 0, 0, 8, 0 };
memset(&s,0,sizeof(s));
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = iCD_AD;
s.SRB_Target = iCD_TA;
s.SRB_Lun = iCD_LU;
s.SRB_Flags = SRB_EVENT_NOTIFY | SRB_ENABLE_RESIDUAL_COUNT;
s.SRB_BufLen = 0x0C;
s.SRB_BufPointer = init1;
s.SRB_SenseLen = SENSE_LEN;
s.SRB_CDBLen = 6;
s.SRB_PostProc = (LPVOID)hEvent;
s.CDBByte[0] = 0x15;
s.CDBByte[4] = 0x0C;
ResetEvent(hEvent);
dwStatus=pSendASPI32Command((LPSRB)&s);
if(dwStatus==SS_PENDING)
WaitGenEvent(WAITFOREVER);
if(s.SRB_Status!=SS_COMP)
return SS_ERR;
return s.SRB_Status;
}
/////////////////////////////////////////////////////////
DWORD ReadSCSI_28(BOOL bWait,FRAMEBUF * f)
{
DWORD dwStatus;
if(!pDeInitFunc)
{
if(iRType==MODE_28_2)
{
if(InitSCSI_28_2()!=SS_COMP) return SS_ERR;
}
else
{
if(InitSCSI_28_1()!=SS_COMP) return SS_ERR;
}
}
memset(&sx,0,sizeof(sx));
sx.SRB_Cmd = SC_EXEC_SCSI_CMD;
sx.SRB_HaId = iCD_AD;
sx.SRB_Target = iCD_TA;
sx.SRB_Lun = iCD_LU;
sx.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
sx.SRB_BufLen = f->dwBufLen;
sx.SRB_BufPointer = &(f->BufData[0]);
sx.SRB_SenseLen = SENSE_LEN;
sx.SRB_CDBLen = 10;
sx.SRB_PostProc = (LPVOID)hEvent;
sx.CDBByte[0] = 0x28; // read10 command
sx.CDBByte[1] = iCD_LU << 5;
sx.CDBByte[2] = (unsigned char)((f->dwFrame >> 24) & 0xFF);
sx.CDBByte[3] = (unsigned char)((f->dwFrame >> 16) & 0xFF);
sx.CDBByte[4] = (unsigned char)((f->dwFrame >> 8) & 0xFF);
sx.CDBByte[5] = (unsigned char)(f->dwFrame & 0xFF);
sx.CDBByte[8] = (unsigned char)(f->dwFrameCnt & 0xFF);
ResetEvent(hEvent);
dwStatus=pSendASPI32Command((LPSRB)&sx);
if(dwStatus==SS_PENDING)
{
if(bWait) WaitGenEvent(WAITFOREVER);
else
{
bDoWaiting=TRUE;
return SS_COMP;
}
}
if(sx.SRB_Status!=SS_COMP)
return SS_ERR;
return SS_COMP;
}
/////////////////////////////////////////////////////////
// DVD MODE
DWORD ReadSCSI_28_2048(BOOL bWait,FRAMEBUF * f)
{
DWORD dwStatus;
if(!pDeInitFunc)
{
InitSCSI_28_2048();
//if(InitSCSI_28_2048()!=SS_COMP) return SS_ERR;
}
memset(&sx,0,sizeof(sx));
sx.SRB_Cmd = SC_EXEC_SCSI_CMD;
sx.SRB_HaId = iCD_AD;
sx.SRB_Target = iCD_TA;
sx.SRB_Lun = iCD_LU;
sx.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
sx.SRB_BufLen = f->dwBufLen;
sx.SRB_BufPointer = &(f->BufData[0]);
sx.SRB_SenseLen = SENSE_LEN;
sx.SRB_CDBLen = 10;
sx.SRB_PostProc = (LPVOID)hEvent;
sx.CDBByte[0] = 0x28; // read10 command
sx.CDBByte[1] = iCD_LU << 5;
sx.CDBByte[2] = (unsigned char)((f->dwFrame >> 24) & 0xFF);
sx.CDBByte[3] = (unsigned char)((f->dwFrame >> 16) & 0xFF);
sx.CDBByte[4] = (unsigned char)((f->dwFrame >> 8) & 0xFF);
sx.CDBByte[5] = (unsigned char)(f->dwFrame & 0xFF);
sx.CDBByte[8] = (unsigned char)(f->dwFrameCnt & 0xFF);
sx.CDBByte[9] = 0xF8;
ResetEvent(hEvent);
dwStatus=pSendASPI32Command((LPSRB)&sx);
if(dwStatus==SS_PENDING)
{
if(bWait) WaitGenEvent(WAITFOREVER);
else
{
bDoWaiting=TRUE;
return SS_COMP;
}
}
if(sx.SRB_Status!=SS_COMP)
return SS_ERR;
return SS_COMP;
}
DWORD ReadSCSI_28_2048_Ex(BOOL bWait,FRAMEBUF * f)
{
DWORD dwStatus;
if(!pDeInitFunc)
{
InitSCSI_28_2048();
//if(InitSCSI_28_2048()!=SS_COMP) return SS_ERR;
}
memset(&sx,0,sizeof(sx));
sx.SRB_Cmd = SC_EXEC_SCSI_CMD;
sx.SRB_HaId = iCD_AD;
sx.SRB_Target = iCD_TA;
sx.SRB_Lun = iCD_LU;
sx.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
sx.SRB_BufLen = f->dwBufLen;
sx.SRB_BufPointer = &(f->BufData[0]);
sx.SRB_SenseLen = SENSE_LEN;
sx.SRB_CDBLen = 10;
sx.SRB_PostProc = (LPVOID)hEvent;
sx.CDBByte[0] = 0x28; // read10 command
sx.CDBByte[1] = iCD_LU << 5;
sx.CDBByte[2] = (unsigned char)((f->dwFrame >> 24) & 0xFF);
sx.CDBByte[3] = (unsigned char)((f->dwFrame >> 16) & 0xFF);
sx.CDBByte[4] = (unsigned char)((f->dwFrame >> 8) & 0xFF);
sx.CDBByte[5] = (unsigned char)(f->dwFrame & 0xFF);
sx.CDBByte[8] = (unsigned char)(f->dwFrameCnt & 0xFF);
// NO F8
//sx.CDBByte[9] = 0xF8;
ResetEvent(hEvent);
dwStatus=pSendASPI32Command((LPSRB)&sx);
if(dwStatus==SS_PENDING)
{
if(bWait) WaitGenEvent(WAITFOREVER);
else
{
bDoWaiting=TRUE;
return SS_COMP;
}
}
if(sx.SRB_Status!=SS_COMP)
return SS_ERR;
return SS_COMP;
}
/////////////////////////////////////////////////////////
// stupid subc reading on Teac 532S
char tbuf[2368];
DWORD ReadSCSI_28_Sub(BOOL bWait,FRAMEBUF * f)
{
DWORD dwStatus;
if(!pDeInitFunc)
{
if(iRType==MODE_28_2)
{
if(InitSCSI_28_2()!=SS_COMP) return SS_ERR;
}
else
{
if(InitSCSI_28_1()!=SS_COMP) return SS_ERR;
}
}
memset(&sx,0,sizeof(sx));
sx.SRB_Cmd = SC_EXEC_SCSI_CMD;
sx.SRB_HaId = iCD_AD;
sx.SRB_Target = iCD_TA;
sx.SRB_Lun = iCD_LU;
sx.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
sx.SRB_BufLen = f->dwBufLen;
sx.SRB_BufPointer = &(f->BufData[0]);
sx.SRB_SenseLen = SENSE_LEN;
sx.SRB_CDBLen = 10;
sx.SRB_PostProc = (LPVOID)hEvent;
sx.CDBByte[0] = 0x28; // read10
sx.CDBByte[1] = iCD_LU << 5;
sx.CDBByte[2] = (unsigned char)((f->dwFrame >> 24) & 0xFF);
sx.CDBByte[3] = (unsigned char)((f->dwFrame >> 16) & 0xFF);
sx.CDBByte[4] = (unsigned char)((f->dwFrame >> 8) & 0xFF);
sx.CDBByte[5] = (unsigned char)(f->dwFrame & 0xFF);
sx.CDBByte[8] = (unsigned char)(f->dwFrameCnt & 0xFF);
ResetEvent(hEvent);
dwStatus=pSendASPI32Command((LPSRB)&sx);
if(dwStatus==SS_PENDING)
WaitGenEvent(WAITFOREVER);
if(sx.SRB_Status!=SS_COMP)
return SS_ERR;
memset(&sx,0,sizeof(sx));
sx.SRB_Cmd = SC_EXEC_SCSI_CMD;
sx.SRB_HaId = iCD_AD;
sx.SRB_Target = iCD_TA;
sx.SRB_Lun = iCD_LU;
sx.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
sx.SRB_BufLen = 2368;
sx.SRB_BufPointer = tbuf;
sx.SRB_SenseLen = SENSE_LEN;
sx.SRB_CDBLen = 12;
sx.SRB_PostProc = (LPVOID)hEvent;
sx.CDBByte[0] = 0xD8;
sx.CDBByte[2] = (unsigned char)((f->dwFrame >> 24) & 0xFF);
sx.CDBByte[3] = (unsigned char)((f->dwFrame >> 16) & 0xFF);
sx.CDBByte[4] = (unsigned char)((f->dwFrame >> 8) & 0xFF);
sx.CDBByte[5] = (unsigned char)(f->dwFrame & 0xFF);
sx.CDBByte[9] = (unsigned char)(f->dwFrameCnt & 0xFF);
sx.CDBByte[10] = 1;
ResetEvent(hEvent);
dwStatus=pSendASPI32Command((LPSRB)&sx);
if(dwStatus==SS_PENDING)
WaitGenEvent(WAITFOREVER);
if(sx.SRB_Status!=SS_COMP)
return SS_ERR;
memcpy(&SubCData[12],&tbuf[2352],16);
return SS_COMP;
}
/////////////////////////////////////////////////////////
// various simple scsi sub data read funcs... used for
// ripping and subread checking... first 2352 bytes can
// be trash after read, only the bytes after are important
/////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////
int ReadSub_BE_2(unsigned long addr,unsigned char * pBuf,int iNum)
{
DWORD dwStatus;
memset(&sx,0,sizeof(sx));
sx.SRB_Cmd = SC_EXEC_SCSI_CMD;
sx.SRB_HaId = iCD_AD;
sx.SRB_Target = iCD_TA;
sx.SRB_Lun = iCD_LU;
sx.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
sx.SRB_BufLen = 2368*iNum;
sx.SRB_BufPointer = pBuf;
sx.SRB_SenseLen = SENSE_LEN;
sx.SRB_CDBLen = 12;
sx.SRB_PostProc = (LPVOID)hEvent;
sx.CDBByte[0] = 0xBE;
sx.CDBByte[2] = (unsigned char)((addr >> 24) & 0xFF);
sx.CDBByte[3] = (unsigned char)((addr >> 16) & 0xFF);
sx.CDBByte[4] = (unsigned char)((addr >> 8) & 0xFF);
sx.CDBByte[5] = (unsigned char)(addr & 0xFF);
sx.CDBByte[8] = iNum;
sx.CDBByte[9] = 0xF8;
sx.CDBByte[10] = 0x2;
ResetEvent(hEvent);
dwStatus=pSendASPI32Command( (LPSRB)&sx );
if(dwStatus==SS_PENDING)
WaitGenEvent(WAITSUB);
if(sx.SRB_Status!=SS_COMP)
return 0;
return 1;
}
/////////////////////////////////////////////////////////
int ReadSub_BE_2_1(unsigned long addr,unsigned char * pBuf,int iNum)
{
DWORD dwStatus;
memset(&sx,0,sizeof(sx));
sx.SRB_Cmd = SC_EXEC_SCSI_CMD;
sx.SRB_HaId = iCD_AD;
sx.SRB_Target = iCD_TA;
sx.SRB_Lun = iCD_LU;
sx.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
sx.SRB_BufLen = 2448*iNum; // special! 96 bytes instead of 16
sx.SRB_BufPointer = pBuf;
sx.SRB_SenseLen = SENSE_LEN;
sx.SRB_CDBLen = 12;
sx.SRB_PostProc = (LPVOID)hEvent;
sx.CDBByte[0] = 0xBE;
sx.CDBByte[2] = (unsigned char)((addr >> 24) & 0xFF);
sx.CDBByte[3] = (unsigned char)((addr >> 16) & 0xFF);
sx.CDBByte[4] = (unsigned char)((addr >> 8) & 0xFF);
sx.CDBByte[5] = (unsigned char)(addr & 0xFF);
sx.CDBByte[8] = iNum;
sx.CDBByte[9] = 0xF8;
sx.CDBByte[10] = 0x1;
ResetEvent(hEvent);
dwStatus=pSendASPI32Command((LPSRB)&sx);
if(dwStatus==SS_PENDING)
WaitGenEvent(WAITSUB);
if(sx.SRB_Status!=SS_COMP)
return 0;
return 1;
}
/////////////////////////////////////////////////////////
int ReadSub_D8(unsigned long addr,unsigned char * pBuf,int iNum)
{
DWORD dwStatus;
memset(&sx,0,sizeof(sx));
sx.SRB_Cmd = SC_EXEC_SCSI_CMD;
sx.SRB_HaId = iCD_AD;
sx.SRB_Target = iCD_TA;
sx.SRB_Lun = iCD_LU;
sx.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
sx.SRB_BufLen = 2368*iNum;
sx.SRB_BufPointer = pBuf;
sx.SRB_SenseLen = SENSE_LEN;
sx.SRB_CDBLen = 12;
sx.SRB_PostProc = (LPVOID)hEvent;
sx.CDBByte[0] = 0xD8;
sx.CDBByte[2] = (unsigned char)((addr >> 24) & 0xFF);
sx.CDBByte[3] = (unsigned char)((addr >> 16) & 0xFF);
sx.CDBByte[4] = (unsigned char)((addr >> 8) & 0xFF);
sx.CDBByte[5] = (unsigned char)(addr & 0xFF);
sx.CDBByte[9] = iNum;
sx.CDBByte[10] = 1;
ResetEvent(hEvent);
dwStatus=pSendASPI32Command((LPSRB)&sx);
if(dwStatus==SS_PENDING)
WaitGenEvent(WAITFOREVER);
if(sx.SRB_Status!=SS_COMP)
return 0;
return 1;
}
/////////////////////////////////////////////////////////
// liteon subdata decoding
void DecodeSub_BE_2_1(unsigned char * pBuf)
{
int i,j;
unsigned char * pS=pBuf;
unsigned char c;
for(i=0;i<12;i++)
{
c=0;
for(j=7;j>=0;j--,pS++)
{
if(*pS & 0x40) c|=(1<<j);
}
*(pBuf+i)=c;
}
for(i=12;i<16;i++) *(pBuf+i)=0;
}
/////////////////////////////////////////////////////////
// auto-detection of read mode (without subc), called
// on plugin startup
#define MAXMODES 6
DWORD CheckSCSIReadMode(void)
{
DWORD dwStatus;int i,j,k,iCnt;char * p;
int iModes[MAXMODES]={MODE_BE_2,MODE_BE_1,MODE_28_1,MODE_28_2,MODE_28_2048,MODE_28_2048_Ex};
int iBlock[MAXMODES]={2352, 2352, 2352, 2352, 2048, 2048};
unsigned char cdb[3000];
FRAMEBUF * f=(FRAMEBUF *)cdb;
for(i=0;i<MAXMODES;i++) // loop avail read modes
{
f->dwFrame = 16; // we check on addr 16 (should be available on all ps2 cds/dvds)
f->dwFrameCnt = 1;
f->dwBufLen = iBlock[i];
pDeInitFunc = NULL;
iRType=iModes[i]; // set global read mode
GetGenReadFunc(iRType); // get read func pointer
for(j=0;j<3;j++) // try it 3 times
{
memset(f->BufData,0xAA,f->dwBufLen); // fill buf with AA
dwStatus=pReadFunc(TRUE,f); // do the read
#ifdef DBGOUT
auxprintf("status %d\n",dwStatus);
#endif
if(dwStatus!=SS_COMP) continue; // error? try again
p=&(f->BufData[0]);
#ifdef DBGOUT
auxprintf("check mode %d\n",i);
#endif
for(k=0,iCnt=0;k<(int)f->dwBufLen;k+=4,p+=4) // now check the returned data
{
#ifdef DBGOUT
// auxprintf("%08x ",*((DWORD *)p));
#endif
if(*((DWORD *)p)==0xAAAAAAAA) // -> still AA? bad
iCnt++;
else iCnt=0;
if(iCnt>=8) {dwStatus=SS_ERR;break;} // -> if we have found many AA's, the reading was bad
}
if(dwStatus==SS_COMP) // reading was a success, no AA's?
{
iRType = iModes[i]; // -> set found mode
iUsedBlockSize = iBlock[i];
if(iUsedBlockSize==2352)
iUsedMode=CDVD_MODE_2352;
else iUsedMode=CDVD_MODE_2048;
#ifdef DBGOUT
auxprintf("mode found %d\n",i);
#endif
return dwStatus; // -> bye
}
}
if(pDeInitFunc) pDeInitFunc(); // deinit, try next mode
}
return dwStatus;
}
/////////////////////////////////////////////////////////
// dummy read dunc
DWORD ReadSCSI_Dummy(BOOL bWait,FRAMEBUF * f)
{
return SS_ERR;
}
/////////////////////////////////////////////////////////