ATAPI BAD COMMAND response now correctly sets IDE sector count to 3;

ATAPI READ TOC PMA ATIP command now uses direct SCSI passthrough when using IOCtl on Windows;
ATAPI READ TOC PMA ATIP command now supports non-MSF raw mode;
ATAPI READ TOC PMA ATIP command now returns the given maximum length if the actual length of the data is above it;
ATAPI READ TOC PMA ATPI command on Windows IOCtl now returns size of data in the returned buffer's header.
This commit is contained in:
OBattler
2016-12-25 01:57:56 +01:00
parent e46a34a505
commit c7443b47b5
6 changed files with 112 additions and 31 deletions

View File

@@ -482,7 +482,7 @@ static int SCSICommand(const UCHAR *cdb, UCHAR *buf, uint32_t len)
DWORD ioctl_bytes; DWORD ioctl_bytes;
DWORD out_size; DWORD out_size;
int ioctl_rv = 0; int ioctl_rv = 0;
UCHAR tbuf[2856]; UCHAR tbuf[65535];
struct sptd_with_sense struct sptd_with_sense
{ {
SCSI_PASS_THROUGH_DIRECT s; SCSI_PASS_THROUGH_DIRECT s;
@@ -759,6 +759,10 @@ static int ioctl_readtoc(unsigned char *b, unsigned char starttrack, int msf, in
} }
if (single) break; if (single) break;
} }
if (len > maxlen)
{
len = maxlen;
}
b[0] = (uint8_t)(((len-2) >> 8) & 0xff); b[0] = (uint8_t)(((len-2) >> 8) & 0xff);
b[1] = (uint8_t)((len-2) & 0xff); b[1] = (uint8_t)((len-2) & 0xff);
/* pclog("Table of Contents (%i bytes) : \n",size); /* pclog("Table of Contents (%i bytes) : \n",size);
@@ -811,9 +815,45 @@ static int ioctl_readtoc_session(unsigned char *b, int msf, int maxlen)
b[len++]=temp; b[len++]=temp;
} }
if (len > maxlen)
{
len = maxlen;
}
b[0] = ((len - 2) >> 8) & 0xff;
b[1] = (len - 2) & 0xff;
return len; return len;
} }
static void ioctl_readtoc_raw(uint8_t *b, int msf, int maxlen)
{
UCHAR cdb[12];
UCHAR buf[65535];
int len = 0;
ioctl_open(0);
cdb[0] = 0x43;
cdb[1] = msf ? 2 : 0;
cdb[2] = 2;
cdb[3] = cdb[4] = cdb[5] = cdb[6] = 0;
cdb[7] = (maxlen >> 8) & 0xff;
cdb[8] = maxlen & 0xff;
cdb[9] = cdb[10] = cdb[11] = 0;
SCSICommand(cdb, buf, 65535);
len = buf[0];
len <<= 8;
len |= buf[1];
len += 2;
memcpy(b, buf, len);
ioctl_close();
}
#if 0
static int ioctl_readtoc_raw(unsigned char *b, int maxlen) static int ioctl_readtoc_raw(unsigned char *b, int maxlen)
{ {
int len=4; int len=4;
@@ -855,8 +895,12 @@ static int ioctl_readtoc_raw(unsigned char *b, int maxlen)
b[len++]=toc.Descriptors[i].Msf[2]; b[len++]=toc.Descriptors[i].Msf[2];
} }
b[0] = (len >> 8) & 0xff;
b[1] = len & 0xff;
return len; return len;
} }
#endif
static uint32_t ioctl_size() static uint32_t ioctl_size()
{ {

View File

@@ -221,6 +221,10 @@ static int iso_readtoc(unsigned char *buf, unsigned char start_track, int msf, i
*q++ = last_block; *q++ = last_block;
} }
len = q - buf; len = q - buf;
if (len > maxlen)
{
len = maxlen;
}
buf[0] = (uint8_t)(((len-2) >> 8) & 0xff); buf[0] = (uint8_t)(((len-2) >> 8) & 0xff);
buf[1] = (uint8_t)((len-2) & 0xff); buf[1] = (uint8_t)((len-2) & 0xff);
return len; return len;
@@ -243,10 +247,14 @@ static int iso_readtoc_session(unsigned char *buf, int msf, int maxlen)
*q++ = 0; /* frame */ *q++ = 0; /* frame */
*q++ = 0; *q++ = 0;
if (maxlen < 12)
{
return maxlen;
}
return 12; return 12;
} }
static int iso_readtoc_raw(unsigned char *buf, int maxlen) static int iso_readtoc_raw(unsigned char *buf, int msf, int maxlen)
{ {
uint8_t *q; uint8_t *q;
int len; int len;
@@ -288,9 +296,19 @@ static int iso_readtoc_raw(unsigned char *buf, int maxlen)
*q++ = 0; /* frame */ *q++ = 0; /* frame */
last_block = image_size >> 11; last_block = image_size >> 11;
/* this is raw, must be msf */ /* this is raw, must be msf */
if (msf)
{
*q++ = 0; /* reserved */ *q++ = 0; /* reserved */
lba_to_msf(q, last_block); lba_to_msf(q, last_block);
q += 3; q += 3;
}
else
{
*q++ = (last_block >> 24) & 0xff;
*q++ = (last_block >> 16) & 0xff;
*q++ = (last_block >> 8) & 0xff;
*q++ = last_block & 0xff;
}
*q++ = 1; /* session number */ *q++ = 1; /* session number */
*q++ = 0x14; /* ADR, control */ *q++ = 0x14; /* ADR, control */
@@ -300,12 +318,25 @@ static int iso_readtoc_raw(unsigned char *buf, int maxlen)
*q++ = 0; /* sec */ *q++ = 0; /* sec */
*q++ = 0; /* frame */ *q++ = 0; /* frame */
/* same here */ /* same here */
if (msf)
{
*q++ = 0; /* reserved */
lba_to_msf(q, 0);
q += 3;
}
else
{
*q++ = 0; *q++ = 0;
*q++ = 0; *q++ = 0;
*q++ = 0; *q++ = 0;
*q++ = 0; *q++ = 0;
}
len = q - buf; len = q - buf;
if (len > maxlen)
{
len = maxlen;
}
buf[0] = (uint8_t)(((len-2) >> 8) & 0xff); buf[0] = (uint8_t)(((len-2) >> 8) & 0xff);
buf[1] = (uint8_t)((len-2) & 0xff); buf[1] = (uint8_t)((len-2) & 0xff);
return len; return len;

View File

@@ -81,7 +81,7 @@ static int null_readtoc_session(unsigned char *b, int msf, int maxlen)
return 0; return 0;
} }
static int null_readtoc_raw(unsigned char *b, int maxlen) static int null_readtoc_raw(unsigned char *b, int msf, int maxlen)
{ {
return 0; return 0;
} }

View File

@@ -8,7 +8,7 @@ typedef struct CDROM
int (*medium_changed)(void); int (*medium_changed)(void);
int (*readtoc)(uint8_t *b, uint8_t starttrack, int msf, int maxlen, int single); int (*readtoc)(uint8_t *b, uint8_t starttrack, int msf, int maxlen, int single);
int (*readtoc_session)(uint8_t *b, int msf, int maxlen); int (*readtoc_session)(uint8_t *b, int msf, int maxlen);
int (*readtoc_raw)(uint8_t *b, int maxlen); int (*readtoc_raw)(uint8_t *b, int msf, int maxlen);
uint8_t (*getcurrentsubchannel)(uint8_t *b, int msf); uint8_t (*getcurrentsubchannel)(uint8_t *b, int msf);
void (*read_capacity)(uint8_t *b); void (*read_capacity)(uint8_t *b);
void (*read_header)(uint8_t *in_cdb, uint8_t *b); void (*read_header)(uint8_t *in_cdb, uint8_t *b);

View File

@@ -666,7 +666,7 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
} */ } */
} }
fdc.dor=val; fdc.dor=val;
// printf("DOR now %02X (%04X:%04X)\n",val, CS, cpu_state.pc); printf("DOR now %02X (%04X:%04X)\n",val, CS, cpu_state.pc);
return; return;
case 3: case 3:
/* TDR */ /* TDR */
@@ -686,10 +686,10 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc.perp &= 0xfc; fdc.perp &= 0xfc;
fdc_reset(); fdc_reset();
} }
// pclog("DSR now: %02X\n", val); pclog("DSR now: %02X\n", val);
return; return;
case 5: /*Command register*/ case 5: /*Command register*/
// pclog("CMD now: %02X\n", val); pclog("CMD now: %02X\n", val);
if ((fdc.stat & 0xf0) == 0xb0) if ((fdc.stat & 0xf0) == 0xb0)
{ {
if (fdc.pcjr || !fdc.fifo) if (fdc.pcjr || !fdc.fifo)
@@ -793,6 +793,7 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc.stat |= 0x90; fdc.stat |= 0x90;
break; break;
case 8: /*Sense interrupt status*/ case 8: /*Sense interrupt status*/
if (!fdc.fintr && !fdc_reset_stat) pclog("Attempted SENSE INTERRUPT STATUS without FINTR\n");
if (!fdc.fintr && !fdc_reset_stat) goto bad_command; if (!fdc.fintr && !fdc_reset_stat) goto bad_command;
// printf("Sense interrupt status %i\n",curdrive); // printf("Sense interrupt status %i\n",curdrive);
fdc.lastdrive = fdc.drive; fdc.lastdrive = fdc.drive;
@@ -1216,7 +1217,7 @@ bad_command:
case 7: case 7:
if (!AT) return; if (!AT) return;
fdc.rate=val&3; fdc.rate=val&3;
// pclog("Rate now: %i\n", val & 3); pclog("Rate now: %i\n", val & 3);
disc_3f7=val; disc_3f7=val;
return; return;
@@ -1254,7 +1255,7 @@ uint8_t fdc_read(uint16_t addr, void *priv)
break; break;
case 2: case 2:
temp = fdc.dor; temp = fdc.dor;
// pclog("Read DOR: %02X\n", fdc.dor); pclog("Read DOR: %02X\n", fdc.dor);
break; break;
case 3: case 3:
drive = real_drive(fdc.dor & 3); drive = real_drive(fdc.dor & 3);
@@ -1284,7 +1285,7 @@ uint8_t fdc_read(uint16_t addr, void *priv)
return 0; return 0;
} }
temp=fdc.stat; temp=fdc.stat;
// pclog("Read MSR: %02X\n", fdc.stat); pclog("Read MSR: %02X\n", fdc.stat);
break; break;
case 5: /*Data*/ case 5: /*Data*/
fdc.stat&=~0x80; fdc.stat&=~0x80;
@@ -1296,14 +1297,14 @@ uint8_t fdc_read(uint16_t addr, void *priv)
{ {
temp = fdc_fifo_buf_read(); temp = fdc_fifo_buf_read();
} }
// pclog("Read DAT: %02X\n", temp); pclog("Read DAT: %02X\n", temp);
break; break;
} }
if (paramstogo) if (paramstogo)
{ {
paramstogo--; paramstogo--;
temp=fdc.res[10 - paramstogo]; temp=fdc.res[10 - paramstogo];
// pclog("Read result: %02X\n", temp); pclog("Read result: %02X\n", temp);
// pclog("Read param %i %02X\n",10-paramstogo,temp); // pclog("Read param %i %02X\n",10-paramstogo,temp);
if (!paramstogo) if (!paramstogo)
{ {
@@ -1322,15 +1323,16 @@ uint8_t fdc_read(uint16_t addr, void *priv)
fdc.stat = 0x80; fdc.stat = 0x80;
lastbyte=0; lastbyte=0;
temp=fdc.dat; temp=fdc.dat;
// pclog("Read DAT: %02X\n", temp); pclog("Read DAT: %02X\n", temp);
fdc.data_ready = 0; fdc.data_ready = 0;
} }
if (discint==0xA) /* What the heck is this even doing?! */
/* if (discint==0xA)
{ {
timer_process(); timer_process();
disctime = 1024 * (1 << TIMER_SHIFT); disctime = 1024 * (1 << TIMER_SHIFT);
timer_update_outstanding(); timer_update_outstanding();
} } */
fdc.stat &= 0xf0; fdc.stat &= 0xf0;
break; break;
case 7: /*Disk change*/ case 7: /*Disk change*/
@@ -1345,7 +1347,7 @@ uint8_t fdc_read(uint16_t addr, void *priv)
{ {
temp |= 0x7F; temp |= 0x7F;
} }
// pclog("Read CCR: %02X\n", temp); pclog("Read CCR: %02X\n", temp);
// printf("- DC %i %02X %02X %i %i - ",fdc.dor & 3, fdc.dor, 0x10 << (fdc.dor & 3), discchanged[fdc.dor & 1], driveempty[fdc.dor & 1]); // printf("- DC %i %02X %02X %i %i - ",fdc.dor & 3, fdc.dor, 0x10 << (fdc.dor & 3), discchanged[fdc.dor & 1], driveempty[fdc.dor & 1]);
// discchanged[fdc.dor&1]=0; // discchanged[fdc.dor&1]=0;
break; break;

View File

@@ -1114,6 +1114,7 @@ uint8_t readide(int ide_board, uint16_t addr)
else else
{ {
temp = (uint8_t)ide->secount; temp = (uint8_t)ide->secount;
// pclog("Returning sector count: %i\n", temp);
} }
break; break;
@@ -1704,7 +1705,8 @@ void callbackide(int ide_board)
{ {
readcdmode=0; readcdmode=0;
ide->pos=0; ide->pos=0;
ide->secount = (uint8_t)((ide->secount&0xF8)|1); // ide->secount = (uint8_t)((ide->secount&0xF8)|1);
ide->secount = 1;
ide->atastat = READY_STAT | DRQ_STAT |(ide->atastat&ERR_STAT); ide->atastat = READY_STAT | DRQ_STAT |(ide->atastat&ERR_STAT);
//ide_irq_raise(ide); //ide_irq_raise(ide);
// pclog("1 Preparing to recieve packet max DRQ count %04X\n",ide->cylinder); // pclog("1 Preparing to recieve packet max DRQ count %04X\n",ide->cylinder);
@@ -1818,7 +1820,7 @@ void atapi_command_send_init(IDE *ide, uint8_t command, int req_length, int allo
if ((ide->cylinder & 1) && !(alloc_length <= ide->cylinder)) if ((ide->cylinder & 1) && !(alloc_length <= ide->cylinder))
{ {
pclog("Odd byte count (0x%04x) to ATAPI command 0x%02x, using 0x%04x\n", ide->cylinder, command, ide->cylinder - 1); // pclog("Odd byte count (0x%04x) to ATAPI command 0x%02x, using 0x%04x\n", ide->cylinder, command, ide->cylinder - 1);
ide->cylinder--; ide->cylinder--;
} }
@@ -1889,9 +1891,9 @@ static void atapicommand(int ide_board)
int ret; int ret;
int real_pos; int real_pos;
#if 0 // pclog("ATAPI command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, %i, Unit attention: %i\n",idebufferb[0],SCSISense.SenseKey,SCSISense.Asc,SCSISense.Ascq,ins,SCSISense.UnitAttention);
pclog("ATAPI command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, %i, Unit attention: %i\n",idebufferb[0],SCSISense.SenseKey,SCSISense.Asc,SCSISense.Ascq,ins,SCSISense.UnitAttention);
#if 0
int CdbLength; int CdbLength;
for (CdbLength = 1; CdbLength < 12; CdbLength++) for (CdbLength = 1; CdbLength < 12; CdbLength++)
pclog("ATAPI CDB[%d] = 0x%02X\n", CdbLength, idebufferb[CdbLength]); pclog("ATAPI CDB[%d] = 0x%02X\n", CdbLength, idebufferb[CdbLength]);
@@ -2076,7 +2078,7 @@ static void atapicommand(int ide_board)
case 2: /*Raw*/ case 2: /*Raw*/
// pclog("ATAPI: READ TOC type requested: Raw TOC\n"); // pclog("ATAPI: READ TOC type requested: Raw TOC\n");
len=idebufferb[8]+(idebufferb[7]<<8); len=idebufferb[8]+(idebufferb[7]<<8);
len=cdrom->readtoc_raw(idebufferb,len); len=cdrom->readtoc_raw(idebufferb,msf,len);
break; break;
default: default:
// pclog("ATAPI: Unknown READ TOC type requested: %i\n", (idebufferb[9]>>6)); // pclog("ATAPI: Unknown READ TOC type requested: %i\n", (idebufferb[9]>>6));
@@ -2101,6 +2103,7 @@ static void atapicommand(int ide_board)
ide->pos=0; ide->pos=0;
idecallback[ide_board]=60*IDE_TIME; idecallback[ide_board]=60*IDE_TIME;
ide->packlen=len; ide->packlen=len;
// pclog("READ_TOC_PMA_ATIP format %02X, length %i (%i)\n", toc_format, ide->cylinder, idebufferb[1]);
return; return;
case GPCMD_READ_CD: case GPCMD_READ_CD:
@@ -2854,6 +2857,7 @@ atapi_out:
SCSISense.SenseKey = SENSE_ILLEGAL_REQUEST; SCSISense.SenseKey = SENSE_ILLEGAL_REQUEST;
SCSISense.Asc = ASC_ILLEGAL_OPCODE; SCSISense.Asc = ASC_ILLEGAL_OPCODE;
ide->packetstatus = ATAPI_STATUS_ERROR; ide->packetstatus = ATAPI_STATUS_ERROR;
ide->secount = 3;
idecallback[ide_board]=50*IDE_TIME; idecallback[ide_board]=50*IDE_TIME;
break; break;