Reimplemented the READ SUBCHANNEL command for both ATAPI and SCSI.
This commit is contained in:
@@ -529,6 +529,21 @@ static void ioctl_read_capacity(uint8_t *b)
|
|||||||
ioctl_close();
|
ioctl_close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ioctl_read_subchannel(uint8_t *in_cdb, uint8_t *b)
|
||||||
|
{
|
||||||
|
const UCHAR cdb[12];
|
||||||
|
UCHAR buf[24];
|
||||||
|
|
||||||
|
ioctl_open(0);
|
||||||
|
|
||||||
|
memcpy(cdb, in_cdb, 12);
|
||||||
|
SCSICommand(cdb, buf, 24);
|
||||||
|
|
||||||
|
memcpy(b, buf, 24);
|
||||||
|
|
||||||
|
ioctl_close();
|
||||||
|
}
|
||||||
|
|
||||||
static void ioctl_read_header(uint8_t *in_cdb, uint8_t *b)
|
static void ioctl_read_header(uint8_t *in_cdb, uint8_t *b)
|
||||||
{
|
{
|
||||||
const UCHAR cdb[12];
|
const UCHAR cdb[12];
|
||||||
@@ -1054,6 +1069,7 @@ static CDROM ioctl_cdrom=
|
|||||||
ioctl_readtoc_raw,
|
ioctl_readtoc_raw,
|
||||||
ioctl_getcurrentsubchannel,
|
ioctl_getcurrentsubchannel,
|
||||||
ioctl_read_capacity,
|
ioctl_read_capacity,
|
||||||
|
ioctl_read_subchannel,
|
||||||
ioctl_read_header,
|
ioctl_read_header,
|
||||||
ioctl_read_disc_information,
|
ioctl_read_disc_information,
|
||||||
ioctl_read_track_information,
|
ioctl_read_track_information,
|
||||||
|
@@ -18,6 +18,8 @@ void iso_close(void);
|
|||||||
static FILE* iso_image;
|
static FILE* iso_image;
|
||||||
static int iso_changed = 0;
|
static int iso_changed = 0;
|
||||||
|
|
||||||
|
static uint32_t lba = 0;
|
||||||
|
|
||||||
static uint32_t iso_cd_pos = 0, iso_cd_end = 0;
|
static uint32_t iso_cd_pos = 0, iso_cd_end = 0;
|
||||||
|
|
||||||
void iso_audio_callback(int16_t *output, int len)
|
void iso_audio_callback(int16_t *output, int len)
|
||||||
@@ -64,6 +66,7 @@ static void iso_stop(void)
|
|||||||
static void iso_seek(uint32_t pos)
|
static void iso_seek(uint32_t pos)
|
||||||
{
|
{
|
||||||
// pclog("iso_seek stub\n");
|
// pclog("iso_seek stub\n");
|
||||||
|
lba = pos;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,8 +116,39 @@ static int iso_medium_changed(void)
|
|||||||
|
|
||||||
static uint8_t iso_getcurrentsubchannel(uint8_t *b, int msf)
|
static uint8_t iso_getcurrentsubchannel(uint8_t *b, int msf)
|
||||||
{
|
{
|
||||||
// pclog("iso_getcurrentsubchannel stub\n");
|
long size;
|
||||||
return 0;
|
int pos=0;
|
||||||
|
if (strlen(iso_path) == 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
b[pos++]=0;
|
||||||
|
b[pos++]=0;
|
||||||
|
b[pos++]=0;
|
||||||
|
|
||||||
|
int32_t temp = lba;
|
||||||
|
if (msf)
|
||||||
|
{
|
||||||
|
memset(&(b[pos]), 0, 8);
|
||||||
|
lba_to_msf(&(b[pos]), temp);
|
||||||
|
pos += 4;
|
||||||
|
lba_to_msf(&(b[pos]), temp);
|
||||||
|
pos += 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
b[pos++] = temp >> 24;
|
||||||
|
b[pos++] = temp >> 16;
|
||||||
|
b[pos++] = temp >> 8;
|
||||||
|
b[pos++] = temp;
|
||||||
|
b[pos++] = temp >> 24;
|
||||||
|
b[pos++] = temp >> 16;
|
||||||
|
b[pos++] = temp >> 8;
|
||||||
|
b[pos++] = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0x13;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void iso_eject(void)
|
static void iso_eject(void)
|
||||||
@@ -418,6 +452,7 @@ static CDROM iso_cdrom =
|
|||||||
iso_getcurrentsubchannel,
|
iso_getcurrentsubchannel,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
iso_sector_data_type,
|
iso_sector_data_type,
|
||||||
|
@@ -134,6 +134,7 @@ static CDROM null_cdrom =
|
|||||||
null_getcurrentsubchannel,
|
null_getcurrentsubchannel,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
null_sector_data_type,
|
null_sector_data_type,
|
||||||
|
@@ -11,6 +11,7 @@ typedef struct CDROM
|
|||||||
int (*readtoc_raw)(uint8_t *b, int msf, 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_subchannel)(uint8_t *in_cdb, uint8_t *b);
|
||||||
void (*read_header)(uint8_t *in_cdb, uint8_t *b);
|
void (*read_header)(uint8_t *in_cdb, uint8_t *b);
|
||||||
void (*read_disc_information)(uint8_t *b);
|
void (*read_disc_information)(uint8_t *b);
|
||||||
int (*read_track_information)(uint8_t *in_cdb, uint8_t *b);
|
int (*read_track_information)(uint8_t *in_cdb, uint8_t *b);
|
||||||
|
52
src/ide.c
52
src/ide.c
@@ -2577,25 +2577,53 @@ static void atapicommand(int ide_board)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case GPCMD_READ_SUBCHANNEL:
|
case GPCMD_READ_SUBCHANNEL:
|
||||||
temp=idebufferb[2]&0x40;
|
if (idebufferb[3] > 3)
|
||||||
if (idebufferb[3]!=1)
|
|
||||||
{
|
{
|
||||||
// pclog("Read subchannel check condition %02X\n",idebufferb[3]);
|
// pclog("Read subchannel check condition %02X\n",idebufferb[3]);
|
||||||
atapi_invalid_field(ide);
|
atapi_invalid_field(ide);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos=0;
|
switch(idebufferb[3])
|
||||||
idebufferb[pos++]=0;
|
|
||||||
idebufferb[pos++]=0; /*Audio status*/
|
|
||||||
idebufferb[pos++]=0; idebufferb[pos++]=0; /*Subchannel length*/
|
|
||||||
idebufferb[pos++]=1; /*Format code*/
|
|
||||||
idebufferb[1]=cdrom->getcurrentsubchannel(&idebufferb[5],msf);
|
|
||||||
// pclog("Read subchannel complete - audio status %02X\n",idebufferb[1]);
|
|
||||||
len=16;
|
|
||||||
if (!temp)
|
|
||||||
{
|
{
|
||||||
len=4;
|
case 0:
|
||||||
|
alloc_length = 4;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
alloc_length = 16;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
alloc_length = 24;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cdrom->read_subchannel)
|
||||||
|
{
|
||||||
|
cdrom->read_subchannel(idebufferb, idebufferb);
|
||||||
|
len = alloc_length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
temp = idebufferb[3] & 3;
|
||||||
|
temp |= (idebufferb[2] & 0x40);
|
||||||
|
memset(idebufferb, 24, 0);
|
||||||
|
pos = 0;
|
||||||
|
idebufferb[pos++]=0;
|
||||||
|
idebufferb[pos++]=0; /*Audio status*/
|
||||||
|
idebufferb[pos++]=0; idebufferb[pos++]=0; /*Subchannel length*/
|
||||||
|
idebufferb[pos++]=temp & 3; /*Format code*/
|
||||||
|
if ((temp & 3) == 1)
|
||||||
|
{
|
||||||
|
idebufferb[1]=cdrom->getcurrentsubchannel(&idebufferb[5],msf);
|
||||||
|
}
|
||||||
|
if (!(temp & 0x40) || ((temp & 3) == 0))
|
||||||
|
{
|
||||||
|
len=4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
len = alloc_length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ide->packetstatus = ATAPI_STATUS_DATA;
|
ide->packetstatus = ATAPI_STATUS_DATA;
|
||||||
ide->cylinder=len;
|
ide->cylinder=len;
|
||||||
|
@@ -1120,25 +1120,54 @@ SCSIOut:
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case GPCMD_READ_SUBCHANNEL:
|
case GPCMD_READ_SUBCHANNEL:
|
||||||
Temp = cdb[2] & 0x40;
|
if (cdb[3] > 3)
|
||||||
if (cdb[3] != 1)
|
|
||||||
{
|
{
|
||||||
SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
|
SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
|
||||||
SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00);
|
SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00);
|
||||||
SCSICallback[id]=50*SCSI_TIME;
|
SCSICallback[id]=50*SCSI_TIME;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = 0;
|
switch(cdb[3])
|
||||||
cmdbuffer[pos++] = 0;
|
{
|
||||||
cmdbuffer[pos++] = 0; /*Audio status*/
|
case 0:
|
||||||
cmdbuffer[pos++] = 0; cmdbuffer[pos++] = 0; /*Subchannel length*/
|
alloc_length = 4;
|
||||||
cmdbuffer[pos++] = 1; /*Format code*/
|
break;
|
||||||
cmdbuffer[1] = cdrom->getcurrentsubchannel(&cmdbuffer[5], msf);
|
case 1:
|
||||||
len = 16;
|
alloc_length = 16;
|
||||||
if (!Temp)
|
break;
|
||||||
len = 4;
|
default:
|
||||||
|
alloc_length = 24;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cdrom->read_subchannel)
|
||||||
|
{
|
||||||
|
cdrom->read_subchannel(cdb, cmdbuffer);
|
||||||
|
len = alloc_length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset(cmdbuffer, 24, 0);
|
||||||
|
pos = 0;
|
||||||
|
cmdbuffer[pos++]=0;
|
||||||
|
cmdbuffer[pos++]=0; /*Audio status*/
|
||||||
|
cmdbuffer[pos++]=0; cmdbuffer[pos++]=0; /*Subchannel length*/
|
||||||
|
cmdbuffer[pos++]=cdb[3]; /*Format code*/
|
||||||
|
if (!(cdb[2] & 0x40) || (cdb[3] == 0))
|
||||||
|
{
|
||||||
|
len = 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
len = alloc_length;
|
||||||
|
}
|
||||||
|
if (cdb[3] == 1)
|
||||||
|
{
|
||||||
|
cmdbuffer[1]=cdrom->getcurrentsubchannel(&cmdbuffer[5],msf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SCSIPhase = SCSI_PHASE_DATAIN;
|
SCSIPhase = SCSI_PHASE_DATAIN;
|
||||||
SCSIStatus = SCSI_STATUS_OK;
|
SCSIStatus = SCSI_STATUS_OK;
|
||||||
SCSICallback[id]=1000*SCSI_TIME;
|
SCSICallback[id]=1000*SCSI_TIME;
|
||||||
|
Reference in New Issue
Block a user