Overhauled CD-ROM selection for SCSI and ATAPI, including model and vendor specific commands.

Fixed the Spock SCSI ID selection.
Fixed CD Audio on NCR 5380-based SCSI controllers.
Added a proprietary CD-ROM controller selection (not hooked up yet).
All on qt only.
This commit is contained in:
TC1995
2023-01-07 23:48:45 +01:00
parent d501a61dfb
commit e5496e2638
19 changed files with 1941 additions and 473 deletions

View File

@@ -1068,6 +1068,10 @@ pc_reset_hard_init(void)
/* Reset the Hard Disk Controller module. */ /* Reset the Hard Disk Controller module. */
hdc_reset(); hdc_reset();
/* Reset the CD-ROM Controller module. */
cdrom_interface_reset();
/* Reset and reconfigure the SCSI layer. */ /* Reset and reconfigure the SCSI layer. */
scsi_card_init(); scsi_card_init();

View File

@@ -23,9 +23,12 @@
#include <wchar.h> #include <wchar.h>
#define HAVE_STDARG_H #define HAVE_STDARG_H
#include <86box/86box.h> #include <86box/86box.h>
#include <86box/device.h>
#include <86box/config.h> #include <86box/config.h>
#include <86box/cdrom.h> #include <86box/cdrom.h>
#include <86box/cdrom_image.h> #include <86box/cdrom_image.h>
#include <86box/cdrom_interface.h>
#include <86box/cdrom_mitsumi.h>
#include <86box/plat.h> #include <86box/plat.h>
#include <86box/scsi.h> #include <86box/scsi.h>
#include <86box/scsi_device.h> #include <86box/scsi_device.h>
@@ -43,9 +46,6 @@
#define MIN_SEEK 2000 #define MIN_SEEK 2000
#define MAX_SEEK 333333 #define MAX_SEEK 333333
#define CD_BCD(x) (((x) % 10) | (((x) / 10) << 4))
#define CD_DCB(x) ((((x) &0xf0) >> 4) * 10 + ((x) &0x0f))
#pragma pack(push, 1) #pragma pack(push, 1)
typedef struct { typedef struct {
uint8_t user_data[2048], uint8_t user_data[2048],
@@ -94,6 +94,8 @@ static uint8_t extra_buffer[296];
cdrom_t cdrom[CDROM_NUM]; cdrom_t cdrom[CDROM_NUM];
int cdrom_interface_current;
#ifdef ENABLE_CDROM_LOG #ifdef ENABLE_CDROM_LOG
int cdrom_do_log = ENABLE_CDROM_LOG; int cdrom_do_log = ENABLE_CDROM_LOG;
@@ -112,6 +114,145 @@ cdrom_log(const char *fmt, ...)
# define cdrom_log(fmt, ...) # define cdrom_log(fmt, ...)
#endif #endif
static const device_t cdrom_interface_none_device = {
.name = "None",
.internal_name = "none",
.flags = 0,
.local = 0,
.init = NULL,
.close = NULL,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
static const struct {
const device_t *device;
} controllers[] = {
// clang-format off
{ &cdrom_interface_none_device },
{ NULL }
// clang-format on
};
/* Reset the CD-ROM Interface, whichever one that is. */
void
cdrom_interface_reset(void)
{
cdrom_log("CD-ROM Interface: reset(current=%d)\n",
cdrom_interface_current);
/* If we have a valid controller, add its device. */
if (!controllers[cdrom_interface_current].device)
return;
device_add(controllers[cdrom_interface_current].device);
}
char *
cdrom_interface_get_internal_name(int cdinterface)
{
return device_get_internal_name(controllers[cdinterface].device);
}
int
cdrom_interface_get_from_internal_name(char *s)
{
int c = 0;
while (controllers[c].device != NULL) {
if (!strcmp((char *) controllers[c].device->internal_name, s))
return c;
c++;
}
return 0;
}
const device_t *
cdrom_interface_get_device(int cdinterface)
{
return (controllers[cdinterface].device);
}
int
cdrom_interface_has_config(int cdinterface)
{
const device_t *dev = cdrom_interface_get_device(cdinterface);
if (dev == NULL)
return (0);
if (!device_has_config(dev))
return (0);
return (1);
}
int
cdrom_interface_get_flags(int cdinterface)
{
return (controllers[cdinterface].device->flags);
}
int
cdrom_interface_available(int cdinterface)
{
return (device_available(controllers[cdinterface].device));
}
char *
cdrom_getname(int type)
{
return (char *) cdrom_drive_types[type].name;
}
char *
cdrom_get_internal_name(int type)
{
return (char *) cdrom_drive_types[type].internal_name;
}
int
cdrom_get_from_internal_name(char *s)
{
int c = 0;
while (strlen(cdrom_drive_types[c].internal_name)) {
if (!strcmp((char *) cdrom_drive_types[c].internal_name, s))
return c;
c++;
}
return 0;
}
void
cdrom_set_type(int model, int type)
{
cdrom[model].type = type;
}
int
cdrom_get_type(int model)
{
return cdrom[model].type;
}
static __inline int
bin2bcd(int x)
{
return (x % 10) | ((x / 10) << 4);
}
static __inline int
bcd2bin(int x)
{
return (x >> 4) * 10 + (x & 0x0f);
}
int int
cdrom_lba_to_msf_accurate(int lba) cdrom_lba_to_msf_accurate(int lba)
{ {
@@ -258,12 +399,26 @@ cdrom_stop(cdrom_t *dev)
} }
void void
cdrom_seek(cdrom_t *dev, uint32_t pos) cdrom_seek(cdrom_t *dev, uint32_t pos, uint8_t vendor_type)
{ {
int m, s, f;
if (!dev) if (!dev)
return; return;
cdrom_log("CD-ROM %i: Seek to LBA %08X\n", dev->id, pos); cdrom_log("CD-ROM %i: Seek to LBA %08X, vendor type = %02x.\n", dev->id, pos, vendor_type);
switch (vendor_type) {
case 0x40:
m = bcd2bin((pos >> 24) & 0xff);
s = bcd2bin((pos >> 16) & 0xff);
f = bcd2bin((pos >> 8) & 0xff);
pos = MSFtoLBA(m, s, f) - 150;
break;
case 0x80:
pos = bcd2bin((pos >> 24) & 0xff);
break;
}
dev->seek_pos = pos; dev->seek_pos = pos;
cdrom_stop(dev); cdrom_stop(dev);
@@ -323,18 +478,6 @@ cdrom_audio_callback(cdrom_t *dev, int16_t *output, int len)
return ret; return ret;
} }
static __inline int
bin2bcd(int x)
{
return (x % 10) | ((x / 10) << 4);
}
static __inline int
bcd2bin(int x)
{
return (x >> 4) * 10 + (x & 0x0f);
}
static void static void
msf_from_bcd(int *m, int *s, int *f) msf_from_bcd(int *m, int *s, int *f)
{ {
@@ -365,20 +508,22 @@ cdrom_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len, int ismsf)
/* Track-relative audio play. */ /* Track-relative audio play. */
dev->ops->get_track_info(dev, ismsf & 0xff, 0, &ti); dev->ops->get_track_info(dev, ismsf & 0xff, 0, &ti);
pos += MSFtoLBA(ti.m, ti.s, ti.f) - 150; pos += MSFtoLBA(ti.m, ti.s, ti.f) - 150;
} else if (ismsf == 2) { } else if ((ismsf == 2) || (ismsf == 3)) {
dev->ops->get_track_info(dev, pos, 0, &ti); dev->ops->get_track_info(dev, pos, 0, &ti);
pos = MSFtoLBA(ti.m, ti.s, ti.f) - 150; pos = MSFtoLBA(ti.m, ti.s, ti.f) - 150;
if (ismsf == 2) {
/* We have to end at the *end* of the specified track, /* We have to end at the *end* of the specified track,
not at the beginning. */ not at the beginning. */
dev->ops->get_track_info(dev, len, 1, &ti); dev->ops->get_track_info(dev, len, 1, &ti);
len = MSFtoLBA(ti.m, ti.s, ti.f) - 150; len = MSFtoLBA(ti.m, ti.s, ti.f) - 150;
}
} else if (ismsf == 1) { } else if (ismsf == 1) {
m = (pos >> 16) & 0xff; m = (pos >> 16) & 0xff;
s = (pos >> 8) & 0xff; s = (pos >> 8) & 0xff;
f = pos & 0xff; f = pos & 0xff;
/* NEC CDR-260 speaks BCD. */ /* NEC CDR-260 speaks BCD. */
if ((dev->bus_type == CDROM_BUS_ATAPI) && dev->early) if (!strcmp(cdrom_drive_types[dev->type].internal_name, "NEC_CD-ROM_DRIVE260_1.01") || (!strcmp(cdrom_drive_types[dev->type].internal_name, "NEC_CD-ROM_DRIVE260_1.00"))) /*NEC*/
msf_from_bcd(&m, &s, &f); msf_from_bcd(&m, &s, &f);
if (pos == 0xffffff) { if (pos == 0xffffff) {
@@ -392,7 +537,7 @@ cdrom_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len, int ismsf)
f = len & 0xff; f = len & 0xff;
/* NEC CDR-260 speaks BCD. */ /* NEC CDR-260 speaks BCD. */
if ((dev->bus_type == CDROM_BUS_ATAPI) && dev->early) if (!strcmp(cdrom_drive_types[dev->type].internal_name, "NEC_CD-ROM_DRIVE260_1.01") || (!strcmp(cdrom_drive_types[dev->type].internal_name, "NEC_CD-ROM_DRIVE260_1.00"))) /*NEC*/
msf_from_bcd(&m, &s, &f); msf_from_bcd(&m, &s, &f);
len = MSFtoLBA(m, s, f) - 150; len = MSFtoLBA(m, s, f) - 150;
@@ -434,33 +579,41 @@ cdrom_audio_track_search(cdrom_t *dev, uint32_t pos, int type, uint8_t playbit)
switch (type) { switch (type) {
case 0x00: case 0x00:
if (pos == 0xffffffff) { if (pos == 0xffffffff) {
cdrom_log("CD-ROM %i: Search from current position\n", dev->id); cdrom_log("CD-ROM %i: (type 0) Search from current position\n", dev->id);
pos = dev->seek_pos; pos = dev->seek_pos;
} }
dev->seek_pos = pos;
break; break;
case 0x40: case 0x40:
m = CD_DCB((pos >> 24) & 0xff); m = bcd2bin((pos >> 24) & 0xff);
s = CD_DCB((pos >> 16) & 0xff); s = bcd2bin((pos >> 16) & 0xff);
f = CD_DCB((pos >> 8) & 0xff); f = bcd2bin((pos >> 8) & 0xff);
if (pos == 0xffffffff) { if (pos == 0xffffffff) {
cdrom_log("CD-ROM %i: Search from current position\n", dev->id); cdrom_log("CD-ROM %i: (type 1) Search from current position\n", dev->id);
pos = dev->seek_pos; pos = dev->seek_pos;
} else } else
pos = MSFtoLBA(m, s, f) - 150; pos = MSFtoLBA(m, s, f) - 150;
dev->seek_pos = pos;
break;
case 0x80:
if (pos == 0xffffffff) {
cdrom_log("CD-ROM %i: (type 2) Search from current position\n", dev->id);
pos = dev->seek_pos;
}
dev->seek_pos = (pos >> 24) & 0xff;
break; break;
} }
/* Unlike standard commands, if there's a data track on an Audio CD (mixed mode) /* Unlike standard commands, if there's a data track on an Audio CD (mixed mode)
the playback continues with the audio muted (Toshiba CD-ROM SCSI-2 manual reference). */ the playback continues with the audio muted (Toshiba CD-ROM SCSI-2 manual reference). */
dev->seek_pos = pos;
dev->cd_buflen = 0; dev->cd_buflen = 0;
dev->cd_status = playbit ? CD_STATUS_PLAYING : CD_STATUS_PAUSED; dev->cd_status = playbit ? CD_STATUS_PLAYING : CD_STATUS_PAUSED;
return 1; return 1;
} }
uint8_t uint8_t
cdrom_toshiba_audio_play(cdrom_t *dev, uint32_t pos, int type) cdrom_audio_play_toshiba(cdrom_t *dev, uint32_t pos, int type)
{ {
int m = 0, s = 0, f = 0; int m = 0, s = 0, f = 0;
@@ -468,31 +621,85 @@ cdrom_toshiba_audio_play(cdrom_t *dev, uint32_t pos, int type)
return 0; return 0;
/*Preliminary support, revert if too incomplete*/ /*Preliminary support, revert if too incomplete*/
cdrom_log("Toshiba Play Audio: MSF = %06x, cdstatus = %02x\n", pos, dev->cd_status);
switch (type) { switch (type) {
case 0x00:
dev->cd_end = pos;
break;
case 0x40: case 0x40:
m = CD_DCB((pos >> 24) & 0xff); m = bcd2bin((pos >> 24) & 0xff);
s = CD_DCB((pos >> 16) & 0xff); s = bcd2bin((pos >> 16) & 0xff);
f = CD_DCB((pos >> 8) & 0xff); f = bcd2bin((pos >> 8) & 0xff);
pos = MSFtoLBA(m, s, f) - 150; pos = MSFtoLBA(m, s, f) - 150;
dev->cd_end = pos;
break;
case 0x80:
dev->cd_end = (pos >> 24) & 0xff;
break; break;
case 0xc0: case 0xc0:
if (pos == 0xffffffff) { if (pos == 0xffffffff) {
cdrom_log("CD-ROM %i: Playing from current position\n", dev->id); cdrom_log("CD-ROM %i: Playing from current position\n", dev->id);
pos = dev->cd_end; pos = dev->cd_end;
} }
dev->cd_end = pos;
break; break;
} }
cdrom_log("Toshiba/NEC Play Audio: MSF = %06x, type = %02x, cdstatus = %02x\n", pos, type, dev->cd_status);
/* Unlike standard commands, if there's a data track on an Audio CD (mixed mode) /* Unlike standard commands, if there's a data track on an Audio CD (mixed mode)
the playback continues with the audio muted (Toshiba CD-ROM SCSI-2 manual reference). */ the playback continues with the audio muted (Toshiba CD-ROM SCSI-2 manual reference). */
dev->cd_end = pos;
dev->cd_buflen = 0; dev->cd_buflen = 0;
dev->cd_status = CD_STATUS_PLAYING; dev->cd_status = CD_STATUS_PLAYING;
return 1; return 1;
} }
uint8_t
cdrom_audio_scan(cdrom_t *dev, uint32_t pos, int type)
{
int m = 0, s = 0, f = 0;
if (dev->cd_status == CD_STATUS_DATA_ONLY)
return 0;
cdrom_log("Audio Scan: MSF = %06x, type = %02x\n", pos, type);
switch (type) {
case 0x00:
if (pos == 0xffffffff) {
cdrom_log("CD-ROM %i: (type 0) Search from current position\n", dev->id);
pos = dev->seek_pos;
}
dev->seek_pos = pos;
break;
case 0x40:
m = bcd2bin((pos >> 24) & 0xff);
s = bcd2bin((pos >> 16) & 0xff);
f = bcd2bin((pos >> 8) & 0xff);
if (pos == 0xffffffff) {
cdrom_log("CD-ROM %i: (type 1) Search from current position\n", dev->id);
pos = dev->seek_pos;
} else
pos = MSFtoLBA(m, s, f) - 150;
dev->seek_pos = pos;
break;
case 0x80:
dev->seek_pos = (pos >> 24) & 0xff;
break;
}
/* Do this at this point, since it's at this point that we know the
actual LBA position to start playing from. */
if (!(dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO)) {
cdrom_log("CD-ROM %i: LBA %08X not on an audio track\n", dev->id, pos);
cdrom_stop(dev);
return 0;
}
dev->cd_buflen = 0;
return 1;
}
void void
cdrom_audio_pause_resume(cdrom_t *dev, uint8_t resume) cdrom_audio_pause_resume(cdrom_t *dev, uint8_t resume)
{ {
@@ -509,7 +716,6 @@ cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, int msf)
uint32_t dat; uint32_t dat;
dev->ops->get_subchannel(dev, dev->seek_pos, &subc); dev->ops->get_subchannel(dev, dev->seek_pos, &subc);
cdrom_log("CD-ROM %i: Returned subchannel at %02i:%02i.%02i\n", subc.abs_m, subc.abs_s, subc.abs_f);
if (dev->cd_status == CD_STATUS_DATA_ONLY) if (dev->cd_status == CD_STATUS_DATA_ONLY)
ret = 0x15; ret = 0x15;
@@ -522,8 +728,12 @@ cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, int msf)
ret = 0x13; ret = 0x13;
} }
if (b[pos] > 1) cdrom_log("CD-ROM %i: Returned subchannel at %02i:%02i.%02i, ret = %02x, seek pos = %08x, cd_end = %08x.\n", dev->id, subc.abs_m, subc.abs_s, subc.abs_f, ret, dev->seek_pos, dev->cd_end);
if (b[pos] > 1) {
cdrom_log("B[%i] = %02x, ret = %02x.\n", pos, b[pos], ret);
return ret; return ret;
}
b[pos++] = subc.attr; b[pos++] = subc.attr;
b[pos++] = subc.track; b[pos++] = subc.track;
@@ -533,7 +743,7 @@ cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, int msf)
b[pos] = 0; b[pos] = 0;
/* NEC CDR-260 speaks BCD. */ /* NEC CDR-260 speaks BCD. */
if ((dev->bus_type == CDROM_BUS_ATAPI) && dev->early) { if (!strcmp(cdrom_drive_types[dev->type].internal_name, "NEC_CD-ROM_DRIVE260_1.01") || (!strcmp(cdrom_drive_types[dev->type].internal_name, "NEC_CD-ROM_DRIVE260_1.00"))) /*NEC*/ {
m = subc.abs_m; m = subc.abs_m;
s = subc.abs_s; s = subc.abs_s;
f = subc.abs_f; f = subc.abs_f;
@@ -552,7 +762,7 @@ cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, int msf)
b[pos] = 0; b[pos] = 0;
/* NEC CDR-260 speaks BCD. */ /* NEC CDR-260 speaks BCD. */
if ((dev->bus_type == CDROM_BUS_ATAPI) && dev->early) { if (!strcmp(cdrom_drive_types[dev->type].internal_name, "NEC_CD-ROM_DRIVE260_1.01") || (!strcmp(cdrom_drive_types[dev->type].internal_name, "NEC_CD-ROM_DRIVE260_1.00"))) /*NEC*/ {
m = subc.rel_m; m = subc.rel_m;
s = subc.rel_s; s = subc.rel_s;
f = subc.rel_f; f = subc.rel_f;
@@ -583,6 +793,78 @@ cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, int msf)
return ret; return ret;
} }
void
cdrom_get_current_subchannel_sony(cdrom_t *dev, uint8_t *b, int msf)
{
subchannel_t subc;
int pos = 0, m, s, f;
uint32_t dat;
dev->ops->get_subchannel(dev, dev->seek_pos, &subc);
cdrom_log("CD-ROM %i: Returned subchannel at %02i:%02i.%02i, ret = %02x, seek pos = %08x, cd_end = %08x.\n", dev->id, subc.abs_m, subc.abs_s, subc.abs_f, ret, dev->seek_pos, dev->cd_end);
b[pos++] = subc.attr;
b[pos++] = subc.track;
b[pos++] = subc.index;
if (msf) {
b[pos++] = subc.rel_m;
b[pos++] = subc.rel_s;
b[pos++] = subc.rel_f;
b[pos++] = subc.abs_m;
b[pos++] = subc.abs_s;
b[pos++] = subc.abs_f;
} else {
dat = MSFtoLBA(subc.rel_m, subc.rel_s, subc.rel_f);
b[pos++] = (dat >> 16) & 0xff;
b[pos++] = (dat >> 8) & 0xff;
b[pos++] = dat & 0xff;
dat = MSFtoLBA(subc.abs_m, subc.abs_s, subc.abs_f) - 150;
b[pos++] = (dat >> 16) & 0xff;
b[pos++] = (dat >> 8) & 0xff;
b[pos++] = dat & 0xff;
}
}
uint8_t
cdrom_get_audio_status_sony(cdrom_t *dev, uint8_t *b, int msf)
{
uint8_t ret;
subchannel_t subc;
int m, s, f;
uint32_t dat;
dev->ops->get_subchannel(dev, dev->seek_pos, &subc);
if (dev->cd_status == CD_STATUS_DATA_ONLY)
ret = 0x05;
else {
if (dev->cd_status == CD_STATUS_PLAYING)
ret = dev->sound_on ? 0x00 : 0x02;
else if (dev->cd_status == CD_STATUS_PAUSED)
ret = 0x01;
else
ret = 0x03;
}
if (msf) {
b[0] = 0;
b[1] = subc.abs_m;
b[2] = subc.abs_s;
b[3] = subc.abs_f;
} else {
dat = MSFtoLBA(subc.abs_m, subc.abs_s, subc.abs_f) - 150;
b[0] = (dat >> 24) & 0xff;
b[1] = (dat >> 16) & 0xff;
b[2] = (dat >> 8) & 0xff;
b[3] = dat & 0xff;
}
return ret;
}
uint8_t uint8_t
cdrom_get_current_subcodeq_playstatus(cdrom_t *dev, uint8_t *b) cdrom_get_current_subcodeq_playstatus(cdrom_t *dev, uint8_t *b)
{ {
@@ -599,16 +881,14 @@ cdrom_get_current_subcodeq_playstatus(cdrom_t *dev, uint8_t *b)
ret = (dev->cd_status == CD_STATUS_PLAYING) ? 0x00 : dev->audio_op; ret = (dev->cd_status == CD_STATUS_PLAYING) ? 0x00 : dev->audio_op;
b[0] = subc.attr; b[0] = subc.attr;
b[1] = CD_BCD(subc.track); b[1] = bin2bcd(subc.track);
b[2] = CD_BCD(subc.index); b[2] = bin2bcd(subc.index);
b[3] = CD_BCD(subc.rel_m); b[3] = bin2bcd(subc.rel_m);
b[4] = CD_BCD(subc.rel_s); b[4] = bin2bcd(subc.rel_s);
b[5] = CD_BCD(subc.rel_f); b[5] = bin2bcd(subc.rel_f);
b[6] = CD_BCD(subc.abs_m); b[6] = bin2bcd(subc.abs_m);
b[7] = CD_BCD(subc.abs_s); b[7] = bin2bcd(subc.abs_s);
b[8] = CD_BCD(subc.abs_f); b[8] = bin2bcd(subc.abs_f);
cdrom_log("CD-ROM %i: Returned subcode-q at %02i:%02i.%02i, track=%02x\n", dev->id, b[3], b[4], b[5], b[1]);
return ret; return ret;
} }
@@ -670,7 +950,7 @@ read_toc_normal(cdrom_t *dev, unsigned char *b, unsigned char start_track, int m
b[len++] = 0; b[len++] = 0;
/* NEC CDR-260 speaks BCD. */ /* NEC CDR-260 speaks BCD. */
if ((dev->bus_type == CDROM_BUS_ATAPI) && dev->early) { if (!strcmp(cdrom_drive_types[dev->type].internal_name, "NEC_CD-ROM_DRIVE260_1.01") || (!strcmp(cdrom_drive_types[dev->type].internal_name, "NEC_CD-ROM_DRIVE260_1.00"))) { /*NEC*/
m = ti.m; m = ti.m;
s = ti.s; s = ti.s;
f = ti.f; f = ti.f;
@@ -720,7 +1000,7 @@ read_toc_session(cdrom_t *dev, unsigned char *b, int msf)
b[len++] = 0; b[len++] = 0;
/* NEC CDR-260 speaks BCD. */ /* NEC CDR-260 speaks BCD. */
if ((dev->bus_type == CDROM_BUS_ATAPI) && dev->early) { if (!strcmp(cdrom_drive_types[dev->type].internal_name, "NEC_CD-ROM_DRIVE260_1.01") || (!strcmp(cdrom_drive_types[dev->type].internal_name, "NEC_CD-ROM_DRIVE260_1.00"))) { /*NEC*/
m = ti.m; m = ti.m;
s = ti.s; s = ti.s;
f = ti.f; f = ti.f;
@@ -778,6 +1058,75 @@ read_toc_raw(cdrom_t *dev, unsigned char *b)
return len; return len;
} }
static int
read_toc_sony(cdrom_t *dev, unsigned char *b, unsigned char start_track, int msf)
{
track_info_t ti;
int i, len = 4;
int m, s, f;
int first_track, last_track;
uint32_t temp;
cdrom_log("read_toc_sony(%08X, %08X, %02X, %i)\n", dev, b, start_track, msf);
dev->ops->get_tracks(dev, &first_track, &last_track);
/* Byte 2 = Number of the first track */
dev->ops->get_track_info(dev, 1, 0, &ti);
b[2] = ti.number;
cdrom_log(" b[2] = %02X\n", b[2]);
/* Byte 3 = Number of the last track before the lead-out track */
dev->ops->get_track_info(dev, last_track, 0, &ti);
b[3] = ti.number;
cdrom_log(" b[3] = %02X\n", b[2]);
if (start_track == 0x00)
first_track = 0;
else {
first_track = -1;
for (i = 0; i <= last_track; i++) {
dev->ops->get_track_info(dev, i + 1, 0, &ti);
if (ti.number >= start_track) {
first_track = i;
break;
}
}
}
cdrom_log(" first_track = %i, last_track = %i\n", first_track, last_track);
/* No suitable starting track, return with error. */
if (first_track == -1) {
#ifdef ENABLE_CDROM_LOG
cdrom_log(" [ERROR] No suitable track found\n");
#endif
return -1;
}
for (i = first_track; i <= last_track; i++) {
cdrom_log(" tracks(%i) = %02X, %02X, %i:%02i.%02i\n", i, ti.attr, ti.number, ti.m, ti.s, ti.f);
dev->ops->get_track_info(dev, i + 1, 0, &ti);
b[len++] = ti.attr;
b[len++] = ti.number; /* track number */
if (msf) {
b[len++] = 0;
b[len++] = ti.m;
b[len++] = ti.s;
b[len++] = ti.f;
} else {
temp = MSFtoLBA(ti.m, ti.s, ti.f) - 150;
b[len++] = temp >> 24;
b[len++] = temp >> 16;
b[len++] = temp >> 8;
b[len++] = temp;
}
}
return len;
}
int int
cdrom_read_toc(cdrom_t *dev, unsigned char *b, int type, unsigned char start_track, int msf, int max_len) cdrom_read_toc(cdrom_t *dev, unsigned char *b, int type, unsigned char start_track, int msf, int max_len)
{ {
@@ -806,6 +1155,21 @@ cdrom_read_toc(cdrom_t *dev, unsigned char *b, int type, unsigned char start_tra
return len; return len;
} }
int
cdrom_read_toc_sony(cdrom_t *dev, unsigned char *b, unsigned char start_track, int msf, int max_len)
{
int len;
len = read_toc_sony(dev, b, start_track, msf);
len = MIN(len, max_len);
b[0] = (uint8_t) (((len - 2) >> 8) & 0xff);
b[1] = (uint8_t) ((len - 2) & 0xff);
return len;
}
/* New API calls for Mitsumi CD-ROM. */ /* New API calls for Mitsumi CD-ROM. */
void void
cdrom_get_track_buffer(cdrom_t *dev, uint8_t *buf) cdrom_get_track_buffer(cdrom_t *dev, uint8_t *buf)
@@ -841,7 +1205,7 @@ cdrom_get_q(cdrom_t *dev, uint8_t *buf, int *curtoctrk, uint8_t mode)
dev->ops->get_track_info(dev, *curtoctrk, 0, &ti); dev->ops->get_track_info(dev, *curtoctrk, 0, &ti);
buf[0] = (ti.attr << 4) & 0xf0; buf[0] = (ti.attr << 4) & 0xf0;
buf[1] = ti.number; buf[1] = ti.number;
buf[2] = CD_BCD(*curtoctrk + 1); buf[2] = bin2bcd(*curtoctrk + 1);
buf[3] = ti.m; buf[3] = ti.m;
buf[4] = ti.s; buf[4] = ti.s;
buf[5] = ti.f; buf[5] = ti.f;
@@ -888,36 +1252,50 @@ cdrom_mitsumi_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len)
return 1; return 1;
} }
void uint8_t
cdrom_read_disc_info_toc(cdrom_t *dev, unsigned char *b, unsigned char track, int type) cdrom_read_disc_info_toc(cdrom_t *dev, unsigned char *b, unsigned char track, int type)
{ {
track_info_t ti; track_info_t ti;
int first_track, last_track; int first_track, last_track;
int m = 0, s = 0, f = 0;
dev->ops->get_tracks(dev, &first_track, &last_track); dev->ops->get_tracks(dev, &first_track, &last_track);
cdrom_log("Read DISC Info TOC Type = %d.\n", type); cdrom_log("Read DISC Info TOC Type = %d, track = %d, first_track = %d, last_track = %d.\n", type, track, first_track, last_track);
switch (type) { switch (type) {
case 0: case 0:
b[0] = CD_BCD(first_track); b[0] = bin2bcd(first_track);
b[1] = CD_BCD(last_track); b[1] = bin2bcd(last_track);
b[2] = 0; b[2] = 0;
b[3] = 0; b[3] = 0;
cdrom_log("CD-ROM %i: Returned Toshiba/NEC disc information (type 0) at %02i:%02i\n", dev->id, b[0], b[1]);
break; break;
case 1: case 1:
dev->ops->get_track_info(dev, 0xAA, 0, &ti); dev->ops->get_track_info(dev, 0xaa, 0, &ti);
b[0] = CD_BCD(ti.m); m = ti.m;
b[1] = CD_BCD(ti.s); s = ti.s;
b[2] = CD_BCD(ti.f); f = ti.f;
msf_to_bcd(&m, &s, &f);
b[0] = m;
b[1] = s;
b[2] = f;
b[3] = 0; b[3] = 0;
cdrom_log("CD-ROM %i: Returned Toshiba/NEC disc information (type 1) at %02i:%02i.%02i, track=%d\n", dev->id, b[0], b[1], b[2], bcd2bin(track));
break; break;
case 2: case 2:
dev->ops->get_track_info(dev, CD_DCB(track), 0, &ti); if (track > bin2bcd(last_track))
b[0] = CD_BCD(ti.m); return 0;
b[1] = CD_BCD(ti.s);
b[2] = CD_BCD(ti.f); dev->ops->get_track_info(dev, bcd2bin(track), 0, &ti);
m = ti.m;
s = ti.s;
f = ti.f;
msf_to_bcd(&m, &s, &f);
b[0] = m;
b[1] = s;
b[2] = f;
b[3] = ti.attr; b[3] = ti.attr;
cdrom_log("CD-ROM %i: Returned Toshiba disc information at %02i:%02i.%02i, track=%d\n", dev->id, b[0], b[1], b[2], CD_DCB(track)); cdrom_log("CD-ROM %i: Returned Toshiba/NEC disc information (type 2) at %02i:%02i.%02i, track=%d, m=%02i,s=%02i,f=%02i, tno=%02x.\n", dev->id, b[0], b[1], b[2], bcd2bin(track), m, s, f, ti.attr);
break; break;
case 3: case 3:
b[0] = 0x00; /*TODO: correct it further, mark it as CD-Audio/CD-ROM disc for now*/ b[0] = 0x00; /*TODO: correct it further, mark it as CD-Audio/CD-ROM disc for now*/
@@ -926,6 +1304,8 @@ cdrom_read_disc_info_toc(cdrom_t *dev, unsigned char *b, unsigned char track, in
b[3] = 0; b[3] = 0;
break; break;
} }
return 1;
} }
static int static int
@@ -1203,7 +1583,7 @@ read_mode2_xa_form2(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t
int int
cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type,
int cdrom_sector_flags, int *len) int cdrom_sector_flags, int *len, uint8_t vendor_type)
{ {
uint8_t *b, *temp_b; uint8_t *b, *temp_b;
uint32_t msf, lba; uint32_t msf, lba;
@@ -1224,8 +1604,23 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int c
lba = MSFtoLBA(m, s, f) - 150; lba = MSFtoLBA(m, s, f) - 150;
msf = sector; msf = sector;
} else { } else {
switch (vendor_type) {
case 0x00:
lba = sector; lba = sector;
msf = cdrom_lba_to_msf_accurate(sector); msf = cdrom_lba_to_msf_accurate(sector);
break;
case 0x40:
m = bcd2bin((sector >> 24) & 0xff);
s = bcd2bin((sector >> 16) & 0xff);
f = bcd2bin((sector >> 8) & 0xff);
lba = MSFtoLBA(m, s, f) - 150;
msf = sector;
break;
case 0x80:
lba = bcd2bin((sector >> 24) & 0xff);
msf = sector;
break;
}
} }
if (dev->ops->track_type) if (dev->ops->track_type)

View File

@@ -61,6 +61,7 @@
#include <86box/scsi.h> #include <86box/scsi.h>
#include <86box/scsi_device.h> #include <86box/scsi_device.h>
#include <86box/cdrom.h> #include <86box/cdrom.h>
#include <86box/cdrom_interface.h>
#include <86box/zip.h> #include <86box/zip.h>
#include <86box/mo.h> #include <86box/mo.h>
#include <86box/sound.h> #include <86box/sound.h>
@@ -904,6 +905,15 @@ load_storage_controllers(void)
p = NULL; p = NULL;
} }
p = ini_section_get_string(cat, "cdrom_interface", NULL);
if (p != NULL)
cdrom_interface_current = cdrom_interface_get_from_internal_name(p);
if (free_p) {
free(p);
p = NULL;
}
ide_ter_enabled = !!ini_section_get_int(cat, "ide_ter", 0); ide_ter_enabled = !!ini_section_get_int(cat, "ide_ter", 0);
ide_qua_enabled = !!ini_section_get_int(cat, "ide_qua", 0); ide_qua_enabled = !!ini_section_get_int(cat, "ide_qua", 0);
@@ -1321,8 +1331,13 @@ load_floppy_and_cdrom_drives(void)
sprintf(temp, "cdrom_%02i_speed", c + 1); sprintf(temp, "cdrom_%02i_speed", c + 1);
cdrom[c].speed = ini_section_get_int(cat, temp, 8); cdrom[c].speed = ini_section_get_int(cat, temp, 8);
sprintf(temp, "cdrom_%02i_early", c + 1);
cdrom[c].early = ini_section_get_int(cat, temp, 0); sprintf(temp, "cdrom_%02i_type", c + 1);
p = ini_section_get_string(cat, temp, (c == 1) ? "86BOX_CD-ROM_1.00" : "none");
cdrom_set_type(c, cdrom_get_from_internal_name(p));
if (cdrom_get_type(c) > KNOWN_CDROM_DRIVE_TYPES)
cdrom_set_type(c, KNOWN_CDROM_DRIVE_TYPES);
ini_section_delete_var(cat, temp);
/* Default values, needed for proper operation of the Settings dialog. */ /* Default values, needed for proper operation of the Settings dialog. */
cdrom[c].ide_channel = cdrom[c].scsi_device_id = c + 2; cdrom[c].ide_channel = cdrom[c].scsi_device_id = c + 2;
@@ -2470,6 +2485,12 @@ save_storage_controllers(void)
ini_section_set_string(cat, "hdc", ini_section_set_string(cat, "hdc",
hdc_get_internal_name(hdc_current)); hdc_get_internal_name(hdc_current));
if (cdrom_interface_current == 0)
ini_section_delete_var(cat, "cdrom_interface");
else
ini_section_set_string(cat, "cdrom_interface",
cdrom_interface_get_internal_name(cdrom_interface_current));
if (ide_ter_enabled == 0) if (ide_ter_enabled == 0)
ini_section_delete_var(cat, "ide_ter"); ini_section_delete_var(cat, "ide_ter");
else else
@@ -2717,17 +2738,25 @@ save_floppy_and_cdrom_drives(void)
ini_section_set_int(cat, temp, cdrom[c].speed); ini_section_set_int(cat, temp, cdrom[c].speed);
} }
sprintf(temp, "cdrom_%02i_early", c + 1); sprintf(temp, "cdrom_%02i_type", c + 1);
if ((cdrom[c].bus_type == 0) || (cdrom[c].early == 0)) { if ((cdrom[c].bus_type == 0) || (cdrom[c].bus_type == CDROM_BUS_MITSUMI)) {
ini_section_delete_var(cat, temp); ini_section_delete_var(cat, temp);
} else { } else {
ini_section_set_int(cat, temp, cdrom[c].early); ini_section_set_string(cat, temp,
cdrom_get_internal_name(cdrom_get_type(c)));
} }
sprintf(temp, "cdrom_%02i_parameters", c + 1); sprintf(temp, "cdrom_%02i_parameters", c + 1);
if (cdrom[c].bus_type == 0) { if (cdrom[c].bus_type == 0) {
ini_section_delete_var(cat, temp); ini_section_delete_var(cat, temp);
} else { } else { /*In case one wants an ATAPI drive on SCSI and vice-versa.*/
if (cdrom[c].bus_type == CDROM_BUS_ATAPI) {
if (cdrom_drive_types[cdrom_get_type(c)].bus_type == BUS_TYPE_SCSI)
cdrom[c].bus_type = CDROM_BUS_SCSI;
} else if (cdrom[c].bus_type == CDROM_BUS_SCSI) {
if (cdrom_drive_types[cdrom_get_type(c)].bus_type == BUS_TYPE_IDE)
cdrom[c].bus_type = CDROM_BUS_ATAPI;
}
sprintf(tmp2, "%u, %s", cdrom[c].sound_on, sprintf(tmp2, "%u, %s", cdrom[c].sound_on,
hdd_bus_to_string(cdrom[c].bus_type, 1)); hdd_bus_to_string(cdrom[c].bus_type, 1));
ini_section_set_string(cat, temp, tmp2); ini_section_set_string(cat, temp, tmp2);

View File

@@ -60,6 +60,54 @@ enum {
CDROM_BUS_USB CDROM_BUS_USB
}; };
#define KNOWN_CDROM_DRIVE_TYPES 30
#define BUS_TYPE_ALL 0
#define BUS_TYPE_IDE 1
#define BUS_TYPE_SCSI 2
static const struct
{
const char vendor[9];
const char model[17];
const char revision[5];
const char *name;
const char *internal_name;
const int bus_type;
} cdrom_drive_types[] =
{
{ "86BOX", "CD-ROM", "1.00", "(ATAPI/SCSI) 86BOX CD-ROM 1.00", "86BOX_CD-ROM_1.00", BUS_TYPE_ALL},
{ "AZT", "CDA46802I", "1.15", "(ATAPI) AZT CDA46802I 1.15", "AZT_CDA46802I_1.15", BUS_TYPE_IDE},
{ "BTC", "CD-ROM BCD36XH", "U1.0", "(ATAPI) BTC CD-ROM BCD36XH U1.0", "BTC_CD-ROM_BCD36XH_U1.0", BUS_TYPE_IDE},
{ "GOLDSTAR", "CRD-8160B", "3.14", "(ATAPI) GOLDSTAR CRD-8160B 3.14", "GOLDSTAR_CRD-8160B_3.14", BUS_TYPE_IDE},
{ "HITACHI", "CDR-8130", "0020", "(ATAPI) HITACHI CDR-8130 0020", "HITACHI_CDR-8130_0020", BUS_TYPE_IDE},
{ "KENWOOD", "CD-ROM UCR-421", "208E", "(ATAPI) KENWOOD CD-ROM UCR-421 208E", "KENWOOD_CD-ROM_UCR-421_208E", BUS_TYPE_IDE},
{ "MATSHITA", "CD-ROM CR-587", "7S13", "(ATAPI) MATSHITA CD-ROM CR-587 7S13", "MATSHITA_CD-ROM_CR-587_7S13", BUS_TYPE_IDE},
{ "MATSHITA", "CD-ROM CR-588", "LS15", "(ATAPI) MATSHITA CD-ROM CR-588 LS15", "MATSHITA_CD-ROM_CR-588_LS15", BUS_TYPE_IDE},
{ "MITSUMI", "CRMC-FX4820T", "D02A", "(ATAPI) MITSUMI CRMC-FX4820T D02A", "MITSUMI_CRMC-FX4820T_D02A", BUS_TYPE_IDE},
{ "NEC", "CD-ROM DRIVE:260", "1.00", "(ATAPI) NEC CD-ROM DRIVE:260 1.00", "NEC_CD-ROM_DRIVE260_1.00", BUS_TYPE_IDE},
{ "NEC", "CD-ROM DRIVE:260", "1.01", "(ATAPI) NEC CD-ROM DRIVE:260 1.01", "NEC_CD-ROM_DRIVE260_1.01", BUS_TYPE_IDE},
{ "NEC", "CDR-1300A", "1.05", "(ATAPI) NEC CDR-1300A 1.05", "NEC_CDR-1300A_1.05", BUS_TYPE_IDE},
{ "PHILIPS", "CD-ROM PCA403CD", "U31P", "(ATAPI) PHILIPS CD-ROM PCA403CD U31P", "PHILIPS_CD-ROM_PCA403CD_U31P", BUS_TYPE_IDE},
{ "SONY", "CD-ROM CDU76", "1.0i", "(ATAPI) SONY CD-ROM CDU76 1.0i", "SONY_CD-ROM_CDU76_1.0i", BUS_TYPE_IDE},
{ "SONY", "CD-ROM CDU311", "3.0h", "(ATAPI) SONY CD-ROM CDU311 3.0h", "SONY_CD-ROM_CDU311_3.0h", BUS_TYPE_IDE},
{ "TOSHIBA", "CD-ROM XM-5702B", "TA70", "(ATAPI) TOSHIBA CD-ROM XM-5702B TA70", "TOSHIBA_CD-ROM_XM-5702B_TA70", BUS_TYPE_IDE},
{ "CHINON", "CD-ROM CDS-431", "H42 ", "(SCSI) CHINON CD-ROM CDS-431 H42", "CHINON_CD-ROM_CDS-431_H42", BUS_TYPE_SCSI},
{ "DEC", "RRD45 (C) DEC", "0436", "(SCSI) DEC RRD45 0436", "DEC_RRD45_0436", BUS_TYPE_SCSI},
{ "MATSHITA", "CD-ROM CR-501", "1.0b", "(SCSI) MATSHITA CD-ROM CR-501 1.0b", "MATSHITA_CD-ROM_CR-501_1.0b", BUS_TYPE_SCSI},
{ "NEC", "CD-ROM DRIVE:74", "1.00", "(SCSI) NEC CD-ROM DRIVE:74 1.00", "NEC_CD-ROM_DRIVE74_1.00", BUS_TYPE_SCSI},
{ "NEC", "CD-ROM DRIVE:464", "1.05", "(SCSI) NEC CD-ROM DRIVE:464 1.05", "NEC_CD-ROM_DRIVE464_1.05", BUS_TYPE_SCSI},
{ "SONY", "CD-ROM CDU-541", "1.0i", "(SCSI) SONY CD-ROM CDU-541 1.0i", "SONY_CD-ROM_CDU-541_1.0i", BUS_TYPE_SCSI},
{ "SONY", "CD-ROM CDU-76S", "1.00", "(SCSI) SONY CD-ROM CDU-76S 1.00", "SONY_CD-ROM_CDU-76S_1.00", BUS_TYPE_SCSI},
{ "PHILIPS", "CDD2600", "1.07", "(SCSI) PHILIPS CDD2600 1.07", "PHILIPS_CDD2600_1.07", BUS_TYPE_SCSI},
{ "PIONEER", "CD-ROM DRM-604X", "2403", "(SCSI) PIONEER CD-ROM DRM-604X 2403", "PIONEER_CD-ROM_DRM-604X_2403", BUS_TYPE_SCSI},
{ "PLEXTOR", "CD-ROM PX-32TS", "1.03", "(SCSI) PLEXTOR CD-ROM PX-32TS 1.03", "PLEXTOR_CD-ROM_PX-32TS_1.03", BUS_TYPE_SCSI},
{ "TEAC", "CD-R55S", "1.0R", "(SCSI) TEAC CD-R55S 1.0R", "TEAC_CD-R55S_1.0R", BUS_TYPE_SCSI},
{ "TOSHIBA", "CD-ROM DRIVE:XM", "3433", "(SCSI) TOSHIBA CD-ROM DRIVE:XM 3433", "TOSHIBA_CD-ROM_DRIVEXM_3433", BUS_TYPE_SCSI},
{ "TOSHIBA", "CD-ROM XM-3301TA", "0272", "(SCSI) TOSHIBA CD-ROM XM-3301TA 0272", "TOSHIBA_CD-ROM_XM-3301TA_0272", BUS_TYPE_SCSI},
{ "TOSHIBA", "CD-ROM XM-5701TA", "3136", "(SCSI) TOSHIBA CD-ROM XM-5701TA 3136", "TOSHIBA_CD-ROM_XM-5701TA_3136", BUS_TYPE_SCSI},
{ "", "", "", "", "", -1},
};
/* To shut up the GCC compilers. */ /* To shut up the GCC compilers. */
struct cdrom; struct cdrom;
@@ -113,7 +161,7 @@ typedef struct cdrom {
uint32_t sound_on, cdrom_capacity, uint32_t sound_on, cdrom_capacity,
early, seek_pos, early, seek_pos,
seek_diff, cd_end; seek_diff, cd_end, type;
int host_drive, prev_host_drive, int host_drive, prev_host_drive,
cd_buflen, audio_op; cd_buflen, audio_op;
@@ -132,6 +180,13 @@ typedef struct cdrom {
extern cdrom_t cdrom[CDROM_NUM]; extern cdrom_t cdrom[CDROM_NUM];
extern char *cdrom_getname(int type);
extern char *cdrom_get_internal_name(int type);
extern int cdrom_get_from_internal_name(char *s);
extern void cdrom_set_type(int model, int type);
extern int cdrom_get_type(int model);
extern int cdrom_lba_to_msf_accurate(int lba); extern int cdrom_lba_to_msf_accurate(int lba);
extern double cdrom_seek_time(cdrom_t *dev); extern double cdrom_seek_time(cdrom_t *dev);
extern void cdrom_stop(cdrom_t *dev); extern void cdrom_stop(cdrom_t *dev);
@@ -139,20 +194,24 @@ extern int cdrom_is_pre(cdrom_t *dev, uint32_t lba);
extern int cdrom_audio_callback(cdrom_t *dev, int16_t *output, int len); extern int cdrom_audio_callback(cdrom_t *dev, int16_t *output, int len);
extern uint8_t cdrom_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len, int ismsf); extern uint8_t cdrom_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len, int ismsf);
extern uint8_t cdrom_audio_track_search(cdrom_t *dev, uint32_t pos, int type, uint8_t playbit); extern uint8_t cdrom_audio_track_search(cdrom_t *dev, uint32_t pos, int type, uint8_t playbit);
extern uint8_t cdrom_toshiba_audio_play(cdrom_t *dev, uint32_t pos, int type); extern uint8_t cdrom_audio_play_toshiba(cdrom_t *dev, uint32_t pos, int type);
extern void cdrom_audio_pause_resume(cdrom_t *dev, uint8_t resume); extern void cdrom_audio_pause_resume(cdrom_t *dev, uint8_t resume);
extern uint8_t cdrom_audio_scan(cdrom_t *dev, uint32_t pos, int type);
extern uint8_t cdrom_get_audio_status_sony(cdrom_t *dev, uint8_t *b, int msf);
extern uint8_t cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, int msf); extern uint8_t cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, int msf);
extern void cdrom_get_current_subchannel_sony(cdrom_t *dev, uint8_t *b, int msf);
extern uint8_t cdrom_get_current_subcodeq_playstatus(cdrom_t *dev, uint8_t *b); extern uint8_t cdrom_get_current_subcodeq_playstatus(cdrom_t *dev, uint8_t *b);
extern int cdrom_read_toc(cdrom_t *dev, unsigned char *b, int type, extern int cdrom_read_toc(cdrom_t *dev, unsigned char *b, int type,
unsigned char start_track, int msf, int max_len); unsigned char start_track, int msf, int max_len);
extern int cdrom_read_toc_sony(cdrom_t *dev, unsigned char *b, unsigned char start_track, int msf, int max_len);
extern void cdrom_get_track_buffer(cdrom_t *dev, uint8_t *buf); extern void cdrom_get_track_buffer(cdrom_t *dev, uint8_t *buf);
extern void cdrom_get_q(cdrom_t *dev, uint8_t *buf, int *curtoctrk, uint8_t mode); extern void cdrom_get_q(cdrom_t *dev, uint8_t *buf, int *curtoctrk, uint8_t mode);
extern uint8_t cdrom_mitsumi_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len); extern uint8_t cdrom_mitsumi_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len);
extern int cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, extern int cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf,
int cdrom_sector_type, int cdrom_sector_flags, int *len); int cdrom_sector_type, int cdrom_sector_flags, int *len, uint8_t vendor_type);
extern void cdrom_read_disc_info_toc(cdrom_t *dev, unsigned char *b, unsigned char track, int type); extern uint8_t cdrom_read_disc_info_toc(cdrom_t *dev, unsigned char *b, unsigned char track, int type);
extern void cdrom_seek(cdrom_t *dev, uint32_t pos); extern void cdrom_seek(cdrom_t *dev, uint32_t pos, uint8_t vendor_type);
extern void cdrom_close_handler(uint8_t id); extern void cdrom_close_handler(uint8_t id);
extern void cdrom_insert(uint8_t id); extern void cdrom_insert(uint8_t id);

View File

@@ -0,0 +1,31 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Definitions for the common CD-ROM interface controller handler.
*
*
*
* Authors: TheCollector1995
*
* Copyright 2022 TheCollector1995.
*/
#ifndef EMU_CDROM_INTERFACE_H
#define EMU_CDROM_INTERFACE_H
extern int cdrom_interface_current;
extern void cdrom_interface_reset(void);
extern char *cdrom_interface_get_internal_name(int cdinterface);
extern int cdrom_interface_get_from_internal_name(char *s);
extern int cdrom_interface_has_config(int cdinterface);
extern const device_t *cdrom_interface_get_device(int cdinterface);
extern int cdrom_interface_get_flags(int cdinterface);
extern int cdrom_interface_available(int cdinterface);
#endif /*EMU_CDROM_INTERFACE_H*/

View File

@@ -49,6 +49,10 @@ typedef struct {
packet_len, pos; packet_len, pos;
double callback; double callback;
mode_sense_pages_t ms_pages_saved_sony;
mode_sense_pages_t ms_drive_status_pages_saved;
int sony_vendor;
} scsi_cdrom_t; } scsi_cdrom_t;
#endif #endif

View File

@@ -53,6 +53,8 @@
#define GPCMD_SEEK_6 0x0b #define GPCMD_SEEK_6 0x0b
#define GPCMD_IOMEGA_SET_PROTECTION_MODE 0x0c #define GPCMD_IOMEGA_SET_PROTECTION_MODE 0x0c
#define GPCMD_IOMEGA_EJECT 0x0d /* ATAPI only? */ #define GPCMD_IOMEGA_EJECT 0x0d /* ATAPI only? */
#define GPCMD_NO_OPERATION_TOSHIBA 0x0d /* Toshiba Vendor Unique command */
#define GPCMD_NO_OPERATION_NEC 0x0d /* NEC Vendor Unique command */
#define GPCMD_INQUIRY 0x12 #define GPCMD_INQUIRY 0x12
#define GPCMD_VERIFY_6 0x13 #define GPCMD_VERIFY_6 0x13
#define GPCMD_MODE_SELECT_6 0x15 #define GPCMD_MODE_SELECT_6 0x15
@@ -64,7 +66,7 @@
#define GPCMD_PREVENT_REMOVAL 0x1e #define GPCMD_PREVENT_REMOVAL 0x1e
#define GPCMD_READ_FORMAT_CAPACITIES 0x23 #define GPCMD_READ_FORMAT_CAPACITIES 0x23
#define GPCMD_READ_CDROM_CAPACITY 0x25 #define GPCMD_READ_CDROM_CAPACITY 0x25
#define GPCMD_CHINON_UNKNOWN 0x26 #define GPCMD_UNKNOWN_CHINON 0x26 /*Chinon Vendor Unique command*/
#define GPCMD_READ_10 0x28 #define GPCMD_READ_10 0x28
#define GPCMD_READ_GENERATION 0x29 #define GPCMD_READ_GENERATION 0x29
#define GPCMD_WRITE_10 0x2a #define GPCMD_WRITE_10 0x2a
@@ -100,23 +102,51 @@
#define GPCMD_PLAY_CD_OLD 0xb4 #define GPCMD_PLAY_CD_OLD 0xb4
#define GPCMD_READ_CD_OLD 0xb8 #define GPCMD_READ_CD_OLD 0xb8
#define GPCMD_READ_CD_MSF 0xb9 #define GPCMD_READ_CD_MSF 0xb9
#define GPCMD_SCAN 0xba #define GPCMD_AUDIO_SCAN 0xba
#define GPCMD_SET_SPEED 0xbb #define GPCMD_SET_SPEED 0xbb
#define GPCMD_PLAY_CD 0xbc #define GPCMD_PLAY_CD 0xbc
#define GPCMD_MECHANISM_STATUS 0xbd #define GPCMD_MECHANISM_STATUS 0xbd
#define GPCMD_READ_CD 0xbe #define GPCMD_READ_CD 0xbe
#define GPCMD_SEND_DVD_STRUCTURE 0xbf /* This is for writing only, irrelevant to 86Box. */ #define GPCMD_SEND_DVD_STRUCTURE 0xbf /* This is for writing only, irrelevant to 86Box. */
#define GPCMD_CHINON_EJECT 0xc0 /* Chinon Vendor Unique command */ #define GPCMD_EJECT_CHINON 0xc0 /* Chinon Vendor Unique command */
#define GPCMD_AUDIO_TRACK_SEARCH 0xc0 /* Toshiba Vendor Unique command */ #define GPCMD_AUDIO_TRACK_SEARCH_TOSHIBA 0xc0 /* Toshiba Vendor Unique command */
#define GPCMD_TOSHIBA_PLAY_AUDIO 0xc1 /* Toshiba Vendor Unique command */ #define GPCMD_UNKNOWN_SONY 0xc0 /* Sony Vendor Unique command */
#define GPCMD_PLAY_AUDIO_TOSHIBA 0xc1 /* Toshiba Vendor Unique command */
#define GPCMD_READ_TOC_SONY 0xc1 /* Sony Vendor Unique command */
#define GPCMD_PAUSE_RESUME_ALT 0xc2 #define GPCMD_PAUSE_RESUME_ALT 0xc2
#define GPCMD_STILL 0xc2 /* Toshiba Vendor Unique command */ #define GPCMD_READ_SUBCHANNEL_MATSUSHITA 0xc2 /* Matsushita Vendor Unique command */
#define GPCMD_CADDY_EJECT 0xc4 /* Toshiba Vendor Unique command */ #define GPCMD_READ_SUBCHANNEL_SONY 0xc2 /* Sony Vendor Unique command */
#define GPCMD_CHINON_STOP 0xc6 /* Chinon Vendor Unique command */ #define GPCMD_STILL_TOSHIBA 0xc2 /* Toshiba Vendor Unique command */
#define GPCMD_READ_SUBCODEQ_PLAYING_STATUS 0xc6 /* Toshiba Vendor Unique command */ #define GPCMD_READ_TOC_MATSUSHITA 0xc3 /* Matsushita Vendor Unique command */
#define GPCMD_READ_HEADER_SONY 0xc3 /* Sony Vendor Unique command */
#define GPCMD_SET_STOP_TIME_TOSHIBA 0xc3 /* Toshiba Vendor Unique command */
#define GPCMD_READ_HEADER_MATSUSHITA 0xc4 /* Matsushita Vendor Unique command */
#define GPCMD_PLAYBACK_STATUS_TOSHIBA 0xc4 /* Sony Vendor Unique command */
#define GPCMD_CADDY_EJECT_TOSHIBA 0xc4 /* Toshiba Vendor Unique command */
#define GPCMD_PAUSE_SONY 0xc5 /* Sony Vendor Unique command */
#define GPCMD_PLAY_AUDIO_MATSUSHITA 0xc5 /* Matsushita Vendor Unique command */
#define GPCMD_STOP_CHINON 0xc6 /* Chinon Vendor Unique command */
#define GPCMD_PLAT_TRACK_SONY 0xc6 /* Sony Vendor Unique command */
#define GPCMD_READ_SUBCODEQ_PLAYING_STATUS_TOSHIBA 0xc6 /* Toshiba Vendor Unique command */
#define GPCMD_PLAY_AUDIO_MSF_MATSUSHITA 0xc7 /* Matsushita Vendor Unique command*/
#define GPCMD_PLAY_MSF_SONY 0xc7 /* Sony Vendor Unique command*/
#define GPCMD_READ_DISC_INFORMATION_TOSHIBA 0xc7 /* Toshiba Vendor Unique command */ #define GPCMD_READ_DISC_INFORMATION_TOSHIBA 0xc7 /* Toshiba Vendor Unique command */
#define GPCMD_SCAN_ALT 0xcd /* Should be equivalent to 0xba */ #define GPCMD_PLAY_AUDIO_TRACK_INDEX_MATSUSHITA 0xc8 /* Matsushita Vendor Unique command */
#define GPCMD_PLAY_AUDIO_SONY 0xc8 /* Sony Vendor Unique command */
#define GPCMD_PLAY_AUDIO_TRACK_RELATIVE_10_MATSUSHITA 0xc9 /*Matsushita Vendor Unique command */
#define GPCMD_PLAYBACK_CONTROL_SONY 0xc9 /* Sony Vendor Unique command */
#define GPCMD_PAUSE_RESUME_MATSUSHITA 0xcb /* Matsushita Vendor Unique command */
#define GPCMD_SCAN_PIONEER 0xcd /* Should be equivalent to 0xba */
#define GPCMD_AUDIO_TRACK_SEARCH_NEC 0xd8 /* NEC Vendor Unique command */
#define GPCMD_PLAY_AUDIO_NEC 0xd9 /* NEC Vendor Unique command */
#define GPCMD_STILL_NEC 0xda /* NEC Vendor Unique command */
#define GPCMD_SET_SPEED_ALT 0xda /* Should be equivalent to 0xbb */ #define GPCMD_SET_SPEED_ALT 0xda /* Should be equivalent to 0xbb */
#define GPCMD_SET_STOP_TIME_NEC 0xdb /* NEC Vendor Unique command */
#define GPCMD_CADDY_EJECT_NEC 0xdc /* NEC Vendor Unique command */
#define GPCMD_READ_SUBCODEQ_PLAYING_STATUS_NEC 0xdd /* NEC Vendor Unique command */
#define GPCMD_READ_DISC_INFORMATION_NEC 0xde /* NEC Vendor Unique command */
#define GPCMD_PLAY_AUDIO_12_MATSUSHITA 0xe5 /* Matsushita Vendor Unique command */
#define GPCMD_PLAY_AUDIO_TRACK_RELATIVE_12_MATSUSHITA 0xe9 /* Matsushita Vendor Unique command */
/* Mode page codes for mode sense/set */ /* Mode page codes for mode sense/set */
#define GPMODE_R_W_ERROR_PAGE 0x01 #define GPMODE_R_W_ERROR_PAGE 0x01
@@ -125,6 +155,8 @@
#define GPMODE_RIGID_DISK_PAGE 0x04 /* Rigid disk geometry page */ #define GPMODE_RIGID_DISK_PAGE 0x04 /* Rigid disk geometry page */
#define GPMODE_FLEXIBLE_DISK_PAGE 0x05 #define GPMODE_FLEXIBLE_DISK_PAGE 0x05
#define GPMODE_CACHING_PAGE 0x08 #define GPMODE_CACHING_PAGE 0x08
#define GPMODE_CDROM_PAGE_SONY 0x08
#define GPMODE_CDROM_AUDIO_PAGE_SONY 0x09
#define GPMODE_CDROM_PAGE 0x0d #define GPMODE_CDROM_PAGE 0x0d
#define GPMODE_CDROM_AUDIO_PAGE 0x0e #define GPMODE_CDROM_AUDIO_PAGE 0x0e
#define GPMODE_CAPABILITIES_PAGE 0x2a #define GPMODE_CAPABILITIES_PAGE 0x2a
@@ -139,6 +171,8 @@
#define GPMODEP_RIGID_DISK_PAGE 0x0000000000000010LL #define GPMODEP_RIGID_DISK_PAGE 0x0000000000000010LL
#define GPMODEP_FLEXIBLE_DISK_PAGE 0x0000000000000020LL #define GPMODEP_FLEXIBLE_DISK_PAGE 0x0000000000000020LL
#define GPMODEP_CACHING_PAGE 0x0000000000000100LL #define GPMODEP_CACHING_PAGE 0x0000000000000100LL
#define GPMODEP_CDROM_PAGE_SONY 0x0000000000000200LL
#define GPMODEP_CDROM_AUDIO_PAGE_SONY 0x0000000000000400LL
#define GPMODEP_CDROM_PAGE 0x0000000000002000LL #define GPMODEP_CDROM_PAGE 0x0000000000002000LL
#define GPMODEP_CDROM_AUDIO_PAGE 0x0000000000004000LL #define GPMODEP_CDROM_AUDIO_PAGE 0x0000000000004000LL
#define GPMODEP_CAPABILITIES_PAGE 0x0000040000000000LL #define GPMODEP_CAPABILITIES_PAGE 0x0000040000000000LL

View File

@@ -20,6 +20,7 @@
extern "C" { extern "C" {
#include <86box/hdd.h> #include <86box/hdd.h>
#include <86box/cdrom.h>
} }
#include <QAbstractItemModel> #include <QAbstractItemModel>
@@ -48,14 +49,16 @@ void
Harddrives::populateRemovableBuses(QAbstractItemModel *model) Harddrives::populateRemovableBuses(QAbstractItemModel *model)
{ {
model->removeRows(0, model->rowCount()); model->removeRows(0, model->rowCount());
model->insertRows(0, 3); model->insertRows(0, 4);
model->setData(model->index(0, 0), QObject::tr("Disabled")); model->setData(model->index(0, 0), QObject::tr("Disabled"));
model->setData(model->index(1, 0), QObject::tr("ATAPI")); model->setData(model->index(1, 0), QObject::tr("ATAPI"));
model->setData(model->index(2, 0), QObject::tr("SCSI")); model->setData(model->index(2, 0), QObject::tr("SCSI"));
model->setData(model->index(3, 0), QObject::tr("Mitsumi"));
model->setData(model->index(0, 0), HDD_BUS_DISABLED, Qt::UserRole); model->setData(model->index(0, 0), HDD_BUS_DISABLED, Qt::UserRole);
model->setData(model->index(1, 0), HDD_BUS_ATAPI, Qt::UserRole); model->setData(model->index(1, 0), HDD_BUS_ATAPI, Qt::UserRole);
model->setData(model->index(2, 0), HDD_BUS_SCSI, Qt::UserRole); model->setData(model->index(2, 0), HDD_BUS_SCSI, Qt::UserRole);
model->setData(model->index(3, 0), CDROM_BUS_MITSUMI, Qt::UserRole);
} }
void void
@@ -143,6 +146,9 @@ Harddrives::BusChannelName(uint8_t bus, uint8_t channel)
case HDD_BUS_SCSI: case HDD_BUS_SCSI:
busName = QString("SCSI (%1:%2)").arg(channel >> 4).arg(channel & 15, 2, 10, QChar('0')); busName = QString("SCSI (%1:%2)").arg(channel >> 4).arg(channel & 15, 2, 10, QChar('0'));
break; break;
case CDROM_BUS_MITSUMI:
busName = QString("Mitsumi");
break;
} }
return busName; return busName;

View File

@@ -29,6 +29,7 @@ extern uint64_t tsc;
#include <86box/cartridge.h> #include <86box/cartridge.h>
#include <86box/cassette.h> #include <86box/cassette.h>
#include <86box/cdrom.h> #include <86box/cdrom.h>
#include <86box/cdrom_interface.h>
#include <86box/fdd.h> #include <86box/fdd.h>
#include <86box/hdc.h> #include <86box/hdc.h>
#include <86box/scsi.h> #include <86box/scsi.h>
@@ -300,6 +301,8 @@ MachineStatus::iterateCDROM(const std::function<void(int)> &cb)
continue; continue;
if ((cdrom[i].bus_type == CDROM_BUS_SCSI) && !hasSCSI() && (scsi_card_current[0] == 0) && (scsi_card_current[1] == 0) && (scsi_card_current[2] == 0) && (scsi_card_current[3] == 0)) if ((cdrom[i].bus_type == CDROM_BUS_SCSI) && !hasSCSI() && (scsi_card_current[0] == 0) && (scsi_card_current[1] == 0) && (scsi_card_current[2] == 0) && (scsi_card_current[3] == 0))
continue; continue;
if ((cdrom[i].bus_type == CDROM_BUS_MITSUMI) && (cdrom_interface_current == 0))
continue;
if (cdrom[i].bus_type != 0) { if (cdrom[i].bus_type != 0) {
cb(i); cb(i);
} }

View File

@@ -593,6 +593,9 @@ MediaMenu::cdromUpdateMenu(int i)
case CDROM_BUS_SCSI: case CDROM_BUS_SCSI:
busName = "SCSI"; busName = "SCSI";
break; break;
case CDROM_BUS_MITSUMI:
busName = "Mitsumi";
break;
} }
// menu->setTitle(tr("CD-ROM %1 (%2): %3").arg(QString::number(i+1), busName, name.isEmpty() ? tr("(empty)") : name)); // menu->setTitle(tr("CD-ROM %1 (%2): %3").arg(QString::number(i+1), busName, name.isEmpty() ? tr("(empty)") : name));

View File

@@ -20,6 +20,15 @@
#include "ui_qt_settingsfloppycdrom.h" #include "ui_qt_settingsfloppycdrom.h"
extern "C" { extern "C" {
#include <inttypes.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/timer.h> #include <86box/timer.h>
#include <86box/fdd.h> #include <86box/fdd.h>
#include <86box/cdrom.h> #include <86box/cdrom.h>
@@ -59,6 +68,7 @@ setCDROMBus(QAbstractItemModel *model, const QModelIndex &idx, uint8_t bus, uint
break; break;
case CDROM_BUS_ATAPI: case CDROM_BUS_ATAPI:
case CDROM_BUS_SCSI: case CDROM_BUS_SCSI:
case CDROM_BUS_MITSUMI:
icon = ProgSettings::loadIcon("/cdrom.ico"); icon = ProgSettings::loadIcon("/cdrom.ico");
break; break;
} }
@@ -88,6 +98,18 @@ setCDROMEarly(QAbstractItemModel *model, const QModelIndex &idx, bool early)
model->setData(i, early, Qt::UserRole); model->setData(i, early, Qt::UserRole);
} }
static void
setCDROMType(QAbstractItemModel *model, const QModelIndex &idx, int type)
{
auto i = idx.siblingAtColumn(2);
if (idx.siblingAtColumn(0).data(Qt::UserRole).toUInt() == CDROM_BUS_DISABLED) {
model->setData(i, QCoreApplication::translate("", "None"));
} else if (idx.siblingAtColumn(0).data(Qt::UserRole).toUInt() != CDROM_BUS_MITSUMI) {
model->setData(i, QObject::tr(cdrom_getname(type)));
}
model->setData(i, type, Qt::UserRole);
}
SettingsFloppyCDROM::SettingsFloppyCDROM(QWidget *parent) SettingsFloppyCDROM::SettingsFloppyCDROM(QWidget *parent)
: QWidget(parent) : QWidget(parent)
, ui(new Ui::SettingsFloppyCDROM) , ui(new Ui::SettingsFloppyCDROM)
@@ -134,18 +156,36 @@ SettingsFloppyCDROM::SettingsFloppyCDROM(QWidget *parent)
Models::AddEntry(model, QString("%1x").arg(i + 1), i + 1); Models::AddEntry(model, QString("%1x").arg(i + 1), i + 1);
} }
model = ui->comboBoxCDROMType->model();
i = 0;
while (true) {
QString name = tr(cdrom_getname(i));
if (name.isEmpty()) {
break;
}
Models::AddEntry(model, name, i);
++i;
}
model = new QStandardItemModel(0, 3, this); model = new QStandardItemModel(0, 3, this);
ui->tableViewCDROM->setModel(model); ui->tableViewCDROM->setModel(model);
model->setHeaderData(0, Qt::Horizontal, tr("Bus")); model->setHeaderData(0, Qt::Horizontal, tr("Bus"));
model->setHeaderData(1, Qt::Horizontal, tr("Speed")); model->setHeaderData(1, Qt::Horizontal, tr("Speed"));
model->setHeaderData(2, Qt::Horizontal, tr("Earlier drive")); model->setHeaderData(2, Qt::Horizontal, tr("Type"));
model->insertRows(0, CDROM_NUM); model->insertRows(0, CDROM_NUM);
for (int i = 0; i < CDROM_NUM; i++) { for (int i = 0; i < CDROM_NUM; i++) {
auto idx = model->index(i, 0); auto idx = model->index(i, 0);
int type = cdrom_get_type(i);
setCDROMBus(model, idx, cdrom[i].bus_type, cdrom[i].res); setCDROMBus(model, idx, cdrom[i].bus_type, cdrom[i].res);
setCDROMSpeed(model, idx.siblingAtColumn(1), cdrom[i].speed); setCDROMSpeed(model, idx.siblingAtColumn(1), cdrom[i].speed);
setCDROMEarly(model, idx.siblingAtColumn(2), cdrom[i].early); setCDROMType(model, idx.siblingAtColumn(2), type);
Harddrives::busTrackClass->device_track(1, DEV_CDROM, cdrom[i].bus_type, cdrom[i].bus_type == CDROM_BUS_ATAPI ? cdrom[i].ide_channel : cdrom[i].scsi_device_id); if (cdrom[i].bus_type == CDROM_BUS_ATAPI)
Harddrives::busTrackClass->device_track(1, DEV_CDROM, cdrom[i].bus_type, cdrom[i].ide_channel);
else if (cdrom[i].bus_type == CDROM_BUS_SCSI)
Harddrives::busTrackClass->device_track(1, DEV_CDROM, cdrom[i].bus_type, cdrom[i].scsi_device_id);
else if (cdrom[i].bus_type == CDROM_BUS_MITSUMI)
Harddrives::busTrackClass->device_track(1, DEV_CDROM, cdrom[i].bus_type, 0);
} }
ui->tableViewCDROM->resizeColumnsToContents(); ui->tableViewCDROM->resizeColumnsToContents();
ui->tableViewCDROM->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); ui->tableViewCDROM->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
@@ -183,7 +223,7 @@ SettingsFloppyCDROM::save()
cdrom[i].bus_type = model->index(i, 0).data(Qt::UserRole).toUInt(); cdrom[i].bus_type = model->index(i, 0).data(Qt::UserRole).toUInt();
cdrom[i].res = model->index(i, 0).data(Qt::UserRole + 1).toUInt(); cdrom[i].res = model->index(i, 0).data(Qt::UserRole + 1).toUInt();
cdrom[i].speed = model->index(i, 1).data(Qt::UserRole).toUInt(); cdrom[i].speed = model->index(i, 1).data(Qt::UserRole).toUInt();
cdrom[i].early = model->index(i, 2).data(Qt::UserRole).toUInt(); cdrom_set_type(i, model->index(i, 2).data(Qt::UserRole).toInt());
} }
} }
@@ -202,12 +242,12 @@ SettingsFloppyCDROM::onCDROMRowChanged(const QModelIndex &current)
uint8_t bus = current.siblingAtColumn(0).data(Qt::UserRole).toUInt(); uint8_t bus = current.siblingAtColumn(0).data(Qt::UserRole).toUInt();
uint8_t channel = current.siblingAtColumn(0).data(Qt::UserRole + 1).toUInt(); uint8_t channel = current.siblingAtColumn(0).data(Qt::UserRole + 1).toUInt();
uint8_t speed = current.siblingAtColumn(1).data(Qt::UserRole).toUInt(); uint8_t speed = current.siblingAtColumn(1).data(Qt::UserRole).toUInt();
bool early = current.siblingAtColumn(2).data(Qt::UserRole).toBool(); int type = current.siblingAtColumn(2).data(Qt::UserRole).toInt();
ui->comboBoxBus->setCurrentIndex(-1); ui->comboBoxBus->setCurrentIndex(-1);
auto *model = ui->comboBoxBus->model(); auto* model = ui->comboBoxBus->model();
auto match = model->match(model->index(0, 0), Qt::UserRole, bus); auto match = model->match(model->index(0, 0), Qt::UserRole, bus);
if (!match.isEmpty()) { if (! match.isEmpty()) {
ui->comboBoxBus->setCurrentIndex(match.first().row()); ui->comboBoxBus->setCurrentIndex(match.first().row());
} }
@@ -218,7 +258,7 @@ SettingsFloppyCDROM::onCDROMRowChanged(const QModelIndex &current)
} }
ui->comboBoxSpeed->setCurrentIndex(speed == 0 ? 7 : speed - 1); ui->comboBoxSpeed->setCurrentIndex(speed == 0 ? 7 : speed - 1);
ui->checkBoxEarlierDrive->setChecked(early); ui->comboBoxCDROMType->setCurrentIndex(type);
} }
void void
@@ -250,9 +290,10 @@ SettingsFloppyCDROM::on_comboBoxBus_currentIndexChanged(int index)
int bus = ui->comboBoxBus->currentData().toInt(); int bus = ui->comboBoxBus->currentData().toInt();
bool enabled = (bus != CDROM_BUS_DISABLED); bool enabled = (bus != CDROM_BUS_DISABLED);
ui->comboBoxChannel->setEnabled(enabled); ui->comboBoxChannel->setEnabled((bus == CDROM_BUS_MITSUMI) ? 0 : enabled);
ui->comboBoxSpeed->setEnabled(enabled); ui->comboBoxSpeed->setEnabled((bus == CDROM_BUS_MITSUMI) ? 0 : enabled);
ui->checkBoxEarlierDrive->setEnabled(enabled); ui->comboBoxCDROMType->setEnabled((bus == CDROM_BUS_MITSUMI) ? 0 : enabled);
Harddrives::populateBusChannels(ui->comboBoxChannel->model(), bus); Harddrives::populateBusChannels(ui->comboBoxChannel->model(), bus);
} }
@@ -267,13 +308,25 @@ void
SettingsFloppyCDROM::on_comboBoxBus_activated(int) SettingsFloppyCDROM::on_comboBoxBus_activated(int)
{ {
auto i = ui->tableViewCDROM->selectionModel()->currentIndex().siblingAtColumn(0); auto i = ui->tableViewCDROM->selectionModel()->currentIndex().siblingAtColumn(0);
uint8_t bus_type = ui->comboBoxBus->currentData().toUInt();
Harddrives::busTrackClass->device_track(0, DEV_CDROM, ui->tableViewCDROM->model()->data(i, Qt::UserRole).toInt(), ui->tableViewCDROM->model()->data(i, Qt::UserRole + 1).toInt()); Harddrives::busTrackClass->device_track(0, DEV_CDROM, ui->tableViewCDROM->model()->data(i, Qt::UserRole).toInt(), ui->tableViewCDROM->model()->data(i, Qt::UserRole + 1).toInt());
ui->comboBoxChannel->setCurrentIndex(ui->comboBoxBus->currentData().toUInt() == CDROM_BUS_ATAPI ? Harddrives::busTrackClass->next_free_ide_channel() : Harddrives::busTrackClass->next_free_scsi_id()); if (bus_type == CDROM_BUS_ATAPI)
ui->comboBoxChannel->setCurrentIndex(Harddrives::busTrackClass->next_free_ide_channel());
else if (bus_type == CDROM_BUS_SCSI)
ui->comboBoxChannel->setCurrentIndex(Harddrives::busTrackClass->next_free_scsi_id());
else if (bus_type == CDROM_BUS_MITSUMI)
ui->comboBoxChannel->setCurrentIndex(0);
setCDROMBus( setCDROMBus(
ui->tableViewCDROM->model(), ui->tableViewCDROM->model(),
ui->tableViewCDROM->selectionModel()->currentIndex(), ui->tableViewCDROM->selectionModel()->currentIndex(),
ui->comboBoxBus->currentData().toUInt(), bus_type,
ui->comboBoxChannel->currentData().toUInt()); ui->comboBoxChannel->currentData().toUInt());
setCDROMType(
ui->tableViewCDROM->model(),
ui->tableViewCDROM->selectionModel()->currentIndex(),
ui->comboBoxCDROMType->currentData().toUInt());
Harddrives::busTrackClass->device_track(1, DEV_CDROM, ui->tableViewCDROM->model()->data(i, Qt::UserRole).toInt(), ui->tableViewCDROM->model()->data(i, Qt::UserRole + 1).toInt()); Harddrives::busTrackClass->device_track(1, DEV_CDROM, ui->tableViewCDROM->model()->data(i, Qt::UserRole).toInt(), ui->tableViewCDROM->model()->data(i, Qt::UserRole + 1).toInt());
} }
@@ -291,8 +344,12 @@ SettingsFloppyCDROM::on_comboBoxChannel_activated(int)
} }
void void
SettingsFloppyCDROM::on_checkBoxEarlierDrive_stateChanged(int arg1) SettingsFloppyCDROM::on_comboBoxCDROMType_activated(int)
{ {
auto idx = ui->tableViewCDROM->selectionModel()->currentIndex(); setCDROMType(
setCDROMEarly(ui->tableViewCDROM->model(), idx.siblingAtColumn(2), (arg1 == Qt::Checked) ? true : false); ui->tableViewCDROM->model(),
ui->tableViewCDROM->selectionModel()->currentIndex(),
ui->comboBoxCDROMType->currentData().toUInt());
ui->tableViewCDROM->resizeColumnsToContents();
ui->tableViewCDROM->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
} }

View File

@@ -17,6 +17,7 @@ public:
void save(); void save();
private slots: private slots:
void on_comboBoxCDROMType_activated(int index);
void on_comboBoxChannel_activated(int index); void on_comboBoxChannel_activated(int index);
void on_comboBoxBus_activated(int index); void on_comboBoxBus_activated(int index);
void on_comboBoxSpeed_activated(int index); void on_comboBoxSpeed_activated(int index);
@@ -27,8 +28,6 @@ private slots:
void onFloppyRowChanged(const QModelIndex &current); void onFloppyRowChanged(const QModelIndex &current);
void onCDROMRowChanged(const QModelIndex &current); void onCDROMRowChanged(const QModelIndex &current);
void on_checkBoxEarlierDrive_stateChanged(int arg1);
private: private:
Ui::SettingsFloppyCDROM *ui; Ui::SettingsFloppyCDROM *ui;
}; };

View File

@@ -115,16 +115,20 @@
</item> </item>
<item> <item>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Bus:</string>
</property>
</widget>
</item>
<item row="0" column="2"> <item row="0" column="2">
<widget class="QLabel" name="label_5"> <widget class="QLabel" name="label_7">
<property name="text"> <property name="text">
<string>Channel:</string> <string>Channel:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1">
<widget class="QComboBox" name="comboBoxBus"/>
</item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QLabel" name="label_4"> <widget class="QLabel" name="label_4">
<property name="text"> <property name="text">
@@ -132,25 +136,24 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="0"> <item row="2" column="0">
<widget class="QLabel" name="label_3"> <widget class="QLabel" name="label_5">
<property name="text"> <property name="text">
<string>Bus:</string> <string>Type:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1">
<widget class="QComboBox" name="comboBoxBus"/>
</item>
<item row="0" column="3"> <item row="0" column="3">
<widget class="QComboBox" name="comboBoxChannel"/> <widget class="QComboBox" name="comboBoxChannel"/>
</item> </item>
<item row="1" column="1"> <item row="1" column="1">
<widget class="QComboBox" name="comboBoxSpeed"/> <widget class="QComboBox" name="comboBoxSpeed"/>
</item> </item>
<item row="1" column="2"> <item row="2" column="1" colspan="3">
<widget class="QCheckBox" name="checkBoxEarlierDrive"> <widget class="QComboBox" name="comboBoxCDROMType"/>
<property name="text">
<string>Earlier drive</string>
</property>
</widget>
</item> </item>
</layout> </layout>
</item> </item>

View File

@@ -25,6 +25,7 @@ extern "C" {
#include <86box/hdc.h> #include <86box/hdc.h>
#include <86box/hdc_ide.h> #include <86box/hdc_ide.h>
#include <86box/fdc_ext.h> #include <86box/fdc_ext.h>
#include <86box/cdrom_interface.h>
#include <86box/scsi.h> #include <86box/scsi.h>
#include <86box/scsi_device.h> #include <86box/scsi_device.h>
#include <86box/cassette.h> #include <86box/cassette.h>
@@ -59,6 +60,7 @@ SettingsStorageControllers::save()
} }
hdc_current = ui->comboBoxHD->currentData().toInt(); hdc_current = ui->comboBoxHD->currentData().toInt();
fdc_type = ui->comboBoxFD->currentData().toInt(); fdc_type = ui->comboBoxFD->currentData().toInt();
cdrom_interface_current = ui->comboBoxCDInterface->currentData().toInt();
ide_ter_enabled = ui->checkBoxTertiaryIDE->isChecked() ? 1 : 0; ide_ter_enabled = ui->checkBoxTertiaryIDE->isChecked() ? 1 : 0;
ide_qua_enabled = ui->checkBoxQuaternaryIDE->isChecked() ? 1 : 0; ide_qua_enabled = ui->checkBoxQuaternaryIDE->isChecked() ? 1 : 0;
cassette_enable = ui->checkBoxCassette->isChecked() ? 1 : 0; cassette_enable = ui->checkBoxCassette->isChecked() ? 1 : 0;
@@ -131,6 +133,35 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId)
ui->comboBoxFD->setCurrentIndex(-1); ui->comboBoxFD->setCurrentIndex(-1);
ui->comboBoxFD->setCurrentIndex(selectedRow); ui->comboBoxFD->setCurrentIndex(selectedRow);
/*CD interface controller config*/
model = ui->comboBoxCDInterface->model();
removeRows = model->rowCount();
c = 0;
selectedRow = 0;
while (true) {
/* Skip "internal" if machine doesn't have it. */
QString name = DeviceConfig::DeviceName(cdrom_interface_get_device(c), cdrom_interface_get_internal_name(c), 1);
if (name.isEmpty()) {
break;
}
if (cdrom_interface_available(c)) {
auto *cdrom_interface_dev = cdrom_interface_get_device(c);
if (device_is_valid(cdrom_interface_dev, machineId)) {
int row = Models::AddEntry(model, name, c);
if (c == cdrom_interface_current) {
selectedRow = row - removeRows;
}
}
}
c++;
}
model->removeRows(0, removeRows);
ui->comboBoxCDInterface->setEnabled(model->rowCount() > 0);
ui->comboBoxCDInterface->setCurrentIndex(-1);
ui->comboBoxCDInterface->setCurrentIndex(selectedRow);
for (int i = 0; i < SCSI_BUS_MAX; ++i) { for (int i = 0; i < SCSI_BUS_MAX; ++i) {
auto *cbox = findChild<QComboBox *>(QString("comboBoxSCSI%1").arg(i + 1)); auto *cbox = findChild<QComboBox *>(QString("comboBoxSCSI%1").arg(i + 1));
model = cbox->model(); model = cbox->model();
@@ -187,6 +218,14 @@ SettingsStorageControllers::on_comboBoxFD_currentIndexChanged(int index)
ui->pushButtonFD->setEnabled(hdc_has_config(ui->comboBoxFD->currentData().toInt()) > 0); ui->pushButtonFD->setEnabled(hdc_has_config(ui->comboBoxFD->currentData().toInt()) > 0);
} }
void SettingsStorageControllers::on_comboBoxCDInterface_currentIndexChanged(int index)
{
if (index < 0) {
return;
}
ui->pushButtonCDInterface->setEnabled(cdrom_interface_has_config(ui->comboBoxCDInterface->currentData().toInt()) > 0);
}
void void
SettingsStorageControllers::on_checkBoxTertiaryIDE_stateChanged(int arg1) SettingsStorageControllers::on_checkBoxTertiaryIDE_stateChanged(int arg1)
{ {

View File

@@ -32,10 +32,12 @@ private slots:
void on_pushButtonTertiaryIDE_clicked(); void on_pushButtonTertiaryIDE_clicked();
void on_pushButtonFD_clicked(); void on_pushButtonFD_clicked();
void on_pushButtonHD_clicked(); void on_pushButtonHD_clicked();
void on_pushButtonCDInterface_clicked();
void on_checkBoxQuaternaryIDE_stateChanged(int arg1); void on_checkBoxQuaternaryIDE_stateChanged(int arg1);
void on_checkBoxTertiaryIDE_stateChanged(int arg1); void on_checkBoxTertiaryIDE_stateChanged(int arg1);
void on_comboBoxFD_currentIndexChanged(int index); void on_comboBoxFD_currentIndexChanged(int index);
void on_comboBoxHD_currentIndexChanged(int index); void on_comboBoxHD_currentIndexChanged(int index);
void on_comboBoxCDInterface_currentIndexChanged(int index);
private: private:
Ui::SettingsStorageControllers *ui; Ui::SettingsStorageControllers *ui;

View File

@@ -49,6 +49,23 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>CD-ROM Controller:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="comboBoxCDInterface"/>
</item>
<item row="2" column="2">
<widget class="QPushButton" name="pushButtonCDInterface">
<property name="text">
<string>Configure</string>
</property>
</widget>
</item>
<item row="0" column="1"> <item row="0" column="1">
<widget class="QComboBox" name="comboBoxHD"> <widget class="QComboBox" name="comboBoxHD">
<property name="sizePolicy"> <property name="sizePolicy">
@@ -69,21 +86,21 @@
<item row="1" column="1"> <item row="1" column="1">
<widget class="QComboBox" name="comboBoxFD"/> <widget class="QComboBox" name="comboBoxFD"/>
</item> </item>
<item row="2" column="0"> <item row="3" column="0">
<widget class="QCheckBox" name="checkBoxTertiaryIDE"> <widget class="QCheckBox" name="checkBoxTertiaryIDE">
<property name="text"> <property name="text">
<string>Tertiary IDE Controller</string> <string>Tertiary IDE Controller</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0"> <item row="4" column="0">
<widget class="QCheckBox" name="checkBoxQuaternaryIDE"> <widget class="QCheckBox" name="checkBoxQuaternaryIDE">
<property name="text"> <property name="text">
<string>Quaternary IDE Controller</string> <string>Quaternary IDE Controller</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="2"> <item row="3" column="2">
<widget class="QPushButton" name="pushButtonTertiaryIDE"> <widget class="QPushButton" name="pushButtonTertiaryIDE">
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>false</bool>
@@ -93,7 +110,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="2"> <item row="4" column="2">
<widget class="QPushButton" name="pushButtonQuaternaryIDE"> <widget class="QPushButton" name="pushButtonQuaternaryIDE">
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>false</bool>

File diff suppressed because it is too large Load Diff

View File

@@ -598,7 +598,7 @@ ncr_write(uint16_t port, uint8_t val, void *priv)
break; break;
case 2: /* Mode register */ case 2: /* Mode register */
ncr_log("Write: Mode register, val=%02x\n", val & MODE_DMA); ncr_log("Write: Mode register, val=%02x.\n", val);
if ((val & MODE_ARBITRATE) && !(ncr->mode & MODE_ARBITRATE)) { if ((val & MODE_ARBITRATE) && !(ncr->mode & MODE_ARBITRATE)) {
ncr->icr &= ~ICR_ARB_LOST; ncr->icr &= ~ICR_ARB_LOST;
ncr->icr |= ICR_ARB_IN_PROGRESS; ncr->icr |= ICR_ARB_IN_PROGRESS;
@@ -741,12 +741,7 @@ ncr_read(uint16_t port, void *priv)
break; break;
case 2: /* Mode register */ case 2: /* Mode register */
if (((ncr->mode & 0x30) == 0x30) && ((ncr_dev->type == 1) && (ncr_dev->bios_ver == 1))) ncr_log("Read: Mode register = %02x.\n", ncr->mode);
ncr->mode = 0;
if (((ncr->mode & 0x20) == 0x20) && (ncr_dev->type == 0))
ncr->mode = 0;
ncr_log("Read: Mode register\n");
ret = ncr->mode; ret = ncr->mode;
break; break;
@@ -761,10 +756,10 @@ ncr_read(uint16_t port, void *priv)
ncr_bus_read(ncr_dev); ncr_bus_read(ncr_dev);
ncr_log("NCR cur bus stat=%02x\n", ncr->cur_bus & 0xff); ncr_log("NCR cur bus stat=%02x\n", ncr->cur_bus & 0xff);
ret |= (ncr->cur_bus & 0xff); ret |= (ncr->cur_bus & 0xff);
if ((ncr->icr & ICR_SEL) && ((ncr_dev->type == 1) && (ncr_dev->bios_ver == 1))) if (ncr->icr & ICR_SEL)
ret |= 0x02; ret |= BUS_SEL;
if ((ncr->icr & ICR_BSY) && ((ncr_dev->type == 1) && (ncr_dev->bios_ver == 1))) if (ncr->icr & ICR_BSY)
ret |= 0x40; ret |= BUS_BSY;
break; break;
case 5: /* Bus and Status register */ case 5: /* Bus and Status register */
@@ -783,9 +778,9 @@ ncr_read(uint16_t port, void *priv)
ncr_bus_read(ncr_dev); ncr_bus_read(ncr_dev);
bus = ncr->cur_bus; bus = ncr->cur_bus;
if ((bus & BUS_ACK) || ((ncr->icr & ICR_ACK) && ((ncr_dev->type == 1) && (ncr_dev->bios_ver == 1)))) if ((bus & BUS_ACK) || (ncr->icr & ICR_ACK))
ret |= STATUS_ACK; ret |= STATUS_ACK;
if ((bus & BUS_ATN) || ((ncr->icr & ICR_ATN) && ((ncr_dev->type == 1) && (ncr_dev->bios_ver == 1)))) if ((bus & BUS_ATN) || (ncr->icr & ICR_ATN))
ret |= 0x02; ret |= 0x02;
if ((bus & BUS_REQ) && (ncr->mode & MODE_DMA)) { if ((bus & BUS_REQ) && (ncr->mode & MODE_DMA)) {
@@ -885,6 +880,13 @@ memio_read(uint32_t addr, void *priv)
ncr_log("NCR status ctrl read=%02x\n", ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY); ncr_log("NCR status ctrl read=%02x\n", ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY);
if (!ncr_dev->ncr_busy) if (!ncr_dev->ncr_busy)
ret |= STATUS_53C80_ACCESSIBLE; ret |= STATUS_53C80_ACCESSIBLE;
if (ncr->mode & 0x30) { /*Parity bits*/
if (!(ncr->mode & MODE_DMA)) { /*This is to avoid RTBios 8.10R BIOS problems with the hard disk and detection.*/
ret |= 0x01; /*If the parity bits are set, bit 0 of the 53c400 status port should be set as well.*/
ncr->mode = 0; /*Required by RTASPI10.SYS otherwise it won't initialize.*/
}
}
ncr_log("NCR 53c400 status = %02x.\n", ret);
break; break;
case 0x3981: /* block counter register*/ case 0x3981: /* block counter register*/
@@ -948,6 +950,7 @@ memio_write(uint32_t addr, uint8_t val, void *priv)
case 0x3980: case 0x3980:
switch (addr) { switch (addr) {
case 0x3980: /* Control */ case 0x3980: /* Control */
ncr_log("NCR 53c400 control = %02x, mode = %02x.\n", val, ncr->mode);
if ((val & CTRL_DATA_DIR) && !(ncr_dev->status_ctrl & CTRL_DATA_DIR)) { if ((val & CTRL_DATA_DIR) && !(ncr_dev->status_ctrl & CTRL_DATA_DIR)) {
ncr_dev->buffer_host_pos = MIN(128, dev->buffer_length); ncr_dev->buffer_host_pos = MIN(128, dev->buffer_length);
ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY; ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY;

View File

@@ -126,9 +126,10 @@ typedef struct {
get_pos_info_t get_pos_info; get_pos_info_t get_pos_info;
scb_t scb; scb_t scb;
int adapter_reset;
int scb_id; int scb_id;
int adapter_id; int adapter_id;
int assign;
int present[8];
int cmd_status; int cmd_status;
int cir_status; int cir_status;
@@ -380,7 +381,7 @@ spock_read(uint16_t port, void *p)
break; break;
} }
spock_log("spock_read: port=%04x val=%02x %04x(%05x):%04x %02x\n", port, temp, CS, cs, cpu_state.pc, BH); spock_log("spock_read: port=%04x val=%02x %04x(%05x):%04x.\n", port, temp, CS, cs, cpu_state.pc);
return temp; return temp;
} }
@@ -436,11 +437,14 @@ spock_get_len(spock_t *scsi, scb_t *scb)
static void static void
spock_process_imm_cmd(spock_t *scsi) spock_process_imm_cmd(spock_t *scsi)
{ {
int i; int i, j = 0;
int adapter_id, phys_id, lun_id; int adapter_id, phys_id, lun_id;
scsi->assign = 0;
switch (scsi->command & CMD_MASK) { switch (scsi->command & CMD_MASK) {
case CMD_ASSIGN: case CMD_ASSIGN:
scsi->assign = 1;
adapter_id = (scsi->command >> 16) & 15; adapter_id = (scsi->command >> 16) & 15;
phys_id = (scsi->command >> 20) & 7; phys_id = (scsi->command >> 20) & 7;
lun_id = (scsi->command >> 24) & 7; lun_id = (scsi->command >> 24) & 7;
@@ -458,10 +462,10 @@ spock_process_imm_cmd(spock_t *scsi)
if (phys_id != scsi->adapter_id) { if (phys_id != scsi->adapter_id) {
scsi->dev_id[adapter_id].phys_id = phys_id; scsi->dev_id[adapter_id].phys_id = phys_id;
scsi->dev_id[adapter_id].lun_id = lun_id; scsi->dev_id[adapter_id].lun_id = lun_id;
spock_log("Assign: adapter dev=%x scsi ID=%i LUN=%i\n", adapter_id, scsi->dev_id[adapter_id].phys_id, scsi->dev_id[adapter_id].lun_id); spock_log("Assign: adapter dev=%x scsi ID=%i LUN=%i.\n", adapter_id, scsi->dev_id[adapter_id].phys_id, scsi->dev_id[adapter_id].lun_id);
spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE);
} else { /*Can not assign adapter*/ } else { /*Can not assign adapter*/
spock_log("Assign: PUN=%d, cannot assign adapter\n", phys_id); spock_log("Assign: PUN=%d, cannot assign adapter.\n", phys_id);
spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_COMMAND_FAIL); spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_COMMAND_FAIL);
} }
} }
@@ -481,18 +485,25 @@ spock_process_imm_cmd(spock_t *scsi)
spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE);
break; break;
case CMD_RESET: case CMD_RESET:
spock_log("Reset Command\n"); spock_log("Reset Command, attention = %d.\n", scsi->attention & 0x0f);
if ((scsi->attention & 0x0f) == 0x0f) { /*Adapter reset*/ if ((scsi->attention & 0x0f) == 0x0f) { /*Adapter reset*/
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++) {
scsi_device_reset(&scsi_devices[scsi->bus][i]); scsi_device_reset(&scsi_devices[scsi->bus][i]);
spock_log("Adapter Reset\n"); }
if (!scsi->adapter_reset) /*The early 1990 bios must have its boot drive for (i = 6; i > -1; i--) {
set to ID 6 according https://www.ardent-tool.com/IBM_SCSI/SCSI-A.html */ if (scsi_device_present(&scsi_devices[scsi->bus][i])) {
scsi->adapter_reset = 1; spock_log("Adapter Reset, SCSI reset present devices=%d, phys ID=%d, type=%04x.\n", j, scsi->dev_id[i].phys_id, scsi_devices[scsi->bus][i].type);
scsi->present[j] = i;
j++;
} else {
spock_log("Adapter Reset, SCSI reset not present devices=%d, phys ID=%d, type=%04x.\n", j, scsi->dev_id[i].phys_id, scsi_devices[scsi->bus][i].type);
}
}
scsi->scb_state = 0; scsi->scb_state = 0;
} }
spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE);
break; break;
@@ -505,7 +516,7 @@ spock_process_imm_cmd(spock_t *scsi)
static void static void
spock_execute_cmd(spock_t *scsi, scb_t *scb) spock_execute_cmd(spock_t *scsi, scb_t *scb)
{ {
int c; int c, j;
int old_scb_state; int old_scb_state;
if (scsi->in_reset) { if (scsi->in_reset) {
@@ -519,8 +530,8 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb)
if (scsi->in_reset == 1) { if (scsi->in_reset == 1) {
scsi->basic_ctrl |= CTRL_IRQ_ENA; scsi->basic_ctrl |= CTRL_IRQ_ENA;
spock_set_irq(scsi, 0x0f, IRQ_TYPE_RESET_COMPLETE); }
} else
spock_set_irq(scsi, 0x0f, IRQ_TYPE_RESET_COMPLETE); spock_set_irq(scsi, 0x0f, IRQ_TYPE_RESET_COMPLETE);
/*Reset device mappings*/ /*Reset device mappings*/
@@ -532,6 +543,16 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb)
scsi->dev_id[c].phys_id = -1; scsi->dev_id[c].phys_id = -1;
scsi->in_reset = 0; scsi->in_reset = 0;
for (c = 6; c > -1; c--) {
if (scsi_device_present(&scsi_devices[scsi->bus][c])) {
spock_log("Reset, SCSI reset present devices=%d, phys ID=%d, type=%04x.\n", j, scsi->dev_id[c].phys_id, scsi_devices[scsi->bus][c].type);
scsi->present[j] = c;
j++;
} else {
spock_log("Reset, SCSI reset not present devices=%d, phys ID=%d, type=%04x.\n", j, scsi->dev_id[c].phys_id, scsi_devices[scsi->bus][c].type);
}
}
return; return;
} }
@@ -584,11 +605,11 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb)
" SCB chain address = %08x\n" " SCB chain address = %08x\n"
" Block count = %04x\n" " Block count = %04x\n"
" Block length = %04x\n" " Block length = %04x\n"
" SCB id = %d, Phys id = %d\n", " SCB id = %d, Phys id = %d, Spock CMD = %08x, CMD Mask = %02x.\n",
scb->command, scb->enable, scb->lba_addr, scb->command, scb->enable, scb->lba_addr,
scb->sge.sys_buf_addr, scb->sge.sys_buf_byte_count, scb->sge.sys_buf_addr, scb->sge.sys_buf_byte_count,
scb->term_status_block_addr, scb->scb_chain_addr, scb->term_status_block_addr, scb->scb_chain_addr,
scb->block_count, scb->block_length, scsi->scb_id, scsi->dev_id[scsi->scb_id].phys_id); scb->block_count, scb->block_length, scsi->scb_id, scsi->dev_id[scsi->scb_id].phys_id, scsi->command, scb->command & 0xc0);
switch (scb->command & CMD_MASK) { switch (scb->command & CMD_MASK) {
case CMD_GET_COMPLETE_STATUS: case CMD_GET_COMPLETE_STATUS:
@@ -662,10 +683,7 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb)
break; break;
case CMD_DEVICE_INQUIRY: case CMD_DEVICE_INQUIRY:
if (scb->command != CMD_DEVICE_INQUIRY) scsi->cdb_id = scsi->assign ? scsi->dev_id[scsi->scb_id].phys_id : scsi->present[scsi->scb_id];
scsi->cdb_id = scsi->scb_id;
else
scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id;
spock_log("Device Inquiry, ID=%d\n", scsi->cdb_id); spock_log("Device Inquiry, ID=%d\n", scsi->cdb_id);
scsi->cdb[0] = GPCMD_INQUIRY; scsi->cdb[0] = GPCMD_INQUIRY;
scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/ scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/
@@ -681,12 +699,9 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb)
return; return;
case CMD_SEND_OTHER_SCSI: case CMD_SEND_OTHER_SCSI:
if (scb->command != CMD_SEND_OTHER_SCSI) scsi->cdb_id = scsi->assign ? scsi->dev_id[scsi->scb_id].phys_id : scsi->present[scsi->scb_id];
scsi->cdb_id = scsi->scb_id;
else
scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id;
spock_log("Send Other SCSI, SCB ID=%d, PHYS ID=%d, reset=%d\n", scsi->scb_id, scsi->dev_id[scsi->scb_id].phys_id, scsi->adapter_reset);
dma_bm_read(scsi->scb_addr + 0x18, scsi->cdb, 12, 2); dma_bm_read(scsi->scb_addr + 0x18, scsi->cdb, 12, 2);
spock_log("Send Other SCSI, SCB ID=%d, PHYS ID=%d\n", scsi->scb_id, scsi->dev_id[scsi->scb_id].phys_id);
scsi->cdb[1] = (scsi->cdb[1] & 0x1f) | (scsi->dev_id[scsi->scb_id].lun_id << 5); /*Patch correct LUN into command*/ scsi->cdb[1] = (scsi->cdb[1] & 0x1f) | (scsi->dev_id[scsi->scb_id].lun_id << 5); /*Patch correct LUN into command*/
scsi->cdb_len = (scb->lba_addr & 0xff) ? (scb->lba_addr & 0xff) : 6; scsi->cdb_len = (scb->lba_addr & 0xff) ? (scb->lba_addr & 0xff) : 6;
scsi->scsi_state = SCSI_STATE_SELECT; scsi->scsi_state = SCSI_STATE_SELECT;
@@ -694,11 +709,8 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb)
return; return;
case CMD_READ_DEVICE_CAPACITY: case CMD_READ_DEVICE_CAPACITY:
if (scb->command != CMD_READ_DEVICE_CAPACITY) scsi->cdb_id = scsi->assign ? scsi->dev_id[scsi->scb_id].phys_id : scsi->present[scsi->scb_id];
scsi->cdb_id = scsi->scb_id; spock_log("Device Capacity, SCB ID=%d, PHYS ID=%d\n", scsi->scb_id, scsi->dev_id[scsi->scb_id].phys_id);
else
scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id;
spock_log("Device Capacity, SCB ID=%d, PHYS ID=%d, reset=%d\n", scsi->scb_id, scsi->dev_id[scsi->scb_id].phys_id, scsi->adapter_reset);
scsi->cdb[0] = GPCMD_READ_CDROM_CAPACITY; scsi->cdb[0] = GPCMD_READ_CDROM_CAPACITY;
scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/ scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/
scsi->cdb[2] = 0; /*LBA*/ scsi->cdb[2] = 0; /*LBA*/
@@ -715,11 +727,8 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb)
return; return;
case CMD_READ_DATA: case CMD_READ_DATA:
if (scb->command != CMD_READ_DATA) scsi->cdb_id = scsi->assign ? scsi->dev_id[scsi->scb_id].phys_id : scsi->present[scsi->scb_id];
scsi->cdb_id = scsi->scb_id; spock_log("Device Read Data, SCB ID=%d, PHYS ID=%d\n", scsi->scb_id, scsi->dev_id[scsi->scb_id].phys_id);
else
scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id;
spock_log("Device Read Data, SCB ID=%d, PHYS ID=%d, reset=%d\n", scsi->scb_id, scsi->dev_id[scsi->scb_id].phys_id, scsi->adapter_reset);
scsi->cdb[0] = GPCMD_READ_10; scsi->cdb[0] = GPCMD_READ_10;
scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/ scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/
scsi->cdb[2] = (scb->lba_addr >> 24) & 0xff; /*LBA*/ scsi->cdb[2] = (scb->lba_addr >> 24) & 0xff; /*LBA*/
@@ -736,10 +745,7 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb)
return; return;
case CMD_WRITE_DATA: case CMD_WRITE_DATA:
if (scb->command != CMD_WRITE_DATA) scsi->cdb_id = scsi->assign ? scsi->dev_id[scsi->scb_id].phys_id : scsi->present[scsi->scb_id];
scsi->cdb_id = scsi->scb_id;
else
scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id;
spock_log("Device Write Data\n"); spock_log("Device Write Data\n");
scsi->cdb[0] = GPCMD_WRITE_10; scsi->cdb[0] = GPCMD_WRITE_10;
scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/ scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/
@@ -757,10 +763,7 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb)
return; return;
case CMD_VERIFY: case CMD_VERIFY:
if (scb->command != CMD_VERIFY) scsi->cdb_id = scsi->assign ? scsi->dev_id[scsi->scb_id].phys_id : scsi->present[scsi->scb_id];
scsi->cdb_id = scsi->scb_id;
else
scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id;
spock_log("Device Verify\n"); spock_log("Device Verify\n");
scsi->cdb[0] = GPCMD_VERIFY_10; scsi->cdb[0] = GPCMD_VERIFY_10;
scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/ scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/
@@ -779,10 +782,7 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb)
return; return;
case CMD_REQUEST_SENSE: case CMD_REQUEST_SENSE:
if (scb->command != CMD_REQUEST_SENSE) scsi->cdb_id = scsi->assign ? scsi->dev_id[scsi->scb_id].phys_id : scsi->present[scsi->scb_id];
scsi->cdb_id = scsi->scb_id;
else
scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id;
spock_log("Device Request Sense, ID=%d\n", scsi->cdb_id); spock_log("Device Request Sense, ID=%d\n", scsi->cdb_id);
scsi->cdb[0] = GPCMD_REQUEST_SENSE; scsi->cdb[0] = GPCMD_REQUEST_SENSE;
scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/ scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/
@@ -802,7 +802,7 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb)
if (scsi_device_present(&scsi_devices[scsi->bus][scsi->cdb_id])) { if (scsi_device_present(&scsi_devices[scsi->bus][scsi->cdb_id])) {
if (scsi->last_status == SCSI_STATUS_OK) { if (scsi->last_status == SCSI_STATUS_OK) {
scsi->scb_state = 3; scsi->scb_state = 3;
spock_log("Status is Good on device ID %d, reset = %d\n", scsi->scb_id, scsi->adapter_reset); spock_log("Status is Good on device ID %d, cdb id = %d.\n", scsi->scb_id, scsi->cdb_id);
} else if (scsi->last_status == SCSI_STATUS_CHECK_CONDITION) { } else if (scsi->last_status == SCSI_STATUS_CHECK_CONDITION) {
uint16_t term_stat_block_addr7 = (0xc << 8) | 2; uint16_t term_stat_block_addr7 = (0xc << 8) | 2;
uint16_t term_stat_block_addr8 = 0x20; uint16_t term_stat_block_addr8 = 0x20;
@@ -811,7 +811,7 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb)
spock_set_irq(scsi, scsi->scb_id, IRQ_TYPE_COMMAND_FAIL); spock_set_irq(scsi, scsi->scb_id, IRQ_TYPE_COMMAND_FAIL);
scsi->scb_state = 0; scsi->scb_state = 0;
spock_log("Status Check Condition on device ID %d, reset = %d\n", scsi->scb_id, scsi->adapter_reset); spock_log("Status Check Condition on device ID %d, cdb id = %d.\n", scsi->attention & 0x0f, scsi->cdb_id);
dma_bm_write(scb->term_status_block_addr + 0x7 * 2, (uint8_t *) &term_stat_block_addr7, 2, 2); dma_bm_write(scb->term_status_block_addr + 0x7 * 2, (uint8_t *) &term_stat_block_addr7, 2, 2);
dma_bm_write(scb->term_status_block_addr + 0x8 * 2, (uint8_t *) &term_stat_block_addr8, 2, 2); dma_bm_write(scb->term_status_block_addr + 0x8 * 2, (uint8_t *) &term_stat_block_addr8, 2, 2);
dma_bm_write(scb->term_status_block_addr + 0xb * 2, (uint8_t *) &term_stat_block_addrb, 2, 2); dma_bm_write(scb->term_status_block_addr + 0xb * 2, (uint8_t *) &term_stat_block_addrb, 2, 2);
@@ -822,7 +822,7 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb)
uint16_t term_stat_block_addr8 = 0x10; uint16_t term_stat_block_addr8 = 0x10;
spock_set_irq(scsi, scsi->scb_id, IRQ_TYPE_COMMAND_FAIL); spock_set_irq(scsi, scsi->scb_id, IRQ_TYPE_COMMAND_FAIL);
scsi->scb_state = 0; scsi->scb_state = 0;
spock_log("Status Check Condition on device ID %d on no device, reset = %d\n", scsi->scb_id, scsi->adapter_reset); spock_log("Status Check Condition on device ID %d on no device\n", scsi->scb_id);
dma_bm_write(scb->term_status_block_addr + 0x7 * 2, (uint8_t *) &term_stat_block_addr7, 2, 2); dma_bm_write(scb->term_status_block_addr + 0x7 * 2, (uint8_t *) &term_stat_block_addr7, 2, 2);
dma_bm_write(scb->term_status_block_addr + 0x8 * 2, (uint8_t *) &term_stat_block_addr8, 2, 2); dma_bm_write(scb->term_status_block_addr + 0x8 * 2, (uint8_t *) &term_stat_block_addr8, 2, 2);
} }
@@ -837,7 +837,7 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb)
} else { } else {
spock_set_irq(scsi, scsi->scb_id, IRQ_TYPE_SCB_COMPLETE); spock_set_irq(scsi, scsi->scb_id, IRQ_TYPE_SCB_COMPLETE);
scsi->scb_state = 0; scsi->scb_state = 0;
spock_log("Complete SCB\n"); spock_log("Complete SCB ID = %d.\n", scsi->attention & 0x0f);
} }
break; break;
} }
@@ -856,12 +856,12 @@ spock_process_scsi(spock_t *scsi, scb_t *scb)
break; break;
case SCSI_STATE_SELECT: case SCSI_STATE_SELECT:
spock_log("Selecting ID %d\n", scsi->cdb_id); spock_log("Selecting ID %d, SCB ID %d, LUN %d, adapter id = %d.\n", scsi->cdb_id, scsi->scb_id, scsi->dev_id[scsi->scb_id].lun_id, scsi->attention);
if ((scsi->cdb_id != (uint8_t) -1) && scsi_device_present(&scsi_devices[scsi->bus][scsi->cdb_id])) { if ((scsi->cdb_id != (uint8_t) -1) && scsi_device_present(&scsi_devices[scsi->bus][scsi->cdb_id])) {
scsi->scsi_state = SCSI_STATE_SEND_COMMAND; scsi->scsi_state = SCSI_STATE_SEND_COMMAND;
spock_log("Device selected at ID %i\n", scsi->cdb_id); spock_log("Device selected at ID %i.\n", scsi->cdb_id);
} else { } else {
spock_log("Device selection failed at ID %i\n", scsi->cdb_id); spock_log("Device selection failed at ID %i.\n", scsi->cdb_id);
scsi->scsi_state = SCSI_STATE_IDLE; scsi->scsi_state = SCSI_STATE_IDLE;
if (!scsi->cmd_timer) { if (!scsi->cmd_timer) {
spock_log("Callback to reset\n"); spock_log("Callback to reset\n");
@@ -985,6 +985,7 @@ spock_callback(void *priv)
scsi->cir[3] = scsi->cir_pending[3]; scsi->cir[3] = scsi->cir_pending[3];
scsi->cir_status = 0; scsi->cir_status = 0;
spock_log("SCSI attention = %02x.\n", scsi->attention_pending);
switch (scsi->attention >> 4) { switch (scsi->attention >> 4) {
case 1: /*Immediate command*/ case 1: /*Immediate command*/
scsi->cmd_status = 0x0a; scsi->cmd_status = 0x0a;
@@ -1007,7 +1008,7 @@ spock_callback(void *priv)
scsi->scb_addr = scsi->cir[0] | (scsi->cir[1] << 8) | (scsi->cir[2] << 16) | (scsi->cir[3] << 24); scsi->scb_addr = scsi->cir[0] | (scsi->cir[1] << 8) | (scsi->cir[2] << 16) | (scsi->cir[3] << 24);
scsi->scb_id = scsi->attention & 0x0f; scsi->scb_id = scsi->attention & 0x0f;
scsi->cmd_timer = SPOCK_TIME * 2; scsi->cmd_timer = SPOCK_TIME * 2;
spock_log("Start SCB at ID = %d\n", scsi->scb_id); spock_log("Start SCB at ID = %d, attention = %02x\n", scsi->scb_id, scsi->attention >> 4);
scsi->scb_state = 1; scsi->scb_state = 1;
break; break;
@@ -1019,7 +1020,7 @@ spock_callback(void *priv)
case 0x0e: /*EOI*/ case 0x0e: /*EOI*/
scsi->irq_status = 0; scsi->irq_status = 0;
spock_clear_irq(scsi, scsi->attention & 0xf); spock_clear_irq(scsi, scsi->attention & 0x0f);
break; break;
} }
} }
@@ -1049,10 +1050,9 @@ spock_mca_write(int port, uint8_t val, void *priv)
if (scsi->pos_regs[2] & 1) { if (scsi->pos_regs[2] & 1) {
io_sethandler((((scsi->pos_regs[2] >> 1) & 7) * 8) + 0x3540, 0x0008, spock_read, spock_readw, NULL, spock_write, spock_writew, NULL, scsi); io_sethandler((((scsi->pos_regs[2] >> 1) & 7) * 8) + 0x3540, 0x0008, spock_read, spock_readw, NULL, spock_write, spock_writew, NULL, scsi);
if ((scsi->pos_regs[2] >> 4) == 0x0f) if ((scsi->pos_regs[2] & 0xf0) != 0xf0) {
mem_mapping_disable(&scsi->bios_rom.mapping);
else {
mem_mapping_set_addr(&scsi->bios_rom.mapping, ((scsi->pos_regs[2] >> 4) * 0x2000) + 0xc0000, 0x8000); mem_mapping_set_addr(&scsi->bios_rom.mapping, ((scsi->pos_regs[2] >> 4) * 0x2000) + 0xc0000, 0x8000);
mem_mapping_enable(&scsi->bios_rom.mapping);
} }
} }
} }
@@ -1089,10 +1089,10 @@ spock_mca_reset(void *priv)
scsi->basic_ctrl = 0; scsi->basic_ctrl = 0;
/* Reset all devices on controller reset. */ /* Reset all devices on controller reset. */
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++) {
scsi_device_reset(&scsi_devices[scsi->bus][i]); scsi_device_reset(&scsi_devices[scsi->bus][i]);
scsi->present[i] = 0;
scsi->adapter_reset = 0; }
} }
static void * static void *
@@ -1175,7 +1175,7 @@ static const device_config_t spock_rom_config[] = {
}, },
}, },
{ .name = "", .description = "", .type = CONFIG_END } { .name = "", .description = "", .type = CONFIG_END }
// clang-format on // clang-format on
}; };
const device_t spock_device = { const device_t spock_device = {