CD-ROM: IOCTL now detects medium changes without having to read the host drive's TOC on every operation, improves performance.

This commit is contained in:
OBattler
2025-02-03 10:57:19 +01:00
parent a8918de768
commit 35a12e0826
9 changed files with 340 additions and 192 deletions

View File

@@ -678,8 +678,13 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev)
dev->callback += period;
scsi_cdrom_set_callback(dev);
return;
case 0x43:
dev->drv->seek_diff = dev->drv->seek_pos + 150;
dev->drv->seek_pos = 0;
fallthrough;
case 0x08:
case 0x28:
case 0x42: case 0x44:
case 0xa8:
/* Seek time is in us. */
period = cdrom_seek_time(dev->drv);
@@ -693,7 +698,7 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev)
dev->callback += period;
fallthrough;
case 0x25:
case 0x42 ... 0x44:
// case 0x42 ... 0x44:
case 0x51 ... 0x52:
case 0xad:
case 0xb8 ... 0xb9:
@@ -702,6 +707,11 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev)
dev->callback += 40.0;
/* Account for seek time. */
/* 44100 * 16 bits * 2 channels = 176400 bytes per second */
/*
TODO: This is a bit of a lie - the actual period is closer to
75 * 2448 bytes per second, because the subchannel data
has to be read as well.
*/
bytes_per_second = 176400.0;
bytes_per_second *= (double) dev->drv->cur_speed;
break;
@@ -730,7 +740,19 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev)
period = 1000000.0 / bytes_per_second;
scsi_cdrom_log(dev->log, "Byte transfer period: %" PRIu64 " us\n",
(uint64_t) period);
period = period * (double) (dev->packet_len);
switch (cmd) {
default:
period = period * (double) (dev->packet_len);
break;
case 0x42: case 0x44:
/* READ SUBCHANNEL or READ HEADER - period of 1 entire sector. */
period = period * 2352.0;
break;
case 0x43:
/* READ TOC - period of 175 entire frames. */
period = period * 150.0 * 2352.0;
break;
}
scsi_cdrom_log(dev->log, "Sector transfer period: %" PRIu64 " us\n",
(uint64_t) period);
dev->callback += period;
@@ -1181,25 +1203,6 @@ scsi_cdrom_insert(void *priv)
}
}
static void
scsi_cdrom_ext_insert(void *priv, int ext_medium_changed)
{
scsi_cdrom_t *dev = (scsi_cdrom_t *) priv;
if ((dev == NULL) || (dev->drv == NULL))
return;
if ((dev->drv->ops == NULL) || (ext_medium_changed == -1)) {
dev->unit_attention = 0;
dev->drv->cd_status = CD_STATUS_EMPTY;
scsi_cdrom_log(dev->log, "External media removal\n");
} else if (ext_medium_changed == 1) {
dev->unit_attention = 0;
dev->drv->cd_status |= CD_STATUS_TRANSITION;
scsi_cdrom_log(dev->log, "External media transition\n");
}
}
static int
scsi_command_check_ready(const scsi_cdrom_t *dev, const uint8_t *cdb)
{
@@ -1223,7 +1226,6 @@ static int
scsi_cdrom_pre_execution_check(scsi_cdrom_t *dev, const uint8_t *cdb)
{
int ready;
const int ext_medium_changed = cdrom_ext_medium_changed(dev->drv);
if ((cdb[0] != GPCMD_REQUEST_SENSE) && (dev->cur_lun == SCSI_LUN_USE_CDB) &&
(cdb[1] & 0xe0)) {
@@ -1257,9 +1259,6 @@ scsi_cdrom_pre_execution_check(scsi_cdrom_t *dev, const uint8_t *cdb)
return 0;
}
if (ext_medium_changed != 0)
scsi_cdrom_ext_insert((void *) dev, ext_medium_changed);
if ((dev->drv->cd_status == CD_STATUS_PLAYING) ||
(dev->drv->cd_status == CD_STATUS_PAUSED)) {
ready = 1;
@@ -1270,13 +1269,10 @@ scsi_cdrom_pre_execution_check(scsi_cdrom_t *dev, const uint8_t *cdb)
if ((cdb[0] == GPCMD_TEST_UNIT_READY) || (cdb[0] == GPCMD_REQUEST_SENSE))
ready = 0;
else {
if ((ext_medium_changed != 0) ||
!(scsi_cdrom_command_flags[cdb[0]] & ALLOW_UA)) {
scsi_cdrom_log(dev->log, "(ext_medium_changed != 0): scsi_cdrom_insert()\n");
if (!(scsi_cdrom_command_flags[cdb[0]] & ALLOW_UA))
scsi_cdrom_insert((void *) dev);
}
ready = (dev->drv->cd_status != CD_STATUS_EMPTY) || (ext_medium_changed == -1);
ready = (dev->drv->cd_status != CD_STATUS_EMPTY);
}
} else
ready = (dev->drv->cd_status != CD_STATUS_EMPTY);
@@ -1469,10 +1465,6 @@ void
scsi_cdrom_request_sense_for_scsi(scsi_common_t *sc, uint8_t *buffer, uint8_t alloc_length)
{
scsi_cdrom_t *dev = (scsi_cdrom_t *) sc;
const int ext_medium_changed = cdrom_ext_medium_changed(dev->drv);
if (ext_medium_changed != 0)
scsi_cdrom_ext_insert((void *) dev, ext_medium_changed);
if ((dev->drv->cd_status == CD_STATUS_EMPTY) && dev->unit_attention) {
/*