static void addnativescsi (void)
{
int i, j;
- int devices[MAX_TOTAL_DEVICES];
- int types[MAX_TOTAL_DEVICES];
- struct device_info dis[MAX_TOTAL_DEVICES];
+ int devices[MAX_TOTAL_SCSI_DEVICES];
+ int types[MAX_TOTAL_SCSI_DEVICES];
+ struct device_info dis[MAX_TOTAL_SCSI_DEVICES];
freenativescsi ();
i = 0;
- while (i < MAX_TOTAL_DEVICES) {
+ while (i < MAX_TOTAL_SCSI_DEVICES) {
types[i] = -1;
devices[i] = -1;
- if (sys_command_open (DF_SCSI, i)) {
- if (sys_command_info (DF_SCSI, i, &dis[i], 0)) {
+ if (sys_command_open (i)) {
+ if (sys_command_info (i, &dis[i], 0)) {
devices[i] = i;
types[i] = 100 - i;
if (dis[i].type == INQ_ROMD)
types[i] = 1000 - i;
}
- sys_command_close (DF_SCSI, i);
+ sys_command_close (i);
}
i++;
}
cdrom_paused = 0;
if (unitnum < 0)
return;
- sys_command_cd_pause (DF_IOCTL, unitnum, 0);
- sys_command_cd_stop (DF_IOCTL, unitnum);
- sys_command_cd_pause (DF_IOCTL, unitnum, 1);
+ sys_command_cd_pause (unitnum, 0);
+ sys_command_cd_stop (unitnum);
+ sys_command_cd_pause (unitnum, 1);
}
static void cdaudiostop (void)
qcode_valid = 0;
if (unitnum < 0)
return;
- sys_command_cd_play (DF_IOCTL, unitnum, startlsn, endlsn, scan, subfunc);
+ sys_command_cd_pause (unitnum, 0);
+ sys_command_cd_play (unitnum, startlsn, endlsn, scan, subfunc);
}
static bool isaudiotrack (int startlsn)
{
int j;
int datatrack = 0, secondtrack = 0;
- struct cd_toc_head *th;
cdrom_toc_counter = -1;
- th = sys_command_cd_toc (DF_IOCTL, unitnum);
- if (!th)
+ if (!sys_command_cd_toc (unitnum, &cdrom_toc_cd_buffer))
return 1;
- memcpy (&cdrom_toc_cd_buffer, th, sizeof cdrom_toc_cd_buffer);
memset (cdrom_toc_buffer, 0, MAX_TOC_ENTRIES * 13);
cdrom_data_end = -1;
- for (j = 0; j < th->points; j++) {
- struct cd_toc *s = &th->toc[j];
+ for (j = 0; j < cdrom_toc_cd_buffer.points; j++) {
+ struct cd_toc *s = &cdrom_toc_cd_buffer.toc[j];
uae_u8 *d = &cdrom_toc_buffer[j * 13];
int addr = s->paddress;
int msf = lsn2msf (addr);
struct device_info di1, *di2;
int cd32unit = -1;
int audiounit = -1;
- int opened[MAX_TOTAL_DEVICES];
+ int opened[MAX_TOTAL_SCSI_DEVICES];
int i;
- for (unitnum = 0; unitnum < MAX_TOTAL_DEVICES; unitnum++) {
+ for (unitnum = 0; unitnum < MAX_TOTAL_SCSI_DEVICES; unitnum++) {
opened[unitnum] = 0;
- if (sys_command_open (DF_IOCTL, unitnum)) {
+ if (sys_command_open (unitnum)) {
opened[unitnum] = 1;
- di2 = sys_command_info (DF_IOCTL, unitnum, &di1, 0);
+ di2 = sys_command_info (unitnum, &di1, 0);
if (di2 && di2->type == INQ_ROMD) {
write_log (L"%s: ", di2->label);
if (first < 0)
first = unitnum;
if (!get_cdrom_toc ()) {
if (cdrom_data_end > 0) {
- uae_u8 *p = sys_command_cd_read (DF_IOCTL, unitnum, NULL, 16, 1);
- if (p) {
+ uae_u8 buffer[2048];
+ if (sys_command_cd_read (unitnum, buffer, 16, 1)) {
+ uae_u8 *p = buffer;
if (!memcmp (p + 8, "CDTV", 4) || !memcmp (p + 8, "CD32", 4)) {
uae_u32 crc;
write_log (L"CD32 or CDTV");
if (cd32unit < 0)
cd32unit = unitnum;
- p = sys_command_cd_read (DF_IOCTL, unitnum, NULL, 21, 1);
- crc = get_crc32 (p, 2048);
- if (crc == 0xe56c340f)
- write_log (L" [CD32.TM]");
- write_log (L"\n");
+ if (sys_command_cd_read (unitnum, buffer, 21, 1)) {
+ crc = get_crc32 (buffer, 2048);
+ if (crc == 0xe56c340f)
+ write_log (L" [CD32.TM]");
+ write_log (L"\n");
+ }
} else {
write_log (L"non CD32/CDTV data CD\n");
}
unitnum = first;
if (unitnum >= 0)
opened[unitnum] = 0;
- for (i = 0; i < MAX_TOTAL_DEVICES; i++) {
+ for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
if (opened[i])
- sys_command_close (DF_IOCTL, i);
+ sys_command_close (i);
}
if (unitnum < 0)
return 1;
- di2 = sys_command_info (DF_IOCTL, unitnum, &di1, 0);
+ di2 = sys_command_info (unitnum, &di1, 0);
if (!di2) {
write_log (L"unit %d info failed\n", unitnum);
- sys_command_close (DF_IOCTL, unitnum);
+ sys_command_close (unitnum);
return 1;
}
- if (sys_command_ismedia (DF_IOCTL, unitnum, 0) <= 0)
+ if (sys_command_ismedia (unitnum, 0) <= 0)
cd_hunt = 1;
write_log (L"using drive %s (unit %d, media %d)\n", di2->label, unitnum, di2->media_inserted);
/* make sure CD audio is not playing */
static void sys_cddev_close (void)
{
cdaudiostop_do ();
- sys_command_close (DF_IOCTL, unitnum);
+ sys_command_close (unitnum);
}
static int command_lengths[] = { 1,2,1,1,12,2,1,1,4,1,-1,-1,-1,-1,-1,-1 };
if (cd_hunt) {
cdrom_result_buffer[1] = 0x80;
} else {
- cdrom_result_buffer[1] = sys_command_ismedia (DF_IOCTL, unitnum, 0) > 0 ? 0x83: 0x80;
+ cdrom_result_buffer[1] = sys_command_ismedia (unitnum, 0) > 0 ? 0x83: 0x80;
}
return 2;
}
static void do_hunt (void)
{
int i;
- for (i = 0; i < MAX_TOTAL_DEVICES; i++) {
- if (sys_command_ismedia (DF_IOCTL, i, 1) > 0)
+ for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ if (sys_command_ismedia (i, 1) > 0)
break;
}
- if (i == MAX_TOTAL_DEVICES) {
- if (unitnum >= 0 && sys_command_ismedia (DF_IOCTL, unitnum, 1) >= 0)
+ if (i == MAX_TOTAL_SCSI_DEVICES) {
+ if (unitnum >= 0 && sys_command_ismedia (unitnum, 1) >= 0)
return;
- for (i = 0; i < MAX_TOTAL_DEVICES; i++) {
- if (sys_command_ismedia (DF_IOCTL, i, 1) >= 0)
+ for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ if (sys_command_ismedia (i, 1) >= 0)
break;
}
- if (i == MAX_TOTAL_DEVICES)
+ if (i == MAX_TOTAL_SCSI_DEVICES)
return;
}
if (unitnum >= 0) {
int ou = unitnum;
unitnum = -1;
- sys_command_close (DF_IOCTL, ou);
+ sys_command_close (ou);
}
- if (sys_command_open (DF_IOCTL, i) > 0) {
+ if (sys_command_open (i) > 0) {
struct device_info di = { 0 };
- sys_command_info (DF_IOCTL, i, &di, 0);
+ sys_command_info (i, &di, 0);
unitnum = i;
cd_hunt = 0;
lastmediastate = -1;
if (cd_hunt) {
static int huntcnt;
- if (huntcnt <= 0 && !mediachanged) {
+ if (huntcnt <= 0 && (!mediachanged || unitnum < 0)) {
do_hunt ();
huntcnt = 312 * 50 * 2;
}
uae_u8 *tmp1;
uae_u8 *tmp2;
int tmp3;
- uae_u8 *p;
int offset;
int sector;
switch (b)
{
case 0x0102: // pause
- sys_command_cd_pause (DF_IOCTL, unitnum, 1);
+ sys_command_cd_pause (unitnum, 1);
break;
case 0x0103: // unpause
- sys_command_cd_pause (DF_IOCTL, unitnum, 0);
+ sys_command_cd_pause (unitnum, 0);
break;
case 0x0104: // stop
cdaudiostop_do ();
break;
case 0x0105: // mute change
- sys_command_cd_volume (DF_IOCTL, unitnum, cdrom_muted ? 0 : 0xffff);
+ sys_command_cd_volume (unitnum, cdrom_muted ? 0 : 0x7fff, cdrom_muted ? 0 : 0x7fff);
break;
case 0x0110: // do_play!
- sys_command_cd_volume (DF_IOCTL, unitnum, cdrom_muted ? 0 : 0xffff);
+ sys_command_cd_volume (unitnum, cdrom_muted ? 0 : 0x7fff, cdrom_muted ? 0 : 0x7fff);
cdaudioplay_do ();
break;
}
if (frame2counter <= 0) {
frame2counter = 312 * 50 / 2;
- if (sys_command_cd_qcode (DF_IOCTL, unitnum, qcode_buf)) {
+ if (unitnum >= 0 && sys_command_cd_qcode (unitnum, qcode_buf)) {
uae_u8 as = qcode_buf[1];
qcode_valid = 1;
if (as == AUDIO_STATUS_IN_PROGRESS) {
if (mediacheckcounter <= 0) {
mediacheckcounter = 312 * 50 * 2;
- int media = sys_command_ismedia (DF_IOCTL, unitnum, 1);
+ int media = sys_command_ismedia (unitnum, 1);
if (media < 0) {
if (!cd_hunt) {
- cd_hunt = 1;
write_log (L"CD32: device unit %d lost\n", unitnum);
media = lastmediastate = cdrom_disk = 0;
mediachanged = 1;
cdaudiostop_do ();
+ cd_hunt = 1;
}
} else if (media != lastmediastate) {
write_log (L"CD32: media changed = %d (hunt=%d)\n", media, cd_hunt);
sector_buffer_sector_2 = sector;
offset = 0;
while (offset < SECTOR_BUFFER_SIZE) {
- p = 0;
+ int ok = 0;
if (sector < cdrom_data_end)
- p = sys_command_cd_read (DF_IOCTL, unitnum, NULL, sector, 1);
- if (p)
- memcpy (sector_buffer_2 + offset * 2048, p, 2048);
- sector_buffer_info_2[offset] = p ? 3 : 0;
+ ok = sys_command_cd_read (unitnum, sector_buffer_2 + offset * 2048, sector, 1);
+ sector_buffer_info_2[offset] = ok ? 3 : 0;
offset++;
sector++;
}
{
if (currprefs.cs_cd32cd && cdromok == 0) {
unitnum = -1;
- if (!device_func_init (DEVICE_TYPE_IOCTL)) {
+ if (!device_func_init (0)) {
write_log (L"no CDROM support\n");
return 0;
}
#include "blkdev.h"
#include "scsidev.h"
#include "savestate.h"
+#ifdef RETROPLATFORM
+#include "rp.h"
+#endif
-static int scsiemu;
+static int scsiemu[MAX_TOTAL_SCSI_DEVICES];
-static struct device_functions *device_func[2];
-static int have_ioctl;
-static int openlist[MAX_TOTAL_DEVICES];
-static int forcedunit = -1;
+static struct device_functions *device_func[MAX_TOTAL_SCSI_DEVICES];
+static int openlist[MAX_TOTAL_SCSI_DEVICES];
/* convert minutes, seconds and frames -> logical sector number */
int msf2lsn (int msf)
p[2] = tobcd ((v >> 0) & 0xff);
}
+static struct cd_toc *gettoc (struct cd_toc_head *th, int block)
+{
+ for (int i = th->first_track_offset; i < th->last_track_offset; i++) {
+ struct cd_toc *t = &th->toc[i];
+ if (block < t->paddress) {
+ if (i == th->first_track_offset)
+ return t;
+ else
+ return t - 1;
+ }
+ }
+ return &th->toc[th->last_track_offset];
+}
+
+int isaudiotrack (struct cd_toc_head *th, int block)
+{
+ struct cd_toc *t = gettoc (th, block);
+ if (!t)
+ return 0;
+ return (t->control & 0x0c) != 4;
+}
+int isdatatrack (struct cd_toc_head *th, int block)
+{
+ return !isaudiotrack (th, block);
+}
+
+static int cdscsidevicetype[MAX_TOTAL_SCSI_DEVICES];
+
#ifdef _WIN32
#include "od-win32/win32.h"
extern struct device_functions devicefunc_win32_ioctl;
extern struct device_functions devicefunc_cdimage;
+static struct device_functions *devicetable[] = {
+ NULL,
+ &devicefunc_cdimage,
+ &devicefunc_win32_ioctl,
+ &devicefunc_win32_spti,
+ &devicefunc_win32_aspi,
+ NULL
+};
+static int driver_installed[6];
+
static void install_driver (int flags)
{
- scsiemu = 0;
- device_func[DF_IOCTL] = NULL;
- device_func[DF_SCSI] = NULL;
- if (devicefunc_cdimage.checkbus (flags | DEVICE_TYPE_CHECKAVAIL)) {
- device_func[DF_IOCTL] = &devicefunc_cdimage;
- device_func[DF_SCSI] = &devicefunc_cdimage;
- scsiemu = 1;
- return;
+ for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ scsiemu[i] = false;
+ device_func[i] = NULL;
+ switch (cdscsidevicetype[i])
+ {
+ case SCSI_UNIT_IMAGE:
+ device_func[i] = devicetable[SCSI_UNIT_IMAGE];
+ scsiemu[i] = true;
+ break;
+ case SCSI_UNIT_IOCTL:
+ device_func[i] = devicetable[SCSI_UNIT_IOCTL];
+ scsiemu[i] = true;
+ break;
+ case SCSI_UNIT_SPTI:
+ if (currprefs.win32_uaescsimode == UAESCSI_CDEMU) {
+ device_func[i] = devicetable[SCSI_UNIT_IOCTL];
+ scsiemu[i] = true;
+ } else {
+ device_func[i] = devicetable[SCSI_UNIT_SPTI];
+ }
+ break;
+ case SCSI_UNIT_ASPI:
+ device_func[i] = devicetable[SCSI_UNIT_ASPI];
+ break;
+ }
}
-#ifdef WINDDK
- if (!device_func[DF_IOCTL])
- device_func[DF_IOCTL] = &devicefunc_win32_ioctl;
- if (currprefs.win32_uaescsimode == UAESCSI_CDEMU) {
- device_func[DF_SCSI] = &devicefunc_win32_ioctl;
- scsiemu = 1;
- } else if (flags != DEVICE_TYPE_IOCTL) {
- device_func[DF_SCSI] = &devicefunc_win32_spti;
- if (currprefs.win32_uaescsimode == UAESCSI_ADAPTECASPI ||
- currprefs.win32_uaescsimode == UAESCSI_NEROASPI ||
- currprefs.win32_uaescsimode == UAESCSI_FROGASPI) {
- device_func[DF_SCSI] = &devicefunc_win32_aspi;
- device_func[DF_IOCTL] = 0;
+
+ for (int j = 1; devicetable[j]; j++) {
+ if (!driver_installed[j]) {
+ for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ if (device_func[i] == devicetable[j]) {
+ int ok = device_func[i]->openbus (0);
+ driver_installed[j] = 1;
+ write_log (L"%s driver installed, ok=%d\n", device_func[i]->name, ok);
+ break;
+ }
+ }
}
}
-#endif
- if (device_func[DF_SCSI])
- device_func[DF_SCSI]->checkbus (DEVICE_TYPE_CHECKAVAIL);
- if (device_func[DF_IOCTL])
- device_func[DF_IOCTL]->checkbus (DEVICE_TYPE_CHECKAVAIL);
+
}
#endif
-int sys_command_isopen (int unitnum)
+void blkdev_default_prefs (struct uae_prefs *p)
{
- return openlist[unitnum];
+ for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ p->cdimagefile[i][0] = 0;
+ p->cdimagefileuse[i] = false;
+ p->cdscsidevicetype[i] = SCSI_UNIT_NONE;
+ cdscsidevicetype[i] = SCSI_UNIT_NONE;
+ }
}
-void sys_command_setunit (int unitnum)
+void blkdev_fix_prefs (struct uae_prefs *p)
{
- forcedunit = unitnum;
-}
+ for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++)
+ cdscsidevicetype[i] = p->cdscsidevicetype[i];
-int sys_command_open (int mode, int unitnum)
-{
- int ret = 0;
+ // blkdev_win32_aspi.cpp does not support multi units
+ if (currprefs.win32_uaescsimode >= UAESCSI_ASPI_FIRST) {
+ for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++)
+ cdscsidevicetype[i] = SCSI_UNIT_ASPI;
+ return;
+ }
- if (forcedunit >= 0) {
- if (unitnum != forcedunit)
- return 0;
+ for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ if (cdscsidevicetype[i] != SCSI_UNIT_NONE)
+ continue;
+ if (p->cdimagefileuse[i] || p->cdimagefile[i][0]) {
+ TCHAR *name = p->cdimagefile[i];
+ if (_tcslen (name) == 3 && name[1] == ':' && name[2] == '\\') {
+ if (currprefs.scsi && (currprefs.win32_uaescsimode == UAESCSI_SPTI || currprefs.win32_uaescsimode == UAESCSI_SPTISCAN))
+ cdscsidevicetype[i] = SCSI_UNIT_SPTI;
+ else
+ cdscsidevicetype[i] = SCSI_UNIT_IOCTL;
+ } else {
+ cdscsidevicetype[i] = SCSI_UNIT_IMAGE;
+ }
+ } else if (currprefs.scsi) {
+ if (currprefs.win32_uaescsimode == UAESCSI_CDEMU)
+ cdscsidevicetype[i] = SCSI_UNIT_IOCTL;
+ else if (currprefs.win32_uaescsimode >= UAESCSI_ASPI_FIRST)
+ cdscsidevicetype[i] = SCSI_UNIT_ASPI;
+ else
+ cdscsidevicetype[i] = SCSI_UNIT_SPTI;
+ } else {
+ cdscsidevicetype[i] = SCSI_UNIT_IOCTL;
+ }
}
- if (mode == DF_SCSI || !have_ioctl) {
- if (device_func[DF_SCSI] != NULL)
- ret = device_func[DF_SCSI]->opendev (unitnum);
- } else {
- ret = device_func[DF_IOCTL]->opendev (unitnum);
+}
+
+
+int sys_command_isopen (int unitnum)
+{
+ return openlist[unitnum];
+}
+
+int sys_command_open (int unitnum)
+{
+ int ret = 0;
+ if (openlist[unitnum])
+ write_log (L"BUG unit %d open: opencnt=%d!\n", unitnum, openlist[unitnum]);
+ if (device_func[unitnum]) {
+ ret = device_func[unitnum]->opendev (unitnum, currprefs.cdimagefile[unitnum][0] ? currprefs.cdimagefile[unitnum] : NULL);
+ if (ret)
+ openlist[unitnum]++;
}
- if (ret)
- openlist[unitnum]++;
return ret;
}
-void sys_command_close (int mode, int unitnum)
+void sys_command_close (int unitnum)
{
- if (mode == DF_SCSI || !have_ioctl) {
- if (device_func[DF_SCSI] != NULL)
- device_func[DF_SCSI]->closedev (unitnum);
- } else {
- device_func[DF_IOCTL]->closedev (unitnum);
+ if (openlist[unitnum] <= 0)
+ write_log (L"BUG unit %d close: opencnt=%d!\n", unitnum, openlist[unitnum]);
+ if (device_func[unitnum]) {
+ device_func[unitnum]->closedev (unitnum);
+ if (openlist[unitnum] > 0)
+ openlist[unitnum]--;
}
- if (openlist[unitnum] > 0)
- openlist[unitnum]--;
}
void device_func_reset (void)
{
- have_ioctl = 0;
}
int device_func_init (int flags)
{
- static int old_flags = -1;
- int support_scsi = 0, support_ioctl = 0;
- int oflags;
-
- if (flags & DEVICE_TYPE_USE_OLD) {
- if (old_flags >= 0)
- flags = old_flags;
- else
- flags &= ~DEVICE_TYPE_USE_OLD;
+ device_func_reset ();
+ blkdev_fix_prefs (&currprefs);
+ install_driver (flags);
+ return 1;
+}
+
+static TCHAR newimagefiles[MAX_TOTAL_SCSI_DEVICES][256];
+static int imagechangetime[MAX_TOTAL_SCSI_DEVICES];
+static bool cdimagefileinuse[MAX_TOTAL_SCSI_DEVICES], wasopen[MAX_TOTAL_SCSI_DEVICES];
+
+static void check_changes (int unitnum)
+{
+ bool changed = false;
+
+ if (_tcscmp (changed_prefs.cdimagefile[unitnum], currprefs.cdimagefile[unitnum]) != 0)
+ changed = true;
+ if (!changed && changed_prefs.cdimagefile[unitnum][0] == 0 && changed_prefs.cdimagefileuse[unitnum] != currprefs.cdimagefileuse[unitnum])
+ changed = true;
+
+ if (changed) {
+ cdimagefileinuse[unitnum] = changed_prefs.cdimagefileuse[unitnum];
+ _tcscpy (newimagefiles[unitnum], changed_prefs.cdimagefile[unitnum]);
+ changed_prefs.cdimagefile[unitnum][0] = currprefs.cdimagefile[unitnum][0] = 0;
+ currprefs.cdimagefileuse[unitnum] = changed_prefs.cdimagefileuse[unitnum];
+ int pollmode = 0;
+ imagechangetime[unitnum] = 3 * 50;
+ struct device_info di;
+ device_func[unitnum]->info (unitnum, &di, 0);
+ wasopen[unitnum] = di.open;
+ if (wasopen[unitnum]) {
+ device_func[unitnum]->closedev (unitnum);
+ if (currprefs.scsi) {
+ scsi_do_disk_change (unitnum, 0, &pollmode);
+ if (pollmode)
+ imagechangetime[unitnum] = 8 * 50;
+ }
+ }
+ write_log (L"CD: eject (%s)\n", pollmode ? L"slow" : L"fast");
+#ifdef RETROPLATFORM
+ rp_cd_image_change (unitnum, NULL);
+#endif
+ }
+ if (imagechangetime[unitnum] == 0)
+ return;
+ imagechangetime[unitnum]--;
+ if (imagechangetime[unitnum] > 0)
+ return;
+ _tcscpy (currprefs.cdimagefile[unitnum], newimagefiles[unitnum]);
+ _tcscpy (changed_prefs.cdimagefile[unitnum], newimagefiles[unitnum]);
+ currprefs.cdimagefileuse[unitnum] = changed_prefs.cdimagefileuse[unitnum] = cdimagefileinuse[unitnum];
+ newimagefiles[unitnum][0] = 0;
+ write_log (L"CD: delayed insert '%s'\n", currprefs.cdimagefile[unitnum][0] ? currprefs.cdimagefile[unitnum] : L"<EMPTY>");
+ device_func_init (0);
+ if (wasopen[unitnum]) {
+ if (!device_func[unitnum]->opendev (unitnum, currprefs.cdimagefile[unitnum])) {
+ write_log (L"-> device open failed\n");
+ }
+ }
+ wasopen[unitnum] = 0;
+ if (currprefs.scsi) {
+ struct device_info di;
+ device_func[unitnum]->info (unitnum, &di, 0);
+ int pollmode;
+ scsi_do_disk_change (unitnum, 1, &pollmode);
}
+#ifdef RETROPLATFORM
+ rp_cd_image_change (unitnum, currprefs.cdimagefile[unitnum]);
+#endif
+ config_changed = 1;
- old_flags = flags;
+}
- oflags = (flags & DEVICE_TYPE_SCSI) ? 0 : (1 << INQ_ROMD);
+void blkdev_vsync (void)
+{
+ for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++)
+ check_changes (i);
+}
- forcedunit = -1;
- install_driver (flags);
- if (device_func[DF_IOCTL])
- have_ioctl = 1;
- else
- have_ioctl = 0;
- if (flags & DEVICE_TYPE_ALLOWEMU)
- oflags |= DEVICE_TYPE_ALLOWEMU;
- if (device_func[DF_SCSI]) {
- if (device_func[DF_SCSI] != device_func[DF_IOCTL])
- support_scsi = device_func[DF_SCSI]->openbus (oflags) ? 1 : 0;
- else
- support_scsi = 1;
- }
- oflags |= 1 << INQ_ROMD;
- if (have_ioctl)
- support_ioctl = device_func[DF_IOCTL]->openbus (oflags) ? 1 : 0;
- write_log (L"support_scsi = %d support_ioctl = %d\n", support_scsi, support_ioctl);
- return (support_scsi ? (1 << DF_SCSI) : 0) | (support_ioctl ? (1 << DF_IOCTL) : 0);
+static int do_scsi (int unitnum, uae_u8 *cmd, int cmdlen)
+{
+ return 0;
+}
+static int do_scsi (int unitnum, uae_u8 *cmd, int cmdlen, uae_u8 *out, int outsize)
+{
+ return 0;
+}
+
+static int failunit (int unitnum)
+{
+ if (unitnum < 0 || unitnum >= MAX_TOTAL_SCSI_DEVICES)
+ return 1;
+ if (device_func[unitnum] == NULL)
+ return 1;
+ return 0;
}
static int audiostatus (int unitnum)
{
uae_u8 cmd[10] = {0x42,2,0x40,1,0,0,0,(uae_u8)(DEVICE_SCSI_BUFSIZE>>8),(uae_u8)(DEVICE_SCSI_BUFSIZE&0xff),0};
- uae_u8 *p = device_func[DF_SCSI]->exec_in (unitnum, cmd, sizeof (cmd), 0);
+ uae_u8 *p = device_func[unitnum]->exec_in (unitnum, cmd, sizeof (cmd), 0);
if (!p)
return 0;
return p[1];
}
/* pause/unpause CD audio */
-void sys_command_cd_pause (int mode, int unitnum, int paused)
+int sys_command_cd_pause (int unitnum, int paused)
{
- if (mode == DF_SCSI || !have_ioctl) {
+ if (failunit (unitnum))
+ return -1;
+ if (device_func[unitnum]->pause == NULL) {
int as = audiostatus (unitnum);
- if ((paused && as == 0x11) && (!paused && as == 0x12)) {
- uae_u8 cmd[10] = {0x4b,0,0,0,0,0,0,0,paused?0:1,0};
- device_func[DF_SCSI]->exec_out (unitnum, cmd, sizeof (cmd));
- }
- return;
+ uae_u8 cmd[10] = {0x4b,0,0,0,0,0,0,0,paused?0:1,0};
+ do_scsi (unitnum, cmd, sizeof cmd);
+ return as == AUDIO_STATUS_PAUSED;
}
- device_func[DF_IOCTL]->pause (unitnum, paused);
+ return device_func[unitnum]->pause (unitnum, paused);
}
/* stop CD audio */
-void sys_command_cd_stop (int mode, int unitnum)
+void sys_command_cd_stop (int unitnum)
{
- if (mode == DF_SCSI || !have_ioctl) {
+ if (failunit (unitnum))
+ return;
+ if (device_func[unitnum]->stop == NULL) {
int as = audiostatus (unitnum);
- if (as == 0x11) {
- uae_u8 cmd[6] = {0x4e,0,0,0,0,0};
- device_func[DF_SCSI]->exec_out (unitnum, cmd, sizeof (cmd));
- }
+ uae_u8 cmd[6] = {0x4e,0,0,0,0,0};
+ do_scsi (unitnum, cmd, sizeof cmd);
return;
}
- device_func[DF_IOCTL]->stop (unitnum);
+ device_func[unitnum]->stop (unitnum);
}
#if 0
static int adjustplaypos (int unitnum, int startlsn)
{
uae_u8 q[SUBQ_SIZE];
- if (!device_func[DF_IOCTL]->qcode (unitnum, q, startlsn - 1))
+ if (!device_func[unitnum]->qcode (unitnum, q, startlsn - 1))
return startlsn;
int otrack = frombcd (q[4 + 1]);
int lsn = startlsn;
int max = 150;
while (max-- > 0 && startlsn > 0) {
- if (!device_func[DF_IOCTL]->qcode (unitnum, q, startlsn - 1))
+ if (!device_func[unitnum]->qcode (unitnum, q, startlsn - 1))
break;
int track = frombcd (q[4 + 1]);
int idx = frombcd (q[4 + 2]);
#endif
/* play CD audio */
-int sys_command_cd_play (int mode, int unitnum, int startlsn, int endlsn, int scan)
+int sys_command_cd_play (int unitnum, int startlsn, int endlsn, int scan)
{
- if (mode == DF_SCSI || !have_ioctl) {
+ if (failunit (unitnum))
+ return 0;
+ if (device_func[unitnum]->play == NULL) {
uae_u8 cmd[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
-#if 0
- if (scan) {
- cmd[0] = 0xba;
- cmd[1] = scan < 0 ? 0x10 : 0x0;
- cmd[3] = (uae_u8)(startmsf >> 16);
- cmd[4] = (uae_u8)(startmsf >> 8);
- cmd[5] = (uae_u8)(startmsf >> 0);
- cmd[9] = 0x40;
- } else {
-#endif
- int startmsf = lsn2msf (startlsn);
- int endmsf = lsn2msf (endlsn);
- cmd[0] = 0x47;
- cmd[3] = (uae_u8)(startmsf >> 16);
- cmd[4] = (uae_u8)(startmsf >> 8);
- cmd[5] = (uae_u8)(startmsf >> 0);
- cmd[6] = (uae_u8)(endmsf >> 16);
- cmd[7] = (uae_u8)(endmsf >> 8);
- cmd[8] = (uae_u8)(endmsf >> 0);
-#if 0
- }
-#endif
- return device_func[DF_SCSI]->exec_out (unitnum, cmd, sizeof (cmd)) == 0 ? 0 : 1;
+ int startmsf = lsn2msf (startlsn);
+ int endmsf = lsn2msf (endlsn);
+ cmd[0] = 0x47;
+ cmd[3] = (uae_u8)(startmsf >> 16);
+ cmd[4] = (uae_u8)(startmsf >> 8);
+ cmd[5] = (uae_u8)(startmsf >> 0);
+ cmd[6] = (uae_u8)(endmsf >> 16);
+ cmd[7] = (uae_u8)(endmsf >> 8);
+ cmd[8] = (uae_u8)(endmsf >> 0);
+ return do_scsi (unitnum, cmd, sizeof cmd) ? 0 : 1;
}
//startlsn = adjustplaypos (unitnum, startlsn);
- return device_func[DF_IOCTL]->play (unitnum, startlsn, endlsn, scan, NULL);
+ return device_func[unitnum]->play (unitnum, startlsn, endlsn, scan, NULL);
}
/* play CD audio with subchannels */
-int sys_command_cd_play (int mode, int unitnum, int startlsn, int endlsn, int scan, play_subchannel_callback subfunc)
+int sys_command_cd_play (int unitnum, int startlsn, int endlsn, int scan, play_subchannel_callback subfunc)
{
- if (mode == DF_SCSI || !have_ioctl)
+ if (failunit (unitnum))
return 0;
+ if (device_func[unitnum]->play == NULL)
+ return sys_command_cd_play (unitnum, startlsn, endlsn, scan);
//startlsn = adjustplaypos (unitnum, startlsn);
- return device_func[DF_IOCTL]->play (unitnum, startlsn, endlsn, scan, subfunc);
+ return device_func[unitnum]->play (unitnum, startlsn, endlsn, scan, subfunc);
}
/* set CD audio volume */
-void sys_command_cd_volume (int mode, int unitnum, uae_u16 volume)
+uae_u32 sys_command_cd_volume (int unitnum, uae_u16 volume_left, uae_u16 volume_right)
{
- if (mode == DF_SCSI || !have_ioctl)
- return;
- device_func[DF_IOCTL]->volume (unitnum, volume);
+ if (failunit (unitnum))
+ return 0;
+ if (device_func[unitnum]->volume == NULL)
+ return -1;
+ return device_func[unitnum]->volume (unitnum, volume_left, volume_right);
}
/* read qcode */
-int sys_command_cd_qcode (int mode, int unitnum, uae_u8 *buf)
+int sys_command_cd_qcode (int unitnum, uae_u8 *buf)
{
- if (mode == DF_SCSI || !have_ioctl) {
- uae_u8 cmd[10] = {0x42,2,0x40,1,0,0,0,(uae_u8)(DEVICE_SCSI_BUFSIZE>>8),(uae_u8)(DEVICE_SCSI_BUFSIZE&0xff),0};
- uae_u8 *p = device_func[DF_SCSI]->exec_in (unitnum, cmd, sizeof (cmd), 0);
- if (p) {
- memcpy (buf, p, SUBQ_SIZE);
- return 1;
- }
- return 0;
+ if (failunit (unitnum))
+ return 0;
+ if (device_func[unitnum]->qcode == NULL) {
+ uae_u8 cmd[10] = {0x42,2,0x40,1,0,0,0,(uae_u8)(SUBQ_SIZE>>8),(uae_u8)(SUBQ_SIZE&0xff),0};
+ return do_scsi (unitnum, cmd, sizeof cmd, buf, SUBQ_SIZE);
}
- return device_func[DF_IOCTL]->qcode (unitnum, buf, -1);
+ return device_func[unitnum]->qcode (unitnum, buf, -1);
};
/* read table of contents */
-struct cd_toc_head *sys_command_cd_toc (int mode, int unitnum)
+int sys_command_cd_toc (int unitnum, struct cd_toc_head *toc)
{
- if (mode == DF_SCSI || !have_ioctl) {
- uae_u8 cmd [10] = { 0x43,0,2,0,0,0,1,(uae_u8)(DEVICE_SCSI_BUFSIZE>>8),(uae_u8)(DEVICE_SCSI_BUFSIZE&0xff),0};
- return NULL;
-// return device_func[DF_SCSI]->exec_in (unitnum, cmd, sizeof(cmd), 0);
+ if (failunit (unitnum))
+ return 0;
+ if (device_func[unitnum]->toc == NULL) {
+ uae_u8 buf[4 + 8 * 103];
+ int size = sizeof buf;
+ uae_u8 cmd [10] = { 0x43,0,2,0,0,0,0,(uae_u8)(size>>8),(uae_u8)(size&0xff),0};
+ if (do_scsi (unitnum, cmd, sizeof cmd, buf, size)) {
+ // toc parse to do
+ return 0;
+ }
+ return 0;
}
- return device_func[DF_IOCTL]->toc (unitnum);
+ return device_func[unitnum]->toc (unitnum, toc);
}
/* read one cd sector */
-uae_u8 *sys_command_cd_read (int mode, int unitnum, uae_u8 *data, int block, int size)
+int sys_command_cd_read (int unitnum, uae_u8 *data, int block, int size)
{
- if (mode == DF_SCSI || !have_ioctl) {
- uae_u8 cmd[12] = { 0xbe, 0, 0, 0, 0, 0, 0, 0, 1, 0x10, 0, 0 };
- cmd[3] = (uae_u8)(block >> 16);
- cmd[4] = (uae_u8)(block >> 8);
- cmd[5] = (uae_u8)(block >> 0);
- uae_u8 *p = device_func[DF_SCSI]->exec_in (unitnum, cmd, sizeof (cmd), 0);
- if (p && data)
- memcpy (data, p, size);
- return p;
+ if (failunit (unitnum))
+ return 0;
+ if (device_func[unitnum]->read == NULL) {
+ uae_u8 cmd[12] = { 0xbe, 0, block >> 24, block >> 16, block >> 8, block >> 0, size >> 16, size >> 8, size >> 0, 0x10, 0, 0 };
+ cmd[1] = 2 << 3; // 2048
+ if (!do_scsi (unitnum, cmd, sizeof cmd, data, size * 2048))
+ cmd[1] = 4 << 3; // 2048 mode2
+ return do_scsi (unitnum, cmd, sizeof cmd, data, size * 2048);
}
- return device_func[DF_IOCTL]->read (unitnum, data, block, size);
+ return device_func[unitnum]->read (unitnum, data, block, size);
}
-uae_u8 *sys_command_cd_rawread (int mode, int unitnum, uae_u8 *data, int sector, int size, int sectorsize)
+int sys_command_cd_rawread (int unitnum, uae_u8 *data, int block, int size, int sectorsize)
{
- if (mode == DF_SCSI || !have_ioctl) {
- uae_u8 cmd[12] = { 0xbe, 0, 0, 0, 0, 0, 0, 0, size, 0x10, 0, 0 };
- cmd[3] = (uae_u8)(sector >> 16);
- cmd[4] = (uae_u8)(sector >> 8);
- cmd[5] = (uae_u8)(sector >> 0);
- uae_u8 *p = device_func[DF_SCSI]->exec_in (unitnum, cmd, sizeof (cmd), 0);
- if (p && data)
- memcpy (data, p, size);
- return p;
+ if (failunit (unitnum))
+ return -1;
+ if (device_func[unitnum]->rawread == NULL) {
+ uae_u8 cmd[12] = { 0xbe, 0, block >> 24, block >> 16, block >> 8, block >> 0, size >> 16, size >> 8, size >> 0, 0x10, 0, 0 };
+ return do_scsi (unitnum, cmd, sizeof cmd, data, size * sectorsize);
}
- return device_func[DF_IOCTL]->rawread (unitnum, data, sector, size, sectorsize);
+ return device_func[unitnum]->rawread (unitnum, data, block, size, sectorsize, 0xffff);
+}
+int sys_command_cd_rawread (int unitnum, uae_u8 *data, int block, int size, int sectorsize, uae_u8 scsicmd9, uae_u8 subs)
+{
+ if (failunit (unitnum))
+ return -1;
+ if (device_func[unitnum]->rawread == NULL) {
+ uae_u8 cmd[12] = { 0xbe, 0, block >> 24, block >> 16, block >> 8, block >> 0, size >> 16, size >> 8, size >> 0, 0x10, 0, 0 };
+ return do_scsi (unitnum, cmd, sizeof cmd, data, size * sectorsize);
+ }
+ return device_func[unitnum]->rawread (unitnum, data, block, size, sectorsize, (scsicmd9 << 8) | subs);
}
/* read block */
-uae_u8 *sys_command_read (int mode, int unitnum, uae_u8 *data, int block, int size)
+int sys_command_read (int unitnum, uae_u8 *data, int block, int size)
{
- if (mode == DF_SCSI || !have_ioctl) {
- uae_u8 cmd[10] = { 0x28, 0, 0, 0, 0, 0, 0, 0, 1, 0 };
+ if (failunit (unitnum))
+ return 0;
+ if (device_func[unitnum]->read == NULL) {
+ uae_u8 cmd[12] = { 0xa8, 0, 0, 0, 0, 0, size >> 24, size >> 16, size >> 8, size >> 0, 0, 0 };
cmd[2] = (uae_u8)(block >> 24);
cmd[3] = (uae_u8)(block >> 16);
cmd[4] = (uae_u8)(block >> 8);
cmd[5] = (uae_u8)(block >> 0);
- uae_u8 *p = device_func[DF_SCSI]->exec_in (unitnum, cmd, sizeof (cmd), 0);
- if (p && data)
- memcpy (data, p, size);
- return p;
+ return do_scsi (unitnum, cmd, sizeof cmd, data, size * 2048);
}
- return device_func[DF_IOCTL]->read (unitnum, data, block, size);
+ return device_func[unitnum]->read (unitnum, data, block, size);
}
/* write block */
-int sys_command_write (int mode, int unitnum, uae_u8 *data, int offset, int size)
+int sys_command_write (int unitnum, uae_u8 *data, int offset, int size)
{
- if (mode == DF_SCSI || !have_ioctl) {
- uae_u8 cmd[10] = { 0x2a, 0, 0, 0, 0, 0, 0, 0, size, 0 };
- cmd[2] = (uae_u8)(offset >> 24);
- cmd[3] = (uae_u8)(offset >> 16);
- cmd[4] = (uae_u8)(offset >> 8);
- cmd[5] = (uae_u8)(offset >> 0);
- if (device_func[DF_SCSI]->exec_in (unitnum, cmd, sizeof (cmd), 0))
- return -1;
+ if (failunit (unitnum))
return 0;
- }
- return device_func[DF_IOCTL]->write (unitnum, data, offset, size);
+ if (device_func[unitnum]->write == NULL)
+ return 0;
+ return device_func[unitnum]->write (unitnum, data, offset, size);
}
-int sys_command_ismedia (int mode, int unitnum, int quick)
+int sys_command_ismedia (int unitnum, int quick)
{
- struct device_info di;
-
- if (forcedunit >= 0) {
- if (unitnum != forcedunit)
- return -1;
- }
-
- if (mode == DF_SCSI || !have_ioctl || !device_func[DF_IOCTL]->ismedia) {
- if (quick)
- return -1;
- memset(&di, 0, sizeof di);
- if (device_func[DF_SCSI]->info (unitnum, &di, quick) == NULL, quick)
- return -1;
- return di.media_inserted;
+ if (failunit (unitnum))
+ return -1;
+ if (device_func[unitnum] == NULL) {
+ uae_u8 cmd[6] = { 0, 0, 0, 0, 0, 0 };
+ return do_scsi (unitnum, cmd, sizeof cmd);
} else {
- return device_func[DF_IOCTL]->ismedia (unitnum, quick);
+ return device_func[unitnum]->ismedia (unitnum, quick);
}
}
-struct device_info *sys_command_info (int mode, int unitnum, struct device_info *di, int quick)
-{
- if (mode == DF_SCSI || !have_ioctl)
- return device_func[DF_SCSI]->info (unitnum, di, quick);
- else
- return device_func[DF_IOCTL]->info (unitnum, di, quick);
-}
-
-struct device_scsi_info *sys_command_scsi_info (int mode, int unitnum, struct device_scsi_info *dsi)
+struct device_info *sys_command_info (int unitnum, struct device_info *di, int quick)
{
- if (mode == DF_SCSI || !have_ioctl)
- return device_func[DF_SCSI]->scsiinfo (unitnum, dsi);
- else
- return device_func[DF_IOCTL]->scsiinfo (unitnum, dsi);
+ return device_func[unitnum]->info (unitnum, di, quick);
}
#define MODE_SELECT_6 0x15
dstbak = dst = xmalloc (uae_u8, 4 + 256);
save_u32 (4);
- save_string (currprefs.cdimagefile);
+ for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ save_string (currprefs.cdimagefile[i]);
+ save_u32 (currprefs.cdscsidevicetype[i]);
+ }
*len = dst - dstbak;
return dstbak;
}
flags = restore_u32 ();
s = restore_string ();
if ((flags & 4) && unit == 0) {
- _tcscpy (changed_prefs.cdimagefile, s);
- _tcscpy (currprefs.cdimagefile, s);
+ _tcscpy (changed_prefs.cdimagefile[0], s);
+ _tcscpy (currprefs.cdimagefile[0], s);
}
return src;
}
}
static uae_u64 cmd_readx (int unitnum, uae_u8 *dataptr, int offset, int len)
{
- if (device_func[DF_IOCTL]->read (unitnum, dataptr, offset, len))
+ if (device_func[unitnum]->read (unitnum, dataptr, offset, len))
return len;
else
return 0;
{
return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]);
}
+static int rw (uae_u8 *p)
+{
+ return (p[0] << 8) | (p[1]);
+}
-static struct cd_toc *gettoc (struct device_info *di, int block)
+static void stopplay (int unitnum)
{
- for (int i = di->toc.first_track_offset; i < di->toc.last_track_offset; i++) {
- struct cd_toc *t = &di->toc.toc[i];
- if (t->paddress > block) {
- if (t->point == 1)
- return t;
- return t - 1;
+ sys_command_cd_stop (unitnum);
+}
+
+static int addtocentry (uae_u8 **dstp, int *len, int point, int newpoint, int msf, uae_u8 *head, struct cd_toc_head *th)
+{
+ uae_u8 *dst = *dstp;
+
+ for (int i = 0; i < th->points; i++) {
+ struct cd_toc *t = &th->toc[i];
+ if (t->point == point) {
+ if (*len < 8)
+ return 0;
+ int addr = t->paddress;
+ if (msf)
+ addr = lsn2msf (addr);
+ dst[0] = 0;
+ dst[1] = (t->adr << 4) | t->control;
+ dst[2] = newpoint >= 0 ? newpoint : point;
+ dst[3] = 0;
+ dst[4] = addr >> 24;
+ dst[5] = addr >> 16;
+ dst[6] = addr >> 8;
+ dst[7] = addr >> 0;
+
+ if (point >= 1 && point <= 99) {
+ if (head[2] == 0)
+ head[2] = point;
+ head[3] = point;
+ }
+
+ *len -= 8;
+ *dstp = dst + 8;
+ return 1;
}
}
- return &di->toc.toc[di->toc.last_track_offset];
+ return -1;
+}
+
+static int scsi_read_cd (int unitnum, uae_u8 *cmd, uae_u8 *data, struct device_info *di)
+{
+ int msf = cmd[0] == 0xb9;
+ int start = msf ? msf2lsn (rl (cmd + 2) & 0x00ffffff) : rl (cmd + 2);
+ int len = rl (cmd + 5) & 0x00ffffff;
+ if (msf) {
+ int end = msf2lsn (len);
+ len = end - start;
+ if (len < 0)
+ return -1;
+ }
+ int subs = cmd[10] & 7;
+ if (len == 0)
+ return 0;
+ return sys_command_cd_rawread (unitnum, data, start, len, 0, cmd[9], subs);
}
static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len,
int lr = 0, ls = 0;
int scsi_len = -1;
int status = 0;
- int i;
- char *ss;
struct device_info di;
*reply_len = *sense_len = 0;
memset (r, 0, 256);
memset (s, 0, 256);
- sys_command_info (DF_IOCTL, unitnum, &di, 1);
+ sys_command_info (unitnum, &di, 1);
if (cmdbuf[0] == 0) { /* TEST UNIT READY */
if (nodisk (&di))
scsi_len = 0;
goto end;
}
-
+ write_log (L"SCSIEMU %d: %02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X CMDLEN=%d DATA=%08X LEN=%d\n", unitnum,
+ cmdbuf[0], cmdbuf[1], cmdbuf[2], cmdbuf[3], cmdbuf[4], cmdbuf[5], cmdbuf[6],
+ cmdbuf[7], cmdbuf[8], cmdbuf[9], cmdbuf[10], cmdbuf[11],
+ scsi_cmd_len, scsi_data, *data_len);
switch (cmdbuf[0])
{
case 0x12: /* INQUIRY */
+ {
if ((cmdbuf[1] & 1) || cmdbuf[2] != 0)
goto err;
len = cmdbuf[4];
scsi_len = lr = len < 36 ? (uae_u32)len : 36;
r[2] = 2;
r[3] = 2;
- ss = "UAE";
- i = 0; /* vendor id */
- while (i < 8 && ss[i]) {
- r[8 + i] = ss[i];
- i++;
- }
- while (i < 8) {
- r[8 + i] = 32;
- i++;
- }
- char tmp[256];
- sprintf (tmp, "SCSI CD%d EMU", unitnum);
- ss = tmp;
- i = 0; /* product id */
- while (i < 16 && ss[i]) {
- r[16 + i] = ss[i];
- i++;
- }
- while (i < 16) {
- r[16 + i] = 32;
- i++;
- }
- ss = "0.1";
- i = 0; /* product revision */
- while (i < 4 && ss[i]) {
- r[32 + i] = ss[i];
- i++;
- }
- while (i < 4) {
- r[32 + i] = 32;
- i++;
+ char *s = ua (di.vendorid);
+ memcpy (r + 8, s, strlen (s));
+ xfree (s);
+ s = ua (di.productid);
+ memcpy (r + 16, s, strlen (s));
+ xfree (s);
+ s = ua (di.revision);
+ memcpy (r + 32, s, strlen (s));
+ xfree (s);
+ for (int i = 8; i < 36; i++) {
+ if (r[i] == 0)
+ r[i] = 32;
}
+ }
+ break;
+ case 0xbe: // READ CD
+ case 0xb9: // READ CD MSF
+ if (nodisk (&di))
+ goto nodisk;
+ scsi_len = scsi_read_cd (unitnum, cmdbuf, scsi_data, &di);
+ if (scsi_len == -2)
+ goto notdatatrack;
+ if (scsi_len == -1)
+ goto errreq;
break;
+ case 0x55: // MODE SELECT(10)
+ case 0x15: // MODE SELECT(6)
+ {
+ uae_u8 *p;
+ p = scsi_data + 4;
+ if (cmdbuf[0] == 0x55)
+ p += 4;
+ int pcode = p[0] & 0x3f;
+ if (pcode == 14) { // CD audio control
+ uae_u16 vol_left = (p[9] << 7) | (p[9] >> 1);
+ uae_u16 vol_right = (p[11] << 7) | (p[11] >> 1);
+ sys_command_cd_volume (unitnum, vol_left, vol_right);
+ scsi_len = 0;
+ } else {
+ goto errreq;
+ }
+ }
+ break;
+ case 0x5a: // MODE SENSE(10)
case 0x1a: /* MODE SENSE(6) */
- {
- uae_u8 *p;
- int pc = cmdbuf[2] >> 6;
- int pcode = cmdbuf[2] & 0x3f;
- int dbd = cmdbuf[1] & 8;
- int cyl, cylsec, head, tracksec;
- if (nodisk (&di))
- goto nodisk;
- cyl = di.cylinders;
- head = 1;
- cylsec = tracksec = di.trackspercylinder;
- //write_log (L"MODE SENSE PC=%d CODE=%d DBD=%d\n", pc, pcode, dbd);
- p = r;
+ {
+ uae_u8 *p;
+ int pc = cmdbuf[2] >> 6;
+ int pcode = cmdbuf[2] & 0x3f;
+ int dbd = cmdbuf[1] & 8;
+ if (cmdbuf[0] == 0x5a)
+ dbd = 1;
+ write_log (L"MODE SENSE PC=%d CODE=%d DBD=%d\n", pc, pcode, dbd);
+ p = r;
+ if (cmdbuf[0] == 0x5a) {
+ p[0] = 8 - 1;
+ p[1] = 0;
+ p[2] = 0;
+ p[3] = 0;
+ p[4] = 0;
+ p[5] = 0;
+ p[6] = 0;
+ p[7] = 0;
+ p += 8;
+ } else {
p[0] = 4 - 1;
p[1] = 0;
p[2] = 0;
p[3] = 0;
p += 4;
- if (!dbd) {
- uae_u32 blocks = di.sectorspertrack * di.cylinders * di.trackspercylinder;
- p[-1] = 8;
- wl(p + 0, blocks);
- wl(p + 4, di.bytespersector);
- p += 8;
- }
- if (pcode == 0) {
- p[0] = 0;
- p[1] = 0;
- p[2] = 0x20;
- p[3] = 0;
- r[0] += 4;
- } else if (pcode == 3) {
- p[0] = 3;
- p[1] = 24;
- p[3] = 1;
- p[10] = tracksec >> 8;
- p[11] = tracksec;
- p[12] = di.bytespersector >> 8;
- p[13] = di.bytespersector;
- p[15] = 1; // interleave
- p[20] = 0x80;
- r[0] += p[1];
- } else if (pcode == 4) {
- p[0] = 4;
- wl(p + 1, cyl);
- p[1] = 24;
- p[5] = head;
- wl(p + 13, cyl);
- ww(p + 20, 0);
- r[0] += p[1];
- } else {
- goto err;
- }
- r[0] += r[3];
- scsi_len = lr = r[0] + 1;
- break;
}
- break;
+ if (!dbd) {
+ if (nodisk (&di))
+ goto nodisk;
+ uae_u32 blocks = di.sectorspertrack * di.cylinders * di.trackspercylinder;
+ p[-1] = 8;
+ wl(p + 0, blocks);
+ wl(p + 4, di.bytespersector);
+ p += 8;
+ }
+ if (pcode == 0) {
+ p[0] = 0;
+ p[1] = 0;
+ p[2] = 0x20;
+ p[3] = 0;
+ r[0] += 4;
+ } else if (pcode == 3) {
+ if (nodisk (&di))
+ goto nodisk;
+ p[0] = 3;
+ p[1] = 24;
+ p[3] = 1;
+ p[10] = di.trackspercylinder >> 8;
+ p[11] = di.trackspercylinder;
+ p[12] = di.bytespersector >> 8;
+ p[13] = di.bytespersector;
+ p[15] = 1; // interleave
+ p[20] = 0x80;
+ r[0] += p[1];
+ } else if (pcode == 4) {
+ if (nodisk (&di))
+ goto nodisk;
+ p[0] = 4;
+ wl(p + 1, di.cylinders);
+ p[1] = 24;
+ p[5] = 1;
+ wl(p + 13, di.cylinders);
+ ww(p + 20, 0);
+ r[0] += p[1];
+ } else if (pcode == 14) { // CD audio control
+ uae_u32 vol = sys_command_cd_volume (unitnum, 0xffff, 0xffff);
+ p[0] = 0x0e;
+ p[1] = 0x0e;
+ p[2] = 1;
+ p[3] = 4;
+ p[6] = 0;
+ p[7] = 75;
+ p[8] = 1;
+ p[9] = pc == 0 ? (vol >> 7) & 0xff : 0xff;
+ p[10] = 2;
+ p[11] = pc == 0 ? (vol >> (16 + 7)) & 0xff : 0xff;
+ r[0] += p[1];
+ } else {
+ goto err;
+ }
+ r[0] += r[3];
+ scsi_len = lr = r[0] + 1;
+ }
+ break;
case 0x1d: /* SEND DIAGNOSTICS */
scsi_len = 0;
break;
{
if (nodisk (&di))
goto nodisk;
+ stopplay (unitnum);
offset = ((cmdbuf[1] & 31) << 16) | (cmdbuf[2] << 8) | cmdbuf[3];
- struct cd_toc *t = gettoc (&di, offset);
+ struct cd_toc *t = gettoc (&di.toc, offset);
if ((t->control & 0x0c) == 0x04) {
len = cmdbuf[4];
if (!len)
{
if (nodisk (&di))
goto nodisk;
+ stopplay (unitnum);
offset = rl (cmdbuf + 2);
- struct cd_toc *t = gettoc (&di, offset);
+ struct cd_toc *t = gettoc (&di.toc, offset);
if ((t->control & 0x0c) == 0x04) {
len = rl (cmdbuf + 7 - 2) & 0xffff;
scsi_len = cmd_readx (unitnum, scsi_data, offset, len) * di.bytespersector;
{
if (nodisk (&di))
goto nodisk;
+ stopplay (unitnum);
offset = rl (cmdbuf + 2);
- struct cd_toc *t = gettoc (&di, offset);
+ struct cd_toc *t = gettoc (&di.toc, offset);
if ((t->control & 0x0c) == 0x04) {
len = rl (cmdbuf + 6);
scsi_len = (uae_u32)cmd_readx (unitnum, scsi_data, offset, len) * di.bytespersector;;
goto readprot;
case 0x43: // READ TOC
{
+ if (nodisk (&di))
+ goto nodisk;
uae_u8 *p = scsi_data;
int strack = cmdbuf[6];
int msf = cmdbuf[1] & 2;
+ int format = cmdbuf[2] & 7;
+ if (format >= 3)
+ goto errreq;
int maxlen = (cmdbuf[7] << 8) | cmdbuf[8];
- struct cd_toc_head *toc = sys_command_cd_toc (DF_IOCTL, unitnum);
- if (!toc)
+ struct cd_toc_head ttoc;
+ if (!sys_command_cd_toc (unitnum, &ttoc))
goto readerr;
+ struct cd_toc_head *toc = &ttoc;
if (maxlen < 4)
goto errreq;
- if (strack == 0)
- strack = toc->first_track;
- if (strack >= 100 && strack != 0xaa)
- goto errreq;
- if (strack == 0xaa)
- strack = 0xa2;
- uae_u8 *p2 = p + 4;
- p[2] = 0;
- p[3] = 0;
- for (int i = 0; i < toc->points; i++) {
- if (strack == toc->toc[i].point) {
- int trk = strack >= 100 ? 0xaa : strack;
- if (p[2] == 0)
- p[2] = trk;
- p[3] = trk;
- int addr = toc->toc[i].paddress;
- if (msf)
- addr = lsn2msf (addr);
- if (p2 - p + 8 > maxlen)
+ if (format == 1) {
+ p[0] = 0;
+ p[1] = 8;
+ p[2] = 1;
+ p[3] = 1;
+ p[4] = 0;
+ p[5] = (toc->toc[0].adr << 4) | toc->toc[0].control;
+ p[6] = toc->first_track;
+ p[7] = 0;
+ if (msf)
+ wl (p + 8, lsn2msf (toc->toc[0].address));
+ else
+ wl (p + 8 , toc->toc[0].address);
+ scsi_len = 12;
+ } else if (format == 2 || format == 0) {
+ if (format == 2 && !msf)
+ goto errreq;
+ if (strack == 0)
+ strack = toc->first_track;
+ if (format == 0 && strack >= 100 && strack != 0xaa)
+ goto errreq;
+ uae_u8 *p2 = p + 4;
+ p[2] = 0;
+ p[3] = 0;
+ maxlen -= 4;
+ if (format == 2) {
+ if (!addtocentry (&p2, &maxlen, 0xa0, -1, msf, p, toc))
+ goto errreq;
+ if (!addtocentry (&p2, &maxlen, 0xa1, -1, msf, p, toc))
+ goto errreq;
+ if (!addtocentry (&p2, &maxlen, 0xa2, -1, msf, p, toc))
+ goto errreq;
+ }
+ while (strack < 100) {
+ if (!addtocentry (&p2, &maxlen, strack, -1, msf, p, toc))
goto errreq;
- p2[0] = 0;
- p2[1] = (toc->toc[i].adr << 4) | toc->toc[i].control;
- p2[2] = trk;
- p2[3] = 0;
- p2[4] = addr >> 24;
- p2[5] = addr >> 16;
- p2[6] = addr >> 8;
- p2[7] = addr >> 0;
- p2 += 8;
strack++;
}
- if (i == toc->points - 1) {
- if (strack >= 0xa2)
- break;
- i = 0;
- strack = 0xa2;
+ if (!addtocentry (&p2, &maxlen, 0xa2, 0xaa, msf, p, toc))
+ goto errreq;
+ int tlen = p2 - (p + 4);
+ p[0] = tlen >> 8;
+ p[1] = tlen >> 0;
+ scsi_len = tlen + 4;
+ }
+ }
+ break;
+ case 0x42: // READ SUB-CHANNEL
+ {
+ int msf = cmdbuf[1] & 2;
+ int subq = cmdbuf[2] & 0x40;
+ int format = cmdbuf[3];
+ int track = cmdbuf[6];
+ int len = rw (cmdbuf + 7);
+ uae_u8 buf[SUBQ_SIZE] = { 0 };
+
+ if (nodisk (&di))
+ goto nodisk;
+ sys_command_cd_qcode (unitnum, buf);
+ if (len < 4)
+ goto errreq;
+ scsi_len = 4;
+ scsi_data[0] = 0;
+ scsi_data[1] = buf[1];
+ if (subq && format == 1) {
+ if (len < 4 + 12)
+ goto errreq;
+ scsi_data[2] = 0;
+ scsi_data[3] = 12;
+ scsi_len += 12;
+ scsi_data[4] = 1;
+ scsi_data[5] = (buf[4 + 0] << 4) | (buf[4 + 0] >> 4);
+ scsi_data[6] = frombcd (buf[4 + 1]); // track
+ scsi_data[7] = frombcd (buf[4 + 2]); // index
+ int reladdr = fromlongbcd (&buf[4 + 3]);
+ int absaddr = fromlongbcd (&buf[4 + 7]);
+ if (!msf) {
+ reladdr = msf2lsn (reladdr);
+ absaddr = msf2lsn (absaddr);
+ }
+ wl (scsi_data + 8, absaddr);
+ wl (scsi_data + 12, reladdr);
+ } else {
+ scsi_data[2] = 0;
+ scsi_data[3] = 0;
+ }
+ }
+ break;
+ case 0x1b: // START/STOP
+ sys_command_cd_stop (unitnum);
+ scsi_len = 0;
+ break;
+ case 0x4e: // STOP PLAY/SCAN
+ if (nodisk (&di))
+ goto nodisk;
+ sys_command_cd_stop (unitnum);
+ scsi_len = 0;
+ break;
+ case 0xba: // SCAN
+ {
+ if (nodisk (&di))
+ goto nodisk;
+ struct cd_toc_head ttoc;
+ if (!sys_command_cd_toc (unitnum, &ttoc))
+ goto readerr;
+ struct cd_toc_head *toc = &ttoc;
+ int scan = (cmdbuf[1] & 0x10) ? -1 : 1;
+ int start = rl (cmdbuf + 1) & 0x00ffffff;
+ int end = scan > 0 ? toc->lastaddress : toc->toc[toc->first_track_offset].paddress;
+ int type = cmdbuf[9] >> 6;
+ if (type == 1)
+ start = lsn2msf (start);
+ if (type == 3)
+ goto errreq;
+ if (type == 2) {
+ if (toc->first_track_offset + start >= toc->last_track_offset)
+ goto errreq;
+ start = toc->toc[toc->first_track_offset + start].paddress;
+ }
+ sys_command_cd_play (unitnum, start, end, scan, NULL);
+ scsi_len = 0;
+ }
+ break;
+ case 0x48: // PLAY AUDIO TRACK/INDEX
+ {
+ if (nodisk (&di))
+ goto nodisk;
+ int strack = cmdbuf[4];
+ int etrack = cmdbuf[7];
+ struct cd_toc_head ttoc;
+ if (!sys_command_cd_toc (unitnum, &ttoc))
+ goto readerr;
+ struct cd_toc_head *toc = &ttoc;
+ if (strack < toc->first_track || strack > toc->last_track ||
+ etrack < toc->first_track || etrack > toc->last_track ||
+ strack > etrack)
+ goto errreq;
+ int start = toc->toc[toc->first_track_offset + strack - 1].paddress;
+ int end = etrack == toc->last_track ? toc->lastaddress : toc->toc[toc->first_track_offset + etrack - 1 + 1].paddress;
+ if (!sys_command_cd_play (unitnum, start, end, 0, NULL))
+ goto notdatatrack;
+ scsi_len = 0;
+ }
+ break;
+ case 0x47: // PLAY AUDIO MSF
+ {
+ if (nodisk (&di))
+ goto nodisk;
+ int start = rl (cmdbuf + 2) & 0x00ffffff;
+ if (start == 0x00ffffff) {
+ uae_u8 buf[SUBQ_SIZE] = { 0 };
+ sys_command_cd_qcode (unitnum, buf);
+ start = fromlongbcd (buf + 4 + 7);
+ }
+ int end = msf2lsn (rl (cmdbuf + 5) & 0x00ffffff);
+ start = msf2lsn (start);
+ if (start > end)
+ goto errreq;
+ if (start < end)
+ sys_command_cd_play (unitnum, start, end, 0, NULL);
+ scsi_len = 0;
+ }
+ break;
+ case 0x45: // PLAY AUDIO
+ {
+ if (nodisk (&di))
+ goto nodisk;
+ int start = rl (cmdbuf + 2);
+ int len = rw (cmdbuf + 7);
+ if (len > 0) {
+ if (start == -1) {
+ uae_u8 buf[SUBQ_SIZE] = { 0 };
+ sys_command_cd_qcode (unitnum, buf);
+ start = msf2lsn (fromlongbcd (buf + 4 + 7));
}
+ sys_command_cd_play (unitnum, start, start + len, 0, NULL);
+ }
+ scsi_len = 0;
+ }
+ break;
+ case 0xbc: // PLAY CD
+ {
+ if (nodisk (&di))
+ goto nodisk;
+ int start = -1;
+ int end = -1;
+ if (cmdbuf[1] & 2) {
+ start = msf2lsn (rl (cmdbuf + 2) & 0x00ffffff);
+ end = msf2lsn (rl (cmdbuf + 5) & 0x00ffffff);
+ } else {
+ start = rl (cmdbuf + 2);
+ end = start + rl (cmdbuf + 6);
}
- int tlen = p2 - (p + 4);
- p[0] = tlen >> 8;
- p[1] = tlen >> 0;
- scsi_len = tlen + 4;
+ if (start > end)
+ goto errreq;
+ if (start < end)
+ sys_command_cd_play (unitnum, start, end, 0, NULL);
+ }
+ break;
+ case 0x4b: // PAUSE/RESUME
+ {
+ if (nodisk (&di))
+ goto nodisk;
+ uae_u8 buf[SUBQ_SIZE] = { 0 };
+ int resume = cmdbuf[8] & 1;
+ sys_command_cd_qcode (unitnum, buf);
+ if (buf[1] != AUDIO_STATUS_IN_PROGRESS && buf[1] != AUDIO_STATUS_PAUSED)
+ goto errreq;
+ sys_command_cd_pause (unitnum, resume ? 0 : 1);
+ scsi_len = 0;
}
break;
readprot:
*data_len = scsi_len;
*reply_len = lr;
*sense_len = ls;
+ if (cmdbuf[0])
+ write_log (L"-> DATAOUT=%d ST=%d SENSELEN=%d\n", scsi_len, status, ls);
return status;
}
int io_error = 0;
uae_u8 *scsi_datap, *scsi_datap_org;
uae_u32 scsi_cmd_len_orig = as->cmd_len;
- uae_u8 cmd[16];
+ uae_u8 cmd[16] = { 0 };
uae_u8 replydata[256];
int datalen = as->len;
int senselen = as->sense_len;
int sys_command_scsi_direct_native (int unitnum, struct amigascsi *as)
{
- if (scsiemu) {
+ if (scsiemu[unitnum]) {
return execscsicmd_direct (unitnum, as);
} else {
- if (!device_func[DF_SCSI] || !device_func[DF_SCSI]->exec_direct)
+ if (!device_func[unitnum]->exec_direct)
return -1;
}
- int ret = device_func[DF_SCSI]->exec_direct (unitnum, as);
- if (!ret && device_func[DF_SCSI]->isatapi(unitnum))
+ int ret = device_func[unitnum]->exec_direct (unitnum, as);
+ if (!ret && device_func[unitnum]->isatapi(unitnum))
scsi_atapi_fixup_inquiry (as);
return ret;
}
as.cmd_len = get_word (acmd + 16);
for (i = 0; i < as.cmd_len; i++)
as.cmd[i] = get_byte (ap++);
+ while (i < sizeof as.cmd)
+ as.cmd[i++] = 0;
as.flags = get_byte (acmd + 20);
as.sense_len = get_word (acmd + 26);
struct cdunit {
bool enabled;
+ bool open;
uae_u8 buffer[2352];
struct cdtoc toc[102];
int tracks;
int cdda_play_finished;
int cdda_play;
int cdda_paused;
- int cdda_volume;
- int cdda_volume_main;
+ int cdda_volume[2];
+ int cdda_scan;
int cd_last_pos;
int cdda_start, cdda_end;
play_subchannel_callback cdda_subfunc;
int donotmountme;
TCHAR newfile[MAX_DPATH];
uae_sem_t sub_sem;
+ struct device_info di;
};
-static struct cdunit cdunits[MAX_TOTAL_DEVICES];
+static struct cdunit cdunits[MAX_TOTAL_SCSI_DEVICES];
+static int bus_open;
+
+static struct cdunit *unitisopen (int unitnum)
+{
+ struct cdunit *cdu = &cdunits[unitnum];
+ if (cdu->open)
+ return cdu;
+ return NULL;
+}
static struct cdtoc *findtoc (struct cdunit *cdu, int *sectorp)
{
return ret;
}
+static void sub_to_interleaved (const uae_u8 *s, uae_u8 *d)
+{
+ for (int i = 0; i < 8 * 12; i ++) {
+ int dmask = 0x80;
+ int smask = 1 << (7 - (i & 7));
+ (*d) = 0;
+ for (int j = 0; j < 8; j++) {
+ (*d) |= (s[(i / 8) + j * 12] & smask) ? dmask : 0;
+ dmask >>= 1;
+ }
+ d++;
+ }
+}
+static void sub_to_deinterleaved (const uae_u8 *s, uae_u8 *d)
+{
+ for (int i = 0; i < 8 * 12; i ++) {
+ int dmask = 0x80;
+ int smask = 1 << (7 - (i / 12));
+ (*d) = 0;
+ for (int j = 0; j < 8; j++) {
+ (*d) |= (s[(i % 12) * 8 + j] & smask) ? dmask : 0;
+ dmask >>= 1;
+ }
+ d++;
+ }
+}
+
static void dosub (struct cdunit *cdu, struct cdtoc *t, int sector)
{
- uae_u8 *s, *d;
+ uae_u8 *d;
uae_u8 subbuf[SUB_CHANNEL_SIZE];
uae_u8 subbuf2[SUB_CHANNEL_SIZE];
memset (subbuf, 0, SUB_CHANNEL_SIZE);
int mode = getsub (subbuf, cdu, t, sector);
if (mode == 2) { // deinterleaved -> interleaved
- s = subbuf;
- d = subbuf2;
- for (int i = 0; i < 8 * 12; i ++) {
- int dmask = 0x80;
- int smask = 1 << (7 - (i & 7));
- (*d) = 0;
- for (int j = 0; j < 8; j++) {
- (*d) |= (s[(i / 8) + j * 12] & smask) ? dmask : 0;
- dmask >>= 1;
- }
- d++;
- }
-#if 0
- uae_u8 subbuf3[SUB_CHANNEL_SIZE];
- s = subbuf2;
- d = subbuf3;
- for (int i = 0; i < 8 * 12; i ++) {
- int dmask = 0x80;
- int smask = 1 << (7 - (i / 12));
- (*d) = 0;
- for (int j = 0; j < 8; j++) {
- (*d) |= (s[(i % 12) * 8 + j] & smask) ? dmask : 0;
- dmask >>= 1;
- }
- d++;
- }
-#endif
+ sub_to_interleaved (subbuf, subbuf2);
d = subbuf2;
-
-
} else {
d = subbuf;
}
int i;
WAVEHDR whdr[2];
MMRESULT mmr;
- int volume, volume_main;
+ int volume[2], volume_main;
int oldplay;
mp3decoder *mp3dec = NULL;
- struct cdunit *cdu = &cdunits[0];
+ struct cdunit *cdu = (struct cdunit*)v;
int firstloops;
for (i = 0; i < 2; i++) {
bufon[0] = bufon[1] = 0;
bufnum = 0;
buffered = 0;
- volume = -1;
+ volume[0] = volume[1] = -1;
volume_main = -1;
if (cdda_openwav ()) {
}
}
firstloops = 25;
+ while (cdu->cdda_paused && cdu->cdda_play > 0)
+ Sleep (10);
}
while (!(whdr[bufnum].dwFlags & WHDR_DONE)) {
}
bufon[bufnum] = 0;
+ if (!isaudiotrack (&cdu->di.toc, cdda_pos))
+ goto end; // data track?
+
if ((cdda_pos < cdu->cdda_end || cdu->cdda_end == 0xffffffff) && !cdu->cdda_paused && cdu->cdda_play > 0) {
struct cdtoc *t;
int sector, cnt;
for (cnt = 0; cnt < num_sectors; cnt++) {
sector = cdda_pos;
- cdda_pos++;
+ if (cdu->cdda_scan) {
+ cdda_pos += cdu->cdda_scan;
+ if (cdda_pos < 0)
+ cdda_pos = 0;
+ } else {
+ cdda_pos++;
+ }
if (cdda_pos - num_sectors < cdu->cdda_end && cdda_pos >= cdu->cdda_end)
dofinish = 1;
}
- volume = cdu->cdda_volume;
volume_main = currprefs.sound_volume;
- int vol_mult = (100 - volume_main) * volume / 100;
- if (vol_mult)
- vol_mult++;
- if (vol_mult >= 65536)
- vol_mult = 65536;
+ int vol_mult[2];
+ for (int j = 0; j < 2; j++) {
+ volume[j] = cdu->cdda_volume[j];
+ vol_mult[j] = (100 - volume_main) * volume[j] / 100;
+ if (vol_mult[j])
+ vol_mult[j]++;
+ if (vol_mult[j] >= 32768)
+ vol_mult[j] = 32768;
+ }
uae_s16 *p = (uae_s16*)(px[bufnum]);
for (i = 0; i < num_sectors * 2352 / 4; i++) {
- p[i * 2 + 0] = p[i * 2 + 0] * vol_mult / 65536;
- p[i * 2 + 1] = p[i * 2 + 1] * vol_mult / 65536;
+ p[i * 2 + 0] = p[i * 2 + 0] * vol_mult[0] / 32768;
+ p[i * 2 + 1] = p[i * 2 + 1] * vol_mult[1] / 32768;
}
-
bufon[bufnum] = 1;
mmr = waveOutWrite (cdda_wavehandle, &whdr[bufnum], sizeof (WAVEHDR));
if (mmr != MMSYSERR_NOERROR) {
static int command_pause (int unitnum, int paused)
{
- struct cdunit *cdu = &cdunits[unitnum];
- if (unitnum)
- return 0;
+ struct cdunit *cdu = unitisopen (unitnum);
+ if (!cdu)
+ return -1;
+ int old = cdu->cdda_paused;
cdu->cdda_paused = paused;
- return 1;
+ return old;
}
static int command_stop (int unitnum)
{
- struct cdunit *cdu = &cdunits[unitnum];
- if (unitnum)
+ struct cdunit *cdu = unitisopen (unitnum);
+ if (!cdu)
return 0;
cdda_stop (cdu);
return 1;
static int command_play (int unitnum, int startlsn, int endlsn, int scan, play_subchannel_callback subfunc)
{
- struct cdunit *cdu = &cdunits[unitnum];
- if (unitnum)
+ struct cdunit *cdu = unitisopen (unitnum);
+ if (!cdu)
+ return 0;
+ if (!isaudiotrack (&cdu->di.toc, startlsn))
return 0;
-
- cdu->cdda_paused = 0;
cdu->cdda_play_finished = 0;
cdu->cd_last_pos = startlsn;
cdu->cdda_start = startlsn;
cdu->cdda_end = endlsn;
cdu->cdda_subfunc = subfunc;
+ cdu->cdda_scan = scan > 0 ? 10 : (scan < 0 ? 10 : 0);
if (!cdu->cdda_play)
- uae_start_thread (L"cdda_play", cdda_play_func, NULL, NULL);
+ uae_start_thread (L"cdda_play", cdda_play_func, cdu, NULL);
cdu->cdda_play++;
return 1;
}
static int command_qcode (int unitnum, uae_u8 *buf, int sector)
{
- struct cdunit *cdu = &cdunits[unitnum];
+ struct cdunit *cdu = unitisopen (unitnum);
+ if (!cdu)
+ return 0;
+
uae_u8 subbuf[SUB_CHANNEL_SIZE];
uae_u8 *p;
int trk;
int pos;
int status;
- if (unitnum)
- return NULL;
-
memset (buf, 0, SUBQ_SIZE);
p = buf;
return 1;
}
-static void command_volume (int unitnum, uae_u16 volume)
+static uae_u32 command_volume (int unitnum, uae_u16 volume_left, uae_u16 volume_right)
{
- struct cdunit *cdu = &cdunits[unitnum];
- cdu->cdda_volume = volume;
+ struct cdunit *cdu = unitisopen (unitnum);
+ if (!cdu)
+ return -1;
+ uae_u32 old = (cdu->cdda_volume[1] << 16) | (cdu->cdda_volume[0] << 0);
+ cdu->cdda_volume[0] = volume_left;
+ cdu->cdda_volume[1] = volume_right;
+ return old;
}
-uae_u8 *command_rawread (int unitnum, uae_u8 *data, int sector, int size, int sectorsize)
+static int command_rawread (int unitnum, uae_u8 *data, int sector, int size, int sectorsize, uae_u16 extra)
{
- struct cdunit *cdu = &cdunits[unitnum];
+ int ret = 0;
+ struct cdunit *cdu = unitisopen (unitnum);
+ if (!cdu)
+ return 0;
struct cdtoc *t = findtoc (cdu, §or);
int offset;
- if (unitnum)
- return NULL;
if (!t || t->handle == NULL)
- return NULL;
-
+ return 0;
cdda_stop (cdu);
- if (sectorsize > t->size)
- return NULL;
- offset = 0;
- if (sectorsize == 2336 && t->size == 2352)
- offset = 16;
- zfile_fseek (t->handle, t->offset + sector * t->size + offset, SEEK_SET);
- if (data)
+ if (sectorsize > 0) {
+ if (sectorsize > t->size)
+ return 0;
+ offset = 0;
+ if (sectorsize == 2336 && t->size == 2352)
+ offset = 16;
+ zfile_fseek (t->handle, t->offset + sector * t->size + offset, SEEK_SET);
zfile_fread (data, sectorsize, size, t->handle);
- else
- zfile_fread (cdu->buffer, sectorsize, 1, t->handle);
- cdu->cd_last_pos = sector;
- return cdu->buffer;
+ cdu->cd_last_pos = sector;
+ ret = sectorsize * size;
+ } else {
+ uae_u8 cmd9 = extra >> 8;
+ int sync = (cmd9 >> 7) & 1;
+ int headercodes = (cmd9 >> 5) & 3;
+ int userdata = (cmd9 >> 4) & 1;
+ int edcecc = (cmd9 >> 3) & 1;
+ int errorfield = (cmd9 >> 1) & 3;
+ uae_u8 subs = extra & 7;
+ if (subs != 0 && subs != 1 && subs != 2 && subs != 4)
+ return -1;
+
+ if (isaudiotrack (&cdu->di.toc, sector)) {
+ if (t->size != 2352)
+ return -2;
+ for (int i = 0; i < size; i++) {
+ zfile_fseek (t->handle, t->offset + sector * t->size, SEEK_SET);
+ zfile_fread (data, t->size, 1, t->handle);
+ uae_u8 *p = data + t->size;
+ if (subs) {
+ uae_u8 subdata[SUB_CHANNEL_SIZE];
+ getsub (subdata, cdu, t, sector);
+ if (subs == 4) { // all, de-interleaved
+ memcpy (p, subdata, SUB_CHANNEL_SIZE);
+ p += SUB_CHANNEL_SIZE;
+ } else if (subs == 2) { // q-only
+ memcpy (p, subdata + SUB_ENTRY_SIZE, SUB_ENTRY_SIZE);
+ p += SUB_ENTRY_SIZE;
+ } else if (subs == 1) { // all, interleaved
+ sub_to_interleaved (subdata, p);
+ p += SUB_CHANNEL_SIZE;
+ }
+ }
+ ret += p - data;
+ data = p;
+ sector++;
+ }
+ }
+ }
+ return ret;
}
-static uae_u8 *command_read (int unitnum, uae_u8 *data, int sector, int size)
+static int command_read (int unitnum, uae_u8 *data, int sector, int size)
{
- struct cdunit *cdu = &cdunits[unitnum];
+ struct cdunit *cdu = unitisopen (unitnum);
+ if (!cdu)
+ return 0;
+
struct cdtoc *t = findtoc (cdu, §or);
int offset;
- if (unitnum)
- return NULL;
if (!t || t->handle == NULL)
return NULL;
cdda_stop (cdu);
if (t->size > 2048)
offset = 16;
zfile_fseek (t->handle, t->offset + sector * t->size + offset, SEEK_SET);
- if (data)
- zfile_fread (data, size, 2048, t->handle);
- else
- zfile_fread (cdu->buffer, 2048, 1, t->handle);
+ zfile_fread (data, size, 2048, t->handle);
cdu->cd_last_pos = sector;
- return cdu->buffer;
+ return 1;
}
-static struct cd_toc_head *command_toc (int unitnum)
+static int command_toc (int unitnum, struct cd_toc_head *th)
{
- struct cdunit *cdu = &cdunits[unitnum];
- static struct cd_toc_head statictoc;
- struct cd_toc *toc = &statictoc.toc[0];
+ struct cdunit *cdu = unitisopen (unitnum);
+ if (!cdu)
+ return 0;
+
int i;
- if (unitnum)
- return NULL;
- cdda_stop (cdu);
+ memset (&cdu->di.toc, 0, sizeof (struct cd_toc_head));
if (!cdu->tracks)
- return NULL;
+ return 0;
- memset (&statictoc, 0, sizeof statictoc);
- statictoc.first_track = 1;
- statictoc.last_track = cdu->tracks;
- statictoc.points = cdu->tracks + 3;
- statictoc.tracks = cdu->tracks;
- statictoc.lastaddress = cdu->toc[cdu->tracks].address;
+ memset (th, 0, sizeof (struct cd_toc_head));
+ struct cd_toc *toc = &th->toc[0];
+ th->first_track = 1;
+ th->last_track = cdu->tracks;
+ th->points = cdu->tracks + 3;
+ th->tracks = cdu->tracks;
+ th->lastaddress = cdu->toc[cdu->tracks].address;
toc->adr = 1;
toc->point = 0xa0;
- toc->track = statictoc.first_track;
+ toc->track = th->first_track;
toc++;
- statictoc.first_track_offset = 1;
+ th->first_track_offset = 1;
for (i = 0; i < cdu->tracks; i++) {
toc->adr = cdu->toc[i].adr;
toc->control = cdu->toc[i].ctrl;
toc++;
}
- statictoc.last_track_offset = cdu->tracks;
+ th->last_track_offset = cdu->tracks;
toc->adr = 1;
toc->point = 0xa1;
- toc->track = statictoc.last_track;
+ toc->track = th->last_track;
toc++;
toc->adr = 1;
toc->point = 0xa2;
- toc->paddress = statictoc.lastaddress;
+ toc->paddress = th->lastaddress;
toc++;
+ memcpy (&cdu->di.toc, th, sizeof (struct cd_toc_head));
gui_flicker_led (LED_CD, unitnum, 1);
- return &statictoc;
+ return 1;
}
static void skipspace (TCHAR **s)
return _tcstol (s, &endptr, base);
}
-static int parseccd (struct cdunit *cdu, struct zfile *zcue, TCHAR *img)
+static int parseccd (struct cdunit *cdu, struct zfile *zcue, const TCHAR *img)
{
int mode;
int num, tracknum, trackmode;
return cdu->tracks;
}
-static int parsecue (struct cdunit *cdu, struct zfile *zcue, TCHAR *img)
+static int parsecue (struct cdunit *cdu, struct zfile *zcue, const TCHAR *img)
{
int tracknum, index0, pregap;
int offset, secoffset, newfile;
return cdu->tracks;
}
-static int parse_image (struct cdunit *cdu)
+static int parse_image (struct cdunit *cdu, const TCHAR *img)
{
struct zfile *zcue;
int i;
- TCHAR *img = currprefs.cdimagefile;
- TCHAR *ext;
+ const TCHAR *ext;
int secoffset;
secoffset = 0;
}
-static int open_device (int unitnum)
+static int open_device (int unitnum, const TCHAR *ident)
{
struct cdunit *cdu = &cdunits[unitnum];
- if (!cdu->enabled)
+
+ if (cdu->open)
return 0;
uae_sem_init (&cdu->sub_sem, 0, 1);
- if (!cdu->tracks)
- parse_image (cdu);
+ parse_image (cdu, ident);
+ cdu->open = true;
+ cdu->enabled = true;
+ cdu->cdda_volume[0] = 0x7fff;
+ cdu->cdda_volume[1] = 0x7fff;
+#ifdef RETROPLATFORM
+ rp_cd_change (unitnum, 0);
+ rp_cd_image_change (unitnum, currprefs.cdimagefile[unitnum]);
+#endif
return 1;
}
static void close_device (int unitnum)
{
struct cdunit *cdu = &cdunits[unitnum];
+ if (cdu->open == false)
+ return;
+ cdda_stop (cdu);
unload_image (cdu);
uae_sem_destroy (&cdu->sub_sem);
-}
-
-static int mountme (struct cdunit *cdu, bool checkparse)
-{
- sys_command_setunit (-1);
-
- bool sel = false;
- cdu->donotmountme = 1;
- device_func_init (DEVICE_TYPE_ANY | DEVICE_TYPE_USE_OLD);
- for (int i = 0; i < MAX_TOTAL_DEVICES && !sel; i++) {
- int opened = sys_command_isopen (i);
- struct device_info *discsi, discsi2;
- discsi = 0;
- if (sys_command_open (DF_IOCTL, i)) {
- discsi = sys_command_info (DF_IOCTL, i, &discsi2, 0);
- if (discsi && discsi->type == INQ_ROMD) {
- if (!_tcsicmp (currprefs.cdimagefile, discsi->label)) {
- sys_command_setunit (i);
- write_log (L"Drive '%s' (unit=%d) selected (media=%d)\n", discsi->label, i, discsi->media_inserted);
- cdu->donotmountme = false;
- return -1;
- }
- }
- }
- }
- cdu->donotmountme = -1;
- device_func_init (DEVICE_TYPE_ANY | DEVICE_TYPE_USE_OLD); // activate us again
- cdu->donotmountme = 0;
- if (checkparse) {
- sys_command_setunit (0);
- parse_image (cdu);
- int media = cdu->tracks > 0;
- write_log (L"CDEMU (%s) selected (media=%d)\n", currprefs.cdimagefile, media);
- return 1;
- }
- return 0;
-}
-
-void cdimage_vsync (void)
-{
- struct cdunit *cdu = &cdunits[0];
-
- if (_tcscmp (changed_prefs.cdimagefile, currprefs.cdimagefile)) {
- _tcscpy (cdu->newfile, changed_prefs.cdimagefile);
- changed_prefs.cdimagefile[0] = currprefs.cdimagefile[0] = 0;
- cdu->imagechange = 3 * 50;
- unload_image (cdu);
- int pollmode = 0;
- scsi_do_disk_change (-1, 0, &pollmode);
- if (pollmode)
- cdu->imagechange = 8 * 50;
- write_log (L"CD: eject (%s)\n", pollmode ? L"slow" : L"fast");
-#ifdef RETROPLATFORM
- rp_cd_image_change (0, NULL);
-#endif
- }
- if (cdu->imagechange == 0)
- return;
- cdu->imagechange--;
- if (cdu->imagechange > 0)
- return;
- _tcscpy (currprefs.cdimagefile, cdu->newfile);
- _tcscpy (changed_prefs.cdimagefile, cdu->newfile);
- cdu->newfile[0] = 0;
- write_log (L"CD: delayed insert '%s'\n", currprefs.cdimagefile[0] ? currprefs.cdimagefile : L"<EMPTY>");
- if (currprefs.scsi) {
- cdu->donotmountme = 1;
- int un = scsi_do_disk_device_change ();
- cdu->donotmountme = 0;
- if (un < 0) {
- cdu->donotmountme = -1;
- device_func_init (DEVICE_TYPE_ANY); // activate us again
- cdu->donotmountme = 0;
- parse_image (cdu);
- scsi_do_disk_change (255, 1, NULL);
- }
- } else {
- mountme (cdu, true);
- }
+ cdu->open = false;
+ cdu->enabled = false;
#ifdef RETROPLATFORM
- rp_cd_image_change (0, currprefs.cdimagefile);
+ rp_cd_change (unitnum, 1);
+ rp_cd_image_change (unitnum, currprefs.cdimagefile[unitnum]);
#endif
- config_changed = 1;
}
static int ismedia (int unitnum, int quick)
static struct device_info *info_device (int unitnum, struct device_info *di, int quick)
{
struct cdunit *cdu = &cdunits[unitnum];
+ memset (di, 0, sizeof (struct device_info));
if (!cdu->enabled)
return 0;
+ di->open = cdu->open;
di->removable = 1;
di->bus = unitnum;
di->target = 0;
di->sectorspertrack = cdu->cdsize / di->bytespersector;
if (ismedia (unitnum, 1)) {
di->media_inserted = 1;
- _tcscpy (di->mediapath, currprefs.cdimagefile);
+ _tcscpy (di->mediapath, currprefs.cdimagefile[0]);
}
memset (&di->toc, 0, sizeof (struct cd_toc_head));
- struct cd_toc_head *th = command_toc (unitnum);
- if (th)
- memcpy (&di->toc, th, sizeof (struct cd_toc_head));
+ command_toc (unitnum, &di->toc);
di->write_protected = 1;
di->type = INQ_ROMD;
- di->id = 255;
+ di->unitnum = unitnum + 1;
_tcscpy (di->label, L"CDEMU");
return di;
}
-static int check_bus (int flags)
+static void close_bus (void)
{
- struct cdunit *cdu = &cdunits[0];
- cdu->enabled = true;
- if (!(flags & DEVICE_TYPE_CHECKAVAIL))
- return 1;
- if (cdu->donotmountme < 0 || (flags & DEVICE_TYPE_ALLOWEMU))
- return 1;
- if (cdu->donotmountme > 0)
- return 0;
- if (cdu->imagechange)
- return 1;
- int v = currprefs.cdimagefile[0] ? 1 : 0;
- if (v) {
- if (mountme (cdu, false) < 0) // is it supported <drive letter:>\?
- return 0;
- }
- if (currprefs.cdimagefileuse) {
- v = 1;
+ if (!bus_open) {
+ write_log (L"IMAGE close_bus() when already closed!\n");
+ return;
}
- return v;
+ bus_open = 0;
+ write_log (L"IMAGE driver closed.\n");
}
static int open_bus (int flags)
{
- struct cdunit *cdu = &cdunits[0];
- if (!(flags & DEVICE_TYPE_CHECKAVAIL))
+ if (bus_open) {
+ write_log (L"IOCTL open_bus() more than once!\n");
return 1;
- if (cdu->donotmountme < 0 || (flags & DEVICE_TYPE_ALLOWEMU))
- return 1;
- if (cdu->donotmountme > 0)
- return 0;
-
- mountme (cdu, true);
-#ifdef RETROPLATFORM
- rp_cd_change (0, 0);
- rp_cd_image_change (0, currprefs.cdimagefile);
-#endif
+ }
+ bus_open = 1;
+ write_log (L"Image driver open.\n");
return 1;
}
-static void close_bus (void)
-{
-#ifdef RETROPLATFORM
- rp_cd_change (0, 1);
-#endif
-}
-
struct device_functions devicefunc_cdimage = {
- check_bus, open_bus, close_bus, open_device, close_device, info_device,
+ L"IMAGE",
+ open_bus, close_bus, open_device, close_device, info_device,
0, 0, 0,
command_pause, command_stop, command_play, command_volume, command_qcode,
command_toc, command_read, command_rawread, 0,
- 0, 0, ismedia
+ 0, ismedia
};
static volatile int cdtv_hsync, dma_finished, cdtv_sectorsize;
static volatile uae_u64 dma_wait;
-static int first;
static int cd_volume, cd_volume_stored;
static int cd_led;
static int frontpanel;
static int get_toc (void)
{
datatrack = 0;
- struct cd_toc_head *t = sys_command_cd_toc (DF_IOCTL, unitnum);
- if (!t)
+ if (!sys_command_cd_toc (unitnum, &toc))
return 0;
- memcpy (&toc, t, sizeof toc);
last_cd_position = toc.lastaddress;
if (toc.first_track == 1 && (toc.toc[toc.first_track_offset].control & 0x0c) == 0x04)
datatrack = 1;
static int get_qcode (void)
{
- if (!sys_command_cd_qcode (DF_IOCTL, unitnum, cdrom_qcode))
+ if (!sys_command_cd_qcode (unitnum, cdrom_qcode))
return 0;
if (cd_playing) {
if (cdrom_qcode[1] == AUDIO_STATUS_IN_PROGRESS) {
cd_motor = 0;
if (unitnum < 0)
return;
- sys_command_cd_pause (DF_IOCTL, unitnum, 0);
- sys_command_cd_stop (DF_IOCTL, unitnum);
+ sys_command_cd_pause (unitnum, 0);
+ sys_command_cd_stop (unitnum);
}
static void cdaudiostopfp (void)
{
static int pause_audio (int pause)
{
- sys_command_cd_pause (DF_IOCTL, unitnum, pause);
+ sys_command_cd_pause (unitnum, pause);
if (!cd_playing) {
cd_paused = 0;
cd_audio_status = AUDIO_STATUS_NO_STATUS;
{
if (unitnum < 0)
return 0;
- return sys_command_ismedia (DF_IOCTL, unitnum, 0);
+ return sys_command_ismedia (unitnum, 0);
}
static int issub (void)
uae_u32 end = read_comm_pipe_u32_blocking (&requests);
uae_u32 scan = read_comm_pipe_u32_blocking (&requests);
subreset ();
- sys_command_cd_pause (DF_IOCTL, unitnum, 0);
+ sys_command_cd_pause (unitnum, 0);
cd_audio_status = AUDIO_STATUS_PLAY_ERROR;
- sys_command_cd_volume (DF_IOCTL, unitnum, (cd_volume_stored << 6) | (cd_volume_stored >> 4));
- if (sys_command_cd_play (DF_IOCTL, unitnum, start, end, 0, subfunc)) {
+ sys_command_cd_volume (unitnum, (cd_volume_stored << 5) | (cd_volume_stored >> 5), (cd_volume_stored << 5) | (cd_volume_stored >> 5));
+ if (sys_command_cd_play (unitnum, start, end, 0, subfunc)) {
cd_audio_status = AUDIO_STATUS_IN_PROGRESS;
cd_playing = 1;
} else {
cd_paused = 0;
cd_motor = 0;
cd_audio_status = AUDIO_STATUS_PLAY_COMPLETE;
- sys_command_cd_pause (DF_IOCTL, unitnum, 0);
- sys_command_cd_stop (DF_IOCTL, unitnum);
+ sys_command_cd_pause (unitnum, 0);
+ sys_command_cd_stop (unitnum);
cd_isready = 50;
cd_error = 1;
return 0;
cdrom_command_output[0] = flag;
cdrom_command_accepted (1, s, &cdrom_command_cnt_in);
cd_finished = 0;
- if (first == -1)
- first = 100;
}
break;
case 0x82:
}
}
-static uae_u8 *read_raw (int sector, int size)
+static int read_raw (int sector, uae_u8 *dst, int blocksize)
{
int osector = sector - 150;
static struct zfile *f;
static int track;
int trackcnt;
TCHAR fname[MAX_DPATH];
- static uae_u8 buf[4096];
uae_u32 prevlsn = 0;
struct cd_toc *t = &toc.toc[0];
- memset (buf, 0, sizeof buf);
trackcnt = 0;
for (;;) {
int lsn = t->paddress;
track = trackcnt;
}
if (f) {
- write_log (L"CDTV fakeraw: %dx%d=%d\n", sector, size, sector * size);
- zfile_fseek (f, sector * size, SEEK_SET);
- zfile_fread (buf, size, 1, f);
- return buf;
+ write_log (L"CDTV fakeraw: %dx%d=%d\n", sector, blocksize, sector * blocksize);
+ zfile_fseek (f, sector * blocksize, SEEK_SET);
+ zfile_fread (dst, blocksize, 1, f);
+ return 1;
}
- return sys_command_cd_rawread (DF_IOCTL, unitnum, NULL, osector, size, 1);
+ return sys_command_cd_rawread (unitnum, dst, osector, blocksize, 1);
}
static void dma_do_thread (void)
{
static int readsector;
- uae_u8 *p = NULL;
+ int didread = 0;
int cnt;
while (dma_finished)
#endif
dma_wait += cnt * (uae_u64)312 * 50 / 75 + 1;
while (cnt > 0 && dmac_dma) {
- if (!p || readsector != (cdrom_offset / cdtv_sectorsize)) {
+ uae_u8 buffer[2352];
+ if (!didread || readsector != (cdrom_offset / cdtv_sectorsize)) {
readsector = cdrom_offset / cdtv_sectorsize;
if (cdtv_sectorsize == 2336)
- p = read_raw (readsector, cdtv_sectorsize);
+ didread = read_raw (readsector, buffer, cdtv_sectorsize);
else
- p = sys_command_cd_read (DF_IOCTL, unitnum, NULL, readsector, 1);
- if (!p) {
+ didread = sys_command_cd_read (unitnum, buffer, readsector, 1);
+ if (!didread) {
cd_error = 1;
activate_stch = 1;
write_log (L"CDTV: CD read error!\n");
}
}
- put_byte (dmac_acr, p[(cdrom_offset % cdtv_sectorsize) + 0]);
- put_byte (dmac_acr + 1, p[(cdrom_offset % cdtv_sectorsize) + 1]);
+ put_byte (dmac_acr, buffer[(cdrom_offset % cdtv_sectorsize) + 0]);
+ put_byte (dmac_acr + 1, buffer[(cdrom_offset % cdtv_sectorsize) + 1]);
cnt--;
dmac_acr += 2;
cdrom_length -= 2;
}
break;
case 0x0102: // pause
- sys_command_cd_pause (DF_IOCTL, unitnum, 1);
+ sys_command_cd_pause (unitnum, 1);
break;
case 0x0103: // unpause
- sys_command_cd_pause (DF_IOCTL, unitnum, 0);
+ sys_command_cd_pause (unitnum, 0);
break;
case 0x0104: // stop
cdaudiostop ();
last_play_pos = start;
last_play_end = end;
#ifdef CDTV_DEBUG
- write_log (L"PLAY CD AUDIO from %d-%d, %06X (%d) to %06X (%d)\n",
- track_start, track_end, lsn2msf (start), start, lsn2msf (end), end);
+ write_log (L"PLAY CD AUDIO from %06X (%d) to %06X (%d)\n",
+ lsn2msf (start), start, lsn2msf (end), end);
#endif
play_state = 1;
subreset ();
if (cd_volume > 1023)
cd_volume = 1023;
if (unitnum >= 0)
- sys_command_cd_volume (DF_IOCTL, unitnum, (cd_volume << 6) | (cd_volume >> 4));
+ sys_command_cd_volume (unitnum, (cd_volume << 5) | (cd_volume >> 5), (cd_volume << 5) | (cd_volume >> 5));
cd_volume_stored = cd_volume;
cd_volume = 0;
volstrobe2 = 1;
static void do_hunt (void)
{
int i;
- for (i = 0; i < MAX_TOTAL_DEVICES; i++) {
- if (sys_command_ismedia (DF_IOCTL, i, 1) > 0)
+ for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ if (sys_command_ismedia (i, 1) > 0)
break;
}
- if (i == MAX_TOTAL_DEVICES) {
- if (unitnum >= 0 && sys_command_ismedia (DF_IOCTL, unitnum, 1) >= 0)
+ if (i == MAX_TOTAL_SCSI_DEVICES) {
+ if (unitnum >= 0 && sys_command_ismedia (unitnum, 1) >= 0)
return;
- for (i = 0; i < MAX_TOTAL_DEVICES; i++) {
- if (sys_command_ismedia (DF_IOCTL, i, 1) >= 0)
+ for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ if (sys_command_ismedia (i, 1) >= 0)
break;
}
- if (i == MAX_TOTAL_DEVICES)
+ if (i == MAX_TOTAL_SCSI_DEVICES)
return;
}
if (unitnum >= 0) {
cdaudiostop ();
int ou = unitnum;
unitnum = -1;
- sys_command_close (DF_IOCTL, ou);
+ sys_command_close (ou);
}
- if (sys_command_open (DF_IOCTL, i) > 0) {
+ if (sys_command_open (i) > 0) {
struct device_info di = { 0 };
- sys_command_info (DF_IOCTL, i, &di, 0);
+ sys_command_info (i, &di, 0);
unitnum = i;
cd_hunt = 0;
write_log (L"CDTV: autodetected unit %d ('%s')\n", unitnum, di.label);
cd_finished = 0;
cd_led = 0;
stch = 1;
- first = -1;
}
static uae_u32 dmac_bget2 (uaecptr addr)
struct device_info di1, *di2;
int first = -1;
int cdtvunit = -1, audiounit = -1;
- int opened[MAX_TOTAL_DEVICES];
+ int opened[MAX_TOTAL_SCSI_DEVICES];
int i;
if (unitnum >= 0)
- sys_command_close (DF_IOCTL, unitnum);
+ sys_command_close (unitnum);
unitnum = -1;
cdtv_reset ();
- if (!device_func_init (DEVICE_TYPE_IOCTL)) {
+ if (!device_func_init (0)) {
write_log (L"no CDROM support\n");
return;
}
- for (unitnum = 0; unitnum < MAX_TOTAL_DEVICES; unitnum++) {
+ for (unitnum = 0; unitnum < MAX_TOTAL_SCSI_DEVICES; unitnum++) {
opened[unitnum] = 0;
- if (sys_command_open (DF_IOCTL, unitnum)) {
+ if (sys_command_open (unitnum)) {
opened[unitnum] = 1;
- di2 = sys_command_info (DF_IOCTL, unitnum, &di1, 0);
+ di2 = sys_command_info (unitnum, &di1, 0);
if (di2 && di2->type == INQ_ROMD) {
write_log (L"%s: ", di2->label);
if (first < 0)
first = unitnum;
if (get_toc () > 0) {
if (datatrack) {
- uae_u8 *p = sys_command_cd_read (DF_IOCTL, unitnum, NULL, 16, 1);
- if (p) {
- if (!memcmp (p + 8, "CDTV", 4)) {
+ uae_u8 buffer[2048];
+ if (sys_command_cd_read (unitnum, buffer, 16, 1)) {
+ if (!memcmp (buffer + 8, "CDTV", 4)) {
write_log (L"CDTV\n");
if (cdtvunit < 0)
cdtvunit = unitnum;
unitnum = first;
if (unitnum >= 0)
opened[unitnum] = 0;
- for (i = 0; i < MAX_TOTAL_DEVICES; i++) {
+ for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
if (opened[i])
- sys_command_close (DF_IOCTL, i);
+ sys_command_close (i);
}
cd_media = 0;
if (unitnum >= 0) {
thread_alive = 0;
cdaudiostop ();
if (unitnum >= 0)
- sys_command_close (DF_IOCTL, unitnum);
+ sys_command_close (unitnum);
unitnum = -1;
configured = 0;
}
#include "filesys.h"
#include "fsdb.h"
#include "disk.h"
+#include "blkdev.h"
#include "statusline.h"
static int config_newfilesystem;
L"rugby coach", L"cricket captain", L"leviathan",
NULL
};
+static const TCHAR *cdmodes[] = { L"", L"image", L"ioctl", L"spti", L"aspi", 0 };
static const TCHAR *obsolete[] = {
L"accuracy", L"gfx_opengl", L"gfx_32bit_blits", L"32bit_blits",
}
}
- if (p->cdimagefile[0] || p->cdimagefileuse)
- cfgfile_write_str (f, L"cdimage0", p->cdimagefile);
+ for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ if (p->cdimagefile[i][0] || p->cdimagefileuse[i]) {
+ TCHAR tmp2[MAX_DPATH];
+ _stprintf (tmp, L"cdimage%d", i);
+ _tcscpy (tmp2, p->cdimagefile[i]);
+ if (p->cdscsidevicetype[i] != 0 || _tcschr (p->cdimagefile[i], ',')) {
+ _tcscat (tmp2, L",");
+ _tcscat (tmp2, cdmodes[p->cdscsidevicetype[i]]);
+ }
+ cfgfile_write_str (f, tmp, tmp2);
+ }
+ }
if (p->quitstatefile[0])
cfgfile_write_str (f, L"statefile_quit", p->quitstatefile);
}
}
- if (cfgfile_path (option, value, L"cdimage0", p->cdimagefile, sizeof p->cdimagefile / sizeof (TCHAR))) {
- p->cdimagefileuse = true;
- return 1;
+ for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ TCHAR tmp[20];
+ _stprintf (tmp, L"cdimage%d", i);
+ if (!_tcsicmp (option, tmp)) {
+ TCHAR *next = _tcsrchr (value, ',');
+ if (next) {
+ *next = 0;
+ TCHAR *next2 = _tcschr (next + 1, ':');
+ if (next2)
+ *next2 = 0;
+ cfgfile_intval (option, next + 1, tmp, &p->cdscsidevicetype[i], 1);
+ }
+ _tcsncpy (p->cdimagefile[i], value, sizeof p->cdimagefile[i]);
+ p->cdimagefile[i][sizeof p->cdimagefile[i] - 1] = 0;
+ p->cdimagefileuse[i] = true;
+ return 1;
+ }
}
if (cfgfile_intval (option, value, L"sound_frequency", &p->sound_freq, 1)) {
inputdevice_default_prefs (p);
+ blkdev_default_prefs (p);
+
zfile_fclose (default_file);
default_file = NULL;
f = zfile_fopen_empty (NULL, L"configstore", 100000);
int maxhpos_short = MAXHPOS_PAL;
int maxvpos = MAXVPOS_PAL;
int maxvpos_nom = MAXVPOS_PAL; // nominal value (same as maxvpos but "faked" maxvpos in fake 60hz modes)
-static int hsyncstartpos;
-int hsyncstartposnative;
+int hsyncstartpos;
static int maxvpos_total = 511;
int minfirstline = VBLANK_ENDLINE_PAL;
int equ_vblank_endline = EQU_ENDLINE_PAL;
} else {
hsyncstartpos = maxhpos_short + 13;
}
- hsyncstartposnative = coord_hw_to_window_x (hsyncstartpos * 2);
eventtab[ev_hsync].oldcycles = get_cycles ();
eventtab[ev_hsync].evtime = get_cycles () + HSYNCTIME;
events_schedule ();
picasso_handle_vsync ();
#endif
audio_vsync ();
- cdimage_vsync ();
+ blkdev_vsync ();
if (quit_program > 0) {
/* prevent possible infinite loop at wait_cycles().. */
static void fill_line (void)
{
- if (hsyncstartposnative > visible_left_border + gfxvidinfo.width || hposendblank) {
+ int hs = coord_hw_to_window_x (hsyncstartpos * 2);
+ if (hs > visible_left_border + gfxvidinfo.width || hposendblank) {
fill_line2 (visible_left_border, gfxvidinfo.width);
} else {
- fill_line2 (visible_left_border, hsyncstartposnative);
+ fill_line2 (visible_left_border, hs);
hposendblank = 1;
- fill_line2 (visible_left_border + hsyncstartposnative, gfxvidinfo.width - hsyncstartposnative);
+ fill_line2 (visible_left_border + hs, gfxvidinfo.width - hs);
}
}
int i;
int lastpos = visible_left_border;
int endpos = visible_left_border + gfxvidinfo.width;
- int diff = 1 << lores_shift;
for (i = dip_for_drawing->first_color_change; i <= dip_for_drawing->last_color_change; i++) {
int regno = curr_color_changes[i].regno;
TCHAR *validatevolumename (TCHAR *s)
{
stripsemicolon (s);
- stripspace (s);
fixcharset (s);
striplength (s, 30);
return s;
-#define MAX_TOTAL_DEVICES 8
#define DEVICE_SCSI_BUFSIZE (65536 - 1024)
+#define SCSI_UNIT_NONE 0
+#define SCSI_UNIT_IMAGE 1
+#define SCSI_UNIT_IOCTL 2
+#define SCSI_UNIT_SPTI 3
+#define SCSI_UNIT_ASPI 4
+
//#define device_debug write_log
#define device_debug
struct cd_toc toc[MAX_TOC_ENTRIES];
};
-#define DEVICE_TYPE_ANY 1
-#define DEVICE_TYPE_SCSI 2
-#define DEVICE_TYPE_IOCTL 3
-#define DEVICE_TYPE_ALLOWEMU 0x10000000
-#define DEVICE_TYPE_CHECKAVAIL 0x20000000
-#define DEVICE_TYPE_USE_OLD 0x40000000
-
#define SUB_ENTRY_SIZE 12
#define SUB_CHANNEL_SIZE 96
#define SUBQ_SIZE (4 + 12)
#define AUDIO_STATUS_PLAY_ERROR 0x14
#define AUDIO_STATUS_NO_STATUS 0x15
-#define DF_SCSI 0
-#define DF_IOCTL 1
-
struct device_info {
+ bool open;
int type;
int media_inserted;
int removable;
int sectorspertrack;
int bytespersector;
int bus, target, lun;
- int id;
+ int unitnum;
TCHAR label[MAX_DPATH];
TCHAR mediapath[MAX_DPATH];
+ TCHAR vendorid[10];
+ TCHAR productid[18];
+ TCHAR revision[6];
struct cd_toc_head toc;
};
-struct device_scsi_info {
- uae_u8 *buffer;
- int bufsize;
-};
-
struct amigascsi
{
uae_u8 *data;
typedef int (*check_bus_func)(int flags);
typedef int (*open_bus_func)(int flags);
typedef void (*close_bus_func)(void);
-typedef int (*open_device_func)(int);
+typedef int (*open_device_func)(int, const TCHAR*);
typedef void (*close_device_func)(int);
typedef struct device_info* (*info_device_func)(int, struct device_info*, int);
-typedef struct device_scsi_info* (*scsiinfo_func)(int, struct device_scsi_info*);
typedef uae_u8* (*execscsicmd_out_func)(int, uae_u8*, int);
typedef uae_u8* (*execscsicmd_in_func)(int, uae_u8*, int, int*);
typedef int (*execscsicmd_direct_func)(int, struct amigascsi*);
typedef int (*pause_func)(int, int);
typedef int (*stop_func)(int);
typedef int (*play_func)(int, int, int, int, play_subchannel_callback);
-typedef void (*volume_func)(int, uae_u16);
+typedef uae_u32 (*volume_func)(int, uae_u16, uae_u16);
typedef int (*qcode_func)(int, uae_u8*, int);
-typedef struct cd_toc_head* (*toc_func)(int);
-typedef uae_u8* (*read_func)(int, uae_u8*, int, int);
-typedef uae_u8* (*rawread_func)(int, uae_u8*, int, int, int);
+typedef int (*toc_func)(int, struct cd_toc_head*);
+typedef int (*read_func)(int, uae_u8*, int, int);
+typedef int (*rawread_func)(int, uae_u8*, int, int, int, uae_u16);
typedef int (*write_func)(int, uae_u8*, int, int);
typedef int (*isatapi_func)(int);
typedef int (*ismedia_func)(int, int);
struct device_functions {
- check_bus_func checkbus;
- open_bus_func openbus;
- close_bus_func closebus;
- open_device_func opendev;
- close_device_func closedev;
- info_device_func info;
- execscsicmd_out_func exec_out;
- execscsicmd_in_func exec_in;
- execscsicmd_direct_func exec_direct;
-
- pause_func pause;
- stop_func stop;
- play_func play;
+ const TCHAR *name;
+ open_bus_func openbus;
+ close_bus_func closebus;
+ open_device_func opendev;
+ close_device_func closedev;
+ info_device_func info;
+ execscsicmd_out_func exec_out;
+ execscsicmd_in_func exec_in;
+ execscsicmd_direct_func exec_direct;
+
+ pause_func pause;
+ stop_func stop;
+ play_func play;
volume_func volume;
- qcode_func qcode;
- toc_func toc;
- read_func read;
- rawread_func rawread;
- write_func write;
+ qcode_func qcode;
+ toc_func toc;
+ read_func read;
+ rawread_func rawread;
+ write_func write;
- isatapi_func isatapi;
-
- scsiinfo_func scsiinfo;
-
- ismedia_func ismedia;
+ isatapi_func isatapi;
+ ismedia_func ismedia;
};
-extern struct device_functions *device_func[2];
+extern struct device_functions *device_func[MAX_TOTAL_SCSI_DEVICES];
extern int device_func_init(int flags);
extern void device_func_reset(void);
-extern int sys_command_open (int mode, int unitnum);
-extern void sys_command_close (int mode, int unitnum);
+extern int sys_command_open (int unitnum);
+extern void sys_command_close (int unitnum);
extern int sys_command_isopen (int unitnum);
-extern void sys_command_setunit (int unitnum);
-extern struct device_info *sys_command_info (int mode, int unitnum, struct device_info *di, int);
-extern struct device_scsi_info *sys_command_scsi_info (int mode, int unitnum, struct device_scsi_info *di);
-extern void sys_command_cd_pause (int mode, int unitnum, int paused);
-extern void sys_command_cd_stop (int mode, int unitnum);
-extern int sys_command_cd_play (int mode, int unitnum, int startlsn, int endlsn, int);
-extern int sys_command_cd_play (int mode, int unitnum, int startlsn, int endlsn, int scan, play_subchannel_callback subfunc);
-extern void sys_command_cd_volume (int mode, int unitnum, uae_u16 volume);
-extern int sys_command_cd_qcode (int mode, int unitnum, uae_u8*);
-extern struct cd_toc_head *sys_command_cd_toc (int mode, int unitnum);
-extern uae_u8 *sys_command_cd_read (int mode, int unitnum, uae_u8 *data, int block, int size);
-extern uae_u8 *sys_command_cd_rawread (int mode, int unitnum, uae_u8 *data, int sector, int size, int sectorsize);
-extern uae_u8 *sys_command_read (int mode, int unitnum, uae_u8 *data, int block, int size);
-extern int sys_command_write (int mode, int unitnum, uae_u8 *data, int block, int size);
-extern int sys_command_scsi_direct_native(int unitnum, struct amigascsi *as);
+extern struct device_info *sys_command_info (int unitnum, struct device_info *di, int);
+extern int sys_command_cd_pause (int unitnum, int paused);
+extern void sys_command_cd_stop (int unitnum);
+extern int sys_command_cd_play (int unitnum, int startlsn, int endlsn, int);
+extern int sys_command_cd_play (int unitnum, int startlsn, int endlsn, int scan, play_subchannel_callback subfunc);
+extern uae_u32 sys_command_cd_volume (int unitnum, uae_u16 volume_left, uae_u16 volume_right);
+extern int sys_command_cd_qcode (int unitnum, uae_u8*);
+extern int sys_command_cd_toc (int unitnum, struct cd_toc_head*);
+extern int sys_command_cd_read (int unitnum, uae_u8 *data, int block, int size);
+extern int sys_command_cd_rawread (int unitnum, uae_u8 *data, int sector, int size, int sectorsize);
+extern int sys_command_cd_rawread (int unitnum, uae_u8 *data, int sector, int size, int sectorsize, uae_u8 scsicmd9, uae_u8 subs);
+extern int sys_command_read (int unitnum, uae_u8 *data, int block, int size);
+extern int sys_command_write (int unitnum, uae_u8 *data, int block, int size);
+extern int sys_command_scsi_direct_native (int unitnum, struct amigascsi *as);
extern int sys_command_scsi_direct (int unitnum, uaecptr request);
-extern int sys_command_ismedia (int mode, int unitnum, int quick);
+extern int sys_command_ismedia (int unitnum, int quick);
extern void scsi_atapi_fixup_pre (uae_u8 *scsi_cmd, int *len, uae_u8 **data, int *datalen, int *parm);
extern void scsi_atapi_fixup_post (uae_u8 *scsi_cmd, int len, uae_u8 *olddata, uae_u8 *data, int *datalen, int parm);
extern void scsi_log_before (uae_u8 *cdb, int cdblen, uae_u8 *data, int datalen);
extern void scsi_log_after (uae_u8 *data, int datalen, uae_u8 *sense, int senselen);
-extern void cdimage_vsync (void);
+extern void blkdev_vsync (void);
extern int msf2lsn (int msf);
extern int lsn2msf (int lsn);
extern uae_u8 frombcd (uae_u8 v);
extern uae_u8 tobcd (uae_u8 v);
extern int fromlongbcd (uae_u8 *p);
-extern void tolongbcd (uae_u8 *p, int v);
\ No newline at end of file
+extern void tolongbcd (uae_u8 *p, int v);
+
+extern void blkdev_default_prefs (struct uae_prefs *p);
+extern void blkdev_fix_prefs (struct uae_prefs *p);
+extern int isaudiotrack (struct cd_toc_head*, int block);
+extern int isdatatrack (struct cd_toc_head*, int block);
+
extern int maxhpos, maxhpos_short;
extern int maxvpos, maxvpos_nom;
-extern int hsyncstartposnative;
+extern int hsyncstartpos;
extern int minfirstline, vblank_endline, numscrlines;
extern int vblank_hz, fake_vblank_hz, vblank_skip, doublescan;
extern frame_time_t syncbase;
#define IOERR_UNITBUSY -6
#define IOERR_SELFTEST -7
+#define CDERR_NotSpecified 20 /* general catchall */
+#define CDERR_NoSecHdr 21 /* couldn't even find a sector */
+#define CDERR_BadSecPreamble 22 /* sector looked wrong */
+#define CDERR_BadSecID 23 /* ditto */
+#define CDERR_BadHdrSum 24 /* header had incorrect checksum */
+#define CDERR_BadSecSum 25 /* data had incorrect checksum */
+#define CDERR_TooFewSecs 26 /* couldn't find enough sectors */
+#define CDERR_BadSecHdr 27 /* another "sector looked wrong" */
+#define CDERR_WriteProt 28 /* can't write to a protected disk */
+#define CDERR_NoDisk 29 /* no disk in the drive */
+#define CDERR_SeekError 30 /* couldn't find track 0 */
+#define CDERR_NoMem 31 /* ran out of memory */
+#define CDERR_BadUnitNum 32 /* asked for a unit > NUMUNITS */
+#define CDERR_BadDriveType 33 /* not a drive cd.device understands */
+#define CDERR_DriveInUse 34 /* someone else allocated the drive */
+#define CDERR_PostReset 35 /* user hit reset; awaiting doom */
+#define CDERR_BadDataType 36 /* data on disk is wrong type */
+#define CDERR_InvalidState 37 /* invalid cmd under current conditions */
+
+#define CDERR_Phase 42 /* illegal or unexpected SCSI phase */
+#define CDERR_NoBoard 50 /* open failed for non-existant board */
+
+
#define TDERR_DiskChanged 29
#define CMD_INVALID 0
#define TAG_SKIP 3
#define TAG_USER (1 << 31)
-#define NSDEVTYPE_UNKNOWN 0
-#define NSDEVTYPE_GAMEPORT 1
-#define NSDEVTYPE_TIMER 2
-#define NSDEVTYPE_KEYBOARD 3
-#define NSDEVTYPE_INPUT 4
-#define NSDEVTYPE_TRACKDISK 5
-#define NSDEVTYPE_CONSOLE 6
-#define NSDEVTYPE_SANA2 7
-#define NSDEVTYPE_AUDIO 8
-#define NSDEVTYPE_CLIPBOARD 9
-#define NSDEVTYPE_PRINTER 10
-#define NSDEVTYPE_SERIAL 11
-#define NSDEVTYPE_PARALLEL 12
-
-#define CMD_MOTOR 9
-#define CMD_SEEK 10
-#define CMD_FORMAT 11
-#define CMD_REMOVE 12
-#define CMD_CHANGENUM 13
-#define CMD_CHANGESTATE 14
-#define CMD_PROTSTATUS 15
-#define CMD_GETDRIVETYPE 18
-#define CMD_GETNUMTRACKS 19
-#define CMD_ADDCHANGEINT 20
-#define CMD_REMCHANGEINT 21
-#define CMD_GETGEOMETRY 22
-#define CMD_GETDRIVETYPE 18
-#define CMD_GETNUMTRACKS 19
-#define CMD_ADDCHANGEINT 20
-#define CMD_REMCHANGEINT 21
-#define CMD_GETGEOMETRY 22
-#define HD_SCSICMD 28
+#define NSDEVTYPE_UNKNOWN 0
+#define NSDEVTYPE_GAMEPORT 1
+#define NSDEVTYPE_TIMER 2
+#define NSDEVTYPE_KEYBOARD 3
+#define NSDEVTYPE_INPUT 4
+#define NSDEVTYPE_TRACKDISK 5
+#define NSDEVTYPE_CONSOLE 6
+#define NSDEVTYPE_SANA2 7
+#define NSDEVTYPE_AUDIO 8
+#define NSDEVTYPE_CLIPBOARD 9
+#define NSDEVTYPE_PRINTER 10
+#define NSDEVTYPE_SERIAL 11
+#define NSDEVTYPE_PARALLEL 12
-/* Trackdisk64 support */
-#define TD_READ64 24
-#define TD_WRITE64 25
-#define TD_SEEK64 26
-#define TD_FORMAT64 27
+#define CMD_MOTOR 9
+#define CMD_SEEK 10
+#define CMD_FORMAT 11
+#define CMD_REMOVE 12
+#define CMD_CHANGENUM 13
+#define CMD_CHANGESTATE 14
+#define CMD_PROTSTATUS 15
+#define CMD_GETDRIVETYPE 18
+#define CMD_GETNUMTRACKS 19
+#define CMD_ADDCHANGEINT 20
+#define CMD_REMCHANGEINT 21
+#define CMD_GETGEOMETRY 22
+#define CMD_GETDRIVETYPE 18
+#define CMD_GETNUMTRACKS 19
+#define CMD_ADDCHANGEINT 20
+#define CMD_REMCHANGEINT 21
+#define CMD_GETGEOMETRY 22
+#define CD_EJECT 23
+#define TD_READ64 24
+#define TD_WRITE64 25
+#define TD_SEEK64 26
+#define TD_FORMAT64 27
+#define HD_SCSICMD 28
+#define CD_INFO 32
+#define CD_CONFIG 33
+#define CD_TOCMSF 34
+#define CD_TOCLSN 35
+#define CD_READXL 36
+#define CD_PLAYTRACK 37
+#define CD_PLAYMSF 38
+#define CD_PLAYLSN 39
+#define CD_PAUSE 40
+#define CD_SEARCH 41
+#define CD_QCODEMSF 42
+#define CD_QCODELSN 43
+#define CD_ATTENUATE 44
+#define CD_ADDFRAMEINT 45
+#define CD_REMFRAMEINT 46
/* New Style Devices (NSD) support */
#define NSCMD_TD_READ64 0xc000
int unknown;
};
+#define MAX_TOTAL_SCSI_DEVICES 8
+
/* maximum number native input devices supported (single type) */
#define MAX_INPUT_DEVICES 8
/* maximum number of native input device's buttons and axles supported */
TCHAR sername[256];
TCHAR amaxromfile[MAX_DPATH];
TCHAR a2065name[MAX_DPATH];
- TCHAR cdimagefile[MAX_DPATH];
- bool cdimagefileuse;
+ TCHAR cdimagefile[MAX_TOTAL_SCSI_DEVICES][MAX_DPATH];
+ bool cdimagefileuse[MAX_TOTAL_SCSI_DEVICES];
+ int cdscsidevicetype[MAX_TOTAL_SCSI_DEVICES];
TCHAR quitstatefile[MAX_DPATH];
TCHAR path_floppy[256];
void scsidev_install (void);
void scsidev_reset (void);
void scsidev_start_threads (void);
-int scsi_do_disk_change (int device_id, int insert, int *pollmode);
+int scsi_do_disk_change (int unitnum, int insert, int *pollmode);
int scsi_do_disk_device_change (void);
extern int log_scsi;
p->maprom = 0x0f000000;
if (p->tod_hack && p->cs_ciaatod == 0)
p->cs_ciaatod = p->ntscmode ? 2 : 1;
+ blkdev_fix_prefs (p);
target_fixup_options (p);
}
int isatapi;
int removable;
};
-static struct scsi_info si[MAX_TOTAL_DEVICES];
+static struct scsi_info si[MAX_TOTAL_SCSI_DEVICES];
static int unitcnt;
static int getversion(const TCHAR *name, VS_FIXEDFILEINFO *ver)
write_log (L"ASPI: %d:%d:%d '%s' '%s' '%s' ",
scgp->addr.scsibus,scgp->addr.target,scgp->addr.lun, vend, prod, rev);
- if (unitcnt < MAX_TOTAL_DEVICES) {
+ if (unitcnt < MAX_TOTAL_SCSI_DEVICES) {
struct scsi_info *cis = &si[unitcnt];
int use = 0;
write_log (L"[");
static SCSI *scsi_handle;
-static int check_scsi_bus (int flags)
-{
- if (open_driver (NULL)) {
- close_driver ();
- return 1;
- }
- return 0;
-}
-
static int open_scsi_bus (int flags)
{
SCSI *scgp = openscsi (-1, -1, -1);
return 1;
}
-static int open_scsi_device (int unitnum)
+static int open_scsi_device (int unitnum, const TCHAR *ident)
{
if (unitnum >= unitcnt)
return 0;
struct scsi_info *sif = &si[unitnum];
if (unitnum >= unitcnt)
return 0;
+ di->open = sif->handle != 0;
di->bus = sif->scsibus;
di->target = sif->target;
di->lun = sif->lun;
di->media_inserted = mediacheck (unitnum);
di->type = sif->type;
mediacheck_full (unitnum, di);
- di->id = unitnum + 1;
+ di->unitnum = unitnum + 1;
di->removable = sif->removable;
_tcscpy (di->label, sif->label);
if (log_scsi) {
return si[unitnum].isatapi;
}
-static struct device_scsi_info *scsi_info (int unitnum, struct device_scsi_info *dsi)
-{
- dsi->buffer = si[unitnum].buf;
- dsi->bufsize = DEVICE_SCSI_BUFSIZE;
- return dsi;
-}
-
struct device_functions devicefunc_win32_aspi = {
- check_scsi_bus, open_scsi_bus, close_scsi_bus, open_scsi_device, close_scsi_device, info_device,
+ L"ASPI",
+ open_scsi_bus, close_scsi_bus, open_scsi_device, close_scsi_device, info_device,
execscsicmd_out, execscsicmd_in, execscsicmd_direct,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, check_isatapi, scsi_info, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, check_isatapi, 0
};
TCHAR drvletter;
TCHAR drvlettername[10];
TCHAR devname[30];
- int mediainserted;
int type;
- int blocksize;
- CDROM_TOC toc;
+ CDROM_TOC cdromtoc;
UINT errormode;
int playend;
int fullaccess;
int cdda_play_finished;
int cdda_play;
int cdda_paused;
- int cdda_volume;
+ int cdda_volume[2];
+ int cdda_scan;
int cdda_volume_main;
uae_u32 cd_last_pos;
HWAVEOUT cdda_wavehandle;
play_subchannel_callback cdda_subfunc;
struct device_info di;
uae_sem_t sub_sem, sub_sem2;
+ bool open;
};
-static int MCICDA;
+static struct dev_info_ioctl ciw32[MAX_TOTAL_SCSI_DEVICES];
+static int unittable[MAX_TOTAL_SCSI_DEVICES];
+static int bus_open;
-static struct dev_info_ioctl ciw32[MAX_TOTAL_DEVICES];
-
-static void seterrormode (int unitnum)
+static void seterrormode (struct dev_info_ioctl *ciw)
{
- ciw32[unitnum].errormode = SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
+ ciw->errormode = SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
}
-static void reseterrormode (int unitnum)
+static void reseterrormode (struct dev_info_ioctl *ciw)
{
- SetErrorMode (ciw32[unitnum].errormode);
+ SetErrorMode (ciw->errormode);
}
-static void close_device (int unitnum);
-static int open_device (int unitnum);
+static int sys_cddev_open (struct dev_info_ioctl *ciw, int unitnum);
+static void sys_cddev_close (struct dev_info_ioctl *ciw, int unitnum);
-static int unitcheck (int unitnum)
+static int getunitnum (struct dev_info_ioctl *ciw)
{
- if (unitnum >= MAX_TOTAL_DEVICES) {
- if (unitnum < 'A' || unitnum > 'Z')
- return 0;
- return 1;
+ if (!ciw)
+ return -1;
+ int idx = ciw - &ciw32[0];
+ for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ if (unittable[i] - 1 == idx)
+ return i;
}
+ return -1;
+}
+
+static struct dev_info_ioctl *unitcheck (int unitnum)
+{
+ if (unitnum < 0 || unitnum >= MAX_TOTAL_SCSI_DEVICES)
+ return NULL;
+ if (unittable[unitnum] <= 0)
+ return NULL;
+ unitnum = unittable[unitnum] - 1;
if (ciw32[unitnum].drvletter == 0)
- return 0;
- return 1;
+ return NULL;
+ return &ciw32[unitnum];
}
-static bool unitisopen (int unitnum)
+static struct dev_info_ioctl *unitisopen (int unitnum)
{
- if (!unitcheck (unitnum))
- return false;
- if (ciw32[unitnum].tempbuffer == NULL)
- return false;
- return true;
+ struct dev_info_ioctl *di = unitcheck (unitnum);
+ if (!di)
+ return NULL;
+ if (di->open == false)
+ return NULL;
+ return di;
}
static int mcierr (TCHAR *str, DWORD err)
return err;
}
-static int win32_error (int unitnum, const TCHAR *format,...)
+static int win32_error (struct dev_info_ioctl *ciw, int unitnum, const TCHAR *format,...)
{
LPVOID lpMsgBuf;
va_list arglist;
if (err == ERROR_WRONG_DISK) {
write_log (L"IOCTL: media change, re-opening device\n");
- close_device (unitnum);
- if (!open_device (unitnum))
+ sys_cddev_close (ciw, unitnum);
+ if (!sys_cddev_open (ciw, unitnum))
write_log (L"IOCTL: re-opening failed!\n");
return -1;
}
NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf, 0, NULL);
if (log_scsi)
- write_log (L"IOCTL: unit=%d %s,%d: %s\n", unitnum, buf, err, (TCHAR*)lpMsgBuf);
+ write_log (L"IOCTL: unit=%d,%s,%d: %s\n", unitnum, buf, err, (TCHAR*)lpMsgBuf);
va_end (arglist);
return err;
}
-static int close_createfile (int unitnum)
+static int close_createfile (struct dev_info_ioctl *ciw)
{
- struct dev_info_ioctl *ciw = &ciw32[unitnum];
-
ciw->fullaccess = 0;
if (ciw->h != INVALID_HANDLE_VALUE) {
if (log_scsi)
return 0;
}
-static int open_createfile (int unitnum, int fullaccess)
+static int open_createfile (struct dev_info_ioctl *ciw, int fullaccess)
{
- struct dev_info_ioctl *ciw = &ciw32[unitnum];
int cnt = 50;
DWORD len;
if (ciw->h != INVALID_HANDLE_VALUE) {
if (fullaccess && ciw->fullaccess == 0) {
- close_createfile (unitnum);
+ close_createfile (ciw);
} else {
return 1;
}
{
DWORD len;
struct dev_info_ioctl *ciw = (struct dev_info_ioctl*)v;
- int unitnum = ciw32 - ciw;
int cdda_pos;
int num_sectors = CDDA_BUFFERS;
int bufnum;
int i;
WAVEHDR whdr[2];
MMRESULT mmr;
- int volume, volume_main;
+ int volume[2], volume_main;
int oldplay;
int firstloops;
bufon[0] = bufon[1] = 0;
bufnum = 0;
buffered = 0;
- volume = -1;
+ volume[0] = volume[1] = -1;
volume_main = -1;
if (cdda_openwav (ciw)) {
firstloops = 25;
write_log (L"CDDA: playing from %d to %d\n", ciw->cdda_start, ciw->cdda_end);
ciw->subcodevalid = false;
+ while (ciw->cdda_paused && ciw->cdda_play > 0)
+ Sleep (10);
}
if ((cdda_pos < ciw->cdda_end || ciw->cdda_end == 0xffffffff) && !ciw->cdda_paused && ciw->cdda_play) {
RAW_READ_INFO rri;
int sectors = num_sectors;
+ if (!isaudiotrack (&ciw->di.toc, cdda_pos))
+ goto end; // data track?
+
uae_sem_wait (&ciw->sub_sem);
ciw->subcodevalid = false;
memset (ciw->subcode, 0, sizeof ciw->subcode);
} else {
firstloops = -1;
- seterrormode (unitnum);
+ seterrormode (ciw);
rri.DiskOffset.QuadPart = 2048 * (cdda_pos + 0);
rri.SectorCount = sectors;
rri.TrackMode = RawWithSubCode;
}
ciw->subcodevalid = true;
}
- reseterrormode (unitnum);
+ reseterrormode (ciw);
}
uae_sem_post (&ciw->sub_sem);
uae_sem_post (&ciw->sub_sem2);
}
-
- volume = ciw->cdda_volume;
volume_main = currprefs.sound_volume;
- int vol_mult = (100 - volume_main) * volume / 100;
- if (vol_mult)
- vol_mult++;
- if (vol_mult >= 65536)
- vol_mult = 65536;
+ int vol_mult[2];
+ for (int j = 0; j < 2; j++) {
+ volume[j] = ciw->cdda_volume[j];
+ vol_mult[j] = (100 - volume_main) * volume[j] / 100;
+ if (vol_mult[j])
+ vol_mult[j]++;
+ if (vol_mult[j] >= 32768)
+ vol_mult[j] = 32768;
+ }
uae_s16 *p = (uae_s16*)(px[bufnum]);
for (i = 0; i < num_sectors * 2352 / 4; i++) {
- p[i * 2 + 0] = p[i * 2 + 0] * vol_mult / 65536;
- p[i * 2 + 1] = p[i * 2 + 1] * vol_mult / 65536;
+ p[i * 2 + 0] = p[i * 2 + 0] * vol_mult[0] / 32768;
+ p[i * 2 + 1] = p[i * 2 + 1] * vol_mult[1] / 32768;
}
bufon[bufnum] = 1;
}
if (firstloops < 0) {
- cdda_pos += num_sectors;
+ if (ciw->cdda_scan) {
+ cdda_pos += ciw->cdda_scan * num_sectors;
+ if (cdda_pos < 0)
+ cdda_pos = 0;
+ } else {
+ cdda_pos += num_sectors;
+ }
if (cdda_pos - num_sectors < ciw->cdda_end && cdda_pos >= ciw->cdda_end) {
ciw->cdda_play_finished = 1;
ciw->cdda_play = -1;
return NULL;
}
-static void cdda_stop (int unitnum)
+static void cdda_stop (struct dev_info_ioctl *ciw)
{
- struct dev_info_ioctl *ciw = &ciw32[unitnum];
-
if (ciw->cdda_play > 0) {
ciw->cdda_play = -1;
while (ciw->cdda_play) {
/* pause/unpause CD audio */
static int ioctl_command_pause (int unitnum, int paused)
{
- struct dev_info_ioctl *ciw = &ciw32[unitnum];
-
- if (!unitisopen (unitnum))
- return 0;
+ struct dev_info_ioctl *ciw = unitisopen (unitnum);
+ if (!ciw)
+ return -1;
+ int old = ciw->cdda_paused;
ciw->cdda_paused = paused;
- return 1;
+ return old;
}
/* stop CD audio */
static int ioctl_command_stop (int unitnum)
{
- struct dev_info_ioctl *ciw = &ciw32[unitnum];
-
- if (!unitisopen (unitnum))
+ struct dev_info_ioctl *ciw = unitisopen (unitnum);
+ if (!ciw)
return 0;
- cdda_stop (unitnum);
+ cdda_stop (ciw);
return 1;
}
-static void ioctl_command_volume (int unitnum, uae_u16 volume)
+static uae_u32 ioctl_command_volume (int unitnum, uae_u16 volume_left, uae_u16 volume_right)
{
- struct dev_info_ioctl *ciw = &ciw32[unitnum];
-
- ciw->cdda_volume = volume;
+ struct dev_info_ioctl *ciw = unitisopen (unitnum);
+ if (!ciw)
+ return -1;
+ uae_u32 old = (ciw->cdda_volume[1] << 16) | (ciw->cdda_volume[0] << 0);
+ ciw->cdda_volume[0] = volume_left;
+ ciw->cdda_volume[1] = volume_right;
+ return old;
}
/* play CD audio */
static int ioctl_command_play (int unitnum, int startlsn, int endlsn, int scan, play_subchannel_callback subfunc)
{
- struct dev_info_ioctl *ciw = &ciw32[unitnum];
-
- if (!unitisopen (unitnum))
+ struct dev_info_ioctl *ciw = unitisopen (unitnum);
+ if (!ciw)
return 0;
- if (!open_createfile (unitnum, 0))
+ if (!open_createfile (ciw, 0))
+ return 0;
+ if (!isaudiotrack (&ciw->di.toc, startlsn))
return 0;
- ciw->cdda_paused = 0;
ciw->cdda_play_finished = 0;
ciw->cdda_subfunc = subfunc;
+ ciw->cdda_scan = scan > 0 ? 10 : (scan < 0 ? 10 : 0);
if (!ciw->cdda_play) {
uae_start_thread (L"cdda_play", cdda_play, ciw, NULL);
}
/* read qcode */
static int ioctl_command_qcode (int unitnum, uae_u8 *buf, int sector)
{
- struct dev_info_ioctl *ciw = &ciw32[unitnum];
-
- if (!unitisopen (unitnum)) {
- write_log (L"qcode: %d no unit\n", unitnum);
+ struct dev_info_ioctl *ciw = unitisopen (unitnum);
+ if (!ciw)
return 0;
- }
uae_u8 *p;
int trk;
- CDROM_TOC *toc = &ciw->toc;
+ CDROM_TOC *toc = &ciw->cdromtoc;
int pos;
int msf;
int start, end;
int status;
bool valid = false;
- bool regenerate = false;
+ bool regenerate = true;
memset (buf, 0, SUBQ_SIZE);
p = buf;
if (!valid && sector >= 0) {
DWORD len;
uae_sem_wait (&ciw->sub_sem);
- seterrormode (unitnum);
+ seterrormode (ciw);
RAW_READ_INFO rri;
rri.DiskOffset.QuadPart = 2048 * (pos + 0);
rri.SectorCount = 1;
DWORD err = GetLastError ();
write_log (L"IOCTL_CDROM_RAW_READ SUBQ CDDA sector %d returned %d\n", pos, err);
}
- reseterrormode (unitnum);
+ reseterrormode (ciw);
uae_u8 subbuf[SUB_CHANNEL_SIZE];
sub_deinterleave (ciw->tempbuffer + 2352, subbuf);
uae_sem_post (&ciw->sub_sem);
UCHAR SenseBuf[32];
} SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER;
-static uae_u8 *spti_read (int unitnum, int sector, int sectorsize)
+static int do_raw_scsi (struct dev_info_ioctl *ciw, int unitnum, uae_u8 *cmd, int cmdlen, uae_u8 *data, int datalen)
{
DWORD status, returned;
SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb;
- uae_u8 *p = ciw32[unitnum].tempbuffer;
- /* number of bytes returned depends on type of track:
- * CDDA = 2352
- * Mode1 = 2048
- * Mode2 = 2336
- * Mode2 Form 1 = 2048
- * Mode2 Form 2 = 2328
- */
- uae_u8 cmd[12] = { 0xbe, 0, 0, 0, 0, 0, 0, 0, 1, 0x10, 0, 0 };
- int len = sizeof cmd;
-
- if (!unitisopen (unitnum))
+ uae_u8 *p = ciw->tempbuffer;
+ if (!open_createfile (ciw, 1))
return 0;
-
- if (!open_createfile (unitnum, 1))
- return 0;
- ciw32[unitnum].cd_last_pos = sector;
- cmd[3] = (uae_u8)(sector >> 16);
- cmd[4] = (uae_u8)(sector >> 8);
- cmd[5] = (uae_u8)(sector >> 0);
- gui_flicker_led (LED_CD, unitnum, 1);
memset (&swb, 0, sizeof (swb));
- memcpy (swb.spt.Cdb, cmd, len);
+ memcpy (swb.spt.Cdb, cmd, cmdlen);
swb.spt.Length = sizeof (SCSI_PASS_THROUGH);
- swb.spt.CdbLength = len;
+ swb.spt.CdbLength = cmdlen;
swb.spt.DataIn = SCSI_IOCTL_DATA_IN;
swb.spt.DataTransferLength = IOCTL_DATA_BUFFER;
swb.spt.DataBuffer = p;
swb.spt.TimeOutValue = 80 * 60;
swb.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, SenseBuf);
swb.spt.SenseInfoLength = 32;
-
- seterrormode (unitnum);
- status = DeviceIoControl (ciw32[unitnum].h, IOCTL_SCSI_PASS_THROUGH_DIRECT,
+ seterrormode (ciw);
+ status = DeviceIoControl (ciw->h, IOCTL_SCSI_PASS_THROUGH_DIRECT,
&swb, sizeof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER),
&swb, sizeof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER),
&returned, NULL);
- reseterrormode (unitnum);
+ reseterrormode (ciw);
if (!status) {
DWORD err = GetLastError ();
- write_log (L"IOCTL_RAW_SCSI unit %d, ERR=%d ", unitnum, err);
+ write_log (L"IOCTL_RAW_SCSI unit %d, CMD=%d, ERR=%d ", unitnum, cmd[0], err);
return 0;
}
- return p;
+ memcpy (data, p, swb.spt.DataTransferLength > datalen ? datalen : swb.spt.DataTransferLength);
+ return 1;
+}
+
+static int spti_inquiry (struct dev_info_ioctl *ciw, int unitnum, uae_u8 *data)
+{
+ uae_u8 cmd[6] = { 0x12,0,0,0,36,0 }; /* INQUIRY */
+ int len = sizeof cmd;
+
+ do_raw_scsi (ciw, unitnum, cmd, len, data, 256);
+ return 1;
+}
+
+static int spti_read (struct dev_info_ioctl *ciw, int unitnum, uae_u8 *data, int sector, int sectorsize)
+{
+ /* number of bytes returned depends on type of track:
+ * CDDA = 2352
+ * Mode1 = 2048
+ * Mode2 = 2336
+ * Mode2 Form 1 = 2048
+ * Mode2 Form 2 = 2328
+ */
+ uae_u8 cmd[12] = { 0xbe, 0, 0, 0, 0, 0, 0, 0, 1, 0x10, 0, 0 };
+ ciw->cd_last_pos = sector;
+ cmd[3] = (uae_u8)(sector >> 16);
+ cmd[4] = (uae_u8)(sector >> 8);
+ cmd[5] = (uae_u8)(sector >> 0);
+ gui_flicker_led (LED_CD, unitnum, 1);
+ int len = sizeof cmd;
+ return do_raw_scsi (ciw, unitnum, cmd, len, data, sectorsize);
}
-uae_u8 *ioctl_command_rawread (int unitnum, uae_u8 *data, int sector, int size, int sectorsize)
+static void sub_to_deinterleaved (const uae_u8 *s, uae_u8 *d)
{
+ for (int i = 0; i < 8 * 12; i ++) {
+ int dmask = 0x80;
+ int smask = 1 << (7 - (i / 12));
+ (*d) = 0;
+ for (int j = 0; j < 8; j++) {
+ (*d) |= (s[(i % 12) * 8 + j] & smask) ? dmask : 0;
+ dmask >>= 1;
+ }
+ d++;
+ }
+}
+
+static int ioctl_command_rawread (int unitnum, uae_u8 *data, int sector, int size, int sectorsize, uae_u16 extra)
+{
+ struct dev_info_ioctl *ciw = unitisopen (unitnum);
+ if (!ciw)
+ return 0;
+
RAW_READ_INFO rri;
DWORD len;
- uae_u8 *p = ciw32[unitnum].tempbuffer;
+ uae_u8 *p = ciw->tempbuffer;
+ int ret = 0;
if (log_scsi)
write_log (L"IOCTL rawread unit=%d sector=%d blocksize=%d\n", unitnum, sector, sectorsize);
if (!os_vista)
- return spti_read (unitnum, sector, sectorsize);
- if (!open_createfile (unitnum, 1))
+ return spti_read (ciw, unitnum, data, sector, sectorsize);
+ if (!open_createfile (ciw, 1))
return 0;
- cdda_stop (unitnum);
- if (sectorsize != 2336 && sectorsize != 2352 && sectorsize != 2048)
- return 0;
- while (size-- > 0) {
- gui_flicker_led (LED_CD, unitnum, 1);
- seterrormode (unitnum);
+ cdda_stop (ciw);
+ gui_flicker_led (LED_CD, unitnum, 1);
+ if (sectorsize > 0) {
+ if (sectorsize != 2336 && sectorsize != 2352 && sectorsize != 2048)
+ return 0;
+ seterrormode (ciw);
rri.DiskOffset.QuadPart = sector * 2048;
rri.SectorCount = 1;
rri.TrackMode = RawWithSubCode;
len = sectorsize;
memset (p, 0, sectorsize);
- if (!DeviceIoControl (ciw32[unitnum].h, IOCTL_CDROM_RAW_READ, &rri, sizeof rri,
+ if (!DeviceIoControl (ciw->h, IOCTL_CDROM_RAW_READ, &rri, sizeof rri,
p, IOCTL_DATA_BUFFER, &len, NULL)) {
DWORD err = GetLastError ();
write_log (L"IOCTL rawread unit=%d sector=%d blocksize=%d, ERR=%d\n", unitnum, sector, sectorsize, err);
}
- reseterrormode (unitnum);
+ reseterrormode (ciw);
if (data) {
- memcpy (data, p, sectorsize);
+ if (sectorsize == 2352)
+ memcpy (data, p, sectorsize);
+ else
+ memcpy (data, p + 16, sectorsize);
data += sectorsize;
+ ret += sectorsize;
}
- ciw32[unitnum].cd_last_pos = sector;
- break;
+ ciw->cd_last_pos = sector;
+ } else {
+ uae_u8 cmd9 = extra >> 8;
+ int sync = (cmd9 >> 7) & 1;
+ int headercodes = (cmd9 >> 5) & 3;
+ int userdata = (cmd9 >> 4) & 1;
+ int edcecc = (cmd9 >> 3) & 1;
+ int errorfield = (cmd9 >> 1) & 3;
+ uae_u8 subs = extra & 7;
+ if (subs != 0 && subs != 1 && subs != 2 && subs != 4)
+ return -1;
+ if (errorfield >= 3)
+ return -1;
+ uae_u8 *d = data;
+
+ if (isaudiotrack (&ciw->di.toc, sector)) {
+
+ for (int i = 0; i < size; i++) {
+ uae_u8 *odata = data;
+ int blocksize = errorfield == 0 ? 2352 : (errorfield == 1 ? 2352 + 294 : 2352 + 296);
+ int readblocksize = errorfield == 0 ? 2352 : 2352 + 296;
+ seterrormode (ciw);
+ rri.DiskOffset.QuadPart = sector * 2048;
+ rri.SectorCount = 1;
+ rri.TrackMode = errorfield > 0 ? RawWithC2AndSubCode : RawWithSubCode;
+ len = sectorsize;
+ memset (p, 0, blocksize);
+ if (!DeviceIoControl (ciw->h, IOCTL_CDROM_RAW_READ, &rri, sizeof rri, p, IOCTL_DATA_BUFFER, &len, NULL)) {
+ DWORD err = GetLastError ();
+ write_log (L"IOCTL rawread unit=%d sector=%d blocksize=%d, ERR=%d\n", unitnum, sector, sectorsize, err);
+ if (err) {
+ reseterrormode (ciw);
+ return ret;
+ }
+ }
+ reseterrormode (ciw);
+ if (subs == 0) {
+ memcpy (data, p, blocksize);
+ data += blocksize;
+ } else if (subs == 4) { // all, de-interleaved
+ memcpy (data, p, blocksize);
+ data += blocksize;
+ sub_to_deinterleaved (p + readblocksize, data);
+ data += SUB_CHANNEL_SIZE;
+ } else if (subs == 2) { // q-only
+ memcpy (data, p, blocksize);
+ data += blocksize;
+ uae_u8 subdata[SUB_CHANNEL_SIZE];
+ sub_to_deinterleaved (p + readblocksize, subdata);
+ memcpy (data, subdata + SUB_ENTRY_SIZE, SUB_ENTRY_SIZE);
+ p += SUB_ENTRY_SIZE;
+ } else if (subs == 1) { // all, interleaved
+ memcpy (data, p, blocksize);
+ memcpy (data + blocksize, p + readblocksize, SUB_CHANNEL_SIZE);
+ data += blocksize + SUB_CHANNEL_SIZE;
+ }
+ ret += data - odata;
+ sector++;
+ }
+ }
+
+
}
- if (sectorsize == 2352)
- return p;
- return p + 16;
+ return ret;
}
-static int ioctl_command_readwrite (int unitnum, int sector, int size, int write, int blocksize, uae_u8 *data, uae_u8 **ptr)
+static int ioctl_command_readwrite (int unitnum, int sector, int size, int write, uae_u8 *data)
{
+ struct dev_info_ioctl *ciw = unitisopen (unitnum);
+ if (!ciw)
+ return 0;
+
DWORD dtotal;
int cnt = 3;
- uae_u8 *p = ciw32[unitnum].tempbuffer;
+ uae_u8 *p = ciw->tempbuffer;
+ int blocksize = ciw->di.bytespersector;
- *ptr = NULL;
-
- if (!unitisopen (unitnum))
+ if (!open_createfile (ciw, 0))
return 0;
-
- if (!open_createfile (unitnum, 0))
- return 0;
- cdda_stop (unitnum);
- ciw32[unitnum].cd_last_pos = sector;
+ cdda_stop (ciw);
+ ciw->cd_last_pos = sector;
while (cnt-- > 0) {
gui_flicker_led (LED_CD, unitnum, 1);
- seterrormode (unitnum);
- if (SetFilePointer (ciw32[unitnum].h, sector * ciw32[unitnum].blocksize, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
- reseterrormode (unitnum);
- if (win32_error (unitnum, L"SetFilePointer") < 0)
+ seterrormode (ciw);
+ if (SetFilePointer (ciw->h, sector * ciw->di.bytespersector, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
+ reseterrormode (ciw);
+ if (win32_error (ciw, unitnum, L"SetFilePointer") < 0)
continue;
return 0;
}
- reseterrormode (unitnum);
+ reseterrormode (ciw);
break;
}
while (size-- > 0) {
gui_flicker_led (LED_CD, unitnum, 1);
- seterrormode (unitnum);
+ seterrormode (ciw);
if (write) {
if (data) {
memcpy (p, data, blocksize);
data += blocksize;
}
- if (!WriteFile (ciw32[unitnum].h, p, blocksize, &dtotal, 0)) {
+ if (!WriteFile (ciw->h, p, blocksize, &dtotal, 0)) {
int err;
- reseterrormode (unitnum);
- err = win32_error (unitnum, L"WriteFile");
+ reseterrormode (ciw);
+ err = win32_error (ciw, unitnum, L"WriteFile");
if (err < 0)
continue;
if (err == ERROR_WRITE_PROTECT)
return -1;
return 0;
}
- *ptr = p;
} else {
dtotal = 0;
- if (!ReadFile (ciw32[unitnum].h, p, blocksize, &dtotal, 0)) {
- reseterrormode (unitnum);
- if (win32_error (unitnum, L"ReadFile") < 0)
+ if (!ReadFile (ciw->h, p, blocksize, &dtotal, 0)) {
+ reseterrormode (ciw);
+ if (win32_error (ciw, unitnum, L"ReadFile") < 0)
continue;
return 0;
}
if (dtotal == 0) {
/* ESS Mega (CDTV) "fake" data area returns zero bytes and no error.. */
- *ptr = spti_read (unitnum, sector, 2048);
+ spti_read (ciw, unitnum, data, sector, 2048);
if (log_scsi)
- write_log (L"IOCTL unit %d, sector %d: ReadFile()==0. SPTI=%d\n", unitnum, sector, *ptr == 0 ? GetLastError () : 0);
+ write_log (L"IOCTL unit %d, sector %d: ReadFile()==0. SPTI=%d\n", unitnum, sector, GetLastError ());
return 1;
- } else {
- *ptr = p;
}
if (data) {
memcpy (data, p, blocksize);
data += blocksize;
}
}
- reseterrormode (unitnum);
+ reseterrormode (ciw);
gui_flicker_led (LED_CD, unitnum, 1);
}
return 1;
static int ioctl_command_write (int unitnum, uae_u8 *data, int sector, int size)
{
- uae_u8 *ptr;
- return ioctl_command_readwrite (unitnum, sector, size, 1, ciw32[unitnum].blocksize, data, &ptr);
+ return ioctl_command_readwrite (unitnum, sector, size, 1, data);
}
-static uae_u8 *ioctl_command_read (int unitnum, uae_u8 *data, int sector, int size)
+static int ioctl_command_read (int unitnum, uae_u8 *data, int sector, int size)
{
- uae_u8 *ptr;
- if (ioctl_command_readwrite (unitnum, sector, size, 0, ciw32[unitnum].blocksize, data, &ptr) > 0)
- return ptr;
- return NULL;
+ return ioctl_command_readwrite (unitnum, sector, size, 0, data);
}
-static int fetch_geometry (int unitnum, struct device_info *di)
+static int fetch_geometry (struct dev_info_ioctl *ciw, int unitnum, struct device_info *di)
{
DISK_GEOMETRY geom;
DWORD len;
int cnt = 3;
- if (!open_createfile (unitnum, 0))
+ if (!open_createfile (ciw, 0))
return 0;
- uae_sem_wait (&ciw32[unitnum].sub_sem);
- seterrormode (unitnum);
+ uae_sem_wait (&ciw->sub_sem);
+ seterrormode (ciw);
while (cnt-- > 0) {
- if (!DeviceIoControl (ciw32[unitnum].h, IOCTL_CDROM_GET_DRIVE_GEOMETRY, NULL, 0, &geom, sizeof (geom), &len, NULL)) {
- if (win32_error (unitnum, L"IOCTL_CDROM_GET_DRIVE_GEOMETRY") < 0)
+ if (!DeviceIoControl (ciw->h, IOCTL_CDROM_GET_DRIVE_GEOMETRY, NULL, 0, &geom, sizeof (geom), &len, NULL)) {
+ if (win32_error (ciw, unitnum, L"IOCTL_CDROM_GET_DRIVE_GEOMETRY") < 0)
continue;
- reseterrormode (unitnum);
- uae_sem_post (&ciw32[unitnum].sub_sem);
+ reseterrormode (ciw);
+ uae_sem_post (&ciw->sub_sem);
return 0;
}
+ break;
}
- reseterrormode (unitnum);
- uae_sem_post (&ciw32[unitnum].sub_sem);
+ reseterrormode (ciw);
+ uae_sem_post (&ciw->sub_sem);
if (di) {
di->cylinders = geom.Cylinders.LowPart;
di->sectorspertrack = geom.SectorsPerTrack;
return 1;
}
-static int ismedia (int unitnum)
+static int ismedia (struct dev_info_ioctl *ciw, int unitnum)
{
- struct dev_info_ioctl *ciw = &ciw32[unitnum];
- return fetch_geometry (unitnum, &ciw->di);
+ return fetch_geometry (ciw, unitnum, &ciw->di);
}
/* read toc */
-static struct cd_toc_head *ioctl_command_toc (int unitnum)
+static int ioctl_command_toc (int unitnum, struct cd_toc_head *tocout)
{
- struct dev_info_ioctl *ciw = &ciw32[unitnum];
+ struct dev_info_ioctl *ciw = unitisopen (unitnum);
+ if (!ciw)
+ return 0;
+
DWORD len;
int i;
- struct cd_toc_head *th = (struct cd_toc_head*)ciw->tempbuffer;
+ struct cd_toc_head *th = &ciw->di.toc;
struct cd_toc *t = th->toc;
int cnt = 3;
- CDROM_TOC *toc = &ciw->toc;
+ CDROM_TOC *toc = &ciw->cdromtoc;
if (!unitisopen (unitnum))
- return NULL;
+ return 0;
- if (!open_createfile (unitnum, 0))
+ if (!open_createfile (ciw, 0))
return 0;
- cdda_stop (unitnum);
- ciw32[unitnum].cd_last_pos = 0;
gui_flicker_led (LED_CD, unitnum, 1);
while (cnt-- > 0) {
- seterrormode (unitnum);
- if (!DeviceIoControl (ciw32[unitnum].h, IOCTL_CDROM_READ_TOC, NULL, 0, toc, sizeof (CDROM_TOC), &len, NULL)) {
- reseterrormode (unitnum);
- if (win32_error (unitnum, L"IOCTL_CDROM_READ_TOC") < 0)
+ seterrormode (ciw);
+ if (!DeviceIoControl (ciw->h, IOCTL_CDROM_READ_TOC, NULL, 0, toc, sizeof (CDROM_TOC), &len, NULL)) {
+ reseterrormode (ciw);
+ if (win32_error (ciw, unitnum, L"IOCTL_CDROM_READ_TOC") < 0)
continue;
return 0;
}
- reseterrormode (unitnum);
+ reseterrormode (ciw);
break;
}
t++;
gui_flicker_led (LED_CD, unitnum, 1);
- return th;
+ memcpy (tocout, th, sizeof (struct cd_toc_head));
+ return 1;
}
static void update_device_info (int unitnum)
{
- if (!unitcheck (unitnum))
+ struct dev_info_ioctl *ciw = unitcheck (unitnum);
+ if (!ciw)
return;
- struct device_info *di = &ciw32[unitnum].di;
+ struct device_info *di = &ciw->di;
di->bus = unitnum;
di->target = 0;
di->lun = 0;
di->media_inserted = 0;
di->bytespersector = 2048;
- _stprintf (di->mediapath, L"\\\\.\\%c:", ciw32[unitnum].drvletter);
- if (fetch_geometry (unitnum, di)) { // || ioctl_command_toc (unitnum))
+ _stprintf (di->mediapath, L"\\\\.\\%c:", ciw->drvletter);
+ if (fetch_geometry (ciw, unitnum, di)) { // || ioctl_command_toc (unitnum))
di->media_inserted = 1;
- ciw32[unitnum].blocksize = di->bytespersector;
}
- di->write_protected = ciw32[unitnum].type == DRIVE_CDROM ? 1 : 0;
- di->type = ciw32[unitnum].type == DRIVE_CDROM ? INQ_ROMD : INQ_DASD;
- di->id = ciw32[unitnum].drvletter;
- _tcscpy (di->label, ciw32[unitnum].drvlettername);
- memcpy (&di->toc, &ciw32[unitnum].toc, sizeof (struct cd_toc_head));
+ ioctl_command_toc (unitnum, &di->toc);
+ di->removable = ciw->type == DRIVE_CDROM ? 1 : 0;
+ di->write_protected = ciw->type == DRIVE_CDROM ? 1 : 0;
+ di->type = ciw->type == DRIVE_CDROM ? INQ_ROMD : INQ_DASD;
+ di->unitnum = unitnum + 1;
+ _tcscpy (di->label, ciw->drvlettername);
}
/* open device level access to cd rom drive */
-static int sys_cddev_open (int unitnum)
+static int sys_cddev_open (struct dev_info_ioctl *ciw, int unitnum)
{
- struct dev_info_ioctl *ciw = &ciw32[unitnum];
-
- ciw->cdda_volume = 0xffff;
+ uae_u8 inquiry[256];
+ ciw->cdda_volume[0] = 0x7fff;
+ ciw->cdda_volume[1] = 0x7fff;
ciw->cdda_volume_main = currprefs.sound_volume;
/* buffer must be page aligned for device access */
ciw->tempbuffer = (uae_u8*)VirtualAlloc (NULL, IOCTL_DATA_BUFFER, MEM_COMMIT, PAGE_READWRITE);
write_log (L"IOCTL: failed to allocate buffer");
return 1;
}
- if (!open_createfile (unitnum, 0)) {
+ _tcscpy (ciw->di.vendorid, L"UAE");
+ _stprintf (ciw->di.productid, L"SCSI CD%d IMG", unitnum);
+ _tcscpy (ciw->di.revision, L"0.1");
+ if (spti_inquiry (ciw, unitnum, inquiry)) {
+ char tmp[20];
+ TCHAR *s;
+ memcpy (tmp, inquiry + 8, 8);
+ tmp[8] = 0;
+ s = au (tmp);
+ _tcscpy (ciw->di.vendorid, s);
+ xfree (s);
+ memcpy (tmp, inquiry + 16, 16);
+ tmp[16] = 0;
+ s = au (tmp);
+ _tcscpy (ciw->di.productid, s);
+ xfree (s);
+ memcpy (tmp, inquiry + 32, 4);
+ tmp[4] = 0;
+ s = au (tmp);
+ _tcscpy (ciw->di.revision, s);
+ xfree (s);
+ close_createfile (ciw);
+ }
+ if (!open_createfile (ciw, 0)) {
write_log (L"IOCTL: failed to open '%s', err=%d\n", ciw->devname, GetLastError ());
goto error;
}
uae_sem_init (&ciw->sub_sem, 0, 1);
uae_sem_init (&ciw->sub_sem2, 0, 1);
- ciw->mediainserted = ioctl_command_toc (unitnum) ? 1 : 0;
- update_device_info (unitnum);
- write_log (L"IOCTL: device '%s' opened succesfully (unit number=%d,media=%d)\n", ciw->devname, unitnum, ciw->mediainserted);
ioctl_command_stop (unitnum);
+ update_device_info (unitnum);
+ ciw->open = true;
+ write_log (L"IOCTL: device '%s' (%s/%s/%s) opened succesfully (unit=%d,media=%d)\n",
+ ciw->devname, ciw->di.vendorid, ciw->di.productid, ciw->di.revision,
+ unitnum, ciw->di.media_inserted);
return 0;
error:
- win32_error (unitnum, L"CreateFile");
+ win32_error (ciw, unitnum, L"CreateFile");
VirtualFree (ciw->tempbuffer, 0, MEM_RELEASE);
ciw->tempbuffer = NULL;
CloseHandle (ciw->h);
}
/* close device handle */
-void sys_cddev_close (int unitnum)
+static void sys_cddev_close (struct dev_info_ioctl *ciw, int unitnum)
{
- struct dev_info_ioctl *ciw = &ciw32[unitnum];
-
- if (!unitcheck (unitnum))
+ if (ciw->open == false)
return;
- cdda_stop (unitnum);
- close_createfile (unitnum);
+ cdda_stop (ciw);
+ close_createfile (ciw);
VirtualFree (ciw->tempbuffer, 0, MEM_RELEASE);
ciw->tempbuffer = NULL;
uae_sem_destroy (&ciw->sub_sem);
uae_sem_destroy (&ciw->sub_sem2);
+ ciw->open = false;
+ write_log (L"IOCTL: device '%s' closed\n", ciw->devname, unitnum);
}
-static int open_device (int unitnum)
+static int open_device (int unitnum, const TCHAR *ident)
{
- if (!unitcheck (unitnum))
+ struct dev_info_ioctl *ciw = NULL;
+ if (ident) {
+ for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ ciw = &ciw32[i];
+ if (unittable[i] == 0 && ciw->drvletter != 0) {
+ if (!_tcsicmp (ciw->drvlettername, ident)) {
+ unittable[unitnum] = i + 1;
+ if (sys_cddev_open (ciw, unitnum) == 0)
+ return 1;
+ unittable[unitnum] = 0;
+ return 0;
+ }
+ }
+ }
return 0;
- if (sys_cddev_open (unitnum) == 0)
+ }
+ ciw = &ciw32[unitnum];
+ for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ if (unittable[i] == unitnum + 1)
+ return 0;
+ }
+ if (ciw->drvletter == 0)
+ return 0;
+ unittable[unitnum] = unitnum + 1;
+ if (sys_cddev_open (ciw, unitnum) == 0)
return 1;
+ unittable[unitnum] = 0;
return 0;
}
static void close_device (int unitnum)
{
- sys_cddev_close (unitnum);
-}
-
-static void close_bus (void)
-{
+ struct dev_info_ioctl *ciw = unitcheck (unitnum);
+ if (!ciw)
+ return;
+ sys_cddev_close (ciw, unitnum);
+ unittable[unitnum] = 0;
}
static int total_devices;
-static int check_bus (int flags)
+static void close_bus (void)
{
- return 1;
+ if (!bus_open) {
+ write_log (L"IOCTL close_bus() when already closed!\n");
+ return;
+ }
+ total_devices = 0;
+ for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ sys_cddev_close (&ciw32[i], i);
+ memset (&ciw32[i], 0, sizeof (struct dev_info_ioctl));
+ ciw32[i].h = INVALID_HANDLE_VALUE;
+ unittable[i] = 0;
+ }
+ bus_open = 0;
+ write_log (L"IOCTL driver closed.\n");
}
static int open_bus (int flags)
{
int dwDriveMask;
- int drive, i;
- TCHAR tmp[10];
+ int drive;
- for (i = 0; i < MAX_TOTAL_DEVICES; i++) {
- memset (&ciw32[i], 0, sizeof (struct dev_info_ioctl));
- ciw32[i].h = INVALID_HANDLE_VALUE;
+ if (bus_open) {
+ write_log (L"IOCTL open_bus() more than once!\n");
+ return 1;
}
- MCICDA = 1;//os_vista ? 1 : 0;
total_devices = 0;
dwDriveMask = GetLogicalDrives ();
if (log_scsi)
write_log (L"IOCTL: drive mask = %08X\n", dwDriveMask);
dwDriveMask >>= 2; // Skip A and B drives...
- for (drive = 'C'; drive <= 'Z' && total_devices < MAX_TOTAL_DEVICES; drive++) {
+ for (drive = 'C'; drive <= 'Z' && total_devices < MAX_TOTAL_SCSI_DEVICES; drive++) {
if (dwDriveMask & 1) {
int dt;
+ TCHAR tmp[10];
_stprintf (tmp, L"%c:\\", drive);
dt = GetDriveType (tmp);
if (log_scsi)
write_log (L"IOCTL: drive %c type %d\n", drive, dt);
- if (((flags & (1 << INQ_ROMD)) && dt == DRIVE_CDROM) || ((flags & (1 << INQ_DASD)) && dt == DRIVE_FIXED)) {
+ if (dt == DRIVE_CDROM) {
if (log_scsi)
write_log (L"IOCTL: drive %c: = unit %d\n", drive, total_devices);
ciw32[total_devices].drvletter = drive;
_tcscpy (ciw32[total_devices].drvlettername, tmp);
ciw32[total_devices].type = dt;
- ciw32[total_devices].blocksize = 2048;
+ ciw32[total_devices].di.bytespersector = 2048;
_stprintf (ciw32[total_devices].devname, L"\\\\.\\%c:", drive);
+ ciw32[total_devices].h = INVALID_HANDLE_VALUE;
total_devices++;
}
}
dwDriveMask >>= 1;
}
+ bus_open = 1;
+ write_log (L"IOCTL driver open, %d devices.\n", total_devices);
return total_devices;
}
static int ioctl_ismedia (int unitnum, int quick)
{
- if (!unitcheck (unitnum))
- return -1;
- if (!unitisopen (unitnum))
+ struct dev_info_ioctl *ciw = unitisopen (unitnum);
+ if (!ciw)
return -1;
if (quick) {
- struct dev_info_ioctl *ciw = &ciw32[unitnum];
- return ciw->mediainserted;
+ return ciw->di.media_inserted;
}
update_device_info (unitnum);
- return ismedia (unitnum);
+ return ismedia (ciw, unitnum);
}
static struct device_info *info_device (int unitnum, struct device_info *di, int quick)
{
- if (!unitcheck (unitnum))
+ struct dev_info_ioctl *ciw = unitcheck (unitnum);
+ if (!ciw)
return 0;
if (!quick)
update_device_info (unitnum);
- memcpy (di, &ciw32[unitnum].di, sizeof (struct device_info));
+ ciw->di.open = di->open;
+ memcpy (di, &ciw->di, sizeof (struct device_info));
return di;
}
void win32_ioctl_media_change (TCHAR driveletter, int insert)
{
- int i;
-
- for (i = 0; i < MAX_TOTAL_DEVICES; i++) {
- if (ciw32[i].drvletter == driveletter && ciw32[i].mediainserted != insert) {
- write_log (L"IOCTL: media change %s %d\n", ciw32[i].drvlettername, insert);
- ciw32[i].mediainserted = insert;
- update_device_info (i);
- scsi_do_disk_change (driveletter, insert, NULL);
+ for (int i = 0; i < total_devices; i++) {
+ struct dev_info_ioctl *ciw = &ciw32[i];
+ if (ciw->drvletter == driveletter && ciw->di.media_inserted != insert) {
+ write_log (L"IOCTL: media change %s %d\n", ciw->drvlettername, insert);
+ ciw->di.media_inserted = insert;
+ int unitnum = getunitnum (ciw);
+ if (unitnum >= 0) {
+ update_device_info (unitnum);
+ scsi_do_disk_change (unitnum, insert, NULL);
#ifdef RETROPLATFORM
- rp_cd_image_change (i, ciw32[i].drvlettername);
+ rp_cd_image_change (unitnum, ciw->drvlettername);
#endif
+ }
}
}
}
-static struct device_scsi_info *ioctl_scsi_info (int unitnum, struct device_scsi_info *dsi)
-{
- if (!unitcheck (unitnum))
- return 0;
- dsi->buffer = ciw32[unitnum].tempbuffer;
- dsi->bufsize = IOCTL_DATA_BUFFER;
- return dsi;
-}
-
struct device_functions devicefunc_win32_ioctl = {
- check_bus, open_bus, close_bus, open_device, close_device, info_device,
+ L"IOCTL",
+ open_bus, close_bus, open_device, close_device, info_device,
0, 0, 0,
ioctl_command_pause, ioctl_command_stop, ioctl_command_play, ioctl_command_volume, ioctl_command_qcode,
ioctl_command_toc, ioctl_command_read, ioctl_command_rawread, ioctl_command_write,
- 0, ioctl_scsi_info, ioctl_ismedia
+ 0, ioctl_ismedia
};
#endif
UCHAR SenseBuf[32];
} SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER;
-static int unitcnt = 0;
-
struct dev_info_spti {
TCHAR *drvpath;
TCHAR *name;
int bus, path, target, lun;
int scanmode;
uae_u8 *scsibuf;
+ bool open;
+ bool enabled;
+ struct device_info di;
};
static uae_sem_t scgp_sem;
-static struct dev_info_spti dev_info[MAX_TOTAL_DEVICES];
+static struct dev_info_spti dev_info[MAX_TOTAL_SCSI_DEVICES];
+static int unittable[MAX_TOTAL_SCSI_DEVICES];
+static int total_devices;
+static int bus_open;
+
+static int getunitnum (struct dev_info_spti *di)
+{
+ if (!di)
+ return -1;
+ int idx = di - &dev_info[0];
+ for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ if (unittable[i] - 1 == idx)
+ return i;
+ }
+ return -1;
+}
+
+static struct dev_info_spti *unitcheck (int unitnum)
+{
+ if (unitnum < 0 || unitnum >= MAX_TOTAL_SCSI_DEVICES)
+ return NULL;
+ if (unittable[unitnum] <= 0)
+ return NULL;
+ unitnum = unittable[unitnum] - 1;
+ if (dev_info[unitnum].drvletter == 0)
+ return NULL;
+ return &dev_info[unitnum];
+}
+
+static struct dev_info_spti *unitisopen (int unitnum)
+{
+ struct dev_info_spti *di = unitcheck (unitnum);
+ if (!di)
+ return NULL;
+ if (di->open == false)
+ return NULL;
+ return di;
+}
-static int doscsi (int unitnum, SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER *swb, int *err)
+static int doscsi (struct dev_info_spti *di, int unitnum, SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER *swb, int *err)
{
DWORD status, returned;
- struct dev_info_spti *di = &dev_info[unitnum];
*err = 0;
if (log_scsi) {
#define MODE_SELECT_10 0x55
#define MODE_SENSE_10 0x5A
-static int execscsicmd (int unitnum, uae_u8 *data, int len, uae_u8 *inbuf, int inlen)
+static int execscsicmd (struct dev_info_spti *di, int unitnum, uae_u8 *data, int len, uae_u8 *inbuf, int inlen)
{
SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb;
DWORD status;
swb.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, SenseBuf);
swb.spt.SenseInfoLength = 32;
memcpy (swb.spt.Cdb, data, len);
- status = doscsi (unitnum, &swb, &err);
+ status = doscsi (di, unitnum, &swb, &err);
uae_sem_post (&scgp_sem);
dolen = swb.spt.DataTransferLength;
if (!status)
static int execscsicmd_direct (int unitnum, struct amigascsi *as)
{
+ struct dev_info_spti *di = unitisopen (unitnum);
+ if (!di)
+ return -1;
+
SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb;
DWORD status;
int sactual = 0, i;
swb.spt.DataTransferLength = as->len;
swb.spt.DataBuffer = scsi_datap;
- status = doscsi (unitnum, &swb, &err);
+ status = doscsi (di, unitnum, &swb, &err);
as->cmdactual = status == 0 ? 0 : scsi_cmd_len_orig; /* fake scsi_CmdActual */
as->status = swb.spt.ScsiStatus; /* scsi_Status */
static uae_u8 *execscsicmd_out (int unitnum, uae_u8 *data, int len)
{
- int v = execscsicmd (unitnum, data, len, 0, 0);
+ struct dev_info_spti *di = unitisopen (unitnum);
+ if (!di)
+ return 0;
+ int v = execscsicmd (di, unitnum, data, len, 0, 0);
if (v < 0)
return 0;
return data;
static uae_u8 *execscsicmd_in (int unitnum, uae_u8 *data, int len, int *outlen)
{
- int v = execscsicmd (unitnum, data, len, dev_info[unitnum].scsibuf, DEVICE_SCSI_BUFSIZE);
+ struct dev_info_spti *di = unitisopen (unitnum);
+ if (!di)
+ return 0;
+ int v = execscsicmd (di, unitnum, data, len, di->scsibuf, DEVICE_SCSI_BUFSIZE);
if (v < 0)
return 0;
if (v == 0)
return 0;
if (outlen)
*outlen = v;
- return dev_info[unitnum].scsibuf;
+ return di->scsibuf;
}
-static int total_devices;
+static uae_u8 *execscsicmd_in_internal (struct dev_info_spti *di, int unitnum, uae_u8 *data, int len, int *outlen)
+{
+ int v = execscsicmd (di, unitnum, data, len, di->scsibuf, DEVICE_SCSI_BUFSIZE);
+ if (v < 0)
+ return 0;
+ if (v == 0)
+ return 0;
+ if (outlen)
+ *outlen = v;
+ return di->scsibuf;
+}
+static void close_scsi_device2 (struct dev_info_spti *di)
+{
+ if (di->open == false)
+ return;
+ if (di->handle != INVALID_HANDLE_VALUE)
+ CloseHandle (di->handle);
+ di->handle = INVALID_HANDLE_VALUE;
+ di->open = false;
+}
static void close_scsi_device (int unitnum)
{
- if (dev_info[unitnum].handle != INVALID_HANDLE_VALUE) {
- write_log (L"SPTI: unit %d closed\n", unitnum);
- CloseHandle (dev_info[unitnum].handle);
- }
- dev_info[unitnum].handle = INVALID_HANDLE_VALUE;
+ struct dev_info_spti *di = unitisopen (unitnum);
+ if (!di)
+ return;
+ close_scsi_device2 (di);
+ unittable[unitnum] = 0;
}
-static void free_scsi_device(int dev)
+static void free_scsi_device (struct dev_info_spti *di)
{
- close_scsi_device (dev);
- xfree(dev_info[dev].name);
- xfree(dev_info[dev].drvpath);
- xfree(dev_info[dev].inquirydata);
- VirtualFree (dev_info[dev].scsibuf, 0, MEM_RELEASE);
- dev_info[dev].name = NULL;
- dev_info[dev].drvpath = NULL;
- dev_info[dev].inquirydata = NULL;
- dev_info[dev].scsibuf = NULL;
- memset(&dev_info[dev], 0, sizeof (struct dev_info_spti));
+ close_scsi_device2 (di);
+ xfree (di->name);
+ xfree (di->drvpath);
+ xfree (di->inquirydata);
+ VirtualFree (di->scsibuf, 0, MEM_RELEASE);
+ di->name = NULL;
+ di->drvpath = NULL;
+ di->inquirydata = NULL;
+ di->scsibuf = NULL;
+ memset (di, 0, sizeof (struct dev_info_spti));
}
static int rescan (void);
-static int check_scsi_bus (int flags)
+static void close_scsi_bus (void)
{
- return 1;
+ if (!bus_open) {
+ write_log (L"SPTI close_bus() when already closed!\n");
+ return;
+ }
+ for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ free_scsi_device (&dev_info[i]);
+ unittable[i] = 0;
+ }
+ total_devices = 0;
+ bus_open = 0;
+ write_log (L"SPTI driver closed.\n");
}
static int open_scsi_bus (int flags)
{
- int i;
-
+ if (bus_open) {
+ write_log (L"SPTI open_bus() more than once!\n");
+ return 1;
+ }
total_devices = 0;
uae_sem_init (&scgp_sem, 0, 1);
- for (i = 0; i < MAX_TOTAL_DEVICES; i++) {
- memset (&dev_info[i], 0, sizeof (struct dev_info_spti));
- dev_info[i].handle = INVALID_HANDLE_VALUE;
- }
rescan ();
+ bus_open = 1;
+ write_log (L"SPTI driver open, %d devices.\n", total_devices);
return total_devices;
}
-static void close_scsi_bus (void)
+static int mediacheck (struct dev_info_spti *di, int unitnum)
+{
+ uae_u8 cmd [6] = { 0,0,0,0,0,0 }; /* TEST UNIT READY */
+ if (di->open == false)
+ return -1;
+ int v = execscsicmd (di, unitnum, cmd, sizeof cmd, 0, 0);
+ return v >= 0 ? 1 : 0;
+}
+
+static int mediacheck_full (struct dev_info_spti *di, int unitnum, struct device_info *dinfo)
{
- int i;
- for (i = 0; i < total_devices; i++)
- free_scsi_device (i);
+ uae_u8 cmd1[10] = { 0x25,0,0,0,0,0,0,0,0,0 }; /* READ CAPACITY */
+ uae_u8 *p;
+ int outlen;
+
+ dinfo->sectorspertrack = 0;
+ dinfo->trackspercylinder = 0;
+ dinfo->bytespersector = 0;
+ dinfo->cylinders = 0;
+ dinfo->write_protected = 1;
+ if (di->open == false)
+ return 0;
+ outlen = 32;
+ p = execscsicmd_in_internal (di, unitnum, cmd1, sizeof cmd1, &outlen);
+ if (p && outlen >= 8) {
+ dinfo->bytespersector = (p[4] << 24) | (p[5] << 16) | (p[6] << 8) | p[7];
+ dinfo->sectorspertrack = ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]) + 1;
+ dinfo->trackspercylinder = 1;
+ dinfo->cylinders = 1;
+ }
+ if (di->type == INQ_DASD) {
+ uae_u8 cmd2[10] = { 0x5a,0x08,0,0,0,0,0,0,0xf0,0 }; /* MODE SENSE */
+ outlen = 32;
+ p = execscsicmd_in_internal (di, unitnum, cmd2, sizeof cmd2, &outlen);
+ if (p && outlen >= 4) {
+ dinfo->write_protected = (p[3] & 0x80) ? 1 : 0;
+ }
+ }
+ // write_log (L"mediacheck_full(%d,%d,%d,%d,%d)\n",
+ // di->bytespersector, di->sectorspertrack, di->trackspercylinder, di->cylinders, di->write_protected);
+ return 1;
+}
+
+static void update_device_info (int unitnum)
+{
+ struct dev_info_spti *dispti = unitisopen (unitnum);
+ if (!dispti)
+ return;
+ struct device_info *di = &dispti->di;
+ _tcscpy (di->label, dispti->drvletter ? dispti->drvlettername : dispti->name);
+ _tcscpy (di->mediapath, dispti->drvpath);
+ di->bus = 0;
+ di->target = unitnum;
+ di->lun = 0;
+ di->media_inserted = mediacheck (dispti, unitnum);
+ di->removable = dispti->removable;
+ mediacheck_full (dispti, unitnum, di);
+ di->type = dispti->type;
+ di->unitnum = unitnum + 1;
+ if (log_scsi) {
+ write_log (L"MI=%d TP=%d WP=%d CY=%d BK=%d RMB=%d '%s'\n",
+ di->media_inserted, di->type, di->write_protected, di->cylinders, di->bytespersector, di->removable, di->label);
+ }
}
-static void checkcapabilities (int unitnum)
+static void checkcapabilities (struct dev_info_spti *di)
{
- struct dev_info_spti *di = &dev_info[unitnum];
STORAGE_ADAPTER_DESCRIPTOR desc;
STORAGE_PROPERTY_QUERY query;
DWORD ret, status;
}
}
-static int inquiry (int unitnum, struct dev_info_spti *di, uae_u8 *inquirydata)
+static int inquiry (struct dev_info_spti *di, int unitnum, uae_u8 *inquirydata)
{
uae_u8 cmd[6] = { 0x12,0,0,0,36,0 }; /* INQUIRY */
uae_u8 out[INQUIRY_SIZE] = { 0 };
int outlen = sizeof (out);
- uae_u8 *p = execscsicmd_in (unitnum, cmd, sizeof (cmd), &outlen);
+ uae_u8 *p = execscsicmd_in_internal (di, unitnum, cmd, sizeof (cmd), &outlen);
int inqlen = 0;
di->isatapi = 0;
return inqlen;
}
-static int mediacheck (int unitnum)
-{
- uae_u8 cmd [6] = { 0,0,0,0,0,0 }; /* TEST UNIT READY */
- int v;
- if (dev_info[unitnum].handle == INVALID_HANDLE_VALUE)
- return 0;
- v = execscsicmd (unitnum, cmd, sizeof (cmd), 0, 0);
- return v >= 0 ? 1 : 0;
-}
-
-static int mediacheck_full (int unitnum, struct device_info *di)
-{
- uae_u8 cmd1[10] = { 0x25,0,0,0,0,0,0,0,0,0 }; /* READ CAPACITY */
- uae_u8 *p;
- int outlen;
-
- di->sectorspertrack = 0;
- di->trackspercylinder = 0;
- di->bytespersector = 0;
- di->cylinders = 0;
- di->write_protected = 1;
- if (dev_info[unitnum].handle == INVALID_HANDLE_VALUE)
- return 0;
- outlen = 32;
- p = execscsicmd_in (unitnum, cmd1, sizeof cmd1, &outlen);
- if (p && outlen >= 8) {
- di->bytespersector = (p[4] << 24) | (p[5] << 16) | (p[6] << 8) | p[7];
- di->sectorspertrack = ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]) + 1;
- di->trackspercylinder = 1;
- di->cylinders = 1;
- }
- if (di->type == INQ_DASD) {
- uae_u8 cmd2[10] = { 0x5a,0x08,0,0,0,0,0,0,0xf0,0 }; /* MODE SENSE */
- outlen = 32;
- p = execscsicmd_in (unitnum, cmd2, sizeof cmd2, &outlen);
- if (p && outlen >= 4) {
- di->write_protected = (p[3] & 0x80) ? 1 : 0;
- }
- }
- // write_log (L"mediacheck_full(%d,%d,%d,%d,%d)\n",
- // di->bytespersector, di->sectorspertrack, di->trackspercylinder, di->cylinders, di->write_protected);
- return 1;
-}
-
-int open_scsi_device (int unitnum)
+static int open_scsi_device2 (struct dev_info_spti *di, int unitnum)
{
HANDLE h;
TCHAR *dev;
- struct dev_info_spti *di;
- di = &dev_info[unitnum];
- if (unitnum >= total_devices)
- return 0;
- if (!di)
- return 0;
if (di->bus >= 0) {
dev = xmalloc (TCHAR, 100);
_stprintf (dev, L"\\\\.\\Scsi%d:", di->bus);
write_log (L"SPTI: failed to open unit %d err=%d ('%s')\n", unitnum, GetLastError (), dev);
} else {
uae_u8 inqdata[INQUIRY_SIZE + 1] = { 0 };
- checkcapabilities (unitnum);
- if (!inquiry (unitnum, di, inqdata)) {
+ checkcapabilities (di);
+ if (!inquiry (di, unitnum, inqdata)) {
write_log (L"SPTI: inquiry failed unit %d ('%s':%d:%d:%d:%d)\n", unitnum, dev,
di->bus, di->path, di->target, di->lun);
- close_scsi_device (unitnum);
+ close_scsi_device2 (di);
xfree (dev);
return 0;
}
inqdata[INQUIRY_SIZE] = 0;
di->name = my_strdup_ansi ((char*)inqdata + 8);
if (di->type == INQ_ROMD) {
- dev_info[unitnum].mediainserted = mediacheck (unitnum);
+ di->mediainserted = mediacheck (di, unitnum);
write_log (L"SPTI: unit %d (%c:\\) opened [%s], %s, '%s'\n",
unitnum, di->drvletter ? di->drvletter : '*',
di->isatapi ? L"ATAPI" : L"SCSI",
di->inquirydata = xmalloc (uae_u8, INQUIRY_SIZE);
memcpy (di->inquirydata, inqdata, INQUIRY_SIZE);
xfree (dev);
+ update_device_info (unitnum);
+ di->open = true;
return 1;
}
xfree (dev);
return 0;
}
+int open_scsi_device (int unitnum, const TCHAR *ident)
+{
+ struct dev_info_spti *di = NULL;
+ if (ident) {
+ for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ di = &dev_info[i];
+ if (unittable[i] == 0 && di->drvletter != 0) {
+ if (!_tcsicmp (di->drvlettername, ident)) {
+ unittable[unitnum] = i + 1;
+ if (open_scsi_device2 (di, unitnum))
+ return 1;
+ unittable[unitnum] = 0;
+ return 0;
+ }
+ }
+ }
+ return 0;
+ }
+ di = &dev_info[unitnum];
+ for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ if (unittable[i] == unitnum + 1)
+ return 0;
+ }
+ if (di->enabled == 0)
+ return 0;
+ unittable[unitnum] = unitnum + 1;
+ if (open_scsi_device2 (di, unitnum))
+ return 1;
+ unittable[unitnum] = 0;
+ return 0;
+}
-static int adddrive (TCHAR *drvpath, int bus, int pathid, int targetid, int lunid, int scanmode)
+static int adddrive (const TCHAR *drvpath, int bus, int pathid, int targetid, int lunid, int scanmode)
{
struct dev_info_spti *di;
int cnt = total_devices, i;
int freeit = 1;
- if (cnt >= MAX_TOTAL_DEVICES)
+ if (cnt >= MAX_TOTAL_SCSI_DEVICES)
return 0;
for (i = 0; i < total_devices; i++) {
di = &dev_info[i];
di->lun = lunid;
di->scanmode = scanmode;
di->drvletter = 0;
+ di->enabled = true;
for (TCHAR drvletter = 'C'; drvletter <= 'Z'; drvletter++) {
TCHAR drvname[10];
total_devices++;
- if (open_scsi_device (cnt)) {
+ unittable[cnt] = cnt + 1;
+ if (open_scsi_device2 (&dev_info[cnt], cnt)) {
for (i = 0; i < cnt; i++) {
if (!memcmp (di->inquirydata, dev_info[i].inquirydata, INQUIRY_SIZE) && di->scanmode != dev_info[i].scanmode) {
write_log (L"duplicate device, skipped..\n");
}
if (i == cnt) {
freeit = 0;
- close_scsi_device (cnt);
+ close_scsi_device2 (&dev_info[cnt]);
}
}
if (freeit) {
- free_scsi_device (cnt);
+ free_scsi_device (&dev_info[cnt]);
total_devices--;
}
+ unittable[cnt] = 0;
return 1;
}
-static int getid (int unitnum)
-{
- return dev_info[unitnum].drvletter ? dev_info[unitnum].drvletter : unitnum + 1;
-}
-
static struct device_info *info_device (int unitnum, struct device_info *di, int quick)
{
- struct dev_info_spti *dispti;
- if (unitnum >= MAX_TOTAL_DEVICES || dev_info[unitnum].handle == INVALID_HANDLE_VALUE)
+ struct dev_info_spti *dispti = unitcheck (unitnum);
+ if (!dispti)
return NULL;
- dispti = &dev_info[unitnum];
- _tcscpy (di->label, dispti->drvletter ? dispti->drvlettername : dispti->name);
- _tcscpy (di->mediapath, dispti->drvpath);
- di->bus = 0;
- di->target = unitnum;
- di->lun = 0;
- di->media_inserted = mediacheck (unitnum);
- di->removable = dispti->removable;
- mediacheck_full (unitnum, di);
- di->type = dispti->type;
- di->id = getid (unitnum);
- if (log_scsi) {
- write_log (L"MI=%d TP=%d WP=%d CY=%d BK=%d RMB=%d '%s'\n",
- di->media_inserted, di->type, di->write_protected, di->cylinders, di->bytespersector, di->removable, di->label);
- }
+ if (!quick)
+ update_device_info (unitnum);
+ dispti->di.open = di->open;
+ memcpy (di, &dispti->di, sizeof (struct device_info));
return di;
}
void win32_spti_media_change (TCHAR driveletter, int insert)
{
- int i, now;
-
- for (i = 0; i < total_devices; i++) {
- if (dev_info[i].type == INQ_ROMD) {
- now = mediacheck (i);
- if (now != dev_info[i].mediainserted) {
- write_log (L"SPTI: media change %c %d\n", dev_info[i].drvletter, insert);
- dev_info[i].mediainserted = now;
- scsi_do_disk_change (getid (i), insert, NULL);
+ for (int i = 0; i < total_devices; i++) {
+ struct dev_info_spti *di = &dev_info[i];
+ if (di->drvletter == driveletter && di->mediainserted != insert) {
+ write_log (L"SPTI: media change %c %d\n", dev_info[i].drvletter, insert);
+ di->mediainserted = insert;
+ int unitnum = getunitnum (di);
+ if (unitnum >= 0) {
+ update_device_info (unitnum);
+ scsi_do_disk_change (unitnum, insert, NULL);
#ifdef RETROPLATFORM
- rp_cd_image_change (i, dev_info[i].drvletter ? dev_info[i].drvlettername : dev_info[i].name);
+ rp_cd_image_change (unitnum, di->drvletter ? di->drvlettername : di->name);
#endif
}
}
static int check_isatapi (int unitnum)
{
- return dev_info[unitnum].isatapi;
-}
-
-static struct device_scsi_info *scsi_info (int unitnum, struct device_scsi_info *dsi)
-{
- dsi->buffer = dev_info[unitnum].scsibuf;
- dsi->bufsize = DEVICE_SCSI_BUFSIZE;
- return dsi;
+ struct dev_info_spti *di = unitcheck (unitnum);
+ if (!di)
+ return 0;
+ return di->isatapi;
}
-struct device_functions devicefunc_win32_spti = {
- check_scsi_bus, open_scsi_bus, close_scsi_bus, open_scsi_device, close_scsi_device, info_device,
- execscsicmd_out, execscsicmd_in, execscsicmd_direct,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, check_isatapi, scsi_info, 0
-};
-
static int getCDROMProperty (int idx, HDEVINFO DevInfo, const GUID *guid)
{
SP_DEVICE_INTERFACE_DATA interfaceData;
#endif
+
+
+struct device_functions devicefunc_win32_spti = {
+ L"SPTI",
+ open_scsi_bus, close_scsi_bus, open_scsi_device, close_scsi_device, info_device,
+ execscsicmd_out, execscsicmd_in, execscsicmd_direct,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, check_isatapi, 0
+};
} else if (did == di_keyboard) {
if (rdpdevice (buf))
continue;
- if (rnum_kb < 2)
- continue;
if (num_keyboard >= MAX_INPUT_DEVICES)
continue;
did += num_keyboard;
if (rnum_kb && num_keyboard < MAX_INPUT_DEVICES - 1) {
struct didata *did = di_keyboard + num_keyboard;
num_keyboard++;
- rkb++;
+ rnum_kb++;
did->name = my_strdup (L"WinUAE null keyboard");
did->rawinput = NULL;
did->connection = DIDC_RAW;
}
}
if (num == num_keyboard) {
- if (!istest && scancode == DIK_F12 && pressed && isfocus ())
- inputdevice_add_inputcode (AKS_ENTERGUI, 1);
- return;
+ for (num = 0; num < num_keyboard; num++) {
+ if (did->connection == DIDC_RAW && did->acquired && did->rawinput == NULL)
+ break;
+ }
+ if (num == num_keyboard) {
+ if (!istest && scancode == DIK_F12 && pressed && isfocus ())
+ inputdevice_add_inputcode (AKS_ENTERGUI, 1);
+ return;
+ }
}
if (rawkeystate[scancode] == pressed) {
DWORD comlen;
DWORD flags;
if (GetVolumeInformation (volume, NULL, 0, NULL, &comlen, &flags, fsname, sizeof (fsname))) {
- write_log (L"Volume %s FS=%s maxlen=%d flags=%08X\n", volume, fsname, comlen, flags);
+ //write_log (L"Volume %s FS=%s maxlen=%d flags=%08X\n", volume, fsname, comlen, flags);
if (flags & FILE_NAMED_STREAMS)
ret |= MYVOLUMEINFO_STREAMS;
}
hThread = (HANDLE)_beginthreadex (NULL, 0, thread_init, thp, 0, &foo);
if (hThread) {
if (name) {
- write_log (L"Thread '%s' started (%d)\n", name, hThread);
+ //write_log (L"Thread '%s' started (%d)\n", name, hThread);
SetThreadPriority (hThread, THREAD_PRIORITY_HIGHEST);
}
} else {
{
if (num != 0)
return 0;
- _tcscpy (changed_prefs.cdimagefile, name);
+ _tcscpy (changed_prefs.cdimagefile[0], name);
config_changed = 1;
return 1;
}
}
}
- for (i = 0; i < MAX_TOTAL_DEVICES; i++) {
- int v = sys_command_ismedia (DF_IOCTL, i, 1);
+ for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ int v = sys_command_ismedia (i, 1);
if (v >= 0)
cd_mask |= 1 << i;
}
RPSendMessagex (RPIPCGM_DEVICES, RP_DEVICE_CD, cd_mask, NULL, 0, &guestinfo, NULL);
if (cd_mask) {
- for (i = 0; i < MAX_TOTAL_DEVICES; i++) {
+ for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
if ((1 << i) & cd_mask) {
struct device_info di = { 0 };
- if (sys_command_info (DF_IOCTL, i, &di, 0))
+ if (sys_command_info (i, &di, 0))
rp_cd_image_change (i, di.mediapath);
}
}
static int get_aspi (int old)
{
- if ((old == UAESCSI_SPTI || old == UAESCSI_SPTISCAN) && os_winnt_admin)
- return old;
if (old == UAESCSI_NEROASPI && get_aspi_path (1))
return old;
if (old == UAESCSI_FROGASPI && get_aspi_path (2))
return old;
if (old == UAESCSI_ADAPTECASPI && get_aspi_path (0))
return old;
- if (os_winnt_admin)
- return UAESCSI_SPTI;
- else if (get_aspi_path (1))
+ if (get_aspi_path (1))
return UAESCSI_NEROASPI;
else if (get_aspi_path (2))
return UAESCSI_FROGASPI;
p->win32_automount_cddrives = 0;
p->win32_automount_netdrives = 0;
p->win32_kbledmode = 0;
- p->win32_uaescsimode = get_aspi (p->win32_uaescsimode);
+ p->win32_uaescsimode = UAESCSI_CDEMU;
p->win32_borderless = 0;
p->win32_powersavedisabled = 1;
p->sana2 = 0;
p->win32_commandpathend[0] = 0;
}
if (type == 1 || type == 0) {
- p->win32_uaescsimode = get_aspi (p->win32_uaescsimode);
+ p->win32_uaescsimode = UAESCSI_CDEMU;
p->win32_midioutdev = -2;
p->win32_midiindev = 0;
p->win32_automount_removable = 0;
}
if (cfgfile_yesno (option, value, L"aspi", &vb)) {
- p->win32_uaescsimode = false;
+ p->win32_uaescsimode = 0;
if (vb)
p->win32_uaescsimode = get_aspi (0);
if (p->win32_uaescsimode < UAESCSI_ASPI_FIRST)
return 1;
}
- if (cfgfile_strval (option, value, L"uaescsimode", &p->win32_uaescsimode, scsimode, 0))
+ if (cfgfile_strval (option, value, L"uaescsimode", &p->win32_uaescsimode, scsimode, 0)) {
+ // do not forget me!
+ p->win32_uaescsimode = UAESCSI_CDEMU;
return 1;
+ }
if (cfgfile_intval (option, value, L"active_priority", &v, 1)) {
p->win32_active_priority = fetchpri (v, 1);
#define WINUAEPUBLICBETA 1
#define LANG_DLL 1
-#define WINUAEBETA L"3"
-#define WINUAEDATE MAKEBD(2010, 7, 16)
+#define WINUAEBETA L"4"
+#define WINUAEDATE MAKEBD(2010, 7, 18)
#define WINUAEEXTRA L""
#define WINUAEREV L""
static void eject_cd (void)
{
- workprefs.cdimagefile[0] = 0;
+ workprefs.cdimagefile[0][0] = 0;
quickstart_cddrive[0] = 0;
- workprefs.cdimagefileuse = false;
+ workprefs.cdimagefileuse[0] = false;
if (full_property_sheet) {
quickstart_cdtype = 0;
} else {
if (quickstart_cdtype > 0) {
quickstart_cdtype = 1;
- workprefs.cdimagefileuse = true;
+ workprefs.cdimagefileuse[0] = true;
}
}
}
SetDlgItemText (hDlg, id, full_path);
if (quickstart_cddrive[0])
eject_cd ();
- _tcscpy (prefs->cdimagefile, full_path);
+ _tcscpy (prefs->cdimagefile[0], full_path);
DISK_history_add (full_path, -1, HISTORY_CD, 0);
}
workprefs.df[1][0] = 0;
workprefs.df[2][0] = 0;
workprefs.df[3][0] = 0;
- workprefs.cdimagefile[0] = 0;
- workprefs.cdimagefileuse = quickstart_cdtype > 0;
+ workprefs.cdimagefile[0][0] = 0;
+ workprefs.cdimagefileuse[0] = quickstart_cdtype > 0;
load_quickstart (hDlg, 1);
quickstarthost (hDlg, hostconf);
}
int len = sizeof quickstart_cddrive / sizeof (TCHAR);
quickstart_cdtype = 2;
SendDlgItemMessage (hDlg, IDC_CD0Q_TYPE, WM_GETTEXT, (WPARAM)len, (LPARAM)quickstart_cddrive);
- _tcscpy (workprefs.cdimagefile, quickstart_cddrive);
+ _tcscpy (workprefs.cdimagefile[0], quickstart_cddrive);
} else {
eject_cd ();
quickstart_cdtype = val;
}
+ workprefs.cdimagefileuse[0] = quickstart_cdtype > 0;
addfloppytype (hDlg, 1);
addfloppyhistory (hDlg);
}
static void misc_scsi (HWND hDlg)
{
SendDlgItemMessage (hDlg, IDC_SCSIMODE, CB_RESETCONTENT, 0, 0);
- SendDlgItemMessage (hDlg, IDC_SCSIMODE, CB_ADDSTRING, 0, (LPARAM)L"SCSI Emulation");
- SendDlgItemMessage (hDlg, IDC_SCSIMODE, CB_ADDSTRING, 0, (LPARAM)L"SPTI *");
+ SendDlgItemMessage (hDlg, IDC_SCSIMODE, CB_ADDSTRING, 0, (LPARAM)L"SCSI Emulation *");
+ SendDlgItemMessage (hDlg, IDC_SCSIMODE, CB_ADDSTRING, 0, (LPARAM)L"SPTI");
SendDlgItemMessage (hDlg, IDC_SCSIMODE, CB_ADDSTRING, 0, (LPARAM)L"SPTI + SCSI SCAN");
SendDlgItemMessage (hDlg, IDC_SCSIMODE, CB_ADDSTRING, 0, (LPARAM)((get_aspi_path (0)) ? L"AdaptecASPI" : L"(AdaptecASPI)"));
SendDlgItemMessage (hDlg, IDC_SCSIMODE, CB_ADDSTRING, 0, (LPARAM)((get_aspi_path (1)) ? L"NeroASPI" : L"(NeroASPI)"));
struct hfdlg_vals
{
- TCHAR volumename[MAX_DPATH];
TCHAR devicename[MAX_DPATH];
TCHAR filename[MAX_DPATH];
TCHAR fsfilename[MAX_DPATH];
bool original;
};
-static struct hfdlg_vals empty_hfdlg = { L"", L"", L"", L"", 32, 2, 1, 0, 512, 1, 0, 0, 0, 1, 0, 1 };
+static struct hfdlg_vals empty_hfdlg = { L"", L"", L"", 32, 2, 1, 0, 512, 1, 0, 0, 0, 1, 0, 1 };
static struct hfdlg_vals current_hfdlg;
static int archivehd;
case IDC_CD_SELECT:
DiskSelection (hDlg, wParam, 17, &workprefs, NULL);
quickstart_cdtype = 1;
- workprefs.cdimagefileuse = true;
+ workprefs.cdimagefileuse[0] = true;
addcdtype (hDlg, IDC_CD_TYPE);
break;
case IDC_CD_EJECT:
case IDC_CD_TEXT:
getfloppyname (hDlg, 0, 1, IDC_CD_TEXT);
quickstart_cdtype = 1;
- workprefs.cdimagefileuse = true;
+ workprefs.cdimagefileuse[0] = true;
addcdtype (hDlg, IDC_CD_TYPE);
addfloppyhistory_2 (hDlg, 0, IDC_CD_TEXT, HISTORY_CD);
break;
if (quickstart_cdtype >= 2) {
int len = sizeof quickstart_cddrive / sizeof (TCHAR);
quickstart_cdtype = 2;
- workprefs.cdimagefileuse = true;
+ workprefs.cdimagefileuse[0] = true;
SendDlgItemMessage (hDlg, IDC_CD_TYPE, WM_GETTEXT, (WPARAM)len, (LPARAM)quickstart_cddrive);
- _tcscpy (workprefs.cdimagefile, quickstart_cddrive);
+ _tcscpy (workprefs.cdimagefile[0], quickstart_cddrive);
} else {
eject_cd ();
quickstart_cdtype = val;
if (val > 0)
- workprefs.cdimagefileuse = true;
+ workprefs.cdimagefileuse[0] = true;
}
addcdtype (hDlg, IDC_CD_TYPE);
SendDlgItemMessage (hDlg, f_text, CB_RESETCONTENT, 0, 0);
if (type == HISTORY_CD) {
nn = 1;
- text = workprefs.cdimagefile;
+ text = workprefs.cdimagefile[0];
} else {
nn = workprefs.dfxtype[n] + 1;
text = workprefs.df[n];
SendDlgItemMessage (hDlg, id, CB_ADDSTRING, 0, (LPARAM)tmp);
int cdtype = quickstart_cdtype;
if (currentpage != QUICKSTART_ID) {
- if (full_property_sheet && !workprefs.cdimagefileuse && !workprefs.cdimagefile[0])
+ if (full_property_sheet && !workprefs.cdimagefileuse[0] && !workprefs.cdimagefile[0][0])
cdtype = 0;
}
int cnt = 2;
SendDlgItemMessage (hDlg, id, CB_ADDSTRING, 0, (LPARAM)vol);
if (!_tcsicmp (vol, quickstart_cddrive)) {
cdtype = quickstart_cdtype = cnt;
- _tcscpy (workprefs.cdimagefile, vol);
+ _tcscpy (workprefs.cdimagefile[0], vol);
}
cnt++;
}
SetWindowText (GetDlgItem (hDlg, f_enable), tmp);
addcdtype (hDlg, IDC_CD0Q_TYPE);
hide (hDlg, IDC_CD0Q_TYPE, 0);
- text = workprefs.cdimagefile;
+ text = workprefs.cdimagefile[0];
regsetstr (NULL, L"QuickStartCDDrive", quickstart_cdtype >= 2 ? quickstart_cddrive : L"");
regsetint (NULL, L"QuickStartCDType", quickstart_cdtype >= 2 ? 2 : quickstart_cdtype);
} else {
} else {
if (quickstart_cddrive[0])
eject_cd ();
- _tcscpy (workprefs.cdimagefile, tmp);
+ _tcscpy (workprefs.cdimagefile[0], tmp);
}
}
}
ret = 1;
break;
case ZFILE_CDIMAGE:
- _tcscpy (workprefs.cdimagefile, file);
+ _tcscpy (workprefs.cdimagefile[0], file);
break;
default:
if (currentpage < 0 && !full_property_sheet) {
+Beta 4:
+
+- rawinput was disabled if only one keyboard device was detected, input didn't work at all
+ in b3 because of null keyboard (detected only one rawinput keyboard = it was ignore but null
+ keyboard was still added later -> more than one keyboard -> do not fallback to directinput..)
+- redirect unknown rawinput messages to null keyboard (shouldn't happen but you never know..)
+- spaces not allowed in directory filesystem volume name (wrong validation routine used)
+- bottom border was half-blanked in some doublescanned modes
+
+Another major CD update. CD configuration unified, now any CD unit "slot" can point to different
+CD backend (image mounter + scsi emulation, IOCTL drive + scsi emulation, SPTI drive + scsi
+passthrough) On the fly changes fully supported. CD mess is nearly gone, code is finally structured
+logically without special cases. (this finally made SCSI emulation quite easy to implement)
+
+- SCSI emulation is now the default SCSI mode (CDFS and audio tracks always work, switch to
+ SPTI if you need advanced stuff like cd writing) Some audio CD players work for the first time
+ now because some SCSI commands have been obsoleted long time ago like PLAY TRACK/INDEX
+- CD audio DAE emulation does not attempt to play data tracks anymore
+- added most common CD audio SCSI commands to SCSI emulator, OS3.5+ PlayCD confirmed working.
+ Following new SCSI command added:
+ START/STOP, STOP PLAY/SCAN, SCAN, PLAY AUDIO MSF, PLAY AUDIO, PLAY CD, PLAY TRACK/INDEX,
+ PAUSE/RESUME, READ SUB-CHANNEL, READ TOC, MODE SENSE/MODE SELECT (cd audio volume page only),
+ READ CD and READ CF MSF (only audio extraction supported + subchannel options)
+- added CD audio io commands to uaescsi.device (most programs use HD_SCSICMD)
+- emulated INQUIRY vendor, product and revision fetched from real device if possible
+
+Testing:
+
+Load your normal WB3.x configuration (that uses uaescsi.device CDROMs), start emulation
+normally. (This and following betas force SCSI Emulation mode!) Report all changes,
+including logs, SCSI emulation logging is enabled.
+
+Notes:
+
+GUI selection overrides slot 0, for example if you normally have D:\ = uaescsi.device unit 0
+and E:\ = uaescsi.device unit 1, mounting a cd image "ejects" whatever is in unit 0 and
+replaces it with image file.
+
+If CD32 or CDTV is started in "autodetect" mode and it chose unit 1 or later (CD32/CDTV or
+Audio CD inserted), unit 0 changes are ignored until original drive becomes empty. This
+needs to be more intelligent.
+
+Configuration file accepts cdimage0 to cdimage7. Full syntax:
+cdimagex=image path or device name,cd backend(:reserved for future)
+Cd backend not mandatory. Supported CD backend names are:
+image, ioctl, spti and aspi. (this is autoselected when using GUI)
+
+Beta 3:
- most debugger options now accept .b, .w and .l size extension (+special .3 if 3-byte word),
old style separate size values (1, 2, 3 or 4) not supported anymore
struct scsi_data *scsi_alloc_native(int id, int nativeunit)
{
struct scsi_data *sd;
- if (!sys_command_open (DF_SCSI, nativeunit)) {
+ if (!sys_command_open (nativeunit)) {
write_log (L"SCSI: native scsi unit %d failed to open\n", nativeunit);
return NULL;
}
if (!sd)
return;
if (sd->nativescsiunit >= 0) {
- sys_command_close (DF_SCSI, sd->nativescsiunit);
+ sys_command_close (sd->nativescsiunit);
}
xfree(sd);
}
#define ASYNC_REQUEST_NONE 0
#define ASYNC_REQUEST_TEMP 1
#define ASYNC_REQUEST_CHANGEINT 10
+#define ASYNC_REQUEST_FRAMEINT 11
struct devstruct {
int unitnum, aunit;
int opencnt;
int changenum;
- int allow_scsi;
- int allow_ioctl;
int drivetype;
int iscd;
volatile uaecptr d_request[MAX_ASYNC_REQUESTS];
volatile uae_u32 d_request_data[MAX_ASYNC_REQUESTS];
struct device_info di;
uaecptr changeint;
+ int changeint_mediastate;
+
+ int configblocksize;
+ int volumelevel;
+ int fadeframes;
+ int fadetarget;
+ int fadecounter;
smp_comm_pipe requests;
int thread_running;
int inuse;
int unit;
int mode;
- int scsi;
- int ioctl;
- int noscsi;
int type;
int flags; /* OpenDevice() */
};
-static struct devstruct devst[MAX_TOTAL_DEVICES];
+static struct devstruct devst[MAX_TOTAL_SCSI_DEVICES];
static struct priv_devstruct pdevst[MAX_OPEN_DEVICES];
static uae_u32 nscmd_cmd;
static uae_sem_t change_sem;
-static struct device_info *devinfo (int mode, int unitnum, struct device_info *di)
+static struct device_info *devinfo (struct devstruct *devst, struct device_info *di)
{
- return sys_command_info (mode, unitnum, di, 0);
+ struct device_info *dio = sys_command_info (devst->unitnum, di, 0);
+ if (dio) {
+ if (!devst->configblocksize)
+ devst->configblocksize = dio->bytespersector;
+ }
+ return dio;
}
static void io_log (const TCHAR *msg, uaecptr request)
static struct devstruct *getdevstruct (int unit)
{
int i;
- for (i = 0; i < MAX_TOTAL_DEVICES; i++) {
- if (unit >= 0 && devst[i].aunit == unit) return &devst[i];
+ for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
+ if (unit >= 0 && devst[i].aunit == unit)
+ return &devst[i];
}
return 0;
}
if (!dev->opencnt) return;
dev->opencnt--;
if (!dev->opencnt) {
- if (pdev->scsi)
- sys_command_close (DF_SCSI, dev->unitnum);
- if (pdev->ioctl)
- sys_command_close (DF_IOCTL, dev->unitnum);
+ sys_command_close (dev->unitnum);
pdev->inuse = 0;
write_comm_pipe_u32 (&dev->requests, 0, 1);
}
return (uae_u32)-1;
}
-static void setpdev (struct priv_devstruct *pdev, struct devstruct *dev)
-{
- pdev->scsi = dev->allow_scsi ? 1 : 0;
- pdev->ioctl = dev->allow_scsi ? 0 : 1;
- pdev->mode = dev->allow_scsi ? DF_SCSI : DF_IOCTL;
-}
-
static uae_u32 REGPARAM2 dev_open_2 (TrapContext *context, int type)
{
uaecptr ioreq = m68k_areg (regs, 1);
if (log_scsi)
write_log (L"opening %s:%d ioreq=%08X\n", getdevname (type), unit, ioreq);
- if (get_word (ioreq + 0x12) < IOSTDREQ_SIZE)
+ if (get_word (ioreq + 0x12) < IOSTDREQ_SIZE && get_word (ioreq + 0x12) > 0)
return openfail (ioreq, IOERR_BADLENGTH);
if (!dev)
return openfail (ioreq, 32); /* badunitnum */
if (!dev->opencnt) {
for (i = 0; i < MAX_OPEN_DEVICES; i++) {
pdev = &pdevst[i];
- if (pdev->inuse == 0) break;
- }
- if (type == UAEDEV_SCSI_ID && sys_command_open (dev->allow_scsi ? DF_SCSI : DF_IOCTL, dev->unitnum)) {
- setpdev (pdev, dev);
- }
- if (type == UAEDEV_DISK_ID && sys_command_open (DF_IOCTL, dev->unitnum)) {
- pdev->ioctl = 1;
- pdev->mode = DF_IOCTL;
+ if (pdev->inuse == 0)
+ break;
}
- if (!pdev->scsi && !pdev->ioctl)
+ if (!sys_command_open (dev->unitnum))
return openfail (ioreq, IOERR_OPENFAIL);
pdev->type = type;
pdev->unit = unit;
return 0;
}
-
+#if 0
static int scsiemul_switchscsi (const TCHAR *name)
{
struct devstruct *dev = NULL;
struct device_info *discsi, discsi2;
- int i, j, opened[MAX_TOTAL_DEVICES];
+ int i, opened[MAX_TOTAL_SCSI_DEVICES];
bool wasopen = false;
- for (i = 0; i < MAX_TOTAL_DEVICES; i++)
+ for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++)
opened[i] = sys_command_isopen (i);
dev = &devst[0];
- if ((dev->allow_ioctl || dev->allow_scsi) && dev->opencnt)
+ if (dev->opencnt)
wasopen = true;
- if (dev->allow_scsi)
- sys_command_close (DF_SCSI, dev->unitnum);
- if (dev->allow_ioctl)
- sys_command_close (DF_IOCTL, dev->unitnum);
- dev->allow_ioctl = 0;
- dev->allow_scsi = 0;
+ sys_command_close (dev->unitnum);
dev = NULL;
- for (j = 0; j < 2; j++) {
- int mode = j == 0 ? DF_SCSI : DF_IOCTL;
- if (!(device_func_init (j == 0 ? DEVICE_TYPE_SCSI : DEVICE_TYPE_ANY) & (1 << mode)))
- continue;
+ if (device_func_init (DEVICE_TYPE_ANY)) {
if (devst[0].di.media_inserted < 0)
devst[0].di.media_inserted = 0;
i = 0;
- while (i < MAX_TOTAL_DEVICES && dev == NULL) {
+ while (i < MAX_TOTAL_SCSI_DEVICES && dev == NULL) {
discsi = 0;
- if (sys_command_open (mode, i)) {
- discsi = sys_command_info (mode, i, &discsi2, 0);
+ if (sys_command_open ( i)) {
+ discsi = sys_command_info (i, &discsi2, 0);
if (discsi && discsi->type == INQ_ROMD) {
- if (!_tcsicmp (currprefs.cdimagefile, discsi->label)) {
+ if (!_tcsicmp (currprefs.cdimagefile[0], discsi->label)) {
dev = &devst[0];
dev->unitnum = i;
- dev->allow_scsi = j == 0 ? 1 : 0;
- dev->allow_ioctl = j != 0 ? 1 : 0;
dev->drivetype = discsi->type;
memcpy (&dev->di, discsi, sizeof (struct device_info));
dev->iscd = 1;
- write_log (L"%s mounted as uaescsi.device:0 (SCSI=%d IOCTL=%d)\n", discsi->label, dev->allow_scsi, dev->allow_ioctl);
- if (dev->aunit >= 0) {
- struct priv_devstruct *pdev = &pdevst[dev->aunit];
- setpdev (pdev, dev);
- }
+ write_log (L"%s mounted as uaescsi.device:0\n", discsi->label);
if (dev->di.media_inserted) {
dev->di.media_inserted = 0;
scsi_do_disk_change (dev->di.id, 1, NULL);
}
}
if (opened[i] == 0 && !wasopen)
- sys_command_close (mode, i);
+ sys_command_close ( i);
}
i++;
}
}
return -1;
}
-static int scsiemul_switchemu (const TCHAR *name)
-{
- struct devstruct *dev = NULL;
- struct device_info *discsi, discsi2;
-
- if (!device_func_init (DEVICE_TYPE_ANY | DEVICE_TYPE_ALLOWEMU))
- return -1;
- int opened = sys_command_isopen (0);
- if (sys_command_open (DF_IOCTL, 0)) {
- if (discsi = sys_command_info (DF_IOCTL, 0, &discsi2, 0)) {
- dev = &devst[0];
- dev->unitnum = 0;
- dev->allow_scsi = 1;
- dev->allow_ioctl = 1;
- dev->drivetype = discsi->type;
- memcpy (&dev->di, discsi, sizeof (struct device_info));
- dev->iscd = 1;
- write_log (L"IMG_EMU (%s) mounted as uaescsi.device:0\n", name);
- if (dev->aunit >= 0) {
- struct priv_devstruct *pdev = &pdevst[dev->aunit];
- setpdev (pdev, dev);
- }
- dev->di.media_inserted = 0;
- }
- if (!opened)
- sys_command_close (DF_IOCTL, 0);
- return 0;
- }
- return -1;
-}
-
-int scsi_do_disk_device_change (void)
-{
- int ret = scsiemul_switchscsi (currprefs.cdimagefile);
- if (ret < 0) {
- scsiemul_switchemu (currprefs.cdimagefile);
- }
- return ret;
-}
+#endif
-// device_id = -1 and insert==0 -> all medias going away
// pollmode is 1 if no change interrupts found -> increase time of media change
-int scsi_do_disk_change (int device_id, int insert, int *pollmode)
+int scsi_do_disk_change (int unitnum, int insert, int *pollmode)
{
int i, j, ret;
if (!change_sem)
return ret;
uae_sem_wait (&change_sem);
- for (i = 0; i < MAX_TOTAL_DEVICES; i++) {
+ for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
struct devstruct *dev = &devst[i];
- if (dev->di.id == device_id || (device_id < 0 && i == 0)) {
+ if (dev->di.unitnum == unitnum + 1) {
ret = i;
- if ((dev->di.media_inserted > 0 && insert == 0) || (dev->di.media_inserted <= 0 && insert)) {
+ if ((dev->changeint_mediastate > 0 && insert == 0) || (dev->changeint_mediastate <= 0 && insert)) {
+ dev->changeint_mediastate = insert;
if (pollmode)
*pollmode = 1;
if (dev->aunit >= 0) {
struct priv_devstruct *pdev = &pdevst[dev->aunit];
- devinfo (pdev->mode, dev->unitnum, &dev->di);
+ devinfo (dev, &dev->di);
}
- if (device_id < 0 && insert == 0)
- dev->di.media_inserted = -1; // stay away!
dev->changenum++;
j = 0;
while (j < MAX_ASYNC_REQUESTS) {
write_log (L"asyncronous request=%08X aborted, error=%d\n", request, errcode);
}
-static int command_read (int mode, struct devstruct *dev, uaecptr data, uae_u64 offset, uae_u32 length, uae_u32 *io_actual)
+static int command_read (struct devstruct *dev, uaecptr data, uae_u64 offset, uae_u32 length, uae_u32 *io_actual)
{
int blocksize = dev->di.bytespersector;
- uae_u8 *temp;
length /= blocksize;
offset /= blocksize;
while (length > 0) {
- temp = sys_command_read (mode, dev->unitnum, NULL, offset, 1);
- if (!temp)
+ uae_u8 buffer[4096];
+ if (!sys_command_read (dev->unitnum, buffer, offset, 1))
return 20;
- memcpyha_safe (data, temp, blocksize);
+ memcpyha_safe (data, buffer, blocksize);
data += blocksize;
offset++;
length--;
return 0;
}
-static int command_write (int mode, struct devstruct *dev, uaecptr data, uae_u64 offset, uae_u32 length, uae_u32 *io_actual)
+static int command_write (struct devstruct *dev, uaecptr data, uae_u64 offset, uae_u32 length, uae_u32 *io_actual)
{
uae_u32 blocksize = dev->di.bytespersector;
- struct device_scsi_info dsi;
-
- if (!sys_command_scsi_info (mode, dev->unitnum, &dsi))
- return 20;
length /= blocksize;
offset /= blocksize;
while (length > 0) {
+ uae_u8 buffer[4096];
int err;
- memcpyah_safe (dsi.buffer, data, blocksize);
- err = sys_command_write (mode, dev->unitnum, NULL, offset, 1);
+ memcpyah_safe (buffer, data, blocksize);
+ err = sys_command_write (dev->unitnum, buffer, offset, 1);
if (!err)
return 20;
if (err < 0)
return 0;
}
-static int command_cd_read (int mode, struct devstruct *dev, uaecptr data, uae_u64 offset, uae_u32 length, uae_u32 *io_actual)
+static int command_cd_read (struct devstruct *dev, uaecptr data, uae_u64 offset, uae_u32 length, uae_u32 *io_actual)
{
- uae_u8 *temp;
uae_u32 len, sector, startoffset;
+ int blocksize;
+ blocksize = dev->configblocksize;
*io_actual = 0;
- if (dev->di.bytespersector == 0)
- dev->di.bytespersector = 2048;
- startoffset = offset % dev->di.bytespersector;
+ startoffset = offset % blocksize;
offset -= startoffset;
- sector = offset / dev->di.bytespersector;
+ sector = offset / blocksize;
while (length > 0) {
- temp = sys_command_cd_read (mode, dev->unitnum, NULL, sector, 1);
- if (!temp)
- return 20;
+ uae_u8 temp[4096];
+ if (blocksize != 2048) {
+ if (!sys_command_cd_rawread (dev->unitnum, temp, sector, 1, blocksize))
+ return 20;
+ } else {
+ if (!sys_command_cd_read (dev->unitnum, temp, sector, 1))
+ return 20;
+ }
if (startoffset > 0) {
- len = dev->di.bytespersector - startoffset;
+ len = blocksize - startoffset;
if (len > length) len = length;
memcpyha_safe (data, temp + startoffset, len);
length -= len;
data += len;
startoffset = 0;
*io_actual += len;
- } else if (length >= dev->di.bytespersector) {
- len = dev->di.bytespersector;
+ } else if (length >= blocksize) {
+ len = blocksize;
memcpyha_safe (data, temp, len);
length -= len;
data += len;
return 0;
command = get_word (request + 28);
+// write_log (L"%d: CMD=%04X DATA=%08X LEN=%08X OFFSET=%08X ACTUAL=%08X\n",
+// command, io_data, io_length, io_offset, io_actual);
+
switch (command)
{
case CMD_READ:
if (dev->di.media_inserted <= 0)
goto no_media;
if (dev->drivetype == INQ_ROMD) {
- io_error = command_cd_read (pdev->mode, dev, io_data, io_offset, io_length, &io_actual);
+ io_error = command_cd_read (dev, io_data, io_offset, io_length, &io_actual);
} else {
if ((io_offset & bmask) || bmask == 0 || io_data == 0)
goto bad_command;
if ((io_length & bmask) || io_length == 0)
goto bad_len;
- io_error = command_read (pdev->mode, dev, io_data, io_offset, io_length, &io_actual);
+ io_error = command_read (dev, io_data, io_offset, io_length, &io_actual);
}
break;
case TD_READ64:
if ((io_length & bmask) || io_length == 0)
goto bad_len;
if (dev->drivetype == INQ_ROMD)
- io_error = command_cd_read (pdev->mode, dev, io_data, io_offset64, io_length, &io_actual);
+ io_error = command_cd_read (dev, io_data, io_offset64, io_length, &io_actual);
else
- io_error = command_read (pdev->mode, dev, io_data, io_offset64, io_length, &io_actual);
+ io_error = command_read (dev, io_data, io_offset64, io_length, &io_actual);
break;
case CMD_WRITE:
} else if ((io_length & bmask) || io_length == 0) {
goto bad_len;
} else {
- io_error = command_write (pdev->mode, dev, io_data, io_offset, io_length, &io_actual);
+ io_error = command_write (dev, io_data, io_offset, io_length, &io_actual);
}
break;
case TD_WRITE64:
} else if ((io_length & bmask) || io_length == 0) {
goto bad_len;
} else {
- io_error = command_write (pdev->mode, dev, io_data, io_offset64, io_length, &io_actual);
+ io_error = command_write (dev, io_data, io_offset64, io_length, &io_actual);
}
break;
} else if ((io_length & bmask) || io_length == 0) {
goto bad_len;
} else {
- io_error = command_write (pdev->mode, dev, io_data, io_offset, io_length, &io_actual);
+ io_error = command_write (dev, io_data, io_offset, io_length, &io_actual);
}
break;
case TD_FORMAT64:
} else if ((io_length & bmask) || io_length == 0) {
goto bad_len;
} else {
- io_error = command_write (pdev->mode, dev, io_data, io_offset64, io_length, &io_actual);
+ io_error = command_write (dev, io_data, io_offset64, io_length, &io_actual);
}
break;
case CMD_REMOVE:
io_actual = dev->changeint;
dev->changeint = io_data;
+ dev->changeint_mediastate = dev->di.media_inserted;
break;
case CMD_CHANGENUM:
io_actual = dev->changenum;
break;
case CMD_CHANGESTATE:
if (dev->di.media_inserted >= 0) {
- io_actual = devinfo (pdev->mode, dev->unitnum, &dev->di)->media_inserted > 0 ? 0 : 1;
+ io_actual = devinfo (dev, &dev->di)->media_inserted > 0 ? 0 : 1;
} else {
io_actual = 1;
}
break;
case CMD_PROTSTATUS:
- io_actual = devinfo (pdev->mode, dev->unitnum, &dev->di)->write_protected ? -1 : 0;
+ io_actual = devinfo (dev, &dev->di)->write_protected ? -1 : 0;
break;
case CMD_GETDRIVETYPE:
io_actual = dev->drivetype;
case CMD_GETGEOMETRY:
{
struct device_info *di;
- di = devinfo (pdev->mode, dev->unitnum, &dev->di);
+ di = devinfo (dev, &dev->di);
if (di->media_inserted <= 0)
goto no_media;
put_long (io_data + 0, di->bytespersector);
}
break;
case CMD_ADDCHANGEINT:
+ dev->changeint_mediastate = dev->di.media_inserted;
io_error = add_async_request (dev, request, ASYNC_REQUEST_CHANGEINT, io_data);
if (!io_error)
async = 1;
case CMD_REMCHANGEINT:
release_async_request (dev, request);
break;
+
+ case CD_TOCLSN:
+ case CD_TOCMSF:
+ {
+ int msf = command == CD_TOCMSF;
+ struct cd_toc_head toc;
+ if (sys_command_cd_toc (dev->di.unitnum, &toc)) {
+ if (io_offset == 0 && io_length > 0) {
+ int pos = toc.lastaddress;
+ put_byte (io_data, toc.first_track);
+ put_byte (io_data + 1, toc.last_track);
+ if (msf)
+ pos = lsn2msf (pos);
+ put_long (io_data + 2, pos);
+ io_offset++;
+ io_length--;
+ io_data += 6;
+ io_actual++;
+ }
+ for (int i = toc.first_track_offset; i < toc.last_track_offset && io_length > 0; i++) {
+ if (io_offset == toc.toc[i].point) {
+ int pos = toc.toc[i].paddress;
+ put_byte (io_data, (toc.toc[i].control << 4) | toc.toc[i].adr);
+ put_byte (io_data + 1, toc.toc[i].point);
+ if (msf)
+ pos = lsn2msf (pos);
+ put_long (io_data + 2, pos);
+ io_offset++;
+ io_length--;
+ io_data += 6;
+ io_actual++;
+ }
+ }
+ } else {
+ io_error = CDERR_NotSpecified;
+ }
+ }
+ break;
+ case CD_ADDFRAMEINT:
+ io_error = add_async_request (dev, request, ASYNC_REQUEST_FRAMEINT, io_data);
+ if (!io_error)
+ async = 1;
+ break;
+ case CD_REMFRAMEINT:
+ release_async_request (dev, request);
+ break;
+ case CD_ATTENUATE:
+ {
+ if (io_offset != -1) {
+ dev->fadeframes = io_length & 0x7fff;
+ dev->fadetarget = io_offset & 0x7fff;
+ }
+ io_actual = dev->volumelevel;
+ }
+ break;
+ case CD_INFO:
+ {
+ uae_u16 status = 0;
+ struct cd_toc_head toc;
+ uae_u8 subq[SUBQ_SIZE] = { 0 };
+ sys_command_cd_qcode (dev->di.unitnum, subq);
+ status |= 1 << 0; // door closed
+ if (dev->di.media_inserted) {
+ status |= 1 << 1;
+ status |= 1 << 2; // motor on
+ if (sys_command_cd_toc (dev->di.unitnum, &toc)) {
+ status |= 1 << 3; // toc
+ if (subq[1] == AUDIO_STATUS_IN_PROGRESS || subq[1] == AUDIO_STATUS_PAUSED)
+ status |= 1 << 5; // audio play
+ if (subq[1] == AUDIO_STATUS_PAUSED)
+ status |= 1 << 6; // paused
+ if (isdatatrack (&toc, 0))
+ status |= 1 << 4; // data track
+ }
+ }
+ put_word (io_data + 0, 75); // PlaySpeed
+ put_word (io_data + 2, 1200); // ReadSpeed (randomly chose 16x)
+ put_word (io_data + 4, 1200); // ReadXLSpeed
+ put_word (io_data + 6, dev->configblocksize); // SectorSize
+ put_word (io_data + 8, -1); // XLECC
+ put_word (io_data + 10, 0); // EjectReset
+ put_word (io_data + 12, 0); // Reserved * 4
+ put_word (io_data + 14, 0);
+ put_word (io_data + 16, 0);
+ put_word (io_data + 18, 0);
+ put_word (io_data + 20, 1200); // MaxSpeed
+ put_word (io_data + 22, 0xffff); // AudioPrecision (volume)
+ put_word (io_data + 24, status); // Status
+ put_word (io_data + 26, 0); // Reserved2 * 4
+ put_word (io_data + 28, 0);
+ put_word (io_data + 30, 0);
+ put_word (io_data + 32, 0);
+ io_actual = 34;
+ }
+ break;
+ case CD_CONFIG:
+ {
+ while (get_long (io_data) != TAG_DONE) {
+ uae_u32 tag = get_long (io_data);
+ uae_u32 data = get_long (io_data + 4);
+ if (tag == 4) {
+ // TAGCD_SECTORSIZE
+ if (data == 2048 || data == 2336 || data == 2352)
+ dev->configblocksize = data;
+ else
+ io_error = IOERR_BADADDRESS;
+
+ }
+ io_data += 8;
+ }
+ break;
+ }
+ case CD_PAUSE:
+ {
+ int old = sys_command_cd_pause (dev->di.unitnum, io_length);
+ if (old >= 0)
+ io_actual = old;
+ else
+ io_error = IOERR_BADADDRESS;
+ break;
+ }
+ case CD_PLAYLSN:
+ {
+ int start = io_offset;
+ int end = io_length + start;
+ if (!sys_command_cd_play (dev->di.unitnum, start, end, 0, NULL))
+ io_error = IOERR_BADADDRESS;
+ }
+ break;
+ case CD_PLAYMSF:
+ {
+ int start = msf2lsn (io_offset);
+ int end = msf2lsn (io_length) + start;
+ if (!sys_command_cd_play (dev->di.unitnum, start, end, 0, NULL))
+ io_error = IOERR_BADADDRESS;
+ }
+ break;
+ case CD_PLAYTRACK:
+ {
+ struct cd_toc_head toc;
+ int ok = 0;
+ if (sys_command_cd_toc (dev->di.unitnum, &toc)) {
+ for (int i = toc.first_track_offset; i < toc.last_track_offset; i++) {
+ if (i == io_offset && i + io_length <= toc.last_track_offset) {
+ ok = sys_command_cd_play (dev->di.unitnum, toc.toc[i].address, toc.toc[i + io_length].address, 0, NULL);
+ break;
+ }
+ }
+ }
+ if (!ok)
+ io_error = IOERR_BADADDRESS;
+ }
+ break;
+ case CD_QCODEMSF:
+ case CD_QCODELSN:
+ {
+ uae_u8 subq[SUBQ_SIZE];
+ if (sys_command_cd_qcode (dev->di.unitnum, subq)) {
+ if (subq[1] == AUDIO_STATUS_IN_PROGRESS || subq[1] == AUDIO_STATUS_PAUSED) {
+ put_byte (io_data + 0, subq[4 + 0]);
+ put_byte (io_data + 1, frombcd (subq[4 + 1]));
+ put_byte (io_data + 2, frombcd (subq[4 + 2]));
+ put_byte (io_data + 3, subq[4 + 6]);
+ int trackpos = fromlongbcd (subq + 4 + 3);
+ int diskpos = fromlongbcd (subq + 4 + 7);
+ if (command == CD_QCODELSN) {
+ trackpos = msf2lsn (trackpos);
+ diskpos = msf2lsn (diskpos);
+ }
+ put_long (io_data + 4, trackpos);
+ put_long (io_data + 8, diskpos);
+ io_actual = 12;
+ } else {
+ io_error = CDERR_InvalidState;
+ }
+ } else {
+ io_error = IOERR_BADADDRESS;
+ }
+ }
+ break;
+
case HD_SCSICMD:
- if (dev->allow_scsi && pdev->scsi) {
+ {
uae_u32 sdd = get_long (request + 40);
io_error = sys_command_scsi_direct (dev->unitnum, sdd);
if (log_scsi)
write_log (L"scsidev: did io: sdd %p request %p error %d\n", sdd, request, get_byte (request + 31));
- } else {
- io_error = IOERR_NOCMD;
}
break;
case NSCMD_DEVICEQUERY:
{
int i, j;
struct devstruct *dev;
- struct device_info *discsi, discsi2;
int unitnum = 0;
- for (i = 0; i < MAX_TOTAL_DEVICES; i++) {
+ for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
dev = &devst[i];
if (dev->opencnt > 0) {
for (j = 0; j < MAX_ASYNC_REQUESTS; j++) {
abort_async (dev, request, 0, 0);
}
dev->opencnt = 1;
- if (dev->allow_scsi)
- sys_command_close (DF_SCSI, dev->unitnum);
- if (dev->allow_ioctl)
- sys_command_close (DF_IOCTL, dev->unitnum);
+ sys_command_close (dev->unitnum);
}
memset (dev, 0, sizeof (struct devstruct));
dev->unitnum = dev->aunit = -1;
for (i = 0; i < MAX_OPEN_DEVICES; i++)
memset (&pdevst[i], 0, sizeof (struct priv_devstruct));
- int didswitch = -1;
- if (currprefs.cdimagefile[0] || currprefs.cdimagefileuse)
- didswitch = scsiemul_switchscsi (currprefs.cdimagefile);
- if (didswitch < 0) {
- device_func_init (DEVICE_TYPE_SCSI);
- i = j = 0;
- while (i < MAX_TOTAL_DEVICES) {
- int mode = -1;
- dev = &devst[i];
- discsi = 0;
- if (sys_command_open (DF_SCSI, j)) {
- dev->allow_scsi = 1;
- mode = DF_SCSI;
- }
- if (!dev->allow_scsi) {
- if (sys_command_open (DF_IOCTL, j)) {
- dev->allow_ioctl = 1;
- mode = DF_IOCTL;
- }
- }
- if (mode >= 0) {
- discsi = sys_command_info (mode, j, &discsi2, 0);
- sys_command_close (mode, j);
- }
+ device_func_init (0);
+ i = 0;
+ while (i < MAX_TOTAL_SCSI_DEVICES) {
+ dev = &devst[i];
+ struct device_info *discsi, discsi2;
+ if (sys_command_open (i)) {
+ discsi = sys_command_info (i, &discsi2, 0);
if (discsi) {
- dev->unitnum = j;
+ dev->unitnum = i;
dev->drivetype = discsi->type;
memcpy (&dev->di, discsi, sizeof (struct device_info));
+ dev->changeint_mediastate = discsi->media_inserted;
+ dev->configblocksize = discsi->bytespersector;
if (discsi->type == INQ_ROMD)
dev->iscd = 1;
}
- i++;
- j++;
}
+ i++;
}
unitnum = 0;
- for (i = 0; i < MAX_TOTAL_DEVICES; i++) {
+ for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
dev = &devst[i];
+ if (dev->unitnum >= 0)
+ sys_command_close (dev->unitnum);
if (dev->unitnum >= 0 && dev->iscd) {
dev->aunit = unitnum;
+ dev->volumelevel = 0x7fff;
unitnum++;
}
}
if (unitnum == 0)
unitnum = 1;
- for (i = 0; i < MAX_TOTAL_DEVICES; i++) {
+ for (i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
dev = &devst[i];
if (dev->unitnum >= 0) {
if (!dev->iscd) {
if ((mask & ZFD_CD) && ft) {
if (ext && !_tcsicmp (ext, L".iso"))
whf = 2;
+ if (ext && !_tcsicmp (ext, L".ccd"))
+ whf = 9;
if (ext && !_tcsicmp (ext, L".cue"))
whf = 10;
}