mirror of
https://github.com/holub/mame
synced 2025-10-06 17:08:28 +03:00
moved request sense command into t10spc, supporting the old obsolete format and the new one. [smf]
This commit is contained in:
parent
cddbf287ba
commit
b3034cbfca
@ -17,7 +17,7 @@ void t10mmc::t10_start(device_t &device)
|
||||
device.save_item(NAME(last_lba));
|
||||
device.save_item(NAME(num_subblocks));
|
||||
device.save_item(NAME(cur_subblock));
|
||||
device.save_item(NAME(play_err_flag));
|
||||
device.save_item(NAME(m_audio_sense));
|
||||
}
|
||||
|
||||
void t10mmc::t10_reset()
|
||||
@ -36,10 +36,20 @@ void t10mmc::t10_reset()
|
||||
m_sector_bytes = 2048;
|
||||
num_subblocks = 1;
|
||||
cur_subblock = 0;
|
||||
play_err_flag = 0;
|
||||
m_audio_sense = 0;
|
||||
}
|
||||
|
||||
// scsicd_exec_command
|
||||
|
||||
void t10mmc::abort_audio()
|
||||
{
|
||||
if (m_cdda->audio_active())
|
||||
{
|
||||
m_cdda->stop_audio();
|
||||
m_audio_sense = SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_STOPPED_DUE_TO_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Execute a SCSI command.
|
||||
|
||||
@ -47,15 +57,26 @@ void t10mmc::ExecCommand()
|
||||
{
|
||||
int trk;
|
||||
|
||||
// keep updating the sense data while playing audio.
|
||||
if (command[0] == SCSI_CMD_REQUEST_SENSE && m_audio_sense != SCSI_SENSE_ASC_ASCQ_NO_SENSE && m_sense_key == SCSI_SENSE_KEY_NO_SENSE && m_sense_asc == 0 && m_sense_ascq == 0)
|
||||
{
|
||||
if (m_audio_sense == SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS && !m_cdda->audio_active())
|
||||
{
|
||||
m_audio_sense = SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_SUCCESSFULLY_COMPLETED;
|
||||
}
|
||||
|
||||
set_sense(SCSI_SENSE_KEY_NO_SENSE, (sense_asc_ascq_t) m_audio_sense);
|
||||
|
||||
if (m_audio_sense != SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS)
|
||||
{
|
||||
m_audio_sense = SCSI_SENSE_ASC_ASCQ_NO_SENSE;
|
||||
}
|
||||
}
|
||||
|
||||
switch ( command[0] )
|
||||
{
|
||||
case 0x03: // REQUEST SENSE
|
||||
m_phase = SCSI_PHASE_DATAIN;
|
||||
m_transfer_length = SCSILengthFromUINT8( &command[ 4 ] );
|
||||
break;
|
||||
|
||||
case 0x12: // INQUIRY
|
||||
logerror("T10MMC: REQUEST SENSE\n");
|
||||
logerror("T10MMC: INQUIRY\n");
|
||||
m_phase = SCSI_PHASE_DATAIN;
|
||||
m_transfer_length = SCSILengthFromUINT8( &command[ 4 ] );
|
||||
break;
|
||||
@ -72,7 +93,7 @@ void t10mmc::ExecCommand()
|
||||
break;
|
||||
|
||||
case 0x1b: // START STOP UNIT
|
||||
m_cdda->stop_audio();
|
||||
abort_audio();
|
||||
m_phase = SCSI_PHASE_STATUS;
|
||||
m_transfer_length = 0;
|
||||
break;
|
||||
@ -104,7 +125,7 @@ void t10mmc::ExecCommand()
|
||||
cur_subblock = 0;
|
||||
}
|
||||
|
||||
m_cdda->stop_audio();
|
||||
abort_audio();
|
||||
|
||||
m_phase = SCSI_PHASE_DATAIN;
|
||||
m_transfer_length = blocks * m_sector_bytes;
|
||||
@ -142,7 +163,7 @@ void t10mmc::ExecCommand()
|
||||
length = 4;
|
||||
}
|
||||
|
||||
m_cdda->stop_audio();
|
||||
abort_audio();
|
||||
|
||||
m_phase = SCSI_PHASE_DATAIN;
|
||||
m_transfer_length = length;
|
||||
@ -168,13 +189,13 @@ void t10mmc::ExecCommand()
|
||||
|
||||
if (cdrom_get_track_type(cdrom, trk) == CD_TRACK_AUDIO)
|
||||
{
|
||||
play_err_flag = 0;
|
||||
m_cdda->start_audio(lba, blocks);
|
||||
m_audio_sense = SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
logerror("T10MMC: track is NOT audio!\n");
|
||||
play_err_flag = 1;
|
||||
set_sense(SCSI_SENSE_KEY_ILLEGAL_REQUEST, SCSI_SENSE_ASC_ASCQ_ILLEGAL_MODE_FOR_THIS_TRACK);
|
||||
}
|
||||
|
||||
m_phase = SCSI_PHASE_STATUS;
|
||||
@ -184,6 +205,7 @@ void t10mmc::ExecCommand()
|
||||
case 0x48: // PLAY AUDIO TRACK/INDEX
|
||||
// be careful: tracks here are zero-based, but the SCSI command
|
||||
// uses the real CD track number which is 1-based!
|
||||
logerror("T10MMC: PLAY AUDIO T/I: strk %d idx %d etrk %d idx %d frames %d\n", command[4], command[5], command[7], command[8], blocks);
|
||||
lba = cdrom_get_track_start(cdrom, command[4]-1);
|
||||
blocks = cdrom_get_track_start(cdrom, command[7]-1) - lba;
|
||||
if (command[4] > command[7])
|
||||
@ -196,12 +218,19 @@ void t10mmc::ExecCommand()
|
||||
blocks = cdrom_get_track_start(cdrom, command[4]) - lba;
|
||||
}
|
||||
|
||||
if (blocks && cdrom)
|
||||
trk = cdrom_get_track(cdrom, lba);
|
||||
|
||||
if (cdrom_get_track_type(cdrom, trk) == CD_TRACK_AUDIO)
|
||||
{
|
||||
m_cdda->start_audio(lba, blocks);
|
||||
m_audio_sense = SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
logerror("T10MMC: track is NOT audio!\n");
|
||||
set_sense(SCSI_SENSE_KEY_ILLEGAL_REQUEST, SCSI_SENSE_ASC_ASCQ_ILLEGAL_MODE_FOR_THIS_TRACK);
|
||||
}
|
||||
|
||||
logerror("T10MMC: PLAY AUDIO T/I: strk %d idx %d etrk %d idx %d frames %d\n", command[4], command[5], command[7], command[8], blocks);
|
||||
m_phase = SCSI_PHASE_STATUS;
|
||||
m_transfer_length = 0;
|
||||
break;
|
||||
@ -218,10 +247,7 @@ void t10mmc::ExecCommand()
|
||||
break;
|
||||
|
||||
case 0x4e: // STOP
|
||||
if (cdrom)
|
||||
{
|
||||
m_cdda->stop_audio();
|
||||
}
|
||||
abort_audio();
|
||||
|
||||
logerror("T10MMC: STOP_PLAY_SCAN\n");
|
||||
m_phase = SCSI_PHASE_STATUS;
|
||||
@ -259,14 +285,15 @@ void t10mmc::ExecCommand()
|
||||
|
||||
if (cdrom_get_track_type(cdrom, trk) == CD_TRACK_AUDIO)
|
||||
{
|
||||
play_err_flag = 0;
|
||||
m_cdda->start_audio(lba, blocks);
|
||||
m_audio_sense = SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
logerror("T10MMC: track is NOT audio!\n");
|
||||
play_err_flag = 1;
|
||||
set_sense(SCSI_SENSE_KEY_ILLEGAL_REQUEST, SCSI_SENSE_ASC_ASCQ_ILLEGAL_MODE_FOR_THIS_TRACK);
|
||||
}
|
||||
|
||||
m_phase = SCSI_PHASE_STATUS;
|
||||
m_transfer_length = 0;
|
||||
break;
|
||||
@ -287,7 +314,7 @@ void t10mmc::ExecCommand()
|
||||
cur_subblock = 0;
|
||||
}
|
||||
|
||||
m_cdda->stop_audio();
|
||||
abort_audio();
|
||||
|
||||
m_phase = SCSI_PHASE_DATAIN;
|
||||
m_transfer_length = blocks * m_sector_bytes;
|
||||
@ -317,27 +344,6 @@ void t10mmc::ReadData( UINT8 *data, int dataLength )
|
||||
|
||||
switch ( command[0] )
|
||||
{
|
||||
case 0x03: // REQUEST SENSE
|
||||
logerror("T10MMC: Reading REQUEST SENSE data\n");
|
||||
|
||||
memset( data, 0, dataLength );
|
||||
|
||||
data[0] = 0x71; // deferred error
|
||||
|
||||
if (m_cdda->audio_active())
|
||||
{
|
||||
data[12] = 0x00;
|
||||
data[13] = 0x11; // AUDIO PLAY OPERATION IN PROGRESS
|
||||
}
|
||||
else if (play_err_flag)
|
||||
{
|
||||
play_err_flag = 0;
|
||||
data[12] = 0x64; // ILLEGAL MODE FOR THIS TRACK
|
||||
data[13] = 0x00;
|
||||
}
|
||||
// (else 00/00 means no error to report)
|
||||
break;
|
||||
|
||||
case 0x12: // INQUIRY
|
||||
memset( data, 0, dataLength );
|
||||
data[0] = 0x05; // device is present, device is CD/DVD (MMC-3)
|
||||
@ -404,8 +410,6 @@ void t10mmc::ReadData( UINT8 *data, int dataLength )
|
||||
{
|
||||
case 1: // return current position
|
||||
{
|
||||
int msf;
|
||||
|
||||
if (!cdrom)
|
||||
{
|
||||
return;
|
||||
@ -413,8 +417,6 @@ void t10mmc::ReadData( UINT8 *data, int dataLength )
|
||||
|
||||
logerror("T10MMC: READ SUB-CHANNEL Time = %x, SUBQ = %x\n", command[1], command[2]);
|
||||
|
||||
msf = command[1] & 0x2;
|
||||
|
||||
int audio_active = m_cdda->audio_active();
|
||||
if (audio_active)
|
||||
{
|
||||
@ -452,6 +454,7 @@ void t10mmc::ReadData( UINT8 *data, int dataLength )
|
||||
|
||||
last_phys_frame = last_lba;
|
||||
|
||||
int msf = command[1] & 0x2;
|
||||
if (msf)
|
||||
{
|
||||
int m,s,f;
|
||||
|
@ -24,6 +24,8 @@ protected:
|
||||
virtual void t10_start(device_t &device);
|
||||
virtual void t10_reset();
|
||||
|
||||
void abort_audio();
|
||||
|
||||
cdrom_image_device *m_image;
|
||||
cdda_device *m_cdda;
|
||||
cdrom_file *cdrom;
|
||||
@ -33,7 +35,7 @@ protected:
|
||||
UINT32 last_lba;
|
||||
UINT32 num_subblocks;
|
||||
UINT32 cur_subblock;
|
||||
UINT32 play_err_flag;
|
||||
int m_audio_sense;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -34,11 +34,6 @@ void t10sbc::ExecCommand()
|
||||
{
|
||||
switch ( command[0] )
|
||||
{
|
||||
case 0x03: // REQUEST SENSE
|
||||
m_phase = SCSI_PHASE_DATAIN;
|
||||
m_transfer_length = SCSILengthFromUINT8( &command[ 4 ] );
|
||||
break;
|
||||
|
||||
case 0x04: // FORMAT UNIT
|
||||
m_phase = SCSI_PHASE_STATUS;
|
||||
m_transfer_length = 0;
|
||||
@ -123,8 +118,6 @@ void t10sbc::ExecCommand()
|
||||
|
||||
void t10sbc::ReadData( UINT8 *data, int dataLength )
|
||||
{
|
||||
int i;
|
||||
|
||||
// if we're a drive without a disk, return all zeroes
|
||||
if (!disk)
|
||||
{
|
||||
@ -134,14 +127,6 @@ void t10sbc::ReadData( UINT8 *data, int dataLength )
|
||||
|
||||
switch ( command[0] )
|
||||
{
|
||||
case 0x03: // REQUEST SENSE
|
||||
data[0] = 0x80; // valid sense
|
||||
for (i = 1; i < 12; i++)
|
||||
{
|
||||
data[i] = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x12: // INQUIRY
|
||||
memset( data, 0, dataLength );
|
||||
data[0] = 0x00; // device is direct-access (e.g. hard disk)
|
||||
|
@ -1,18 +1,32 @@
|
||||
#include "t10spc.h"
|
||||
|
||||
#define SCSI_SENSE_SIZE 4
|
||||
|
||||
void t10spc::t10_start(device_t &device)
|
||||
{
|
||||
device.save_item(NAME(command));
|
||||
device.save_item(NAME(commandLength));
|
||||
device.save_item(NAME(m_phase));
|
||||
device.save_item(NAME(m_transfer_length));
|
||||
device.save_item(NAME(m_phase));
|
||||
device.save_item(NAME(m_sense_key));
|
||||
device.save_item(NAME(m_sense_asc));
|
||||
device.save_item(NAME(m_sense_ascq));
|
||||
device.save_item(NAME(m_sense_information));
|
||||
}
|
||||
|
||||
void t10spc::t10_reset()
|
||||
{
|
||||
m_phase = SCSI_PHASE_BUS_FREE;
|
||||
m_sense_key = 0;
|
||||
m_sense_asc = 0;
|
||||
m_sense_ascq = 0;
|
||||
m_sense_information = 0;
|
||||
}
|
||||
|
||||
void t10spc::set_sense(sense_key_t key, sense_asc_ascq_t asc_ascq)
|
||||
{
|
||||
m_sense_key = key;
|
||||
m_sense_asc = (asc_ascq >> 8) & 0xff;
|
||||
m_sense_ascq = asc_ascq & 0xff;
|
||||
m_sense_information = 0;
|
||||
}
|
||||
|
||||
void t10spc::ExecCommand()
|
||||
@ -30,8 +44,19 @@ void t10spc::ExecCommand()
|
||||
break;
|
||||
|
||||
case SCSI_CMD_REQUEST_SENSE:
|
||||
m_phase = SCSI_PHASE_DATAOUT;
|
||||
m_transfer_length = SCSI_SENSE_SIZE;
|
||||
m_phase = SCSI_PHASE_DATAIN;
|
||||
if (command[4] == 0)
|
||||
{
|
||||
m_transfer_length = 4;
|
||||
}
|
||||
else if (command[4] > 18)
|
||||
{
|
||||
m_transfer_length = 18;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_transfer_length = command[ 4 ];
|
||||
}
|
||||
break;
|
||||
|
||||
case SCSI_CMD_SEND_DIAGNOSTIC:
|
||||
@ -51,11 +76,38 @@ void t10spc::ReadData( UINT8 *data, int dataLength )
|
||||
switch( command[ 0 ] )
|
||||
{
|
||||
case SCSI_CMD_REQUEST_SENSE:
|
||||
data[ 0 ] = SCSI_SENSE_NO_SENSE;
|
||||
data[ 1 ] = 0x00;
|
||||
data[ 2 ] = 0x00;
|
||||
data[ 3 ] = 0x00;
|
||||
if (command[4] == 0)
|
||||
{
|
||||
data[0] = m_sense_asc & 0x7f;
|
||||
data[1] = (m_sense_information >> 16) & 0x1f;
|
||||
data[2] = (m_sense_information >> 8) & 0xff;
|
||||
data[3] = (m_sense_information >> 0) & 0xff;
|
||||
}
|
||||
else
|
||||
{
|
||||
data[0] = 0x70;
|
||||
data[1] = 0;
|
||||
data[2] = m_sense_key & 0xf;
|
||||
data[3] = (m_sense_information >> 24) & 0xff;
|
||||
data[4] = (m_sense_information >> 16) & 0xff;
|
||||
data[5] = (m_sense_information >> 8) & 0xff;
|
||||
data[6] = (m_sense_information >> 0) & 0xff;
|
||||
data[7] = 10;
|
||||
data[8] = 0;
|
||||
data[9] = 0;
|
||||
data[10] = 0;
|
||||
data[11] = 0;
|
||||
data[12] = m_sense_asc;
|
||||
data[13] = m_sense_ascq;
|
||||
data[14] = 0;
|
||||
data[15] = 0;
|
||||
data[16] = 0;
|
||||
data[17] = 0;
|
||||
}
|
||||
|
||||
set_sense(SCSI_SENSE_KEY_NO_SENSE, SCSI_SENSE_ASC_ASCQ_NO_SENSE);
|
||||
break;
|
||||
|
||||
default:
|
||||
logerror( "SCSIDEV unknown read %02x\n", command[ 0 ] );
|
||||
break;
|
||||
|
@ -29,10 +29,32 @@ protected:
|
||||
int SCSILengthFromUINT8( UINT8 *length ) { if( *length == 0 ) { return 256; } return *length; }
|
||||
int SCSILengthFromUINT16( UINT8 *length ) { return ( *(length) << 8 ) | *(length + 1 ); }
|
||||
|
||||
enum sense_key_t
|
||||
{
|
||||
SCSI_SENSE_KEY_NO_SENSE = 0,
|
||||
SCSI_SENSE_KEY_ILLEGAL_REQUEST = 5
|
||||
};
|
||||
|
||||
enum sense_asc_ascq_t
|
||||
{
|
||||
SCSI_SENSE_ASC_ASCQ_NO_SENSE = 0x0,
|
||||
SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS = 0x0011,
|
||||
SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_PAUSED = 0x0012,
|
||||
SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_SUCCESSFULLY_COMPLETED = 0x0013,
|
||||
SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_STOPPED_DUE_TO_ERROR = 0x0014,
|
||||
SCSI_SENSE_ASC_ASCQ_ILLEGAL_MODE_FOR_THIS_TRACK = 0x6400
|
||||
};
|
||||
|
||||
void set_sense(sense_key_t key, sense_asc_ascq_t asc_ascq);
|
||||
|
||||
UINT8 command[ 32 ];
|
||||
int commandLength;
|
||||
int m_transfer_length;
|
||||
int m_phase;
|
||||
UINT8 m_sense_key;
|
||||
UINT8 m_sense_asc;
|
||||
UINT8 m_sense_ascq;
|
||||
UINT32 m_sense_information;
|
||||
int m_sector_bytes;
|
||||
device_t *m_device;
|
||||
};
|
||||
@ -52,28 +74,4 @@ protected:
|
||||
#define SCSI_CMD_MODE_SELECT ( 0x15 )
|
||||
#define SCSI_CMD_SEND_DIAGNOSTIC ( 0x1d )
|
||||
|
||||
#define SCSI_SENSE_ADDR_VALID 0x80
|
||||
#define SCSI_SENSE_NO_SENSE 0x00
|
||||
#define SCSI_SENSE_NO_INDEX 0x01
|
||||
#define SCSI_SENSE_SEEK_NOT_COMP 0x02
|
||||
#define SCSI_SENSE_WRITE_FAULT 0x03
|
||||
#define SCSI_SENSE_DRIVE_NOT_READY 0x04
|
||||
#define SCSI_SENSE_NO_TRACK0 0x06
|
||||
#define SCSI_SENSE_ID_CRC_ERROR 0x10
|
||||
#define SCSI_SENSE_UNCORRECTABLE 0x11
|
||||
#define SCSI_SENSE_ADDRESS_NF 0x12
|
||||
#define SCSI_SENSE_RECORD_NOT_FOUND 0x14
|
||||
#define SCSI_SENSE_SEEK_ERROR 0x15
|
||||
#define SCSI_SENSE_DATA_CHECK_RETRY 0x18
|
||||
#define SCSI_SENSE_ECC_VERIFY 0x19
|
||||
#define SCSI_SENSE_INTERLEAVE_ERROR 0x1A
|
||||
#define SCSI_SENSE_UNFORMATTED 0x1C
|
||||
#define SCSI_SENSE_ILLEGAL_COMMAND 0x20
|
||||
#define SCSI_SENSE_ILLEGAL_ADDRESS 0x21
|
||||
#define SCSI_SENSE_VOLUME_OVERFLOW 0x23
|
||||
#define SCSI_SENSE_BAD_ARGUMENT 0x24
|
||||
#define SCSI_SENSE_INVALID_LUN 0x25
|
||||
#define SCSI_SENSE_CART_CHANGED 0x28
|
||||
#define SCSI_SENSE_ERROR_OVERFLOW 0x2C
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user