From fcf02a21a877758e99cafbc941f41ab7920f0800 Mon Sep 17 00:00:00 2001 From: Mustafa Tufan Date: Mon, 21 Jan 2013 14:04:17 +0200 Subject: [PATCH] puae 2.6.0b2 --- configure.ac | 8 - src/Makefile.am | 6 +- src/a2091.c | 39 ++- src/blkdev.c | 156 +++++++-- src/blkdev_cdimage.c | 11 +- src/cdtv.c | 4 +- src/cfgfile.c | 90 +++-- src/consolehook.c | 3 +- src/cpummu.c | 206 +++++++++-- src/cpummu30.c | 324 ++++++++++++++---- src/debug.c | 14 +- src/disk.c | 156 +++++---- src/diskutil.c | 1 + src/expansion.c | 2 +- src/filesys.c | 71 +++- src/gayle.c | 724 ++++++++++++++++++++++++--------------- src/gencpu.c | 299 ++++++++++++---- src/hardfile.c | 32 +- src/include/a2091.h | 3 +- src/include/autoconf.h | 13 +- src/include/blkdev.h | 4 + src/include/cdtv.h | 2 +- src/include/cpummu.h | 90 ++++- src/include/cpummu030.h | 123 +++++-- src/include/disk.h | 2 +- src/include/filesys.h | 2 +- src/include/mmu_common.h | 70 ++-- src/include/newcpu.h | 1 + src/include/options.h | 12 +- src/include/savestate.h | 11 +- src/include/scsi.h | 43 ++- src/include/zfile.h | 2 +- src/newcpu.c | 18 +- src/od-generic/memory.c | 23 +- src/rommgr.c | 2 +- src/scsi.c | 75 +++- 36 files changed, 1889 insertions(+), 753 deletions(-) diff --git a/configure.ac b/configure.ac index dde539f..920cafd 100644 --- a/configure.ac +++ b/configure.ac @@ -1431,12 +1431,10 @@ if [[ "x$WANT_SCSIEMU" = "xyes" ]]; then if [[ "$OSDEP" = "od-amiga" ]]; then AC_MSG_RESULT(yes) SCSIOBJS='scsiemul.$(OBJEXT) blkdev.$(OBJEXT) blkdev_cdimage.$(OBJEXT) scsi.$(OBJEXT)' -dnl SCSIOBJS='scsiemul.$(OBJEXT) blkdev.$(OBJEXT) scsi.$(OBJEXT)' UAE_DEFINES="$UAE_DEFINES -DSCSIEMU" if [[ "x$WANT_A2091" = "xyes" ]]; then UAE_DEFINES="$UAE_DEFINES -DA2091" SCSIOBJS='scsiemul.$(OBJEXT) blkdev.$(OBJEXT) blkdev_cdimage.$(OBJEXT) scsi.$(OBJEXT) a2091.$(OBJEXT)' -dnl SCSIOBJS='scsiemul.$(OBJEXT) blkdev.$(OBJEXT) scsi.$(OBJEXT) a2091.$(OBJEXT)' fi NEED_THREAD_SUPPORT=yes else @@ -1471,12 +1469,10 @@ typedef int BOOL; [ AC_MSG_RESULT(yes) SCSIOBJS='scsiemul.$(OBJEXT) blkdev.$(OBJEXT) blkdev_cdimage.$(OBJEXT) blkdev-libscg.$(OBJEXT) scsi.$(OBJEXT)' -dnl SCSIOBJS='scsiemul.$(OBJEXT) blkdev.$(OBJEXT) blkdev-libscg.$(OBJEXT) scsi.$(OBJEXT)' UAE_DEFINES="$UAE_DEFINES -DSCSIEMU" if [[ "x$WANT_A2091" = "xyes" ]]; then UAE_DEFINES="$UAE_DEFINES -DA2091" SCSIOBJS='scsiemul.$(OBJEXT) blkdev.$(OBJEXT) blkdev_cdimage.$(OBJEXT) blkdev-libscg.$(OBJEXT) scsi.$(OBJEXT) a2091.$(OBJEXT)' -dnl SCSIOBJS='scsiemul.$(OBJEXT) blkdev.$(OBJEXT) blkdev-libscg.$(OBJEXT) scsi.$(OBJEXT) a2091.$(OBJEXT)' fi UAE_CPPFLAGS="$UAE_CPPFLAGS $LIBSCG_CPPFLAGS" UAE_LIBS="$LIBSCG_LIBS $UAE_LIBS" @@ -1498,12 +1494,10 @@ typedef int BOOL; [ AC_MSG_RESULT(yes) SCSIOBJS='scsiemul.$(OBJEXT) blkdev.$(OBJEXT) blkdev_cdimage.$(OBJEXT) blkdev-libscg.$(OBJEXT) scsi.$(OBJEXT)' -dnl SCSIOBJS='scsiemul.$(OBJEXT) blkdev.$(OBJEXT) blkdev-libscg.$(OBJEXT) scsi.$(OBJEXT)' UAE_DEFINES="$UAE_DEFINES -DSCSIEMU" if [[ "x$WANT_A2091" = "xyes" ]]; then UAE_DEFINES="$UAE_DEFINES -DA2091" SCSIOBJS='scsiemul.$(OBJEXT) blkdev.$(OBJEXT) blkdev_cdimage.$(OBJEXT) blkdev-libscg.$(OBJEXT) scsi.$(OBJEXT) a2091.$(OBJEXT)' -dnl SCSIOBJS='scsiemul.$(OBJEXT) blkdev.$(OBJEXT) blkdev-libscg.$(OBJEXT) scsi.$(OBJEXT) a2091.$(OBJEXT)' fi NEED_THREAD_SUPPORT=yes if [[ "$srcdir" != "." ]]; then @@ -1526,12 +1520,10 @@ dnl AC_CONFIG_LINKS(src/libschily.a:src/libschily.a) [ AC_MSG_RESULT(yes) SCSIOBJS='scsiemul.$(OBJEXT) blkdev.$(OBJEXT) blkdev_cdimage.$(OBJEXT) scsi.$(OBJEXT)' -dnl SCSIOBJS='scsiemul.$(OBJEXT) blkdev.$(OBJEXT) scsi.$(OBJEXT)' UAE_DEFINES="$UAE_DEFINES -DSCSIEMU -DSCSIEMU_LINUX_IOCTL" if [[ "x$WANT_A2091" = "xyes" ]]; then UAE_DEFINES="$UAE_DEFINES -DA2091" SCSIOBJS='scsiemul.$(OBJEXT) blkdev.$(OBJEXT) blkdev_cdimage.$(OBJEXT) scsi.$(OBJEXT) a2091.$(OBJEXT)' -dnl SCSIOBJS='scsiemul.$(OBJEXT) blkdev.$(OBJEXT) scsi.$(OBJEXT) a2091.$(OBJEXT)' fi NEED_THREAD_SUPPORT=yes ], diff --git a/src/Makefile.am b/src/Makefile.am index c2d1a23..a2e531e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -178,7 +178,7 @@ uae_SOURCES = \ gfxutil.c audio.c sinctable.c statusline.c drawing.c consolehook.c \ native2amiga.c disk.c crc32.c savestate.c arcadia.c cdtv.c cd32_fmv.c \ uaeexe.c uaelib.c uaeresource.c uaeserial.c fdi2raw.c hotkeys.c amax.c \ - ar.c driveclick.c enforcer.c misc.c uaenet.c a2065.c gayle.c ncr_scsi.c \ + ar.c driveclick.c enforcer.c misc.c uaenet.c a2065.c gayle.c blkdev.c blkdev_cdimage.c scsi.c ncr_scsi.c \ missing.c readcpu.c hrtmon.rom.c events.c calc.c aros.rom.c specialmonitors.c EXTRA_uae_SOURCES = \ @@ -187,8 +187,8 @@ EXTRA_uae_SOURCES = \ debug.c identify.c filesys_bootrom.c fsdb.c fsdb_unix.c fsusage.c genblitter.c \ gencpu.c gengenblitter.c gencomp.c genlinetoscr.c hardfile.c \ hardfile_unix.c scsi-none.c scsiemul.c svgancui.c tui.c amax.c \ - akiko.c cd32_fmv.c ar.c blkdev.c blkdev_cdimage.c blkdev-libscg.c \ - blitops.c scsi.c writelog.c + akiko.c cd32_fmv.c ar.c blkdev-libscg.c \ + blitops.c writelog.c uae_DEPENDENCIES = \ @MACHDEP@/libmachdep.a \ diff --git a/src/a2091.c b/src/a2091.c index d0fd9e7..a3dc219 100644 --- a/src/a2091.c +++ b/src/a2091.c @@ -341,7 +341,7 @@ static TCHAR *scsitostring (void) p = buf; p[0] = 0; - for (i = 0; i < gettc () && i < sizeof wd_data; i++) { + for (i = 0; i < scsi->offset && i < sizeof wd_data; i++) { if (i > 0) { _tcscat (p, _T(".")); p++; @@ -419,7 +419,7 @@ static bool do_dma (void) static bool wd_do_transfer_out (void) { #if WD33C93_DEBUG > 0 - write_log (_T("%s SCSI O [%02X] %d/%d %s\n"), WD33C93, wdregs[WD_COMMAND_PHASE], wd_dataoffset, gettc (), scsitostring ()); + write_log (_T("%s SCSI O [%02X] %d/%d TC=%d %s\n"), WD33C93, wdregs[WD_COMMAND_PHASE], scsi->offset, scsi->data_len, gettc (), scsitostring ()); #endif if (wdregs[WD_COMMAND_PHASE] < 0x20) { /* message was sent */ @@ -776,6 +776,9 @@ static void wd_cmd_reset (bool irq) wdregs[0] &= ~(0x08 | 0x10); sasr = 0; wd_selected = false; + scsi = NULL; + scsidelay_irq[0] = 0; + scsidelay_irq[1] = 0; if (irq) set_status ((wdregs[0] & 0x08) ? 1 : 0, 200); } @@ -841,7 +844,7 @@ void wdscsi_put (uae_u8 d) #endif } else if (sasr == WD_DATA) { #if WD33C93_DEBUG_PIO - write_log (_T("%s WD_DATA WRITE %02x %d/%d,%d\n"), WD33C93, d, wd_dataoffset, scsi->len, scsi->data_len); + write_log (_T("%s WD_DATA WRITE %02x %d/%d\n"), WD33C93, d, scsi->offset, scsi->data_len); #endif if (!wd_data_avail) { write_log (_T("%s WD_DATA WRITE without data request!?\n"), WD33C93); @@ -914,7 +917,7 @@ uae_u8 wdscsi_get (void) } int status = scsi_receive_data (scsi, &v); #if WD33C93_DEBUG_PIO - write_log (_T("%s WD_DATA READ %02x %d/%d,%d\n"), WD33C93, v, wd_dataoffset, scsi->len, scsi->data_len); + write_log (_T("%s WD_DATA READ %02x %d/%d\n"), WD33C93, v, scsi->offset, scsi->data_len); #endif if (wd_dataoffset < sizeof wd_data) wd_data[wd_dataoffset] = v; @@ -1533,7 +1536,7 @@ static void freescsi (struct scsi_data *sd) scsi_free (sd); } -int addscsi (int ch, struct hd_hardfiledata *hfd, struct uaedev_config_info *ci, int scsi_level) +int add_scsi_hd (int ch, struct hd_hardfiledata *hfd, struct uaedev_config_info *ci, int scsi_level) { freescsi (scsis[ch]); scsis[ch] = NULL; @@ -1544,7 +1547,15 @@ int addscsi (int ch, struct hd_hardfiledata *hfd, struct uaedev_config_info *ci, if (!hdf_hd_open (hfd)) return 0; hfd->ansi_version = scsi_level; - scsis[ch] = scsi_alloc (ch, hfd); + scsis[ch] = scsi_alloc_hd (ch, hfd); + return scsis[ch] ? 1 : 0; +} + +int add_scsi_cd (int ch, int unitnum) +{ + device_func_init (0); + freescsi (scsis[ch]); + scsis[ch] = scsi_alloc_cd (ch, unitnum); return scsis[ch] ? 1 : 0; } @@ -1606,7 +1617,10 @@ static void addnativescsi (void) int a3000_add_scsi_unit (int ch, struct uaedev_config_info *ci) { - return addscsi (ch, NULL, ci, 2); + if (ci->cd_emu_unit >= 0) + return add_scsi_cd (ch, ci->cd_emu_unit); + else + return add_scsi_hd (ch, NULL, ci, 2); } void a3000scsi_reset (void) @@ -1622,7 +1636,10 @@ void a3000scsi_free (void) int a2091_add_scsi_unit (int ch, struct uaedev_config_info *ci) { - return addscsi (ch, NULL, ci, 1); + if (ci->cd_emu_unit >= 0) + return add_scsi_cd (ch, ci->cd_emu_unit); + else + return add_scsi_hd (ch, NULL, ci, 1); } @@ -1760,6 +1777,8 @@ uae_u8 *save_scsi_hd (int num, int *len, uae_u8 *dstptr) if (!scsis[num]) return NULL; s = scsis[num]; + if (s->hfd == NULL) + return NULL; if (dstptr) dstbak = dst = dstptr; else @@ -1795,7 +1814,7 @@ uae_u8 *restore_scsi_hd (uae_u8 *src) num = restore_u32 (); hfd = xcalloc (struct hd_hardfiledata, 1); - s = scsis[num] = scsi_alloc (num, hfd); + s = scsis[num] = scsi_alloc_hd (num, hfd); restore_u32 (); size = restore_u64 (); path = restore_string (); @@ -1813,7 +1832,7 @@ uae_u8 *restore_scsi_hd (uae_u8 *src) s->hfd->ansi_version = restore_u32 (); if (size) { - addscsi (num, hfd, NULL, s->hfd->ansi_version); + add_scsi_hd (num, hfd, NULL, s->hfd->ansi_version); } xfree (path); return src; diff --git a/src/blkdev.c b/src/blkdev.c index e4a855c..9835442 100644 --- a/src/blkdev.c +++ b/src/blkdev.c @@ -43,6 +43,7 @@ static TCHAR newimagefiles[MAX_TOTAL_SCSI_DEVICES][256]; static int imagechangetime[MAX_TOTAL_SCSI_DEVICES]; static bool cdimagefileinuse[MAX_TOTAL_SCSI_DEVICES]; static int wasopen[MAX_TOTAL_SCSI_DEVICES]; +static bool dev_init; /* convert minutes, seconds and frames -> logical sector number */ int msf2lsn (int msf) @@ -198,11 +199,17 @@ void blkdev_fix_prefs (struct uae_prefs *p) if (p->cdslots[i].inuse || p->cdslots[i].name[0]) { TCHAR *name = p->cdslots[i].name; if (_tcslen (name) == 3 && name[1] == ':' && name[2] == '\\') { +//SPTI 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) { +//EMU if (currprefs.win32_uaescsimode == UAESCSI_CDEMU) +// cdscsidevicetype[i] = SCSI_UNIT_IOCTL; +// else cdscsidevicetype[i] = SCSI_UNIT_SPTI; } else { cdscsidevicetype[i] = SCSI_UNIT_IOCTL; @@ -314,16 +321,16 @@ static int getunitinfo (int unitnum, int drive, unsigned int csu, int *isaudio) return 0; } -static int get_standard_cd_unit2 (unsigned int csu) +static int get_standard_cd_unit2 (struct uae_prefs *p, unsigned int csu) { int unitnum = 0; int isaudio = 0; - if (currprefs.cdslots[unitnum].name[0] || currprefs.cdslots[unitnum].inuse) { - if (currprefs.cdslots[unitnum].name[0]) { + if (p->cdslots[unitnum].name[0] || p->cdslots[unitnum].inuse) { + if (p->cdslots[unitnum].name[0]) { device_func_init (SCSI_UNIT_IOCTL); - if (!sys_command_open_internal (unitnum, currprefs.cdslots[unitnum].name, csu)) { + if (!sys_command_open_internal (unitnum, p->cdslots[unitnum].name, csu)) { device_func_init (SCSI_UNIT_IMAGE); - if (!sys_command_open_internal (unitnum, currprefs.cdslots[unitnum].name, csu)) + if (!sys_command_open_internal (unitnum, p->cdslots[unitnum].name, csu)) goto fallback; } } else { @@ -331,7 +338,25 @@ static int get_standard_cd_unit2 (unsigned int csu) } return unitnum; } - + device_func_init (SCSI_UNIT_IOCTL); + for (int drive = 'C'; drive <= 'Z'; ++drive) { + TCHAR vol[100]; + _stprintf (vol, _T("%c:\\"), drive); + int drivetype = 0; //GetDriveType (vol); + if (drivetype == -1 /*DRIVE_CDROM*/) { + if (sys_command_open_internal (unitnum, vol, csu)) { + if (getunitinfo (unitnum, drive, csu, &isaudio)) + return unitnum; + sys_command_close (unitnum); + } + } + } + if (isaudio) { + TCHAR vol[100]; + _stprintf (vol, _T("%c:\\"), isaudio); + if (sys_command_open_internal (unitnum, vol, csu)) + return unitnum; + } fallback: device_func_init (SCSI_UNIT_IMAGE); if (!sys_command_open_internal (unitnum, _T(""), csu)) { @@ -343,7 +368,7 @@ fallback: int get_standard_cd_unit (unsigned int csu) { - int unitnum = get_standard_cd_unit2 (csu); + int unitnum = get_standard_cd_unit2 (&currprefs, csu); if (unitnum < 0) return -1; #ifdef RETROPLATFORM @@ -368,6 +393,12 @@ int sys_command_isopen (int unitnum) int sys_command_open (int unitnum) { + blkdev_fix_prefs (&currprefs); + if (!dev_init) { + device_func_init (0); + dev_init = true; + } + if (openlist[unitnum]) { openlist[unitnum]++; return -1; @@ -421,6 +452,23 @@ int device_func_init (int flags) return 1; } +bool blkdev_get_info (struct uae_prefs *p, int unitnum, struct device_info *di) +{ + bool open = true, opened = true, ok = false; + if (!openlist[unitnum]) { + blkdev_fix_prefs (p); + install_driver (0); + opened = true; + open = sys_command_open_internal (unitnum, p->cdslots[unitnum].name[0] ? p->cdslots[unitnum].name : NULL, CD_STANDARD_UNIT_DEFAULT) != 0; + } + if (open) { + ok = sys_command_info (unitnum, di, true) != 0; + } + if (open && opened) + sys_command_close_internal (unitnum); + return ok; +} + void blkdev_entergui (void) { for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) { @@ -1087,7 +1135,7 @@ static int scsi_read_cd (int unitnum, uae_u8 *cmd, uae_u8 *data, struct device_i return sys_command_cd_rawread2 (unitnum, data, start, len, 0, (cmd[1] >> 2) & 7, cmd[9], subs); } -static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len, +int scsi_cd_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len, uae_u8 *scsi_data, int *data_len, uae_u8 *r, int *reply_len, uae_u8 *s, int *sense_len) { uae_u64 len, offset; @@ -1116,14 +1164,21 @@ static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len, scsi_cmd_len, scsi_data, *data_len); switch (cmdbuf[0]) { + case 0x03: /* REQUEST SENSE */ + break; + case 0x1e: /* PREVENT/ALLOW MEDIUM REMOVAL */ + scsi_len = 0; + break; case 0x12: /* INQUIRY */ { if ((cmdbuf[1] & 1) || cmdbuf[2] != 0) goto err; len = cmdbuf[4]; - if (cmdbuf[1] >> 5) - goto err; - r[0] = 5; // CDROM + if (cmdbuf[1] >> 5) { + r[0] = 0x7f; + } else { + r[0] = 5; // CDROM + } r[1] |= 0x80; // removable r[2] = 2; /* supports SCSI-2 */ r[3] = 2; /* response data format */ @@ -1380,6 +1435,61 @@ static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len, break; case 0xaa: /* WRITE (12) */ goto readprot; + case 0x51: /* READ DISC INFORMATION */ + { + struct cd_toc_head ttoc; + int maxlen = (cmdbuf[7] << 8) | cmdbuf[8]; + if (nodisk (&di)) + goto nodisk; + if (!sys_command_cd_toc (unitnum, &ttoc)) + goto readerr; + struct cd_toc_head *toc = &ttoc; + uae_u8 *p = scsi_data; + p[0] = 0; + p[1] = 34 - 2; + p[2] = 2 | (3 << 2); // complete cd rom, last session is complete + p[3] = toc->first_track; + p[4] = 1; + p[5] = toc->first_track; + p[6] = toc->last_track; + wl (p + 16, lsn2msf (toc->lastaddress)); + wl (p + 20, 0x00ffffff); + scsi_len = p[1] + 2; + if (scsi_len > maxlen) + scsi_len = maxlen; + } + break; + case 0x52: /* READ TRACK INFORMATION */ + { + struct cd_toc_head ttoc; + int maxlen = (cmdbuf[7] << 8) | cmdbuf[8]; + if (nodisk (&di)) + goto nodisk; + if (!sys_command_cd_toc (unitnum, &ttoc)) + goto readerr; + struct cd_toc_head *toc = &ttoc; + uae_u8 *p = scsi_data; + int lsn; + if (cmdbuf[1] & 1) { + int track = cmdbuf[5]; + lsn = toc->toc[track].address; + } else { + lsn = rl (p + 2); + } + struct cd_toc *t = gettoc (toc, lsn); + p[0] = 0; + p[1] = 28 - 2; + p[2] = t->track; + p[3] = 1; + p[5] = t->control; + p[6] = 0; // data mode, fixme + wl (p + 8, t->address); + wl (p + 24, t[1].address - t->address); + scsi_len = p[1] + 2; + if (scsi_len > maxlen) + scsi_len = maxlen; + } + break; case 0x43: // READ TOC { if (nodisk (&di)) @@ -1391,6 +1501,7 @@ static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len, if (format >= 3) goto errreq; int maxlen = (cmdbuf[7] << 8) | cmdbuf[8]; + int maxlen2 = maxlen; struct cd_toc_head ttoc; if (!sys_command_cd_toc (unitnum, &ttoc)) goto readerr; @@ -1424,23 +1535,24 @@ static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len, maxlen -= 4; if (format == 2) { if (!addtocentry (&p2, &maxlen, 0xa0, -1, msf, p, toc)) - goto errreq; + break; if (!addtocentry (&p2, &maxlen, 0xa1, -1, msf, p, toc)) - goto errreq; + break; if (!addtocentry (&p2, &maxlen, 0xa2, -1, msf, p, toc)) - goto errreq; + break; } while (strack < 100) { if (!addtocentry (&p2, &maxlen, strack, -1, msf, p, toc)) - goto errreq; + break; strack++; } - if (!addtocentry (&p2, &maxlen, 0xa2, 0xaa, msf, p, toc)) - goto errreq; + addtocentry (&p2, &maxlen, 0xa2, 0xaa, msf, p, toc); int tlen = p2 - (p + 2); p[0] = tlen >> 8; p[1] = tlen >> 0; - scsi_len = tlen + 2 + 4; + scsi_len = tlen + 2; + if (scsi_len > maxlen2) + scsi_len = maxlen2; } } break; @@ -1490,10 +1602,6 @@ static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len, scsiemudrv (unitnum, cmdbuf); scsi_len = 0; break; - case 0x1e: // PREVENT/ALLOW MEDIA REMOVAL - // do nothing - scsi_len = 0; - break; case 0x4e: // STOP PLAY/SCAN if (nodisk (&di)) goto nodisk; @@ -1601,7 +1709,7 @@ static int scsi_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len, goto nodisk; int start = rl (cmdbuf + 2); int len; - if (cmd = 0xa5) + if (cmd == 0xa5) len = rl (cmdbuf + 6); else len = rw (cmdbuf + 7); @@ -1728,7 +1836,7 @@ static int execscsicmd_direct (int unitnum, struct amigascsi *as) if (as->sense_len > 32) as->sense_len = 32; - as->status = scsi_emulate (unitnum, cmd, as->cmd_len, scsi_datap, &datalen, replydata, &replylen, as->sensedata, &senselen); + as->status = scsi_cd_emulate (unitnum, cmd, as->cmd_len, scsi_datap, &datalen, replydata, &replylen, as->sensedata, &senselen); as->cmdactual = as->status != 0 ? 0 : as->cmd_len; /* fake scsi_CmdActual */ if (as->status) { diff --git a/src/blkdev_cdimage.c b/src/blkdev_cdimage.c index c4d5ce3..88a3e0e 100644 --- a/src/blkdev_cdimage.c +++ b/src/blkdev_cdimage.c @@ -81,8 +81,7 @@ struct cdunit { play_status_callback cdda_statusfunc; int cdda_delay, cdda_delay_frames; - int imagechange; - TCHAR newfile[MAX_DPATH]; + TCHAR imgname[MAX_DPATH]; uae_sem_t sub_sem; struct device_info di; chd_file *chd_f; @@ -1701,7 +1700,7 @@ static struct device_info *info_device (int unitnum, struct device_info *di, int di->sectorspertrack = (int)(cdu->cdsize / di->bytespersector); if (ismedia (unitnum, 1)) { di->media_inserted = 1; - _tcscpy (di->mediapath, currprefs.cdslots[unitnum].name); + _tcscpy (di->mediapath, cdu->imgname); } memset (&di->toc, 0, sizeof (struct cd_toc_head)); command_toc (unitnum, &di->toc); @@ -1714,6 +1713,9 @@ static struct device_info *info_device (int unitnum, struct device_info *di, int } else { _tcscpy (di->label, _T("IMG:")); } + _tcscpy (di->vendorid, _T("UAE")); + _stprintf (di->productid, _T("SCSICD%d"), unitnum); + _tcscpy (di->revision, _T("1.0")); di->backend = _T("IMAGE"); return di; } @@ -1733,8 +1735,10 @@ static void unload_image (struct cdunit *cdu) xfree (t->extrainfo); } cdrom_close (cdu->chd_cdf); + cdu->chd_cdf = NULL; if (cdu->chd_f) cdu->chd_f->close(); + cdu->chd_f = NULL; memset (cdu->toc, 0, sizeof cdu->toc); cdu->tracks = 0; cdu->cdsize = 0; @@ -1748,6 +1752,7 @@ static int open_device (int unitnum, const TCHAR *ident, int flags) if (!cdu->open) { uae_sem_init (&cdu->sub_sem, 0, 1); + _tcscpy (cdu->imgname, ident); parse_image (cdu, ident); cdu->open = true; cdu->enabled = true; diff --git a/src/cdtv.c b/src/cdtv.c index 02d8ad7..31b909d 100644 --- a/src/cdtv.c +++ b/src/cdtv.c @@ -1659,9 +1659,9 @@ uae_u8 cdtv_battram_read (int addr) return v; } -int cdtv_add_scsi_unit (int ch, struct uaedev_config_info *ci) +int cdtv_add_scsi_hd_unit (int ch, struct uaedev_config_info *ci) { - return addscsi (ch, NULL, ci, 1); + return add_scsi_hd (ch, NULL, ci, 1); } void cdtv_free (void) diff --git a/src/cfgfile.c b/src/cfgfile.c index ffa4233..b550633 100644 --- a/src/cfgfile.c +++ b/src/cfgfile.c @@ -579,7 +579,7 @@ static void write_filesys_config (struct uae_prefs *p, struct zfile *f) if (ci->donotmount) bp = -129; str = cfgfile_put_multipath (&p->path_hardfile, ci->rootdir); - if (!uci->ishdf) { + if (ci->type == UAEDEV_DIR) { _stprintf (tmp, _T("%s,%s:%s:%s,%d"), ci->readonly ? _T("ro") : _T("rw"), ci->devname ? ci->devname : _T(""), ci->volname, str, bp); cfgfile_write_str (f, _T("filesystem2"), tmp); @@ -588,7 +588,7 @@ static void write_filesys_config (struct uae_prefs *p, struct zfile *f) uci->volname, str); zfile_fputs (f, tmp2); #endif - } else { + } else if (ci->type == UAEDEV_HDF || ci->type == UAEDEV_CD) { _stprintf (tmp, _T("%s,%s:%s,%d,%d,%d,%d,%d,%s,%s"), ci->readonly ? _T("ro") : _T("rw"), ci->devname ? ci->devname : _T(""), str, @@ -602,6 +602,7 @@ static void write_filesys_config (struct uae_prefs *p, struct zfile *f) _stprintf (s, _T(",%d/%d/%d"), ci->pcyls, ci->pheads, ci->psecs); } } + if (ci->type == UAEDEV_HDF) cfgfile_write_str (f, _T("hardfile2"), tmp); #if 0 _stprintf (tmp2, _T("hardfile=%s,%d,%d,%d,%d,%s"), @@ -611,7 +612,11 @@ static void write_filesys_config (struct uae_prefs *p, struct zfile *f) #endif } _stprintf (tmp2, _T("uaehf%d"), i); - cfgfile_write (f, tmp2, _T("%s,%s"), uci->ishdf ? _T("hdf") : _T("dir"), tmp); + if (ci->type == UAEDEV_CD) { + cfgfile_write (f, tmp2, _T("cd%d,%s"), ci->cd_emu_unit, tmp); + } else { + cfgfile_write (f, tmp2, _T("%s,%s"), ci->type == UAEDEV_HDF ? _T("hdf") : _T("dir"), tmp); + } xfree (str); } } @@ -2385,7 +2390,7 @@ static struct uaedev_config_data *getuci (struct uae_prefs *p) return NULL; } -struct uaedev_config_data *add_filesys_config (struct uae_prefs *p, int index, struct uaedev_config_info *ci, bool hdf) +struct uaedev_config_data *add_filesys_config (struct uae_prefs *p, int index, struct uaedev_config_info *ci) { struct uaedev_config_data *uci; int i; @@ -2396,8 +2401,18 @@ struct uaedev_config_data *add_filesys_config (struct uae_prefs *p, int index, s return 0; } } + if (ci->type == UAEDEV_CD) { + if (ci->controller > HD_CONTROLLER_SCSI6 || ci->controller < HD_CONTROLLER_IDE0) + return NULL; + } if (index < 0) { + if (ci->type == UAEDEV_CD) { + for (i = 0; i < p->mountitems; i++) { + if (p->mountconfig[i].ci.type == UAEDEV_CD) + return 0; + } + } uci = getuci(p); uci->configoffset = -1; } else { @@ -2407,18 +2422,17 @@ struct uaedev_config_data *add_filesys_config (struct uae_prefs *p, int index, s return 0; memcpy (&uci->ci, ci, sizeof (struct uaedev_config_info)); - uci->ishdf = hdf; validatedevicename (uci->ci.devname); validatevolumename (uci->ci.volname); if (uci->ci.bootpri < -128) uci->ci.donotmount = true; else if (uci->ci.bootpri >= -127) uci->ci.autoboot = true; - if (!uci->ci.devname[0]) { + if (!uci->ci.devname[0] && ci->type != UAEDEV_CD) { TCHAR base[32]; TCHAR base2[32]; int num = 0; - if (uci->ci.rootdir[0] == 0 && !uci->ishdf) + if (uci->ci.rootdir[0] == 0 && ci->type == UAEDEV_DIR) _tcscpy (base, _T("RDH")); else _tcscpy (base, _T("DH")); @@ -2434,7 +2448,7 @@ struct uaedev_config_data *add_filesys_config (struct uae_prefs *p, int index, s _tcscpy (uci->ci.devname, base2); validatedevicename (uci->ci.devname); } - if (!uci->ishdf) { + if (ci->type == UAEDEV_DIR) { TCHAR *s = filesys_createvolname (uci->ci.volname, uci->ci.rootdir, _T("Harddrive")); _tcscpy (uci->ci.volname, s); xfree (s); @@ -2572,6 +2586,8 @@ static bool parse_geo (const TCHAR *tname, struct uaedev_config_info *uci, struc uci->flags = v; if (!_tcsicmp (key, _T("priority"))) uci->priority = v; + if (!_tcsicmp (key, _T("forceload"))) + uci->forceload = v; if (!_tcsicmp (key, _T("bootpri"))) { uci->bootpri = v; uci->donotmount = false; @@ -2616,7 +2632,7 @@ bool get_hd_geometry (struct uaedev_config_info *uci) return false; } -static int cfgfile_parse_newfilesys (struct uae_prefs *p, int nr, bool hdf, TCHAR *value) +static int cfgfile_parse_newfilesys (struct uae_prefs *p, int nr, int type, TCHAR *value, int unit, bool uaehfentry) { struct uaedev_config_info uci; TCHAR *tmpp = _tcschr (value, ','), *tmpp2; @@ -2639,7 +2655,8 @@ static int cfgfile_parse_newfilesys (struct uae_prefs *p, int nr, bool hdf, TCHA goto invalid_fs; value = tmpp; - if (!hdf) { + if (type == 0) { + uci.type = UAEDEV_DIR; tmpp = _tcschr (value, ':'); if (tmpp == 0) goto empty_fs; @@ -2661,7 +2678,7 @@ static int cfgfile_parse_newfilesys (struct uae_prefs *p, int nr, bool hdf, TCHA _tcscpy (uci.devname, devname); if (! getintval (&tmpp, &uci.bootpri, 0)) goto empty_fs; - } else { + } else if (type == 1 || (type == 2 && uaehfentry)) { tmpp = _tcschr (value, ':'); if (tmpp == 0) goto invalid_fs; @@ -2700,6 +2717,16 @@ static int cfgfile_parse_newfilesys (struct uae_prefs *p, int nr, bool hdf, TCHA } } } + if (type == 2) { + uci.cd_emu_unit = unit; + uci.blocksize = 2048; + uci.readonly = true; + uci.type = UAEDEV_CD; + } else { + uci.type = UAEDEV_HDF; + } + } else { + goto invalid_fs; } empty_fs: uci.autoboot = uci.bootpri >= -127; @@ -2713,13 +2740,13 @@ empty_fs: _tcscpy (uci.rootdir, str); } #ifdef FILESYS - add_filesys_config (p, nr, &uci, hdf); + add_filesys_config (p, nr, &uci); #endif // xfree (str); return 1; invalid_fs: - write_log (_T("Invalid filesystem/hardfile specification.\n")); + write_log (_T("Invalid filesystem/hardfile/cd specification.\n")); return 1; } @@ -2732,21 +2759,29 @@ static int cfgfile_parse_filesys (struct uae_prefs *p, const TCHAR *option, TCHA _stprintf (tmp, _T("uaehf%d"), i); if (_tcscmp (option, tmp) == 0) { for (;;) { - bool hdf = false; + int type = -1; + int unit = -1; TCHAR *tmpp = _tcschr (value, ','); if (tmpp == NULL) return 1; *tmpp++ = 0; - if (strcasecmp (value, _T("hdf")) == 0) { - hdf = true; - } else if (strcasecmp (value, _T("dir")) != 0) { - return 1; + if (_tcsicmp (value, _T("hdf")) == 0) { + type = 1; + return 1; /* ignore for now */ + } else if (_tcsnicmp (value, _T("cd"), 2) == 0 && (value[2] == 0 || value[3] == 0)) { + unit = 0; + if (value[2] > 0) + unit = value[2] - '0'; + if (unit >= 0 && unit <= MAX_TOTAL_SCSI_DEVICES) { + type = 2; } -#if 0 // not yet - return cfgfile_parse_newfilesys (p, i, hdf, tmpp); -#else + } else if (_tcsicmp (value, _T("dir")) != 0) { + type = 0; + return 1; /* ignore for now */ + } + if (type >= 0) + return cfgfile_parse_newfilesys (p, -1, type, tmpp, unit, true); return 1; -#endif } return 1; } else if (!_tcsncmp (option, tmp, _tcslen (tmp)) && option[_tcslen (tmp)] == '_') { @@ -2820,7 +2855,8 @@ static int cfgfile_parse_filesys (struct uae_prefs *p, const TCHAR *option, TCHA } str = cfgfile_subst_path_load (UNEXPANDED, &p->path_hardfile, uci.rootdir, true); #ifdef FILESYS - add_filesys_config (p, -1, &uci, hdf); + uci.type = hdf ? UAEDEV_HDF : UAEDEV_DIR; + add_filesys_config (p, -1, &uci); #endif xfree (str); return 1; @@ -2831,9 +2867,9 @@ invalid_fs: } if (_tcscmp (option, _T("filesystem2")) == 0) - return cfgfile_parse_newfilesys (p, -1, false, value); + return cfgfile_parse_newfilesys (p, -1, 0, value, -1, false); if (_tcscmp (option, _T("hardfile2")) == 0) - return cfgfile_parse_newfilesys (p, -1, true, value); + return cfgfile_parse_newfilesys (p, -1, 1, value, -1, false); return 0; } @@ -3857,7 +3893,8 @@ static void parse_filesys_spec (struct uae_prefs *p, bool readonly, const TCHAR _tcscpy (uci.volname, buf); _tcscpy (uci.rootdir, s2); uci.readonly = readonly; - add_filesys_config (p, -1, &uci, false); + uci.type = UAEDEV_DIR; + add_filesys_config (p, -1, &uci); #endif } else { write_log (_T("Usage: [-m | -M] VOLNAME:mount_point\n")); @@ -3889,7 +3926,6 @@ static void parse_hardfile_spec (struct uae_prefs *p, const TCHAR *spec) *x4++ = '\0'; #ifdef FILESYS _tcscpy (uci.rootdir, x4); - //add_filesys_config (p, -1, NULL, NULL, x4, 0, 0, _tstoi (x0), _tstoi (x1), _tstoi (x2), _tstoi (x3), 0, 0, 0, 0, 0, 0, 0); #endif xfree (x0); return; diff --git a/src/consolehook.c b/src/consolehook.c index da3a77a..4fde984 100644 --- a/src/consolehook.c +++ b/src/consolehook.c @@ -55,7 +55,8 @@ void consolehook_config (struct uae_prefs *p) _tcscpy (ci.volname, _T("CLIBOOT")); _tcscpy (ci.devname, _T("DH0")); ci.bootpri = 15; - add_filesys_config (p, -1, &ci, false); + ci.type = UAEDEV_DIR; + add_filesys_config (p, -1, &ci); } static void *console_thread (void *v) diff --git a/src/cpummu.c b/src/cpummu.c index 7661361..df4f44c 100644 --- a/src/cpummu.c +++ b/src/cpummu.c @@ -39,11 +39,17 @@ uae_u32 mmu_is_super; -uae_u32 mmu_tagmask, mmu_pagemask; +uae_u32 mmu_tagmask, mmu_pagemask, mmu_pagemaski; struct mmu_atc_line mmu_atc_array[ATC_TYPE][ATC_WAYS][ATC_SLOTS]; -int mmu060_state; bool mmu_pagesize_8k; +int mmu060_state; +uae_u16 mmu060_opcode; +static bool locked_rmw_cycle; + +int mmu040_movem; +uaecptr mmu040_movem_ea; + static void mmu_dump_ttr(const TCHAR * label, uae_u32 ttr) { DUNUSED(label); @@ -244,7 +250,7 @@ static void mmu_bus_error(uaecptr addr, int fc, bool write, int size, uae_u32 st if (currprefs.mmu_model == 68040) { uae_u16 ssw = 0; - ssw |= fc & MMU_SSW_TM; /* Copy TM */ + ssw |= fc & MMU_SSW_TM; /* TM = FC */ switch (size) { case sz_byte: ssw |= MMU_SSW_SIZE_B; @@ -255,21 +261,45 @@ static void mmu_bus_error(uaecptr addr, int fc, bool write, int size, uae_u32 st case sz_long: ssw |= MMU_SSW_SIZE_L; break; + case 16: // MOVE16 + ssw |= MMU_SSW_SIZE_L; // ?? + ssw |= MMU_SSW_TT0; + break; } regs.wb3_status = write ? 0x80 | ssw : 0; if (!write) ssw |= MMU_SSW_RW; + if (mmu040_movem) { + ssw |= MMU_SSW_CM; + addr = mmu040_movem_ea; + mmu040_movem = 0; + write_log (_T("040 MMU_SSW_CM!\n")); + } + if (locked_rmw_cycle) { + ssw |= MMU_SSW_LK; + locked_rmw_cycle = false; + write_log (_T("040 MMU_SSW_LK!\n")); + } + regs.mmu_ssw = ssw | MMU_SSW_ATC; -#if MMUDEBUG > 2 +#if MMUDEBUG > 0 write_log(_T("040 BUS ERROR: fc=%d w=%d logical=%08x ssw=%04x PC=%08x\n"), fc, write, addr, ssw, m68k_getpc()); #endif } else { uae_u32 fslw = 0; fslw |= write ? MMU_FSLW_W : MMU_FSLW_R; +#if 0 + // read-modify-write? + if (table68k[mmu060_opcode].rmw) { + fslw |= MMU_FSLW_W | MMU_FSLW_R; + } +#endif + + fslw |= fc << 16; /* MMU_FSLW_TM */ switch (size) { case sz_byte: fslw |= MMU_FSLW_SIZE_B; @@ -283,24 +313,39 @@ static void mmu_bus_error(uaecptr addr, int fc, bool write, int size, uae_u32 st case 16: // MOVE16 addr &= ~15; fslw |= MMU_FSLW_SIZE_D; + fslw |= MMU_FSLW_TT_16; break; } - if (mmu060_state == 0) { - fslw |= MMU_FSLW_IO; // opword fetch - } else if ((fc & 2)) { - fslw |= MMU_FSLW_IO | MMU_FSLW_MA; // extension word + if ((fc & 3) == 2) { + if (mmu060_state == 0) { + fslw |= MMU_FSLW_IO; // opword fetch + } else { + fslw |= MMU_FSLW_IO | MMU_FSLW_MA; // extension word + } + } + if (locked_rmw_cycle) { + fslw |= MMU_FSLW_LK; + locked_rmw_cycle = false; + write_log (_T("060 MMU_FSLW_LK!\n")); } fslw |= status; regs.mmu_fslw = fslw; -#if MMUDEBUG > 2 +#if MMUDEBUG > 0 write_log(_T("060 BUS ERROR: fc=%d w=%d logical=%08x ssw=%08x PC=%08x\n"), fc, write, addr, fslw, m68k_getpc()); #endif } regs.mmu_fault_addr = addr; +#if 0 + if (addr == 0x00002180) { + write_log (_T("*")); + extern void activate_debugger(void); + activate_debugger (); + } +#endif THROW(2); } @@ -348,10 +393,7 @@ static uaecptr mmu_fill_atc(uaecptr addr, bool super, bool data, bool write, str l->global = 0; } else { l->valid = 1; - if (mmu_pagesize_8k) - l->phys = (desc & ~0x1fff); - else - l->phys = (desc & ~0xfff); + l->phys = desc & mmu_pagemaski; l->global = (desc & MMU_MMUSR_G) != 0; l->modified = (desc & MMU_MMUSR_M) != 0; l->write_protect = (desc & MMU_MMUSR_W) != 0; @@ -372,7 +414,7 @@ static ALWAYS_INLINE bool mmu_fill_atc_try(uaecptr addr, bool super, bool data, if (write) { if (l1->write_protect) { *status |= MMU_FSLW_WP; -#if MMUDEBUG > 1 +#if MMUDEBUG > 0 write_log(_T("MMU: write protected %lx by atc \n"), addr); #endif mmu_dump_atc(); @@ -395,14 +437,14 @@ uaecptr REGPARAM2 mmu_translate(uaecptr addr, bool super, bool data, bool write) mmu_user_lookup(addr, super, data, write, &l); mmu_fill_atc(addr, super, data, write, l, &status); - if (!l->valid) { -#if MMUDEBUG > 0 + if (!l->valid || (write && l->write_protect)) { +#if MMUDEBUG > 2 write_log(_T("[MMU] mmu_translate error")); #endif THROW(2); } - return l->phys | (addr & (mmu_pagesize_8k?0x00001fff:0x00000fff)); + return l->phys | (addr & mmu_pagemask); } @@ -533,6 +575,7 @@ uae_u32 REGPARAM2 mmu_get_long_unaligned(uaecptr addr, bool data) CATCH(prb) { RESTORE_EXCEPTION; regs.mmu_fault_addr = addr; + regs.mmu_fslw |= MMU_FSLW_MA; regs.mmu_ssw |= MMU_SSW_MA; THROW_AGAIN(prb); } ENDTRY @@ -556,6 +599,63 @@ uae_u32 REGPARAM2 mmu_get_long_unaligned(uaecptr addr, bool data) return res; } +uae_u16 REGPARAM2 mmu_get_rmw_word_unaligned(uaecptr addr) +{ + uae_u16 res; + + res = (uae_u16)mmu_get_user_byte(addr, regs.s != 0, false, true, sz_word) << 8; + SAVE_EXCEPTION; + TRY(prb) { + res |= mmu_get_user_byte(addr + 1, regs.s != 0, false, true, sz_word); + RESTORE_EXCEPTION; + } + CATCH(prb) { + RESTORE_EXCEPTION; + regs.mmu_fault_addr = addr; + regs.mmu_fslw |= MMU_FSLW_MA; + regs.mmu_ssw |= MMU_SSW_MA; + THROW_AGAIN(prb); + } ENDTRY + return res; +} + +uae_u32 REGPARAM2 mmu_get_rmw_long_unaligned(uaecptr addr) +{ + uae_u32 res; + + if (likely(!(addr & 1))) { + res = (uae_u32)mmu_get_user_word(addr, regs.s != 0, false, true, sz_long) << 16; + SAVE_EXCEPTION; + TRY(prb) { + res |= mmu_get_user_word(addr + 2, regs.s != 0, false, true, sz_long); + RESTORE_EXCEPTION; + } + CATCH(prb) { + RESTORE_EXCEPTION; + regs.mmu_fault_addr = addr; + regs.mmu_fslw |= MMU_FSLW_MA; + regs.mmu_ssw |= MMU_SSW_MA; + THROW_AGAIN(prb); + } ENDTRY + } else { + res = (uae_u32)mmu_get_user_byte(addr, regs.s != 0, false, true, sz_long) << 8; + SAVE_EXCEPTION; + TRY(prb) { + res = (res | mmu_get_user_byte(addr + 1, regs.s != 0, false, true, sz_long)) << 8; + res = (res | mmu_get_user_byte(addr + 2, regs.s != 0, false, true, sz_long)) << 8; + res |= mmu_get_user_byte(addr + 3, regs.s != 0, false, true, sz_long); + RESTORE_EXCEPTION; + } + CATCH(prb) { + RESTORE_EXCEPTION; + regs.mmu_fault_addr = addr; + regs.mmu_fslw |= MMU_FSLW_MA; + regs.mmu_ssw |= MMU_SSW_MA; + THROW_AGAIN(prb); + } ENDTRY + } + return res; +} uae_u8 REGPARAM2 mmu_get_byte_slow(uaecptr addr, bool super, bool data, int size, struct mmu_atc_line *cl) { @@ -679,13 +779,13 @@ uae_u32 REGPARAM2 sfc_get_long(uaecptr addr) uae_u32 res; if (likely(!is_unaligned(addr, 4))) - return mmu_get_user_long(addr, super, data, sz_long); + return mmu_get_user_long(addr, super, data, false, sz_long); if (likely(!(addr & 1))) { - res = (uae_u32)mmu_get_user_word(addr, super, data, sz_long) << 16; + res = (uae_u32)mmu_get_user_word(addr, super, data, false, sz_long) << 16; SAVE_EXCEPTION; TRY(prb) { - res |= mmu_get_user_word(addr + 2, super, data, sz_long); + res |= mmu_get_user_word(addr + 2, super, data, false, sz_long); RESTORE_EXCEPTION; } CATCH(prb) { @@ -696,12 +796,12 @@ uae_u32 REGPARAM2 sfc_get_long(uaecptr addr) THROW_AGAIN(prb); } ENDTRY } else { - res = (uae_u32)mmu_get_user_byte(addr, super, data, sz_long) << 8; + res = (uae_u32)mmu_get_user_byte(addr, super, data, false, sz_long) << 8; SAVE_EXCEPTION; TRY(prb) { - res = (res | mmu_get_user_byte(addr + 1, super, data, sz_long)) << 8; - res = (res | mmu_get_user_byte(addr + 2, super, data, sz_long)) << 8; - res |= mmu_get_user_byte(addr + 3, super, data, sz_long); + res = (res | mmu_get_user_byte(addr + 1, super, data, false, sz_long)) << 8; + res = (res | mmu_get_user_byte(addr + 2, super, data, false, sz_long)) << 8; + res |= mmu_get_user_byte(addr + 3, super, data, false, sz_long); RESTORE_EXCEPTION; } CATCH(prb) { @@ -722,12 +822,12 @@ uae_u16 REGPARAM2 sfc_get_word(uaecptr addr) uae_u16 res; if (likely(!is_unaligned(addr, 2))) - return mmu_get_user_word(addr, super, data, sz_word); + return mmu_get_user_word(addr, super, data, false, sz_word); - res = (uae_u16)mmu_get_user_byte(addr, super, data, sz_word) << 8; + res = (uae_u16)mmu_get_user_byte(addr, super, data, false, sz_word) << 8; SAVE_EXCEPTION; TRY(prb) { - res |= mmu_get_user_byte(addr + 1, super, data, sz_word); + res |= mmu_get_user_byte(addr + 1, super, data, false, sz_word); RESTORE_EXCEPTION; } CATCH(prb) { @@ -745,7 +845,7 @@ uae_u8 REGPARAM2 sfc_get_byte(uaecptr addr) bool super = (regs.sfc & 4) != 0; bool data = (regs.sfc & 3) != 2; - return mmu_get_user_byte(addr, super, data, sz_byte); + return mmu_get_user_byte(addr, super, data, false, sz_byte); } void REGPARAM2 dfc_put_long(uaecptr addr, uae_u32 val) @@ -839,13 +939,13 @@ void REGPARAM2 mmu_op_real(uae_u32 opcode, uae_u16 extra) if (opcode & 16) { #if MMUDEBUG > 1 - write_log(_T("pflusha(%u,%u)\n"), glob, regs.dfc); + write_log(_T("pflusha(%u,%u) PC=%08x\n"), glob, regs.dfc, m68k_getpc ()); #endif mmu_flush_atc_all(glob); } else { addr = m68k_areg(regs, regno); #if MMUDEBUG > 1 - write_log(_T("pflush(%u,%u,%x)\n"), glob, regs.dfc, addr); + write_log(_T("pflush(%u,%u,%x) PC=%08x\n"), glob, regs.dfc, addr, m68k_getpc ()); #endif mmu_flush_atc(addr, super, glob); } @@ -958,6 +1058,7 @@ void REGPARAM2 mmu_set_tc(uae_u16 tc) mmu_pagesize_8k = (tc & 0x4000) != 0; mmu_tagmask = mmu_pagesize_8k ? 0xFFFF0000 : 0xFFFF8000; mmu_pagemask = mmu_pagesize_8k ? 0x00001FFF : 0x00000FFF; + mmu_pagemaski = ~mmu_pagemask; regs.mmu_page_size = mmu_pagesize_8k ? 8192 : 4096; mmu_flush_atc_all(true); @@ -981,6 +1082,10 @@ void m68k_do_rte_mmu040 (uaecptr a7) // skip this word put_long_mmu040 (dst_a7 + 8, get_long_mmu040 (src_a7 + 8)); } + if (ssr & MMU_SSW_CM) { + mmu040_movem = 1; + mmu040_movem_ea = get_long_mmu040 (a7 + 8); + } } void flush_mmu040 (uaecptr addr, int n) @@ -1013,6 +1118,47 @@ void m68k_do_bsr_mmu060 (uaecptr oldpc, uae_s32 offset) m68k_incpci (offset); } +void uae_mmu_put_rmw (uaecptr addr, uae_u32 v, int size, int type) +{ + locked_rmw_cycle = true; + if (size == sz_byte) { + mmu_put_byte(addr, v, true, sz_byte); + } else if (size == sz_word) { + if (unlikely(is_unaligned(addr, 2))) { + mmu_put_word_unaligned(addr, v, true); + } else { + mmu_put_word(addr, v, true, sz_word); + } + } else { + if (unlikely(is_unaligned(addr, 4))) + mmu_put_long_unaligned(addr, v, true); + else + mmu_put_long(addr, v, true, sz_long); + } + locked_rmw_cycle = false; +} +uae_u32 uae_mmu_get_rmw (uaecptr addr, int size, int type) +{ + uae_u32 v; + locked_rmw_cycle = true; + if (size == sz_byte) { + v = mmu_get_user_byte(addr, regs.s != 0, true, true, sz_byte); + } else if (size == sz_word) { + if (unlikely(is_unaligned(addr, 2))) { + v = mmu_get_rmw_word_unaligned(addr); + } else { + v = mmu_get_user_word(addr, regs.s != 0, true, true, sz_word); + } + } else { + if (unlikely(is_unaligned(addr, 4))) + v = mmu_get_rmw_long_unaligned(addr); + else + v = mmu_get_user_long(addr, regs.s != 0, true, true, sz_long); + } + locked_rmw_cycle = false; + return v; +} + #ifndef __cplusplus jmp_buf __exbuf; int __exvalue; diff --git a/src/cpummu30.c b/src/cpummu30.c index cc0f87a..0c3bbf1 100644 --- a/src/cpummu30.c +++ b/src/cpummu30.c @@ -40,8 +40,19 @@ #define MMU030_ATC_DBG_MSG 0 #define MMU030_REG_DBG_MSG 0 +#define TT_FC_MASK 0x00000007 +#define TT_FC_BASE 0x00000070 +#define TT_RWM 0x00000100 +#define TT_RW 0x00000200 +#define TT_CI 0x00000400 +#define TT_ENABLE 0x00008000 + +#define TT_ADDR_MASK 0x00FF0000 +#define TT_ADDR_BASE 0xFF000000 + static int bBusErrorReadWrite; static int atcindextable[32]; +static int tt_enabled; int mmu030_idx; @@ -266,6 +277,7 @@ void mmu_op30_pmove (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra) if (!fd && !rw && !(preg==0x18)) { mmu030_flush_atc_all(); } + tt_enabled = (tt0_030 & TT_ENABLE) || (tt1_030 & TT_ENABLE); } void mmu_op30_ptest (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra) @@ -488,17 +500,6 @@ void mmu030_flush_atc_all(void) { * */ - -#define TT_FC_MASK 0x00000007 -#define TT_FC_BASE 0x00000070 -#define TT_RWM 0x00000100 -#define TT_RW 0x00000200 -#define TT_CI 0x00000400 -#define TT_ENABLE 0x00008000 - -#define TT_ADDR_MASK 0x00FF0000 -#define TT_ADDR_BASE 0xFF000000 - /* TT comparision results */ #define TT_NO_MATCH 0x1 #define TT_OK_MATCH 0x2 @@ -514,9 +515,11 @@ TT_info mmu030_decode_tt(uae_u32 TT) { ret.addr_base = TT & TT_ADDR_BASE; ret.addr_mask = ~(((TT&TT_ADDR_MASK)<<8)|0x00FFFFFF); +#if 0 if ((TT&TT_ENABLE) && !(TT&TT_RWM)) { write_log(_T("MMU Warning: Transparent translation of read-modify-write cycle is not correctly handled!\n")); } +#endif #if MMU030_REG_DBG_MSG /* enable or disable debugging messages */ write_log(_T("\n")); @@ -571,6 +574,27 @@ int mmu030_match_ttr(uaecptr addr, uae_u32 fc, bool write) return (tt0|tt1); } +int mmu030_match_ttr_access(uaecptr addr, uae_u32 fc, bool write) +{ + int tt0, tt1; + if (!tt_enabled) + return 0; + tt0 = mmu030_do_match_ttr(tt0_030, mmu030.transparent.tt0, addr, fc, write); + tt1 = mmu030_do_match_ttr(tt1_030, mmu030.transparent.tt1, addr, fc, write); + return (tt0|tt1) & TT_OK_MATCH; +} + +/* Read-Modify-Write */ +int mmu030_match_rmw_ttr_access(uaecptr addr, uae_u32 fc) +{ + int tt0, tt1; + + if (!tt_enabled) + return 0; + tt0 = mmu030_do_match_rmw_ttr(tt0_030, mmu030.transparent.tt0, addr, fc); + tt1 = mmu030_do_match_rmw_ttr(tt1_030, mmu030.transparent.tt1, addr, fc); + return (tt0|tt1) & TT_OK_MATCH; +} /* This function checks if an address matches a transparent * translation register */ @@ -604,6 +628,23 @@ int mmu030_do_match_ttr(uae_u32 tt, TT_info comp, uaecptr addr, uae_u32 fc, bool return TT_NO_MATCH; } +int mmu030_do_match_rmw_ttr(uae_u32 tt, TT_info comp, uaecptr addr, uae_u32 fc) +{ + if ((tt & TT_ENABLE) && (tt & TT_RWM)) { /* transparent translation enabled */ + + /* Compare actual function code with function code base using mask */ + if ((comp.fc_base&comp.fc_mask)==(fc&comp.fc_mask)) { + + /* Compare actual address with address base using mask */ + if ((comp.addr_base&comp.addr_mask)==(addr&comp.addr_mask)) { + + return TT_NO_READ; /* TODO: check this! */ + } + } + } + return TT_NO_MATCH; +} + /* Translation Control Register: @@ -1510,18 +1551,18 @@ uae_u32 mmu030_ptest_table_search(uaecptr logical_addr, uae_u32 fc, bool write, #define ATC030_PHYS_CI 0x04000000 #define ATC030_PHYS_BE 0x08000000 -void mmu030_page_fault(uaecptr addr, bool read, int size, uae_u32 fc) { +static void mmu030_page_fault(uaecptr addr, bool read, int flags, uae_u32 fc) { regs.mmu_fault_addr = addr; regs.mmu_ssw = (fc & 1) ? MMU030_SSW_DF | (MMU030_SSW_DF << 1) : (MMU030_SSW_FB | MMU030_SSW_RB); regs.mmu_ssw |= read ? MMU030_SSW_RW : 0; - regs.mmu_ssw |= size; + regs.mmu_ssw |= flags; regs.mmu_ssw |= fc; bBusErrorReadWrite = read; mm030_stageb_address = addr; -#if 1 + write_log(_T("MMU: page fault (logical addr=%08X SSW=%04x read=%d size=%d fc=%d pc=%08x)\n"), - addr, regs.mmu_ssw, read, (size & MMU030_SSW_SIZE_B) ? 1 : (size & MMU030_SSW_SIZE_W) ? 2 : 4, fc, regs.instruction_pc); -#endif + addr, regs.mmu_ssw, read, (flags & MMU030_SSW_SIZE_B) ? 1 : (flags & MMU030_SSW_SIZE_W) ? 2 : 4, fc, regs.instruction_pc); + THROW(2); } @@ -1537,7 +1578,7 @@ void mmu030_put_long_atc(uaecptr addr, uae_u32 val, int l, uae_u32 fc) { physical_addr += page_index; if (mmu030.atc[l].physical.bus_error || mmu030.atc[l].physical.write_protect) { - mmu030_page_fault(addr, 0, MMU030_SSW_SIZE_L, fc); + mmu030_page_fault(addr, false, MMU030_SSW_SIZE_L, fc); return; } @@ -1556,7 +1597,7 @@ void mmu030_put_word_atc(uaecptr addr, uae_u16 val, int l, uae_u32 fc) { physical_addr += page_index; if (mmu030.atc[l].physical.bus_error || mmu030.atc[l].physical.write_protect) { - mmu030_page_fault(addr, 0, MMU030_SSW_SIZE_W, fc); + mmu030_page_fault(addr, false, MMU030_SSW_SIZE_W, fc); return; } @@ -1575,7 +1616,7 @@ void mmu030_put_byte_atc(uaecptr addr, uae_u8 val, int l, uae_u32 fc) { physical_addr += page_index; if (mmu030.atc[l].physical.bus_error || mmu030.atc[l].physical.write_protect) { - mmu030_page_fault(addr, 0, MMU030_SSW_SIZE_B, fc); + mmu030_page_fault(addr, false, MMU030_SSW_SIZE_B, fc); return; } @@ -1594,7 +1635,7 @@ uae_u32 mmu030_get_long_atc(uaecptr addr, int l, uae_u32 fc) { physical_addr += page_index; if (mmu030.atc[l].physical.bus_error) { - mmu030_page_fault(addr, 1, MMU030_SSW_SIZE_L, fc); + mmu030_page_fault(addr, true, MMU030_SSW_SIZE_L, fc); return 0; } @@ -1613,7 +1654,7 @@ uae_u16 mmu030_get_word_atc(uaecptr addr, int l, uae_u32 fc) { physical_addr += page_index; if (mmu030.atc[l].physical.bus_error) { - mmu030_page_fault(addr, 1, MMU030_SSW_SIZE_W, fc); + mmu030_page_fault(addr, true, MMU030_SSW_SIZE_W, fc); return 0; } @@ -1632,13 +1673,60 @@ uae_u8 mmu030_get_byte_atc(uaecptr addr, int l, uae_u32 fc) { physical_addr += page_index; if (mmu030.atc[l].physical.bus_error) { - mmu030_page_fault(addr, 1, MMU030_SSW_SIZE_B, fc); + mmu030_page_fault(addr, true, MMU030_SSW_SIZE_B, fc); return 0; } return phys_get_byte(physical_addr); } +/* Generic versions of above */ +void mmu030_put_atc_generic(uaecptr addr, uae_u32 val, int l, uae_u32 fc, int size, int flags) { + uae_u32 page_index = addr & mmu030.translation.page.mask; + uae_u32 addr_mask = mmu030.translation.page.imask; + + uae_u32 physical_addr = mmu030.atc[l].physical.addr & addr_mask; +#if MMU030_ATC_DBG_MSG + write_log(_T("ATC match(%i): page addr = %08X, index = %08X (bput %02X)\n"), + l, physical_addr, page_index, val); +#endif + physical_addr += page_index; + + if (mmu030.atc[l].physical.write_protect || mmu030.atc[l].physical.bus_error) { + mmu030_page_fault(addr, false, flags, fc); + return; + } + if (size == sz_byte) + phys_put_byte(physical_addr, val); + else if (size == sz_word) + phys_put_word(physical_addr, val); + else + phys_put_long(physical_addr, val); + +} +uae_u32 mmu030_get_atc_generic(uaecptr addr, int l, uae_u32 fc, int size, int flags, bool checkwrite) { + uae_u32 page_index = addr & mmu030.translation.page.mask; + uae_u32 addr_mask = mmu030.translation.page.imask; + + uae_u32 physical_addr = mmu030.atc[l].physical.addr & addr_mask; +#if MMU030_ATC_DBG_MSG + write_log(_T("ATC match(%i): page addr = %08X, index = %08X (bget %02X)\n"), l, + physical_addr, page_index, phys_get_byte(physical_addr+page_index)); +#endif + physical_addr += page_index; + + if (mmu030.atc[l].physical.bus_error || (checkwrite && mmu030.atc[l].physical.write_protect)) { + mmu030_page_fault(addr, true, flags, fc); + return 0; + } + if (size == sz_byte) + return phys_get_byte(physical_addr); + else if (size == sz_word) + return phys_get_word(physical_addr); + return phys_get_long(physical_addr); +} + + /* This function checks if a certain logical address is in the ATC * by comparing the logical address and function code to the values * stored in the ATC entries. If a matching entry is found it sets @@ -1704,10 +1792,10 @@ void mmu030_atc_handle_history_bit(int entry_num) { * create a new ATC entry and then look up the physical address. */ -void mmu030_put_long(uaecptr addr, uae_u32 val, uae_u32 fc, int size) { +void mmu030_put_long(uaecptr addr, uae_u32 val, uae_u32 fc) { // addr,super,write - if ((!mmu030.enabled) || (mmu030_match_ttr(addr,fc,true)&TT_OK_MATCH) || (fc==7)) { + if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr,fc,true)) || (fc==7)) { phys_put_long(addr,val); return; } @@ -1722,10 +1810,10 @@ void mmu030_put_long(uaecptr addr, uae_u32 val, uae_u32 fc, int size) { } } -void mmu030_put_word(uaecptr addr, uae_u16 val, uae_u32 fc, int size) { +void mmu030_put_word(uaecptr addr, uae_u16 val, uae_u32 fc) { // addr,super,write - if ((!mmu030.enabled) || (mmu030_match_ttr(addr,fc,true)&TT_OK_MATCH) || (fc==7)) { + if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr,fc,true)) || (fc==7)) { phys_put_word(addr,val); return; } @@ -1740,10 +1828,10 @@ void mmu030_put_word(uaecptr addr, uae_u16 val, uae_u32 fc, int size) { } } -void mmu030_put_byte(uaecptr addr, uae_u8 val, uae_u32 fc, int size) { +void mmu030_put_byte(uaecptr addr, uae_u8 val, uae_u32 fc) { // addr,super,write - if ((!mmu030.enabled) || (mmu030_match_ttr(addr, fc, true)&TT_OK_MATCH) || (fc==7)) { + if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr, fc, true)) || (fc==7)) { phys_put_byte(addr,val); return; } @@ -1758,10 +1846,10 @@ void mmu030_put_byte(uaecptr addr, uae_u8 val, uae_u32 fc, int size) { } } -uae_u32 mmu030_get_long(uaecptr addr, uae_u32 fc, int size) { +uae_u32 mmu030_get_long(uaecptr addr, uae_u32 fc) { // addr,super,write - if ((!mmu030.enabled) || (mmu030_match_ttr(addr,fc,false)&TT_OK_MATCH) || (fc==7)) { + if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr,fc,false)) || (fc==7)) { return phys_get_long(addr); } @@ -1775,10 +1863,10 @@ uae_u32 mmu030_get_long(uaecptr addr, uae_u32 fc, int size) { } } -uae_u16 mmu030_get_word(uaecptr addr, uae_u32 fc, int size) { +uae_u16 mmu030_get_word(uaecptr addr, uae_u32 fc) { // addr,super,write - if ((!mmu030.enabled) || (mmu030_match_ttr(addr,fc,false)&TT_OK_MATCH) || (fc==7)) { + if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr,fc,false)) || (fc==7)) { return phys_get_word(addr); } @@ -1792,10 +1880,10 @@ uae_u16 mmu030_get_word(uaecptr addr, uae_u32 fc, int size) { } } -uae_u8 mmu030_get_byte(uaecptr addr, uae_u32 fc, int size) { +uae_u8 mmu030_get_byte(uaecptr addr, uae_u32 fc) { // addr,super,write - if ((!mmu030.enabled) || (mmu030_match_ttr(addr,fc,false)&TT_OK_MATCH) || (fc==7)) { + if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr,fc,false)) || (fc==7)) { return phys_get_byte(addr); } @@ -1810,14 +1898,128 @@ uae_u8 mmu030_get_byte(uaecptr addr, uae_u32 fc, int size) { } -uae_u16 REGPARAM2 mmu030_get_word_unaligned(uaecptr addr, uae_u32 fc) +/* Not commonly used access function */ +void mmu030_put_generic(uaecptr addr, uae_u32 val, uae_u32 fc, int size, int accesssize, int flags) { + + // addr,super,write + if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr, fc, true)) || (fc==7)) { + if (size == sz_byte) + phys_put_byte(addr, val); + else if (size == sz_word) + phys_put_word(addr, val); + else + phys_put_long(addr, val); + return; + } + + int atc_line_num = mmu030_logical_is_in_atc(addr, fc, true); + if (atc_line_num>=0) { + mmu030_put_atc_generic(addr, val, atc_line_num, fc, size, flags); + } else { + mmu030_table_search(addr, fc, true, 0); + atc_line_num = mmu030_logical_is_in_atc(addr, fc, true); + if (accesssize == sz_byte) + flags |= MMU030_SSW_SIZE_B; + else if (accesssize == sz_word) + flags |= MMU030_SSW_SIZE_W; + mmu030_put_atc_generic(addr, val, atc_line_num, fc, size, flags); + } +} +static uae_u32 mmu030_get_generic_rmw(uaecptr addr, uae_u32 fc, int size, int accesssize, int flags) { + + // addr,super,write + if ((!mmu030.enabled) || (mmu030_match_rmw_ttr_access(addr,fc)) || (fc==7)) { + if (size == sz_byte) + return phys_get_byte(addr); + else if (size == sz_word) + return phys_get_word(addr); + return phys_get_long(addr); + } + + int atc_line_num = mmu030_logical_is_in_atc(addr, fc, true); + if (atc_line_num>=0) { + return mmu030_get_atc_generic(addr, atc_line_num, fc, size, flags, true); + } else { + mmu030_table_search(addr, fc, true, 0); + atc_line_num = mmu030_logical_is_in_atc(addr, fc, true); + if (accesssize == sz_byte) + flags |= MMU030_SSW_SIZE_B; + else if (accesssize == sz_word) + flags |= MMU030_SSW_SIZE_W; + return mmu030_get_atc_generic(addr, atc_line_num, fc, size, flags, true); + } +} +uae_u32 mmu030_get_generic(uaecptr addr, uae_u32 fc, int size, int accesssize, int flags) { + if (flags & MMU030_SSW_RM) { + return mmu030_get_generic_rmw(addr, fc, size, accesssize, flags); + } + // addr,super,write + if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr,fc,false)) || (fc==7)) { + if (size == sz_byte) + return phys_get_byte(addr); + else if (size == sz_word) + return phys_get_word(addr); + return phys_get_long(addr); + } + + int atc_line_num = mmu030_logical_is_in_atc(addr, fc, false); + if (atc_line_num>=0) { + return mmu030_get_atc_generic(addr, atc_line_num, fc, size, flags, false); + } else { + mmu030_table_search(addr, fc, false, 0); + atc_line_num = mmu030_logical_is_in_atc(addr, fc, false); + if (accesssize == sz_byte) + flags |= MMU030_SSW_SIZE_B; + else if (accesssize == sz_word) + flags |= MMU030_SSW_SIZE_W; + return mmu030_get_atc_generic(addr, atc_line_num, fc, size, flags, false); + } +} + + +/* RMW is rarely used */ +uae_u32 uae_mmu030_get_rmw(uaecptr addr, int size) +{ + uae_u32 fc = (regs.s ? 4 : 0) | 1; + if (size == sz_byte) { + return mmu030_get_generic(addr, fc, size, size, MMU030_SSW_RM); + } else if (size == sz_word) { + if (unlikely(is_unaligned(addr, 2))) + return mmu030_get_word_unaligned(addr, fc, MMU030_SSW_RM); + else + return mmu030_get_generic(addr, fc, size, size, MMU030_SSW_RM); + } else { + if (unlikely(is_unaligned(addr, 4))) + return mmu030_get_long_unaligned(addr, fc, MMU030_SSW_RM); + else + return mmu030_get_generic(addr, fc, size, size, MMU030_SSW_RM); + } +} +void uae_mmu030_put_rmw(uaecptr addr, uae_u32 val, int size) +{ + uae_u32 fc = (regs.s ? 4 : 0) | 1; + if (size == sz_byte) { + mmu030_put_generic(addr, val, fc, size, size, MMU030_SSW_RM); + } else if (size == sz_word) { + if (unlikely(is_unaligned(addr, 2))) + mmu030_put_word_unaligned(addr, val, fc, MMU030_SSW_RM); + else + mmu030_put_generic(addr, val, fc, size, size, MMU030_SSW_RM); + } else { + if (unlikely(is_unaligned(addr, 4))) + mmu030_put_long_unaligned(addr, val, fc, MMU030_SSW_RM); + else + mmu030_put_generic(addr, val, fc, size, size, MMU030_SSW_RM); + } +} +uae_u16 REGPARAM2 mmu030_get_word_unaligned(uaecptr addr, uae_u32 fc, int flags) { uae_u16 res; - res = (uae_u16)mmu030_get_byte(addr, fc, sz_word) << 8; + res = (uae_u16)mmu030_get_generic(addr, fc, sz_byte, sz_word, flags) << 8; SAVE_EXCEPTION; TRY(prb) { - res |= mmu030_get_byte(addr + 1, fc, sz_word); + res |= mmu030_get_generic(addr + 1, fc, sz_byte, sz_word, flags); RESTORE_EXCEPTION; } CATCH(prb) { @@ -1827,15 +2029,15 @@ uae_u16 REGPARAM2 mmu030_get_word_unaligned(uaecptr addr, uae_u32 fc) return res; } -uae_u32 REGPARAM2 mmu030_get_long_unaligned(uaecptr addr, uae_u32 fc) +uae_u32 REGPARAM2 mmu030_get_long_unaligned(uaecptr addr, uae_u32 fc, int flags) { uae_u32 res; if (likely(!(addr & 1))) { - res = (uae_u32)mmu030_get_word(addr, fc, sz_long) << 16; + res = (uae_u32)mmu030_get_generic(addr, fc, sz_word, sz_long, flags) << 16; SAVE_EXCEPTION; TRY(prb) { - res |= mmu030_get_word(addr + 2, fc, sz_long); + res |= mmu030_get_generic(addr + 2, fc, sz_word, sz_long, flags); RESTORE_EXCEPTION; } CATCH(prb) { @@ -1843,12 +2045,12 @@ uae_u32 REGPARAM2 mmu030_get_long_unaligned(uaecptr addr, uae_u32 fc) THROW_AGAIN(prb); } ENDTRY } else { - res = (uae_u32)mmu030_get_byte(addr, fc, sz_long) << 8; + res = (uae_u32)mmu030_get_generic(addr, fc, sz_byte, sz_long, flags) << 8; SAVE_EXCEPTION; TRY(prb) { - res = (res | mmu030_get_byte(addr + 1, fc, sz_long)) << 8; - res = (res | mmu030_get_byte(addr + 2, fc, sz_long)) << 8; - res |= mmu030_get_byte(addr + 3, fc, sz_long); + res = (res | mmu030_get_generic(addr + 1, fc, sz_byte, sz_long, flags)) << 8; + res = (res | mmu030_get_generic(addr + 2, fc, sz_byte, sz_long, flags)) << 8; + res |= mmu030_get_generic(addr + 3, fc, sz_byte, sz_long, flags); RESTORE_EXCEPTION; } CATCH(prb) { @@ -1860,18 +2062,18 @@ uae_u32 REGPARAM2 mmu030_get_long_unaligned(uaecptr addr, uae_u32 fc) } -void REGPARAM2 mmu030_put_long_unaligned(uaecptr addr, uae_u32 val, uae_u32 fc) +void REGPARAM2 mmu030_put_long_unaligned(uaecptr addr, uae_u32 val, uae_u32 fc, int flags) { SAVE_EXCEPTION; TRY(prb) { if (likely(!(addr & 1))) { - mmu030_put_word(addr, val >> 16, fc, sz_long); - mmu030_put_word(addr + 2, val, fc, sz_long); + mmu030_put_generic(addr, val >> 16, fc, sz_word, sz_long, flags); + mmu030_put_generic(addr + 2, val, fc, sz_word, sz_long, flags); } else { - mmu030_put_byte(addr, val >> 24, fc, sz_long); - mmu030_put_byte(addr + 1, val >> 16, fc, sz_long); - mmu030_put_byte(addr + 2, val >> 8, fc, sz_long); - mmu030_put_byte(addr + 3, val, fc, sz_long); + mmu030_put_generic(addr, val >> 24, fc, sz_byte, sz_long, flags); + mmu030_put_generic(addr + 1, val >> 16, fc, sz_byte, sz_long, flags); + mmu030_put_generic(addr + 2, val >> 8, fc, sz_byte, sz_long, flags); + mmu030_put_generic(addr + 3, val, fc, sz_byte, sz_long, flags); } RESTORE_EXCEPTION; } @@ -1882,12 +2084,12 @@ void REGPARAM2 mmu030_put_long_unaligned(uaecptr addr, uae_u32 val, uae_u32 fc) } ENDTRY } -void REGPARAM2 mmu030_put_word_unaligned(uaecptr addr, uae_u16 val, uae_u32 fc) +void REGPARAM2 mmu030_put_word_unaligned(uaecptr addr, uae_u16 val, uae_u32 fc, int flags) { SAVE_EXCEPTION; TRY(prb) { - mmu030_put_byte(addr, val >> 8, fc, sz_word); - mmu030_put_byte(addr + 1, val, fc, sz_word); + mmu030_put_generic(addr, val >> 8, fc, sz_byte, sz_word, flags); + mmu030_put_generic(addr + 1, val, fc, sz_byte, sz_word, flags); RESTORE_EXCEPTION; } CATCH(prb) { @@ -1906,7 +2108,7 @@ static uaecptr mmu030_get_addr_atc(uaecptr addr, int l, uae_u32 fc, bool write) uae_u32 physical_addr = mmu030.atc[l].physical.addr&addr_mask; physical_addr += page_index; - if (mmu030.atc[l].physical.bus_error) { + if (mmu030.atc[l].physical.bus_error || (write && mmu030.atc[l].physical.write_protect)) { mmu030_page_fault(addr, write == 0, MMU030_SSW_SIZE_B, fc); return 0; } @@ -1927,7 +2129,6 @@ uaecptr mmu030_translate(uaecptr addr, bool super, bool data, bool write) mmu030_table_search(addr, fc, false, 0); return mmu030_get_addr_atc(addr, mmu030_logical_is_in_atc(addr,fc,write), fc, write); } - } /* MMU Reset */ @@ -1965,6 +2166,9 @@ void m68k_do_rte_mmu030 (uaecptr a7) mmu030_disp_store[0] = get_long_mmu030 (a7 + 0x1c); mmu030_disp_store[1] = get_long_mmu030 (a7 + 0x1c + 4); + // Rerun "mmu030_opcode" using restored state. + mmu030_retry = true; + if (frame == 0xb) { uae_u16 idxsize = get_word_mmu030 (a7 + 0x36); for (int i = 0; i < idxsize + 1; i++) { @@ -1975,7 +2179,11 @@ void m68k_do_rte_mmu030 (uaecptr a7) // did we have data fault but DF bit cleared? if (ssw & (MMU030_SSW_DF << 1) && !(ssw & MMU030_SSW_DF)) { // DF not set: mark access as done - if (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1) { + if (ssw & MMU030_SSW_RM) { + // Read-Modify-Write: whole instruction is considered done + write_log (_T("Read-Modify-Write and DF bit cleared! PC=%08x\n"), regs.instruction_pc); + mmu030_retry = false; + } else if (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1) { // if movem, skip next move mmu030_state[1] |= MMU030_STATEFLAG1_MOVEM2; } else { @@ -2003,8 +2211,6 @@ void m68k_do_rte_mmu030 (uaecptr a7) } else { m68k_areg (regs, 7) += 32; } - // Rerun "mmu030_opcode" using restored state. - mmu030_retry = true; } void flush_mmu030 (uaecptr addr, int n) diff --git a/src/debug.c b/src/debug.c index 58c6c02..6f2c5e3 100644 --- a/src/debug.c +++ b/src/debug.c @@ -194,9 +194,9 @@ uae_u32 get_byte_debug (uaecptr addr) regs.s = (debug_mmu_mode & 4) != 0; TRY(p) { if (currprefs.mmu_model == 68030) { - v = mmu030_get_byte (addr, debug_mmu_mode, sz_byte); + v = mmu030_get_byte (addr, debug_mmu_mode); } else { - v = mmu_get_byte (addr, (debug_mmu_mode & 1) ? true : false, sz_byte); + v = mmu_get_user_byte (addr, regs.s != 0, (debug_mmu_mode & 1) ? true : false, false, sz_byte); } } CATCH(p) { } @@ -214,9 +214,9 @@ uae_u32 get_word_debug (uaecptr addr) regs.s = (debug_mmu_mode & 4) != 0; TRY(p) { if (currprefs.mmu_model == 68030) { - v = mmu030_get_word (addr, debug_mmu_mode, sz_word); + v = mmu030_get_word (addr, debug_mmu_mode); } else { - v = mmu_get_word (addr, (debug_mmu_mode & 1) ? true : false, sz_word); + v = mmu_get_user_word (addr, regs.s != 0, (debug_mmu_mode & 1) ? true : false, false, sz_word); } } CATCH(p) { } @@ -234,9 +234,9 @@ uae_u32 get_long_debug (uaecptr addr) regs.s = (debug_mmu_mode & 4) != 0; TRY(p) { if (currprefs.mmu_model == 68030) { - v = mmu030_get_long (addr, debug_mmu_mode, sz_long); + v = mmu030_get_long (addr, debug_mmu_mode); } else { - v = mmu_get_long (addr, (debug_mmu_mode & 1) ? true : false, sz_long); + v = mmu_get_user_long (addr, regs.s != 0, (debug_mmu_mode & 1) ? true : false, false, sz_long); } } CATCH(p) { } @@ -2805,7 +2805,7 @@ static void show_exec_lists (TCHAR t) get_long_debug (doslist + 32) << 2, get_long_debug (doslist + 36)); } xfree (name); - doslist = get_long (doslist) << 2; + doslist = get_long_debug (doslist) << 2; } } else { console_out_f (_T("can't find dos.library\n")); diff --git a/src/disk.c b/src/disk.c index def86e7..e5852a7 100644 --- a/src/disk.c +++ b/src/disk.c @@ -264,30 +264,30 @@ static int dirhash (const uae_char *name) static void disk_date (uae_u8 *p) { - time_t t; - struct tm *today; - int year, days, minutes, ticks; - TCHAR tmp[10]; + static int pdays, pmins, pticks; + int days, mins, ticks; + struct timeval tv; + struct mytimeval mtv; - time (&t); - today = localtime( &t ); - _tcsftime (tmp, sizeof tmp / sizeof (TCHAR), _T("%Y"), today); - year = _tstoi (tmp); - _tcsftime (tmp, sizeof tmp / sizeof (TCHAR), _T("%j"), today); - days = _tstoi (tmp) - 1; - _tcsftime (tmp, sizeof tmp / sizeof (TCHAR), _T("%H"), today); - minutes = _tstoi (tmp) * 60; - _tcsftime (tmp, sizeof tmp / sizeof (TCHAR), _T("%M"), today); - minutes += _tstoi (tmp); - _tcsftime (tmp, sizeof tmp / sizeof (TCHAR), _T("%S"), today); - ticks = _tstoi (tmp) * 50; - while (year > 1978) { - if ( !(year % 100) ? !(year % 400) : !(year % 4) ) days++; - days += 365; - year--; + gettimeofday (&tv, NULL); + tv.tv_sec -= timezone; + mtv.tv_sec = tv.tv_sec; + mtv.tv_usec = tv.tv_usec; + timeval_to_amiga (&mtv, &days, &mins, &ticks); + if (days == pdays && mins == pmins && ticks == pticks) { + ticks++; + if (ticks >= 50 * 60) { + ticks = 0; + mins++; + if (mins >= 24 * 60) + days++; } + } + pdays = days; + pmins = mins; + pticks = ticks; p[0] = days >> 24; p[1] = days >> 16; p[2] = days >> 8; p[3] = days >> 0; - p[4] = minutes >> 24; p[5] = minutes >> 16; p[6] = minutes >> 8; p[7] = minutes >> 0; + p[4] = mins >> 24; p[5] = mins >> 16; p[6] = mins >> 8; p[7] = mins >> 0; p[8] = ticks >> 24; p[9] = ticks >> 16; p[10] = ticks >> 8; p[11] = ticks >> 0; } @@ -299,27 +299,43 @@ static void createbootblock (uae_u8 *sector, int bootable) memcpy (sector, bootblock_ofs, sizeof (bootblock_ofs)); } -static void createrootblock (uae_u8 *sector, char *disk_name) +static void createrootblock (uae_u8 *sector, const char *disk_name) { + char *dn = ua (disk_name); + char *dn2 = dn; + dn2[30] = 0; + if (dn2[0] == 0) + dn2 = "empty"; memset (sector, 0, FS_FLOPPY_BLOCKSIZE); sector[0+3] = 2; sector[12+3] = 0x48; sector[312] = sector[313] = sector[314] = sector[315] = (uae_u8)0xff; sector[316+2] = 881 >> 8; sector[316+3] = 881 & 255; - sector[432] = strlen (disk_name); - strcpy ((char*)sector + 433, disk_name); + sector[432] = strlen (dn2); + strcpy ((char*)sector + 433, dn2); sector[508 + 3] = 1; disk_date (sector + 420); memcpy (sector + 472, sector + 420, 3 * 4); memcpy (sector + 484, sector + 420, 3 * 4); + xfree (dn); } -static int getblock (uae_u8 *bitmap) +static int getblock (uae_u8 *bitmap, int *prev) { - int i = 0; + int i = *prev; while (bitmap[i] != 0xff) { if (bitmap[i] == 0) { bitmap[i] = 1; + *prev = i; + return i; + } + i++; + } + i = 0; + while (bitmap[i] != 0xff) { + if (bitmap[i] == 0) { + bitmap[i] = 1; + *prev = i; return i; } i++; @@ -335,9 +351,9 @@ static void pl (uae_u8 *sector, int offset, uae_u32 v) sector[offset + 3] = v >> 0; } -static int createdirheaderblock (uae_u8 *sector, int parent, const char *filename, uae_u8 *bitmap) +static int createdirheaderblock (uae_u8 *sector, int parent, const char *filename, uae_u8 *bitmap, int *prevblock) { - int block = getblock (bitmap); + int block = getblock (bitmap, prevblock); memset (sector, 0, FS_FLOPPY_BLOCKSIZE); pl (sector, 0, 2); @@ -350,12 +366,12 @@ static int createdirheaderblock (uae_u8 *sector, int parent, const char *filenam return block; } -static int createfileheaderblock (struct zfile *z,uae_u8 *sector, int parent, const char *filename, struct zfile *src, uae_u8 *bitmap) +static int createfileheaderblock (struct zfile *z,uae_u8 *sector, int parent, const char *filename, struct zfile *src, uae_u8 *bitmap, int *prevblock) { uae_u8 sector2[FS_FLOPPY_BLOCKSIZE]; uae_u8 sector3[FS_FLOPPY_BLOCKSIZE]; - int block = getblock (bitmap); - int datablock = getblock (bitmap); + int block = getblock (bitmap, prevblock); + int datablock = getblock (bitmap, prevblock); int datasec = 1; int extensions; int extensionblock, extensioncounter, headerextension = 1; @@ -385,7 +401,7 @@ static int createfileheaderblock (struct zfile *z,uae_u8 *sector, int parent, co int extensionblock2 = extensionblock; if (extensioncounter == FS_EXTENSION_BLOCKS) { extensioncounter = 0; - extensionblock = getblock (bitmap); + extensionblock = getblock (bitmap, prevblock); if (datasec > FS_EXTENSION_BLOCKS + 1) { pl (sector3, 8, FS_EXTENSION_BLOCKS); pl (sector3, FS_FLOPPY_BLOCKSIZE - 8, extensionblock); @@ -408,7 +424,7 @@ static int createfileheaderblock (struct zfile *z,uae_u8 *sector, int parent, co zfile_fread (sector2 + 24, size > FS_OFS_DATABLOCKSIZE ? FS_OFS_DATABLOCKSIZE : size, 1, src); size -= FS_OFS_DATABLOCKSIZE; datablock = 0; - if (size > 0) datablock = getblock (bitmap); + if (size > 0) datablock = getblock (bitmap, prevblock); pl (sector2, 16, datablock); disk_checksum(sector2, sector2 + 20); writeimageblock (z, sector2, datablock2 * FS_FLOPPY_BLOCKSIZE); @@ -430,15 +446,25 @@ static int createfileheaderblock (struct zfile *z,uae_u8 *sector, int parent, co static void createbitmapblock (uae_u8 *sector, uae_u8 *bitmap) { - uae_u8 mask; int i, j; memset (sector, 0, FS_FLOPPY_BLOCKSIZE); - for (i = FS_FLOPPY_RESERVED; i < FS_FLOPPY_TOTALBLOCKS; i += 8) { - mask = 0; - for (j = 0; j < 8; j++) { - if (bitmap[i + j]) mask |= 1 << j; + i = 0; + for (;;) { + uae_u32 mask = 0; + for (j = 0; j < 32; j++) { + if (bitmap[2 + i * 32 + j] == 0xff) + break; + if (!bitmap[2 + i * 32 + j]) + mask |= 1 << j; } - sector[4 + i / 8] = mask; + sector[4 + i * 4 + 0] = mask >> 24; + sector[4 + i * 4 + 1] = mask >> 16; + sector[4 + i * 4 + 2] = mask >> 8; + sector[4 + i * 4 + 3] = mask >> 0; + if (bitmap[2 + i * 32 + j] == 0xff) + break; + i++; + } disk_checksum(sector, sector + 0); } @@ -457,6 +483,7 @@ static int createimagefromexe (struct zfile *src, struct zfile *dst) char *fname2 = "startup-sequence"; char *dirname1 = "s"; struct zfile *ss; + int prevblock; memset (bitmap, 0, sizeof (bitmap)); zfile_fseek (src, 0, SEEK_END); @@ -472,19 +499,21 @@ static int createimagefromexe (struct zfile *src, struct zfile *dst) bitmap[881] = 1; bitmap[0] = 1; bitmap[1] = 1; + bitmap[1760] = -1; + prevblock = 880; - dblock1 = createdirheaderblock (sector2, 880, dirname1, bitmap); + dblock1 = createdirheaderblock (sector2, 880, dirname1, bitmap, &prevblock); ss = zfile_fopen_empty (src, fname1b, strlen (fname1)); zfile_fwrite (fname1, strlen(fname1), 1, ss); - fblock1 = createfileheaderblock (dst, sector1, dblock1, fname2, ss, bitmap); + fblock1 = createfileheaderblock (dst, sector1, dblock1, fname2, ss, bitmap, &prevblock); zfile_fclose (ss); pl (sector2, 24 + dirhash (fname2) * 4, fblock1); disk_checksum(sector2, sector2 + 20); writeimageblock (dst, sector2, dblock1 * FS_FLOPPY_BLOCKSIZE); - fblock1 = createfileheaderblock (dst, sector1, 880, fname1, src, bitmap); + fblock1 = createfileheaderblock (dst, sector1, 880, fname1, src, bitmap, &prevblock); - createrootblock (sector1, "empty"); + createrootblock (sector1, zfile_getfilename (src)); pl (sector1, 24 + dirhash (fname1) * 4, fblock1); pl (sector1, 24 + dirhash (dirname1) * 4, dblock1); disk_checksum(sector1, sector1 + 20); @@ -499,6 +528,11 @@ static int createimagefromexe (struct zfile *src, struct zfile *dst) return 1; } +static bool isfloppysound (drive *drv) +{ + return drv->useturbo == 0; +} + static int get_floppy_speed (void) { int m = currprefs.floppy_speed; @@ -665,12 +699,12 @@ static void reset_drive (int num) } /* code for track display */ -static void update_drive_gui (int num) +static void update_drive_gui (int num, bool force) { drive *drv = floppy + num; bool writ = dskdmaen == DSKDMA_WRITE && drv->state && !((selected | disabled) & (1 << num)); - if (drv->state == gui_data.drive_motor[num] + if (!force && drv->state == gui_data.drive_motor[num] && drv->cyl == gui_data.drive_track[num] && side == gui_data.drive_side && drv->crc32 == gui_data.crc32[num] @@ -1153,9 +1187,10 @@ static int drive_insert (drive * drv, struct uae_prefs *p, int dnum, const TCHAR drv->mfmpos %= drv->tracklen; drv->prevtracklen = 0; #ifdef DRIVESOUND - driveclick_insert (drv - floppy, 0); + if (isfloppysound (drv)) + driveclick_insert (drv - floppy, 0); #endif - update_drive_gui (drv - floppy); + update_drive_gui (drv - floppy, false); return 1; } @@ -1218,7 +1253,8 @@ static void drive_step (drive * drv, int step_direction) if (drv->cyl) { drv->cyl--; #ifdef DRIVESOUND - driveclick_click (drv - floppy, drv->cyl); + if (isfloppysound (drv)) + driveclick_click (drv - floppy, drv->cyl); #endif } /* else @@ -1237,7 +1273,8 @@ static void drive_step (drive * drv, int step_direction) if (drv->cyl >= maxtrack) write_log (_T("program tried to step over track %d\n"), maxtrack); #ifdef DRIVESOUND - driveclick_click (drv - floppy, drv->cyl); + if (isfloppysound (drv)) + driveclick_click (drv - floppy, drv->cyl); #endif } rand_shifter (); @@ -1279,7 +1316,8 @@ static void drive_motor (drive * drv, bool off) drv->dskready_up_time = DSKREADY_UP_TIME; rand_shifter (); #ifdef DRIVESOUND - driveclick_motor (drv - floppy, drv->dskready_down_time == 0 ? 2 : 1); + if (isfloppysound (drv)) + driveclick_motor (drv - floppy, drv->dskready_down_time == 0 ? 2 : 1); #endif if (disk_debug_logging > 1) write_log (_T(" ->motor on")); @@ -2053,7 +2091,6 @@ static int drive_write_ext2 (uae_u16 *bigmfmbuf, struct zfile *diskfile, trackid } static void drive_write_data (drive * drv); -bool disk_creatediskfile (const TCHAR *name, int type, drive_type adftype, const TCHAR *disk_name, bool ffs, bool bootable, struct zfile *copyfrom); static bool convert_adf_to_ext2 (drive *drv, int mode) { @@ -2162,7 +2199,8 @@ static void drive_write_data (drive * drv) static void drive_eject (drive * drv) { #ifdef DRIVESOUND - driveclick_insert (drv - floppy, 1); + if (isfloppysound (drv)) + driveclick_insert (drv - floppy, 1); #endif gui_disk_image_change (drv - floppy, NULL, drv->wrprot); drive_image_free (drv); @@ -2321,7 +2359,7 @@ bool disk_creatediskfile (const TCHAR *name, int type, drive_type adftype, const if (copyfrom) zfile_fseek (copyfrom, pos, SEEK_SET); if (f) - DISK_history_add (name, -1, HISTORY_FLOPPY, 1); + DISK_history_add (name, -1, HISTORY_FLOPPY, true); return ok; } @@ -2415,7 +2453,7 @@ void disk_eject (int num) drive_eject (floppy + num); *currprefs.floppyslots[num].df = *changed_prefs.floppyslots[num].df = 0; floppy[num].newname[0] = 0; - update_drive_gui (num); + update_drive_gui (num, true); } int DISK_history_add (const TCHAR *name, int idx, int type, int donotcheck) @@ -2555,7 +2593,7 @@ void DISK_vsync (void) drive_insert (drv, &currprefs, i, drv->newname, false); if (disk_debug_logging > 0) write_log (_T("delayed insert, drive %d, image '%s'\n"), i, drv->newname); - update_drive_gui (i); + update_drive_gui (i, false); } } } @@ -2675,7 +2713,7 @@ void DISK_select (uae_u8 data) for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) { floppy[dr].state = (!(selected & (1 << dr))) | !floppy[dr].motoroff; - update_drive_gui (dr); + update_drive_gui (dr, false); } prev_data = data; if (disk_debug_logging > 1) @@ -3402,7 +3440,7 @@ void DSKLEN (uae_u16 v, int hpos) } for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) - update_drive_gui (dr); + update_drive_gui (dr, false); /* Try to make floppy access from Kickstart faster. */ if (dskdmaen != DSKDMA_READ && dskdmaen != DSKDMA_WRITE) @@ -3759,8 +3797,10 @@ void restore_disk_finish (void) { int cnt = 0; for (int i = 0; i < MAX_FLOPPY_DRIVES; i++) { - if (currprefs.floppyslots[i].dfxtype >= 0) + if (currprefs.floppyslots[i].dfxtype >= 0) { + update_drive_gui (i, true); cnt++; + } } currprefs.nr_floppies = changed_prefs.nr_floppies = cnt; DISK_check_change (); diff --git a/src/diskutil.c b/src/diskutil.c index 01fa8bc..47ba93a 100644 --- a/src/diskutil.c +++ b/src/diskutil.c @@ -1,5 +1,6 @@ #include "sysconfig.h" #include "sysdeps.h" + #include "crc32.h" #include "diskutil.h" diff --git a/src/expansion.c b/src/expansion.c index b437b06..501a080 100644 --- a/src/expansion.c +++ b/src/expansion.c @@ -955,7 +955,7 @@ static void expamem_map_fastcard (void) static void expamem_init_fastcard (void) { uae_u16 mid = (currprefs.cs_a2091 || currprefs.uae_hide) ? commodore : uae_id; - uae_u8 pid = (currprefs.cs_a2091 || currprefs.uae_hide) ? commodore_a2091_ram : 1; + uae_u8 pid = (currprefs.cs_a2091 || currprefs.uae_hide) ? commodore_a2091_ram : (currprefs.maprom ? 1 : 81); expamem_init_clear (); if (allocated_fastmem == 0x100000) diff --git a/src/filesys.c b/src/filesys.c index d047dd3..836d6de 100644 --- a/src/filesys.c +++ b/src/filesys.c @@ -299,9 +299,10 @@ int get_filesys_unitconfig (struct uae_prefs *p, int index, struct mountedinfo * memset (mi, 0, sizeof (struct mountedinfo)); memset (&uitmp, 0, sizeof uitmp); + _tcscpy (mi->rootdir, uci->ci.rootdir); if (!ui) { ui = &uitmp; - if (!uci->ishdf) { + if (uci->ci.type == UAEDEV_DIR) { mi->ismounted = 1; if (uci->ci.rootdir && _tcslen (uci->ci.rootdir) == 0) return FILESYS_VIRTUAL; @@ -313,7 +314,7 @@ int get_filesys_unitconfig (struct uae_prefs *p, int index, struct mountedinfo * return -1; mi->ismedia = true; return FILESYS_VIRTUAL; - } else { + } else if (uci->ci.type == UAEDEV_HDF) { ui->hf.ci.readonly = true; ui->hf.ci.blocksize = uci->ci.blocksize; if (!hdf_open (&ui->hf, uci->ci.rootdir)) { @@ -330,23 +331,41 @@ int get_filesys_unitconfig (struct uae_prefs *p, int index, struct mountedinfo * if (ui->hf.drive_empty) mi->ismedia = 0; hdf_close (&ui->hf); + } else if (uci->ci.type == UAEDEV_CD) { + struct device_info di; + ui->hf.ci.readonly = true; + ui->hf.ci.blocksize = uci->ci.blocksize; + mi->size = -1; + mi->ismounted = true; + if (blkdev_get_info (p, ui->hf.ci.cd_emu_unit, &di)) { + mi->ismedia = di.media_inserted; + _tcscpy (mi->rootdir, di.label); + } +#if 0 + if (ui->hf.ci.cd_emu_unit == 0) + _tcscpy (mi->rootdir, _T("CD")); + else + _stprintf (mi->rootdir, _T("CD %d"), ui->hf.ci.cd_emu_unit); +#endif } } else { if (!ui->controller || (ui->controller && p->cs_ide)) { mi->ismounted = 1; - if (uci->ishdf) + if (uci->ci.type == UAEDEV_HDF) mi->ismedia = ui->hf.drive_empty ? false : true; else mi->ismedia = true; } } + if (mi->size < 0) + return -1; mi->size = ui->hf.virtsize; if (uci->ci.highcyl) { uci->ci.cyls = mi->nrcyls = uci->ci.highcyl; } else { uci->ci.cyls = mi->nrcyls = (int)(uci->ci.sectors * uci->ci.surfaces ? (ui->hf.virtsize / uci->ci.blocksize) / (uci->ci.sectors * uci->ci.surfaces) : 0); } - if (!uci->ishdf) + if (uci->ci.type == UAEDEV_DIR) return FILESYS_VIRTUAL; if (uci->ci.reserved == 0 && uci->ci.sectors == 0 && uci->ci.surfaces == 0) { if (ui->hf.flags & 1) @@ -504,6 +523,7 @@ void uci_set_defaults (struct uaedev_config_info *uci, bool rdb) uci->stacksize = 4000; uci->priority = -129; uci->sectorsperblock = 1; + uci->cd_emu_unit = -1; } static int set_filesys_unit_1 (int nr, struct uaedev_config_info *ci) @@ -765,7 +785,7 @@ static void initialize_mountinfo (void) #endif } else if (currprefs.cs_cdtvscsi) { #ifdef CDTV - cdtv_add_scsi_unit (uci->controller - HD_CONTROLLER_SCSI0, uci); + cdtv_add_scsi_hd_unit (uci->controller - HD_CONTROLLER_SCSI0, uci); allocuci (&currprefs, nr, -1); #endif } @@ -6107,6 +6127,14 @@ static uae_u32 REGPARAM2 filesys_dev_bootfilesys (TrapContext *context) } fsnode = get_long (fsnode); } + if (type == FILESYS_HARDFILE) { + uae_u32 pf = get_long (parmpacket + PP_FSHDSTART + 8); // fse_PatchFlags + for (int i = 0; i < 32; i++) { + if (pf & (1 << i)) + put_long (devicenode + 4 + i * 4, get_long (parmpacket + PP_FSHDSTART + 8 + 4 + i * 4)); + } + put_long (devicenode + 4 + 7 * 4, 0); // seglist + } return 0; } @@ -6621,8 +6649,10 @@ static void addfakefilesys (uaecptr parmpacket, uae_u32 dostype, int ver, int re flags = 0x180; for (i = 0; i < 140; i++) put_byte (parmpacket + PP_FSHDSTART + i, 0); - put_long (parmpacket + 80, dostype); - put_long (parmpacket + PP_FSHDSTART, dostype); + if (dostype) { + put_long (parmpacket + 80, dostype); + put_long (parmpacket + PP_FSHDSTART, dostype); + } if (ver >= 0 && rev >= 0) put_long (parmpacket + PP_FSHDSTART + 4, (ver << 16) | rev); @@ -6661,17 +6691,18 @@ static int dofakefilesys (UnitInfo *uip, uaecptr parmpacket, struct uaedev_confi struct zfile *zf; int ver = -1, rev = -1; uae_u32 dostype; - uaecptr seg; // we already have custom filesystem loaded for earlier hardfile? - seg = getfakefilesysseg (uip); - if (seg) { - // yes, re-use it. - put_long (parmpacket + PP_FSSIZE, 0); - put_long (parmpacket + PP_FSPTR, seg); - put_long (parmpacket + PP_ADDTOFSRES, 0); - write_log (_T("HDF: faked RDB filesystem '%s' reused\n"), uip->filesysdir); - return FILESYS_HARDFILE; + if (!ci->forceload) { + uaecptr seg = getfakefilesysseg (uip); + if (seg) { + // yes, re-use it. + put_long (parmpacket + PP_FSSIZE, 0); + put_long (parmpacket + PP_FSPTR, seg); + put_long (parmpacket + PP_ADDTOFSRES, 0); + write_log (_T("HDF: faked RDB filesystem '%s' reused\n"), uip->filesysdir); + return FILESYS_HARDFILE; + } } if (!ci->dostype) { @@ -6681,8 +6712,10 @@ static int dofakefilesys (UnitInfo *uip, uaecptr parmpacket, struct uaedev_confi } else { dostype = ci->dostype; } - if (dostype == 0) + if (dostype == 0) { + addfakefilesys (parmpacket, dostype, ver, rev, ci); return FILESYS_HARDFILE; + } tmp[0] = 0; if (uip->filesysdir && _tcslen (uip->filesysdir) > 0) { _tcscpy (tmp, uip->filesysdir); @@ -6695,6 +6728,7 @@ static int dofakefilesys (UnitInfo *uip, uaecptr parmpacket, struct uaedev_confi } if (tmp[0] == 0) { write_log (_T("RDB: no filesystem for dostype 0x%08X (%s)\n"), dostype, dostypes (dostype)); + addfakefilesys (parmpacket, dostype, ver, rev, ci); if ((dostype & 0xffffff00) == 0x444f5300) return FILESYS_HARDFILE; write_log (_T("RDB: mounted without filesys\n")); @@ -6703,6 +6737,7 @@ static int dofakefilesys (UnitInfo *uip, uaecptr parmpacket, struct uaedev_confi write_log (_T("RDB: fakefilesys, trying to load '%s', dostype 0x%08X (%s)\n"), tmp, dostype, dostypes (dostype)); zf = zfile_fopen (tmp, _T("rb"), ZFD_NORMAL); if (!zf) { + addfakefilesys (parmpacket, dostype, ver, rev, ci); write_log (_T("RDB: filesys not found\n")); if ((dostype & 0xffffff00) == 0x444f5300) return FILESYS_HARDFILE; @@ -6822,6 +6857,8 @@ static uae_u32 REGPARAM2 filesys_dev_storeinfo (TrapContext *context) uaecptr parmpacket = m68k_areg (regs, 0); struct uaedev_config_info *ci = &uip[unit_no].hf.ci; + put_long (parmpacket + PP_ADDTOFSRES, 0); + put_long (parmpacket + PP_FSSIZE, 0); if (iscd) { TCHAR *cdname = NULL; uaecptr cdname_amiga; diff --git a/src/gayle.c b/src/gayle.c index 476dcc8..7ece3e5 100644 --- a/src/gayle.c +++ b/src/gayle.c @@ -27,6 +27,8 @@ #include "gui.h" #include "a2091.h" #include "ncr_scsi.h" +#include "blkdev.h" +#include "scsi.h" #define PCMCIA_SRAM 1 #define PCMCIA_IDE 2 @@ -76,7 +78,7 @@ read 1 byte to stop reset */ /* IDE drive registers */ #define IDE_DATA 0x00 #define IDE_ERROR 0x01 /* see err-bits */ -#define IDE_NSECTOR 0x02 /* nr of sectors to read/write */ +#define IDE_NSECTOR 0x02 /* sector count, nr of sectors to read/write */ #define IDE_SECTOR 0x03 /* starting sector */ #define IDE_LCYL 0x04 /* starting cylinder */ #define IDE_HCYL 0x05 /* high byte of starting cyl */ @@ -85,12 +87,13 @@ read 1 byte to stop reset */ #define IDE_DEVCON 0x0406 #define IDE_DRVADDR 0x0407 /* STATUS bits */ -#define IDE_STATUS_ERR 0x01 -#define IDE_STATUS_IDX 0x02 -#define IDE_STATUS_DRQ 0x08 -#define IDE_STATUS_DSC 0x10 -#define IDE_STATUS_DRDY 0x40 -#define IDE_STATUS_BSY 0x80 +#define IDE_STATUS_ERR 0x01 // 0 +#define IDE_STATUS_IDX 0x02 // 1 +#define IDE_STATUS_DRQ 0x08 // 3 +#define IDE_STATUS_DSC 0x10 // 4 +#define IDE_STATUS_DRDY 0x40 // 6 +#define IDE_STATUS_BSY 0x80 // 7 +#define ATAPI_STATUS_CHK IDE_STATUS_ERR /* ERROR bits */ #define IDE_ERR_UNC 0x40 #define IDE_ERR_MC 0x20 @@ -98,6 +101,11 @@ read 1 byte to stop reset */ #define IDE_ERR_MCR 0x08 #define IDE_ERR_ABRT 0x04 #define IDE_ERR_NM 0x02 +#define ATAPI_ERR_EOM 0x02 +#define ATAPI_ERR_ILI 0x01 +/* ATAPI interrupt reason (Sector Count) */ +#define ATAPI_IO 0x02 +#define ATAPI_CD 0x01 /* * These are at different offsets from the base @@ -166,13 +174,16 @@ struct ide_registers { uae_u8 ide_select, ide_nsector, ide_sector, ide_lcyl, ide_hcyl, ide_devcon, ide_error, ide_feat; uae_u8 ide_nsector2, ide_sector2, ide_lcyl2, ide_hcyl2, ide_feat2; - uae_u8 ide_drv; + uae_u8 ide_status; }; struct ide_hdf { struct hd_hardfiledata hdhfd; - struct ide_registers *regs; + struct ide_registers regs; + struct ide_registers *regs0; + struct ide_registers *regs1; + struct ide_hdf *pair; uae_u8 secbuf[SECBUF_SIZE]; int data_offset; @@ -180,14 +191,19 @@ struct ide_hdf int data_multi; int lba48; uae_u8 multiple_mode; - uae_u8 status; int irq_delay; int irq; int num; int type; int blocksize; int maxtransferstate; + int ide_drv; + bool atapi; + int cd_unit_num; + int packet_cnt; + int packet_data_size; + struct scsi_data scsi; }; #define TOTAL_IDE 3 @@ -195,7 +211,7 @@ struct ide_hdf #define PCMCIA_IDE_ID 2 static struct ide_hdf *idedrive[TOTAL_IDE * 2]; -static struct ide_registers ideregs[TOTAL_IDE]; +static struct ide_registers ideregs[TOTAL_IDE * 2]; struct hd_hardfiledata *pcmcia_sram; static int pcmcia_card; @@ -252,22 +268,30 @@ static uae_u8 checkpcmciaideirq (void) return 0; } +static bool isdrive (struct ide_hdf *drv) +{ + return drv->hdhfd.size != 0 || drv->atapi; +} + static uae_u8 checkgayleideirq (void) { int i; + bool irq = false; + if (!idedrive) return 0; for (i = 0; i < 2; i++) { - if (ideregs[i].ide_devcon & 2) - continue; - if (idedrive[i]->irq || idedrive[i + 2]->irq) { - /* IDE killer feature. Do not eat interrupt to make booting faster. */ - if (idedrive[i]->irq && idedrive[i]->hdhfd.size == 0) - idedrive[i]->irq = 0; - return GAYLE_IRQ_IDE; + if (idedrive[i]->ide_drv == i) { + if (!(idedrive[i]->regs.ide_devcon & 2) && (idedrive[i]->irq || idedrive[i + 2]->irq)) + irq = true; } + /* IDE killer feature. Do not eat interrupt to make booting faster. */ + if (idedrive[i]->irq && !isdrive (idedrive[i])) + idedrive[i]->irq = 0; + if (idedrive[i + 2]->irq && !isdrive (idedrive[i + 2])) + idedrive[i + 2]->irq = 0; } - return 0; + return irq ? GAYLE_IRQ_IDE : 0; } void rethink_gayle (void) @@ -406,26 +430,25 @@ static uae_u8 read_gayle_cs (void) static void ide_interrupt (void) { - if (ide->regs->ide_devcon & 2) - return; - //ide->status |= IDE_STATUS_BSY; ide->irq_delay = 2; } static void ide_interrupt_do (struct ide_hdf *ide) { - ide->status &= ~IDE_STATUS_BSY; + ide->regs.ide_status &= ~IDE_STATUS_BSY; ide->irq_delay = 0; + if (ide->regs.ide_devcon & 2) + return; ide->irq = 1; rethink_gayle (); } static void ide_fail_err (uae_u8 err) { - ide->regs->ide_error |= err; - if (ide->regs->ide_drv == 1 && idedrive[ide2 + 1]->hdhfd.size == 0) - idedrive[ide2]->status |= IDE_STATUS_ERR; - ide->status |= IDE_STATUS_ERR; + ide->regs.ide_error |= err; + if (ide->ide_drv == 1 && !isdrive (ide + 1)) + idedrive[ide2]->regs.ide_status |= IDE_STATUS_ERR; + ide->regs.ide_status |= IDE_STATUS_ERR; ide_interrupt (); } static void ide_fail (void) @@ -437,7 +460,7 @@ static void ide_data_ready (void) { memset (ide->secbuf, 0, ide->blocksize); ide->data_offset = 0; - ide->status |= IDE_STATUS_DRQ; + ide->regs.ide_status |= IDE_STATUS_DRQ; ide->data_size = ide->blocksize; ide->data_multi = 1; ide_interrupt (); @@ -446,8 +469,8 @@ static void ide_data_ready (void) static void ide_recalibrate (void) { write_log (_T("IDE%d recalibrate\n"), ide->num); - ide->regs->ide_sector = 0; - ide->regs->ide_lcyl = ide->regs->ide_hcyl = 0; + ide->regs.ide_sector = 0; + ide->regs.ide_lcyl = ide->regs.ide_hcyl = 0; ide_interrupt (); } static void ide_identify_drive (void) @@ -458,7 +481,7 @@ static void ide_identify_drive (void) TCHAR tmp[100]; bool atapi = ide->atapi; - if (ide->hdhfd.size == 0) { + if (!isdrive (ide)) { ide_fail (); return; } @@ -478,7 +501,10 @@ static void ide_identify_drive (void) pw (20, 3); pw (21, ide->blocksize); pw (22, 4); - ps (23, _T("0.4"), 8); /* firmware revision */ + ps (23, _T("0.5"), 8); /* firmware revision */ + if (ide->atapi) + _tcscpy (tmp, _T("UAE-ATAPI")); + else _stprintf (tmp, _T("UAE-IDE %s"), ide->hdhfd.hfd.product_id); ps (27, tmp, 40); /* model */ pw (47, MAX_IDE_MULTIPLE_SECTORS >> (ide->blocksize / 512 - 1)); /* max sectors in multiple mode */ @@ -493,9 +519,9 @@ static void ide_identify_drive (void) totalsecs = ide->hdhfd.cyls * ide->hdhfd.heads * ide->hdhfd.secspertrack; pw (57, (uae_u16)totalsecs); pw (58, (uae_u16)(totalsecs >> 16)); - v = idedrive[ide->regs->ide_drv]->multiple_mode; + v = idedrive[ide->ide_drv]->multiple_mode; pw (59, (v > 0 ? 0x100 : 0) | v); - totalsecs = ide->hdhfd.size / ide->blocksize; + totalsecs = ide->blocksize ? ide->hdhfd.size / ide->blocksize : 0; if (totalsecs > 0x0fffffff) totalsecs = 0x0fffffff; pw (60, (uae_u16)totalsecs); @@ -528,27 +554,31 @@ static void ide_identify_drive (void) static void ide_execute_drive_diagnostics (bool irq) { - ide->regs->ide_error = 1; + ide->regs.ide_error = 0x01; // device ok if (ide->atapi) { - ide->regs->ide_sector = ide->regs->ide_nsector = 1; - ide->regs->ide_lcyl = 0x14; - ide->regs->ide_hcyl = 0xeb; + ide->regs.ide_nsector = 1; + ide->regs.ide_sector = 1; + ide->regs.ide_lcyl = 0x14; + ide->regs.ide_hcyl = 0xeb; + ide->regs.ide_status = IDE_STATUS_BSY; } else { - ide->regs->ide_sector = ide->regs->ide_nsector = 1; - ide->regs->ide_select = 0; - ide->regs->ide_lcyl = ide->regs->ide_hcyl = 0; + ide->regs.ide_nsector = 1; + ide->regs.ide_sector = 1; + ide->regs.ide_lcyl = 0; + ide->regs.ide_hcyl = 0; + ide->regs.ide_status = IDE_STATUS_BSY | IDE_STATUS_DRDY; } if (irq) ide_interrupt (); else - ide->status &= ~IDE_STATUS_BSY; + ide->regs.ide_status &= ~IDE_STATUS_BSY; } static void ide_initialize_drive_parameters (void) { if (ide->hdhfd.size) { - ide->hdhfd.secspertrack = ide->regs->ide_nsector == 0 ? 256 : ide->regs->ide_nsector; - ide->hdhfd.heads = (ide->regs->ide_select & 15) + 1; + ide->hdhfd.secspertrack = ide->regs.ide_nsector == 0 ? 256 : ide->regs.ide_nsector; + ide->hdhfd.heads = (ide->regs.ide_select & 15) + 1; ide->hdhfd.cyls = (ide->hdhfd.size / ide->blocksize) / (ide->hdhfd.secspertrack * ide->hdhfd.heads); if (ide->hdhfd.heads * ide->hdhfd.cyls * ide->hdhfd.secspertrack > 16515072 || ide->lba48) { ide->hdhfd.cyls = ide->hdhfd.cyls_def; @@ -556,8 +586,8 @@ static void ide_initialize_drive_parameters (void) ide->hdhfd.secspertrack = ide->hdhfd.secspertrack_def; } } else { - ide->regs->ide_error |= IDE_ERR_ABRT; - ide->status |= IDE_STATUS_ERR; + ide->regs.ide_error |= IDE_ERR_ABRT; + ide->regs.ide_status |= IDE_STATUS_ERR; } write_log (_T("IDE%d initialize drive parameters, CYL=%d,SPT=%d,HEAD=%d\n"), ide->num, ide->hdhfd.cyls, ide->hdhfd.secspertrack, ide->hdhfd.heads); @@ -565,33 +595,33 @@ static void ide_initialize_drive_parameters (void) } static void ide_set_multiple_mode (void) { - write_log (_T("IDE%d drive multiple mode = %d\n"), ide->num, ide->regs->ide_nsector); - ide->multiple_mode = ide->regs->ide_nsector; + write_log (_T("IDE%d drive multiple mode = %d\n"), ide->num, ide->regs.ide_nsector); + ide->multiple_mode = ide->regs.ide_nsector; ide_interrupt (); } static void ide_set_features (void) { - int type = ide->regs->ide_nsector >> 3; - int mode = ide->regs->ide_nsector & 7; + int type = ide->regs.ide_nsector >> 3; + int mode = ide->regs.ide_nsector & 7; - write_log (_T("IDE%d set features %02X (%02X)\n"), ide->num, ide->regs->ide_feat, ide->regs->ide_nsector); + write_log (_T("IDE%d set features %02X (%02X)\n"), ide->num, ide->regs.ide_feat, ide->regs.ide_nsector); ide_fail (); } static void get_lbachs (struct ide_hdf *ide, uae_u64 *lbap, unsigned int *cyl, unsigned int *head, unsigned int *sec, int lba48) { - if (lba48 && (ide->regs->ide_select & 0x40)) { + if (lba48 && (ide->regs.ide_select & 0x40)) { uae_u64 lba; - lba = (ide->regs->ide_hcyl << 16) | (ide->regs->ide_lcyl << 8) | ide->regs->ide_sector; - lba |= ((ide->regs->ide_hcyl2 << 16) | (ide->regs->ide_lcyl2 << 8) | ide->regs->ide_sector2) << 24; + lba = (ide->regs.ide_hcyl << 16) | (ide->regs.ide_lcyl << 8) | ide->regs.ide_sector; + lba |= ((ide->regs.ide_hcyl2 << 16) | (ide->regs.ide_lcyl2 << 8) | ide->regs.ide_sector2) << 24; *lbap = lba; } else { - if (ide->regs->ide_select & 0x40) { - *lbap = ((ide->regs->ide_select & 15) << 24) | (ide->regs->ide_hcyl << 16) | (ide->regs->ide_lcyl << 8) | ide->regs->ide_sector; + if (ide->regs.ide_select & 0x40) { + *lbap = ((ide->regs.ide_select & 15) << 24) | (ide->regs.ide_hcyl << 16) | (ide->regs.ide_lcyl << 8) | ide->regs.ide_sector; } else { - *cyl = (ide->regs->ide_hcyl << 8) | ide->regs->ide_lcyl; - *head = ide->regs->ide_select & 15; - *sec = ide->regs->ide_sector; + *cyl = (ide->regs.ide_hcyl << 8) | ide->regs.ide_lcyl; + *head = ide->regs.ide_select & 15; + *sec = ide->regs.ide_sector; *lbap = (((*cyl) * ide->hdhfd.heads + (*head)) * ide->hdhfd.secspertrack) + (*sec) - 1; } } @@ -600,22 +630,22 @@ static void get_lbachs (struct ide_hdf *ide, uae_u64 *lbap, unsigned int *cyl, u static int get_nsec (int lba48) { if (lba48) - return (ide->regs->ide_nsector == 0 && ide->regs->ide_nsector2 == 0) ? 65536 : (ide->regs->ide_nsector2 * 256 + ide->regs->ide_nsector); + return (ide->regs.ide_nsector == 0 && ide->regs.ide_nsector2 == 0) ? 65536 : (ide->regs.ide_nsector2 * 256 + ide->regs.ide_nsector); else - return ide->regs->ide_nsector == 0 ? 256 : ide->regs->ide_nsector; + return ide->regs.ide_nsector == 0 ? 256 : ide->regs.ide_nsector; } static int dec_nsec (int lba48, int v) { if (lba48) { uae_u16 nsec; - nsec = ide->regs->ide_nsector2 * 256 + ide->regs->ide_nsector; - ide->regs->ide_nsector -= v; - ide->regs->ide_nsector2 = nsec >> 8; - ide->regs->ide_nsector = nsec & 0xff; - return (ide->regs->ide_nsector2 << 8) | ide->regs->ide_nsector; + nsec = ide->regs.ide_nsector2 * 256 + ide->regs.ide_nsector; + ide->regs.ide_nsector -= v; + ide->regs.ide_nsector2 = nsec >> 8; + ide->regs.ide_nsector = nsec & 0xff; + return (ide->regs.ide_nsector2 << 8) | ide->regs.ide_nsector; } else { - ide->regs->ide_nsector -= v; - return ide->regs->ide_nsector; + ide->regs.ide_nsector -= v; + return ide->regs.ide_nsector; } } @@ -623,21 +653,21 @@ static void put_lbachs (struct ide_hdf *ide, uae_u64 lba, unsigned int cyl, unsi { if (lba48) { lba += inc; - ide->regs->ide_hcyl = (lba >> 16) & 0xff; - ide->regs->ide_lcyl = (lba >> 8) & 0xff; - ide->regs->ide_sector = lba & 0xff; + ide->regs.ide_hcyl = (lba >> 16) & 0xff; + ide->regs.ide_lcyl = (lba >> 8) & 0xff; + ide->regs.ide_sector = lba & 0xff; lba >>= 24; - ide->regs->ide_hcyl2 = (lba >> 16) & 0xff; - ide->regs->ide_lcyl2 = (lba >> 8) & 0xff; - ide->regs->ide_sector2 = lba & 0xff; + ide->regs.ide_hcyl2 = (lba >> 16) & 0xff; + ide->regs.ide_lcyl2 = (lba >> 8) & 0xff; + ide->regs.ide_sector2 = lba & 0xff; } else { - if (ide->regs->ide_select & 0x40) { + if (ide->regs.ide_select & 0x40) { lba += inc; - ide->regs->ide_select &= ~15; - ide->regs->ide_select |= (lba >> 24) & 15; - ide->regs->ide_hcyl = (lba >> 16) & 0xff; - ide->regs->ide_lcyl = (lba >> 8) & 0xff; - ide->regs->ide_sector = lba & 0xff; + ide->regs.ide_select &= ~15; + ide->regs.ide_select |= (lba >> 24) & 15; + ide->regs.ide_hcyl = (lba >> 16) & 0xff; + ide->regs.ide_lcyl = (lba >> 8) & 0xff; + ide->regs.ide_sector = lba & 0xff; } else { sec += inc; while (sec >= ide->hdhfd.secspertrack) { @@ -648,11 +678,11 @@ static void put_lbachs (struct ide_hdf *ide, uae_u64 lba, unsigned int cyl, unsi cyl++; } } - ide->regs->ide_select &= ~15; - ide->regs->ide_select |= head; - ide->regs->ide_sector = sec; - ide->regs->ide_hcyl = cyl >> 8; - ide->regs->ide_lcyl = (uae_u8)cyl; + ide->regs.ide_select &= ~15; + ide->regs.ide_select |= head; + ide->regs.ide_sector = sec; + ide->regs.ide_hcyl = cyl >> 8; + ide->regs.ide_lcyl = (uae_u8)cyl; } } } @@ -661,7 +691,7 @@ static void check_maxtransfer (int state) { if (state == 1) { // transfer was started - if (ide->maxtransferstate < 2 && ide->regs->ide_nsector == 0) { + if (ide->maxtransferstate < 2 && ide->regs.ide_nsector == 0) { ide->maxtransferstate = 1; } else if (ide->maxtransferstate == 2) { // second transfer was started (part of split) @@ -703,7 +733,7 @@ static void ide_read_sectors (int flags) } ide->data_multi = multi ? ide->multiple_mode : 1; ide->data_offset = 0; - ide->status |= IDE_STATUS_DRQ; + ide->regs.ide_status |= IDE_STATUS_DRQ; ide->data_size = nsec * ide->blocksize; ide_interrupt (); } @@ -739,18 +769,24 @@ static void ide_write_sectors (int flags) } ide->data_multi = multi ? ide->multiple_mode : 1; ide->data_offset = 0; - ide->status |= IDE_STATUS_DRQ; + ide->regs.ide_status |= IDE_STATUS_DRQ; ide->data_size = nsec * ide->blocksize; } static void atapi_packet (void) { - ide->regs->ide_error = 1; /* C/D = 1 */ - ide->status = IDE_STATUS_DRQ; - ide->data_size = (ide->regs->ide_hcyl << 8) | ide->regs->ide_lcyl; + ide->data_size = (ide->regs.ide_hcyl << 8) | ide->regs.ide_lcyl; if (ide->data_size == 65535) ide->data_size = 65534; - + ide->packet_data_size = (ide->data_size + 1) & ~1; + ide->data_size = 12; + write_log (_T("ATAPI packet command\n")); + ide->packet_cnt = 1; + ide->data_multi = 1; + ide->data_offset = 0; + ide->regs.ide_status = IDE_STATUS_DRQ; + ide->regs.ide_nsector = ATAPI_CD; + ide->regs.ide_error = 0; } static void ide_do_command (uae_u8 cmd) @@ -759,63 +795,120 @@ static void ide_do_command (uae_u8 cmd) if (IDE_LOG > 1) write_log (_T("**** IDE%d command %02X\n"), ide->num, cmd); - ide->status &= ~ (IDE_STATUS_DRDY | IDE_STATUS_DRQ | IDE_STATUS_ERR); - ide->regs->ide_error = 0; + ide->regs.ide_status &= ~ (IDE_STATUS_DRDY | IDE_STATUS_DRQ | IDE_STATUS_ERR); + ide->regs.ide_error = 0; if (ide->atapi) { + if (cmd == 0x08) { /* device reset */ - ide_execute_drive_diagnostics (false); + ide_execute_drive_diagnostics (true); } else if (cmd == 0xa1) { /* identify packet device */ ide_identify_drive (); } else if (cmd == 0xa0) { /* packet */ atapi_packet (); + } else { + ide_execute_drive_diagnostics (false); + ide_fail (); + write_log (_T("IDE%d: unknown ATAPI command 0x%02x\n"), ide->num, cmd); + } + + } else { + + if (cmd == 0x10) { /* recalibrate */ + ide_recalibrate (); + } else if (cmd == 0xec) { /* identify drive */ + ide_identify_drive (); + } else if (cmd == 0x90) { /* execute drive diagnostics */ + ide_execute_drive_diagnostics (true); + } else if (cmd == 0x91) { /* initialize drive parameters */ + ide_initialize_drive_parameters (); + } else if (cmd == 0xc6) { /* set multiple mode */ + ide_set_multiple_mode (); + } else if (cmd == 0x20 || cmd == 0x21) { /* read sectors */ + ide_read_sectors (0); + } else if (cmd == 0x24 && lba48) { /* read sectors ext */ + ide_read_sectors (2); + } else if (cmd == 0xc4) { /* read multiple */ + ide_read_sectors (1); + } else if (cmd == 0x29 && lba48) { /* read multiple ext */ + ide_read_sectors (1|2); + } else if (cmd == 0x30 || cmd == 0x31) { /* write sectors */ + ide_write_sectors (0); + } else if (cmd == 0x34 && lba48) { /* write sectors ext */ + ide_write_sectors (2); + } else if (cmd == 0xc5) { /* write multiple */ + ide_write_sectors (1); + } else if (cmd == 0x39 && lba48) { /* write multiple ext */ + ide_write_sectors (1|2); + } else if (cmd == 0x50) { /* format track (nop) */ + ide_interrupt (); + } else if (cmd == 0xef) { /* set features */ + ide_set_features (); + } else if (cmd == 0x00) { /* nop */ + ide_fail (); + } else if (cmd == 0xe0 || cmd == 0xe1 || cmd == 0xe7 || cmd == 0xea) { /* standby now/idle/flush cache/flush cache ext */ + ide_interrupt (); + } else if (cmd == 0xe5) { /* check power mode */ + ide->regs.ide_nsector = 0xff; + ide_interrupt (); + } else { + ide_fail (); + write_log (_T("IDE%d: unknown ATA command 0x%02x\n"), ide->num, cmd); } } +} - if (cmd == 0x10) { /* recalibrate */ - ide_recalibrate (); - } else if (cmd == 0xec) { /* identify drive */ - ide_identify_drive (); - } else if (cmd == 0x90) { /* execute drive diagnostics */ - ide_execute_drive_diagnostics (true); - } else if (cmd == 0x91) { /* initialize drive parameters */ - ide_initialize_drive_parameters (); - } else if (cmd == 0xc6) { /* set multiple mode */ - if (ide->atapi) - ide_fail (); - else - ide_set_multiple_mode (); - } else if (cmd == 0x20 || cmd == 0x21) { /* read sectors */ - ide_read_sectors (0); - } else if (cmd == 0x24 && lba48) { /* read sectors ext */ - ide_read_sectors (2); - } else if (cmd == 0xc4) { /* read multiple */ - ide_read_sectors (1); - } else if (cmd == 0x29 && lba48) { /* read multiple ext */ - ide_read_sectors (1|2); - } else if (cmd == 0x30 || cmd == 0x31) { /* write sectors */ - ide_write_sectors (0); - } else if (cmd == 0x34 && lba48) { /* write sectors ext */ - ide_write_sectors (2); - } else if (cmd == 0xc5) { /* write multiple */ - ide_write_sectors (1); - } else if (cmd == 0x39 && lba48) { /* write multiple ext */ - ide_write_sectors (1|2); - } else if (cmd == 0x50) { /* format track (nop) */ - ide_interrupt (); - } else if (cmd == 0xef) { /* set features */ - ide_set_features (); - } else if (cmd == 0x00) { /* nop */ - ide_fail (); - } else if (cmd == 0xe0 || cmd == 0xe1 || cmd == 0xe7 || cmd == 0xea) { /* standby now/idle/flush cache/flush cache ext */ - ide_interrupt (); - } else if (cmd == 0xe5) { /* check power mode */ - ide->regs->ide_nsector = 0xff; - ide_interrupt (); - } else { - ide_fail (); - write_log (_T("IDE%d: unknown command %x\n"), ide->num, cmd); +static void atapi_data_done (void) +{ + ide->regs.ide_nsector = ATAPI_IO | ATAPI_CD; + ide->regs.ide_status = IDE_STATUS_DRDY; +} + +static void do_packet_command (void) +{ + memcpy (ide->scsi.cmd, ide->secbuf, 12); + ide->scsi.cmd_len = 12; + if (IDE_LOG > 0) { + uae_u8 *c = ide->scsi.cmd; + write_log (_T("SCSI %02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x\n"), + c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8], c[9], c[10], c[11], c[12]); } + ide->packet_cnt = 0; + scsi_emulate_analyze (&ide->scsi); + if (ide->scsi.direction <= 0) { + // data in + scsi_emulate_cmd (&ide->scsi); + ide->data_size = ide->scsi.data_len; + if (ide->data_size > ide->packet_data_size) + ide->data_size = ide->packet_data_size; + ide->data_offset = 0; + ide->regs.ide_status = 0; + if (ide->scsi.status) { + // error + ide->regs.ide_status = ATAPI_STATUS_CHK; + ide->regs.ide_error = ide->scsi.status << 4; + atapi_data_done (); + } else if (ide->scsi.data_len) { + // data + ide->regs.ide_status = IDE_STATUS_DRQ; + memcpy (ide->secbuf, ide->scsi.buffer, ide->scsi.data_len); + ide->packet_cnt = -1; + ide->regs.ide_nsector = ATAPI_IO; + } else { + // no data + atapi_data_done (); + } + } else { + // data out + ide->regs.ide_status = IDE_STATUS_DRQ; + ide->packet_cnt = -1; + ide->regs.ide_nsector = 0; + ide->data_size = ide->scsi.data_len; + if (ide->data_size > ide->packet_data_size) + ide->data_size = ide->packet_data_size; + } + ide->regs.ide_lcyl = ide->data_size & 0xff; + ide->regs.ide_hcyl = ide->data_size >> 8; } static uae_u16 ide_get_data (void) @@ -830,49 +923,65 @@ static uae_u16 ide_get_data (void) write_log (_T("IDE%d DATA read\n"), ide->num); if (ide->data_size == 0) { if (IDE_LOG > 0) - write_log (_T("IDE%d DATA read without DRQ!?\n"), ide->num); - if (ide->hdhfd.size == 0) + write_log (_T("IDE%d DATA read without DRQ!? PC=%08X\n"), ide->num, m68k_getpc ()); + if (!isdrive (ide)) return 0xffff; return 0; } - nsec = 0; - if (ide->data_offset == 0 && ide->data_size >= 0) { - get_lbachs (ide, &lba, &cyl, &head, &sec, ide->lba48); - nsec = get_nsec (ide->lba48); - if (nsec * ide->blocksize > ide->hdhfd.size - lba * ide->blocksize) - nsec = (ide->hdhfd.size - lba * ide->blocksize) / ide->blocksize; - if (nsec <= 0) { - ide_data_ready (); - ide_fail_err (IDE_ERR_IDNF); - return 0; - } - if (nsec > ide->data_multi) - nsec = ide->data_multi; - hdf_read (&ide->hdhfd.hfd, ide->secbuf, lba * ide->blocksize, nsec * ide->blocksize); - if (!dec_nsec (ide->lba48, nsec)) - last = true; - if (IDE_LOG > 1) - write_log (_T("IDE%d read, read %d bytes to buffer\n"), ide->num, nsec * ide->blocksize); - } - - v = ide->secbuf[ide->data_offset + 1] | (ide->secbuf[ide->data_offset + 0] << 8); - ide->data_offset += 2; - if (ide->data_size < 0) { - ide->data_size += 2; - } else { - ide->data_size -= 2; - if (((ide->data_offset % ide->blocksize) == 0) && ((ide->data_offset / ide->blocksize) % ide->data_multi) == 0) { + if (ide->packet_cnt) { + v = ide->secbuf[ide->data_offset + 1] | (ide->secbuf[ide->data_offset + 0] << 8); + ide->data_offset += 2; + if (ide->data_size < 0) + ide->data_size += 2; + else + ide->data_size -= 2; + if (ide->data_size == 0) { + ide->packet_cnt = 0; + atapi_data_done (); + if (IDE_LOG > 1) + write_log (_T("IDE%d ATAPI read finished\n"), ide->num); irq = true; - ide->data_offset = 0; } - } - if (ide->data_size == 0) { - ide->status &= ~IDE_STATUS_DRQ; - if (IDE_LOG > 1) - write_log (_T("IDE%d read finished\n"), ide->num); - } - if (nsec) { - put_lbachs (ide, lba, cyl, head, sec, last ? nsec - 1 : nsec, ide->lba48); + } else { + nsec = 0; + if (ide->data_offset == 0 && ide->data_size >= 0) { + get_lbachs (ide, &lba, &cyl, &head, &sec, ide->lba48); + nsec = get_nsec (ide->lba48); + if (nsec * ide->blocksize > ide->hdhfd.size - lba * ide->blocksize) + nsec = (ide->hdhfd.size - lba * ide->blocksize) / ide->blocksize; + if (nsec <= 0) { + ide_data_ready (); + ide_fail_err (IDE_ERR_IDNF); + return 0; + } + if (nsec > ide->data_multi) + nsec = ide->data_multi; + hdf_read (&ide->hdhfd.hfd, ide->secbuf, lba * ide->blocksize, nsec * ide->blocksize); + if (!dec_nsec (ide->lba48, nsec)) + last = true; + if (IDE_LOG > 1) + write_log (_T("IDE%d read, read %d bytes to buffer\n"), ide->num, nsec * ide->blocksize); + } + + v = ide->secbuf[ide->data_offset + 1] | (ide->secbuf[ide->data_offset + 0] << 8); + ide->data_offset += 2; + if (ide->data_size < 0) { + ide->data_size += 2; + } else { + ide->data_size -= 2; + if (((ide->data_offset % ide->blocksize) == 0) && ((ide->data_offset / ide->blocksize) % ide->data_multi) == 0) { + irq = true; + ide->data_offset = 0; + } + } + if (ide->data_size == 0) { + ide->regs.ide_status &= ~IDE_STATUS_DRQ; + if (IDE_LOG > 1) + write_log (_T("IDE%d read finished\n"), ide->num); + } + if (nsec) { + put_lbachs (ide, lba, cyl, head, sec, last ? nsec - 1 : nsec, ide->lba48); + } } if (irq) { ide_interrupt (); @@ -899,28 +1008,44 @@ static void ide_write_drive (bool last) static void ide_put_data (uae_u16 v) { - int irq = 0; + bool irq = false; if (IDE_LOG > 4) write_log (_T("IDE%d DATA write %04x %d/%d\n"), ide->num, v, ide->data_offset, ide->data_size); if (ide->data_size == 0) { if (IDE_LOG > 0) - write_log (_T("IDE%d DATA write without DRQ!?\n"), ide->num); + write_log (_T("IDE%d DATA write without DRQ!? PC=%08X\n"), ide->num, m68k_getpc ()); return; } ide->secbuf[ide->data_offset + 1] = v & 0xff; ide->secbuf[ide->data_offset + 0] = v >> 8; ide->data_offset += 2; ide->data_size -= 2; + if (ide->packet_cnt) { if (ide->data_size == 0) { - irq = 1; - ide_write_drive (true); - ide->status &= ~IDE_STATUS_DRQ; - if (IDE_LOG > 1) - write_log (_T("IDE%d write finished\n"), ide->num); - } else if (((ide->data_offset % ide->blocksize) == 0) && ((ide->data_offset / ide->blocksize) % ide->data_multi) == 0) { - irq = 1; - ide_write_drive (false); + if (ide->packet_cnt > 0) { + do_packet_command (); + } else if (ide->packet_cnt < 0) { + ide->packet_cnt = 0; + memcpy (&ide->scsi.buffer, ide->secbuf, ide->data_size); + ide->scsi.data_len = ide->data_size; + scsi_emulate_cmd (&ide->scsi); + if (IDE_LOG > 1) + write_log (_T("IDE%d ATAPI write finished\n"), ide->num); + } + irq = true; + } + } else { + if (ide->data_size == 0) { + irq = true; + ide_write_drive (true); + ide->regs.ide_status &= ~IDE_STATUS_DRQ; + if (IDE_LOG > 1) + write_log (_T("IDE%d write finished\n"), ide->num); + } else if (((ide->data_offset % ide->blocksize) == 0) && ((ide->data_offset / ide->blocksize) % ide->data_multi) == 0) { + irq = 1; + ide_write_drive (false); + } } if (irq) ide_interrupt (); @@ -930,7 +1055,7 @@ static int get_gayle_ide_reg (uaecptr addr) { uaecptr a = addr; addr &= 0xffff; - if (addr >= 0x3020 && addr <= 0x3021 && currprefs.cs_ide == IDE_A4000) + if (addr >= GAYLE_IRQ_4000 && addr <= GAYLE_IRQ_4000 + 1 && currprefs.cs_ide == IDE_A4000) return -1; addr &= ~0x2020; addr >>= 2; @@ -941,74 +1066,84 @@ static int get_gayle_ide_reg (uaecptr addr) addr &= ~0x400; } } - ide = idedrive[ide2 + (ide->regs->ide_drv ? 1 : 0)]; + ide = idedrive[ide2 + (ide->ide_drv ? 1 : 0)]; return addr; } static uae_u32 ide_read_reg (int ide_reg) { uae_u8 v = 0; - bool isdrive = ide->hdhfd.size != 0; + bool isdrv = isdrive (ide); + + if (ide->regs.ide_status & IDE_STATUS_BSY) + ide_reg = IDE_STATUS; + if (!isdrive (ide)) { + v = 0; + goto end; + } switch (ide_reg) { case IDE_DRVADDR: - v = ((ide->regs->ide_drv ? 2 : 1) | ((ide->regs->ide_select & 15) << 2)) ^ 0xff; + v = ((ide->ide_drv ? 2 : 1) | ((ide->regs.ide_select & 15) << 2)) ^ 0xff; break; case IDE_DATA: break; case IDE_ERROR: - v = ide->regs->ide_error; + v = ide->regs.ide_error; break; case IDE_NSECTOR: - if (isdrive) { - if (ide->regs->ide_devcon & 0x80) - v = ide->regs->ide_nsector2; + if (isdrv) { + if (ide->regs.ide_devcon & 0x80) + v = ide->regs.ide_nsector2; else - v = ide->regs->ide_nsector; + v = ide->regs.ide_nsector; } break; case IDE_SECTOR: - if (isdrive) { - if (ide->regs->ide_devcon & 0x80) - v = ide->regs->ide_sector2; + if (isdrv) { + if (ide->regs.ide_devcon & 0x80) + v = ide->regs.ide_sector2; else - v = ide->regs->ide_sector; + v = ide->regs.ide_sector; check_maxtransfer (2); } break; case IDE_LCYL: - if (isdrive) { - if (ide->regs->ide_devcon & 0x80) - v = ide->regs->ide_lcyl2; + if (isdrv) { + if (ide->regs.ide_devcon & 0x80) + v = ide->regs.ide_lcyl2; else - v = ide->regs->ide_lcyl; + v = ide->regs.ide_lcyl; } break; case IDE_HCYL: - if (isdrive) { - if (ide->regs->ide_devcon & 0x80) - v = ide->regs->ide_hcyl2; + if (isdrv) { + if (ide->regs.ide_devcon & 0x80) + v = ide->regs.ide_hcyl2; else - v = ide->regs->ide_hcyl; + v = ide->regs.ide_hcyl; } break; case IDE_SELECT: - v = ide->regs->ide_select; + v = ide->regs.ide_select; break; case IDE_STATUS: - ide->irq = 0; /* fall through */ + ide->irq = 0; + /* fall through */ case IDE_DEVCON: /* ALTSTATUS when reading */ - if (!isdrive) { + if (!isdrv) { v = 0; - if (ide->regs->ide_error) + if (ide->regs.ide_error) v |= IDE_STATUS_ERR; } else { - v = ide->status; + v = ide->regs.ide_status; + if (!ide->atapi) v |= IDE_STATUS_DRDY | IDE_STATUS_DSC; } break; } +end: if (IDE_LOG > 2 && ide_reg > 0 && (1 || ide->num > 0)) write_log (_T("IDE%d GET register %d->%02X\n"), ide->num, ide_reg, (uae_u32)v & 0xff); return v; @@ -1016,7 +1151,7 @@ static uae_u32 ide_read_reg (int ide_reg) static void ide_write_reg (int ide_reg, uae_u32 val) { - ide->regs->ide_devcon &= ~0x80; /* clear HOB */ + ide->regs.ide_devcon &= ~0x80; /* clear HOB */ if (IDE_LOG > 2 && ide_reg > 0 && (1 || ide->num > 0)) write_log (_T("IDE%d PUT register %d=%02X\n"), ide->num, ide_reg, (uae_u32)val & 0xff); switch (ide_reg) @@ -1024,39 +1159,45 @@ static void ide_write_reg (int ide_reg, uae_u32 val) case IDE_DRVADDR: break; case IDE_DEVCON: - if ((ide->regs->ide_devcon & 4) == 0 && (val & 4) != 0) + if ((ide->regs.ide_devcon & 4) == 0 && (val & 4) != 0) ide_execute_drive_diagnostics (false); - ide->regs->ide_devcon = val; + ide->regs.ide_devcon = val; break; case IDE_DATA: break; case IDE_ERROR: - ide->regs->ide_feat2 = ide->regs->ide_feat; - ide->regs->ide_feat = val; + ide->regs.ide_feat2 = ide->regs.ide_feat; + ide->regs.ide_feat = val; break; case IDE_NSECTOR: - ide->regs->ide_nsector2 = ide->regs->ide_nsector; - ide->regs->ide_nsector = val; + ide->regs.ide_nsector2 = ide->regs.ide_nsector; + ide->regs.ide_nsector = val; break; case IDE_SECTOR: - ide->regs->ide_sector2 = ide->regs->ide_sector; - ide->regs->ide_sector = val; + ide->regs.ide_sector2 = ide->regs.ide_sector; + ide->regs.ide_sector = val; break; case IDE_LCYL: - ide->regs->ide_lcyl2 = ide->regs->ide_lcyl; - ide->regs->ide_lcyl = val; + ide->regs.ide_lcyl2 = ide->regs.ide_lcyl; + ide->regs.ide_lcyl = val; break; case IDE_HCYL: - ide->regs->ide_hcyl2 = ide->regs->ide_hcyl; - ide->regs->ide_hcyl = val; + ide->regs.ide_hcyl2 = ide->regs.ide_hcyl; + ide->regs.ide_hcyl = val; break; case IDE_SELECT: - ide->regs->ide_select = val; - ide->regs->ide_drv = (val & 0x10) ? 1 : 0; + ide->regs0->ide_select = val; + ide->regs1->ide_select = val; +#if IDE_LOG > 2 + if (ide->ide_drv != (val & 0x10) ? 1 : 0) + write_log (_T("DRIVE=%d\n"), (val & 0x10) ? 1 : 0); +#endif + ide->pair->ide_drv = ide->ide_drv = (val & 0x10) ? 1 : 0; break; case IDE_STATUS: ide->irq = 0; - ide_do_command (val); + if (isdrive (ide)) + ide_do_command (val); break; } } @@ -1067,7 +1208,7 @@ static uae_u32 gayle_read2 (uaecptr addr) uae_u8 v = 0; addr &= 0xffff; - if ((IDE_LOG > 2 && (addr != 0x2000 && addr != 0x2001 && addr != 0x2020 && addr != 0x2021 && addr != GAYLE_IRQ_1200)) || IDE_LOG > 4) + if ((IDE_LOG > 3 && (addr != 0x2000 && addr != 0x2001 && addr != 0x3020 && addr != 0x3021 && addr != GAYLE_IRQ_1200)) || IDE_LOG > 5) write_log (_T("IDE_READ %08X PC=%X\n"), addr, M68K_GETPC); if (currprefs.cs_ide <= 0) { if (addr == 0x201c) // AR1200 IDE detection hack @@ -1093,7 +1234,7 @@ static uae_u32 gayle_read2 (uaecptr addr) } ide_reg = get_gayle_ide_reg (addr); /* Emulated "ide killer". Prevents long KS boot delay if no drives installed */ - if (idedrive[0]->hdhfd.size == 0 && idedrive[2]->hdhfd.size == 0) { + if (!isdrive (idedrive[0]) && !isdrive (idedrive[1]) && !isdrive (idedrive[2]) && !isdrive (idedrive[3])) { if (ide_reg == IDE_STATUS) return 0x7f; return 0xff; @@ -1105,7 +1246,7 @@ static void gayle_write2 (uaecptr addr, uae_u32 val) { int ide_reg; - if ((IDE_LOG > 2 && (addr != 0x2000 && addr != 0x2001 && addr != 0x2020 && addr != 0x2021 && addr != GAYLE_IRQ_1200)) || IDE_LOG > 4) + if ((IDE_LOG > 3 && (addr != 0x2000 && addr != 0x2001 && addr != 0x2020 && addr != 0x2021 && addr != GAYLE_IRQ_1200)) || IDE_LOG > 5) write_log (_T("IDE_WRITE %08X=%02X PC=%X\n"), addr, (uae_u32)val & 0xff, M68K_GETPC); if (currprefs.cs_ide <= 0) return; @@ -1563,8 +1704,10 @@ static void alloc_ide_mem (struct ide_hdf **ide, int max) int i; for (i = 0; i < max; i++) { - if (!ide[i]) + if (!ide[i]) { ide[i] = xcalloc (struct ide_hdf, 1); + ide[i]->cd_unit_num = -1; + } } } @@ -1576,14 +1719,38 @@ static struct ide_hdf *add_ide_unit (int ch, struct uaedev_config_info *ci) ide = idedrive[ch]; if (ci) memcpy (&ide->hdhfd.hfd.ci, ci, sizeof (struct uaedev_config_info)); - if (!hdf_hd_open (&ide->hdhfd)) - return NULL; - ide->blocksize = ide->hdhfd.hfd.ci.blocksize; - ide->lba48 = ide->hdhfd.size >= 128 * (uae_u64)0x40000000 ? 1 : 0; - ide->status = 0; + if (ci->cd_emu_unit >= 0) { + device_func_init (0); + ide->cd_unit_num = ci->cd_emu_unit; + if (!sys_command_open (ide->cd_unit_num)) { + write_log (_T("IDE: CD EMU unit %d failed to open\n"), ide->cd_unit_num); + return NULL; + } + ide->atapi = true; + ide->blocksize = 512; + gui_flicker_led (LED_CD, ch, -1); + ide->scsi.cd_emu_unit = ide->cd_unit_num; + + write_log (_T("IDE%d CD %d\n"), ch, ide->cd_unit_num); + + } else { + if (!hdf_hd_open (&ide->hdhfd)) + return NULL; + ide->blocksize = ide->hdhfd.hfd.ci.blocksize; + ide->lba48 = ide->hdhfd.size >= 128 * (uae_u64)0x40000000 ? 1 : 0; + gui_flicker_led (LED_HD, ch, -1); + ide->cd_unit_num = -1; + + write_log (_T("IDE%d HD '%s', LCHS=%d/%d/%d. PCHS=%d/%d/%d %uM. LBA48=%d\n"), + ch, ide->hdhfd.hfd.ci.rootdir, + ide->hdhfd.cyls, ide->hdhfd.heads, ide->hdhfd.secspertrack, + ide->hdhfd.hfd.ci.pcyls, ide->hdhfd.hfd.ci.pheads, ide->hdhfd.hfd.ci.psecs, + (int)(ide->hdhfd.size / (1024 * 1024)), ide->lba48); + + } + ide->regs.ide_status = 0; ide->data_offset = 0; ide->data_size = 0; - gui_flicker_led (LED_HD, ch, -1); return ide; } @@ -1611,7 +1778,7 @@ static int get_pcmcmia_ide_reg (uaecptr addr, int width) addr |= 1; } ide = idedrive[PCMCIA_IDE_ID * 2]; - if (ide->regs->ide_drv) + if (ide->ide_drv) ide = idedrive[PCMCIA_IDE_ID * 2 + 1]; if (pcmcia_configured == 1) { // IO mapped linear @@ -2261,8 +2428,13 @@ void gayle_free_units (void) for (i = 0; i < TOTAL_IDE * 2; i++) { struct ide_hdf *ide = idedrive[i]; if (ide) { - hdf_hd_close (&ide->hdhfd); + if (ide->cd_unit_num >= 0) { + sys_command_close (ide->cd_unit_num); + } else { + hdf_hd_close (&ide->hdhfd); + } memset (ide, 0, sizeof (struct ide_hdf)); + ide->cd_unit_num = -1; } } freepcmcia (1); @@ -2297,11 +2469,6 @@ int gayle_add_ide_unit (int ch, struct uaedev_config_info *ci) ide = add_ide_unit (ch, ci); if (ide == NULL) return 0; - write_log (_T("GAYLE_IDE%d '%s', LCHS=%d/%d/%d. PCHS=%d/%d/%d %uM. LBA48=%d\n"), - ch, ide->hdhfd.hfd.ci.rootdir, - ide->hdhfd.cyls, ide->hdhfd.heads, ide->hdhfd.secspertrack, - ide->hdhfd.hfd.ci.pcyls, ide->hdhfd.hfd.ci.pheads, ide->hdhfd.hfd.ci.psecs, - (int)(ide->hdhfd.size / (1024 * 1024)), ide->lba48); ide->type = IDE_GAYLE; //dumphdf (&ide->hdhfd.hfd); return 1; @@ -2341,19 +2508,20 @@ static void initide (void) if (isrestore ()) return; for (i = 0; i < TOTAL_IDE; i++) { - ideregs[i].ide_error = 1; - ideregs[i].ide_sector = ideregs[i].ide_nsector = 1; - ideregs[i].ide_select = 0; - ideregs[i].ide_lcyl = ideregs[i].ide_hcyl = ideregs[i].ide_devcon = ideregs[i].ide_feat = 0; - idedrive[i * 2 + 0]->regs = &ideregs[i]; - idedrive[i * 2 + 1]->regs = &ideregs[i]; ide = idedrive[i * 2 + 0]; + ide->regs0 = &ide->regs; + ide->regs1 = &idedrive[i * 2 + 1]->regs; + ide->pair = idedrive[i * 2 + 1]; ide_execute_drive_diagnostics (false); + ide = idedrive[i * 2 + 1]; + ide->regs1 = &ide->regs; + ide->regs0 = &idedrive[i * 2 + 0]->regs; + ide->pair = idedrive[i * 2 + 0]; ide_execute_drive_diagnostics (false); } ide_splitter = 0; - if (idedrive[2]->hdhfd.size) { + if (isdrive (idedrive[2]) || isdrive(idedrive[3])) { ide_splitter = 1; write_log (_T("IDE splitter enabled\n")); } @@ -2442,19 +2610,19 @@ uae_u8 *save_ide (int num, int *len, uae_u8 *dstptr) save_u32 (ide->hdhfd.cyls); save_u32 (ide->hdhfd.heads); save_u32 (ide->hdhfd.secspertrack); - save_u8 (ide->regs->ide_select); - save_u8 (ide->regs->ide_nsector); - save_u8 (ide->regs->ide_nsector2); - save_u8 (ide->regs->ide_sector); - save_u8 (ide->regs->ide_sector2); - save_u8 (ide->regs->ide_lcyl); - save_u8 (ide->regs->ide_lcyl2); - save_u8 (ide->regs->ide_hcyl); - save_u8 (ide->regs->ide_hcyl2); - save_u8 (ide->regs->ide_feat); - save_u8 (ide->regs->ide_feat2); - save_u8 (ide->regs->ide_error); - save_u8 (ide->regs->ide_devcon); + save_u8 (ide->regs.ide_select); + save_u8 (ide->regs.ide_nsector); + save_u8 (ide->regs.ide_nsector2); + save_u8 (ide->regs.ide_sector); + save_u8 (ide->regs.ide_sector2); + save_u8 (ide->regs.ide_lcyl); + save_u8 (ide->regs.ide_lcyl2); + save_u8 (ide->regs.ide_hcyl); + save_u8 (ide->regs.ide_hcyl2); + save_u8 (ide->regs.ide_feat); + save_u8 (ide->regs.ide_feat2); + save_u8 (ide->regs.ide_error); + save_u8 (ide->regs.ide_devcon); save_u64 (ide->hdhfd.hfd.virtual_size); save_u32 (ide->hdhfd.hfd.ci.sectors); save_u32 (ide->hdhfd.hfd.ci.surfaces); @@ -2483,19 +2651,19 @@ uae_u8 *restore_ide (uae_u8 *src) ide->hdhfd.cyls = restore_u32 (); ide->hdhfd.heads = restore_u32 (); ide->hdhfd.secspertrack = restore_u32 (); - ide->regs->ide_select = restore_u8 (); - ide->regs->ide_nsector = restore_u8 (); - ide->regs->ide_sector = restore_u8 (); - ide->regs->ide_lcyl = restore_u8 (); - ide->regs->ide_hcyl = restore_u8 (); - ide->regs->ide_feat = restore_u8 (); - ide->regs->ide_nsector2 = restore_u8 (); - ide->regs->ide_sector2 = restore_u8 (); - ide->regs->ide_lcyl2 = restore_u8 (); - ide->regs->ide_hcyl2 = restore_u8 (); - ide->regs->ide_feat2 = restore_u8 (); - ide->regs->ide_error = restore_u8 (); - ide->regs->ide_devcon = restore_u8 (); + ide->regs.ide_select = restore_u8 (); + ide->regs.ide_nsector = restore_u8 (); + ide->regs.ide_sector = restore_u8 (); + ide->regs.ide_lcyl = restore_u8 (); + ide->regs.ide_hcyl = restore_u8 (); + ide->regs.ide_feat = restore_u8 (); + ide->regs.ide_nsector2 = restore_u8 (); + ide->regs.ide_sector2 = restore_u8 (); + ide->regs.ide_lcyl2 = restore_u8 (); + ide->regs.ide_hcyl2 = restore_u8 (); + ide->regs.ide_feat2 = restore_u8 (); + ide->regs.ide_error = restore_u8 (); + ide->regs.ide_devcon = restore_u8 (); ide->hdhfd.hfd.virtual_size = restore_u64 (); ide->hdhfd.hfd.ci.sectors = restore_u32 (); ide->hdhfd.hfd.ci.surfaces = restore_u32 (); diff --git a/src/gencpu.c b/src/gencpu.c index c3cc934..f21d18f 100755 --- a/src/gencpu.c +++ b/src/gencpu.c @@ -63,6 +63,8 @@ static int optimized_flags; #define GF_FC 32 #define GF_MOVE 64 #define GF_IR2IRC 128 +#define GF_LRMW 256 +#define GF_NOFAULTPC 512 /* For the current opcode, the next lower level that will have different code. * Initialized to -1 for each opcode. If it remains unchanged, indicates we @@ -89,6 +91,8 @@ static int mmudisp020cnt; static char *srcl, *dstl; static char *srcw, *dstw; static char *srcb, *dstb; +static char *srcbrmw, *srcwrmw, *srclrmw; +static char *dstbrmw, *dstwrmw, *dstlrmw; static char *prefetch_long, *prefetch_word; static char *srcli, *srcwi, *srcbi, *nextl, *nextw, *nextb; static char *srcld, *dstld; @@ -478,28 +482,6 @@ static void sync_m68k_pc (void) m68k_pc_offset = 0; } -static void gen_set_fault_pc (void) -{ - if (using_mmu != 68040) - return; - sync_m68k_pc (); - printf ("\tregs.instruction_pc = m68k_getpci ();\n"); - m68k_pc_offset = 0; -} - -static void syncmovepc (int getv, int flags) -{ -#if 0 - if (!(flags & GF_MOVE)) - return; - if (getv == 1) { - sync_m68k_pc (); - //fill_prefetch_next (); - } -#endif -} - - static void addmmufixup (char *reg) { if (!using_mmu) @@ -520,6 +502,40 @@ static void clearmmufixup (int cnt) } } +static void gen_set_fault_pc (void) +{ + if (using_mmu != 68040) + return; + sync_m68k_pc (); + printf ("\tregs.instruction_pc = m68k_getpci ();\n"); + m68k_pc_offset = 0; + clearmmufixup (0); +} + +static void add_mmu040_movem (int movem) +{ + if (movem != 3) + return; + printf ("\tif (mmu040_movem) {\n"); + printf ("\t\tsrca = mmu040_movem_ea;\n"); + printf ("\t} else\n"); + start_brace (); +} + + +static void syncmovepc (int getv, int flags) +{ +#if 0 + if (!(flags & GF_MOVE)) + return; + if (getv == 1) { + sync_m68k_pc (); + //fill_prefetch_next (); + } +#endif +} + + /* getv == 1: fetch data; getv != 0: check for odd address. If movem != 0, * the calling routine handles Apdi and Aipi modes. * gb-- movem == 2 means the same thing but for a MOVE16 instruction */ @@ -624,6 +640,7 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g if (next_cpu_level < 1) next_cpu_level = 1; sync_m68k_pc (); + add_mmu040_movem (movem); start_brace (); /* This would ordinarily be done in gen_nextiword, which we bypass. */ insn_n_cycles += 4; @@ -639,7 +656,9 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g } break; case PC16: // (d16,PC,Xn) - printf ("\tuaecptr %sa = m68k_getpc () + %d;\n", name, m68k_pc_offset); + printf ("\tuaecptr %sa;\n", name); + add_mmu040_movem (movem); + printf ("\t%sa = m68k_getpc () + %d;\n", name, m68k_pc_offset); printf ("\t%sa += (uae_s32)(uae_s16)%s;\n", name, gen_nextiword (flags)); break; case PC8r: // (d8,PC,Xn) @@ -649,6 +668,7 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g if (next_cpu_level < 1) next_cpu_level = 1; sync_m68k_pc (); + add_mmu040_movem (movem); start_brace (); /* This would ordinarily be done in gen_nextiword, which we bypass. */ insn_n_cycles += 4; @@ -780,9 +800,9 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g } } else { switch (size) { - case sz_byte: insn_n_cycles += 4; printf ("\tuae_s8 %s = %s (%sa);\n", name, srcb, name); break; - case sz_word: insn_n_cycles += 4; printf ("\tuae_s16 %s = %s (%sa);\n", name, srcw, name); break; - case sz_long: insn_n_cycles += 8; printf ("\tuae_s32 %s = %s (%sa);\n", name, srcl, name); break; + case sz_byte: insn_n_cycles += 4; printf ("\tuae_s8 %s = %s (%sa);\n", name, (flags & GF_LRMW) ? srcbrmw : srcb, name); break; + case sz_word: insn_n_cycles += 4; printf ("\tuae_s16 %s = %s (%sa);\n", name, (flags & GF_LRMW) ? srcwrmw : srcw, name); break; + case sz_long: insn_n_cycles += 8; printf ("\tuae_s32 %s = %s (%sa);\n", name, (flags & GF_LRMW) ? srclrmw : srcl, name); break; default: abort (); } } @@ -823,6 +843,10 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g default: break; } + + if (movem == 3) { + close_brace (); + } } @@ -875,7 +899,8 @@ static void genastore_2 (char *from, amodes mode, char *reg, wordsizes size, cha case absl: case PC16: case PC8r: - gen_set_fault_pc (); + if (!(flags & GF_NOFAULTPC)) + gen_set_fault_pc (); if (using_ce020) { switch (size) { case sz_byte: @@ -928,7 +953,7 @@ static void genastore_2 (char *from, amodes mode, char *reg, wordsizes size, cha if (flags & GF_FC) printf ("\tdfc%s_put_byte (%sa, %s);\n", mmu_postfix, to, from); else - printf ("\t%s (%sa, %s);\n", dstb, to, from); + printf ("\t%s (%sa, %s);\n", (flags & GF_LRMW) ? dstbrmw : dstb, to, from); break; case sz_word: insn_n_cycles += 4; @@ -937,7 +962,7 @@ static void genastore_2 (char *from, amodes mode, char *reg, wordsizes size, cha if (flags & GF_FC) printf ("\tdfc%s_put_word (%sa, %s);\n", mmu_postfix, to, from); else - printf ("\t%s (%sa, %s);\n", dstw, to, from); + printf ("\t%s (%sa, %s);\n", (flags & GF_LRMW) ? dstwrmw :dstw, to, from); break; case sz_long: insn_n_cycles += 8; @@ -946,7 +971,7 @@ static void genastore_2 (char *from, amodes mode, char *reg, wordsizes size, cha if (flags & GF_FC) printf ("\tdfc%s_put_long (%sa, %s);\n", mmu_postfix, to, from); else - printf ("\t%s (%sa, %s);\n", dstl, to, from); + printf ("\t%s (%sa, %s);\n", (flags & GF_LRMW) ? dstlrmw : dstl, to, from); break; default: abort (); @@ -993,6 +1018,14 @@ static void genastore (char *from, amodes mode, char *reg, wordsizes size, char { genastore_2 (from, mode, reg, size, to, 0, 0); } +static void genastore_tas (char *from, amodes mode, char *reg, wordsizes size, char *to) +{ + genastore_2 (from, mode, reg, size, to, 0, GF_LRMW); +} +static void genastore_cas (char *from, amodes mode, char *reg, wordsizes size, char *to) +{ + genastore_2 (from, mode, reg, size, to, 0, GF_LRMW | GF_NOFAULTPC); +} static void genastore_rev (char *from, amodes mode, char *reg, wordsizes size, char *to) { genastore_2 (from, mode, reg, size, to, 1, 0); @@ -1002,6 +1035,95 @@ static void genastore_fc (char *from, amodes mode, char *reg, wordsizes size, ch genastore_2 (from, mode, reg, size, to, 1, GF_FC); } +static void movem_mmu060 (const char *code, int size, bool put, bool aipi, bool apdi) +{ + char *index; + int dphase, aphase; + int i; + if (apdi) { + dphase = 1; aphase = 0; + index = "movem_index2"; + } else { + dphase = 0; aphase = 1; + index = "movem_index1"; + } + + for (i = 0; i < 2; i++) { + char reg; + if (i == dphase) + reg = 'd'; + else + reg = 'a'; + printf ("\twhile (%cmask) {\n", reg); + if (apdi) + printf ("\t\tsrca -= %d;\n", size); + if (put) { + printf ("\t\t%s, m68k_%creg (regs, %s[%cmask]));\n", code, reg, index, reg); + } else { + printf ("\t\tm68k_%creg (regs, %s[%cmask]) = %s;\n", reg, index, reg, code); + } + if (!apdi) + printf ("\t\tsrca += %d;\n", size); + printf ("\t\t%cmask = movem_next[%cmask];\n", reg, reg); + printf ("\t}\n"); + } + if (aipi || apdi) + printf ("\tm68k_areg (regs, dstreg) = srca;\n"); +} + +static bool mmu040_special_movem (uae_u16 opcode) +{ + if (using_mmu != 68040) + return false; + return (((((opcode >> 3) & 7) == 7) && ((opcode & 7) == 2 || (opcode & 7) == 3)) || ((opcode >> 3) & 7) == 6); +} + +static void movem_mmu040 (const char *code, int size, bool put, bool aipi, bool apdi, uae_u16 opcode) +{ + char *index; + int dphase, aphase; + bool mvm = false; + int i; + + if (apdi) { + dphase = 1; aphase = 0; + index = "movem_index2"; + } else { + dphase = 0; aphase = 1; + index = "movem_index1"; + } + + if (mmu040_special_movem (opcode)) { + printf ("\tmmu040_movem = 1;\n"); + printf ("\tmmu040_movem_ea = srca;\n"); + mvm = true; + } + + for (i = 0; i < 2; i++) { + char reg; + if (i == dphase) + reg = 'd'; + else + reg = 'a'; + printf ("\twhile (%cmask) {\n", reg); + if (apdi) + printf ("\t\tsrca -= %d;\n", size); + if (put) { + printf ("\t\t%s, m68k_%creg (regs, %s[%cmask]));\n", code, reg, index, reg); + } else { + printf ("\t\tm68k_%creg (regs, %s[%cmask]) = %s;\n", reg, index, reg, code); + } + if (!apdi) + printf ("\t\tsrca += %d;\n", size); + printf ("\t\t%cmask = movem_next[%cmask];\n", reg, reg); + printf ("\t}\n"); + } + if (aipi || apdi) + printf ("\tm68k_areg (regs, dstreg) = srca;\n"); + if (mvm) + printf ("\tmmu040_movem = 0;\n"); +} + /* 68030 MMU does not restore register state if it bus faults. * (also there wouldn't be enough space in stack frame to store all registers) */ @@ -1064,10 +1186,14 @@ static void genmovemel (uae_u16 opcode) count_read += table68k[opcode].size == sz_long ? 2 : 1; printf ("\tuae_u16 mask = %s;\n", gen_nextiword (0)); printf ("\tuae_u32 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n"); - genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1, 0); + genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, mmu040_special_movem (opcode) ? 3 : 1, 0); start_brace (); if (using_mmu == 68030) { movem_mmu030 (getcode, size, false, table68k[opcode].dmode == Aipi, false); + } else if (using_mmu == 68060) { + movem_mmu060 (getcode, size, false, table68k[opcode].dmode == Aipi, false); + } else if (using_mmu == 68040) { + movem_mmu040 (getcode, size, false, table68k[opcode].dmode == Aipi, false, opcode); } else { printf ("\twhile (dmask) { m68k_dreg (regs, movem_index1[dmask]) = %s; srca += %d; dmask = movem_next[dmask]; }\n", getcode, size); @@ -1124,14 +1250,19 @@ static void genmovemle (uae_u16 opcode) count_write += table68k[opcode].size == sz_long ? 2 : 1; printf ("\tuae_u16 mask = %s;\n", gen_nextiword (0)); - genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1, 0); + genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, mmu040_special_movem (opcode) ? 3 : 1, 0); start_brace (); - if (using_mmu == 68030) { + if (using_mmu >= 68030) { if (table68k[opcode].dmode == Apdi) printf ("\tuae_u16 amask = mask & 0xff, dmask = (mask >> 8) & 0xff;\n"); else printf ("\tuae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n"); - movem_mmu030 (putcode, size, true, false, table68k[opcode].dmode == Apdi); + if (using_mmu == 68030) + movem_mmu030 (putcode, size, true, false, table68k[opcode].dmode == Apdi); + else if (using_mmu == 68060) + movem_mmu060 (putcode, size, true, false, table68k[opcode].dmode == Apdi); + else if (using_mmu == 68040) + movem_mmu040 (putcode, size, true, false, table68k[opcode].dmode == Apdi, opcode); } else { if (table68k[opcode].dmode == Apdi) { printf ("\tuae_u16 amask = mask & 0xff, dmask = (mask >> 8) & 0xff;\n"); @@ -1139,9 +1270,12 @@ static void genmovemle (uae_u16 opcode) printf ("\tint type = get_cpu_model () >= 68020;\n"); printf ("\twhile (amask) {\n"); printf ("\t\tsrca -= %d;\n", size); - if (!using_mmu) - printf ("\t\tif (type) m68k_areg (regs, dstreg) = srca;\n"); - printf ("\t\t%s, m68k_areg (regs, movem_index2[amask]));\n", putcode); + + printf ("\t\tif (!type || movem_index2[amask] != dstreg)\n"); + printf ("\t\t\t%s, m68k_areg (regs, movem_index2[amask]));\n", putcode); + printf ("\t\telse\n"); + printf ("\t\t\t%s, m68k_areg (regs, movem_index2[amask]) - %d);\n", putcode, size); + printf ("\t\tamask = movem_next[amask];\n"); printf ("\t}\n"); printf ("\twhile (dmask) { srca -= %d; %s, m68k_dreg (regs, movem_index2[dmask])); dmask = movem_next[dmask]; }\n", @@ -1568,6 +1702,12 @@ static void gen_opcode (unsigned long int opcode) do_cycles = "do_cycles"; srcwd = srcld = NULL; dstwd = dstld = NULL; + srcbrmw = NULL; + srcwrmw = NULL; + srclrmw = NULL; + dstbrmw = NULL; + dstwrmw = NULL; + dstlrmw = NULL; if (using_indirect) { // tracer @@ -1666,6 +1806,12 @@ static void gen_opcode (unsigned long int opcode) dstw = "put_word_mmu030_state"; srcb = "get_byte_mmu030_state"; dstb = "put_byte_mmu030_state"; + srcbrmw = "get_rmw_byte_mmu030_state"; + srcwrmw = "get_rmw_word_mmu030_state"; + srclrmw = "get_rmw_long_mmu030_state"; + dstbrmw = "put_rmw_byte_mmu030_state"; + dstwrmw = "put_rmw_word_mmu030_state"; + dstlrmw = "put_rmw_long_mmu030_state"; srcld = "get_long_mmu030"; srcwd = "get_word_mmu030"; dstld = "put_long_mmu030"; @@ -1686,6 +1832,12 @@ static void gen_opcode (unsigned long int opcode) dstw = "put_word_mmu040"; srcb = "get_byte_mmu040"; dstb = "put_byte_mmu040"; + srcbrmw = "get_rmw_byte_mmu040"; + srcwrmw = "get_rmw_word_mmu040"; + srclrmw = "get_rmw_long_mmu040"; + dstbrmw = "put_rmw_byte_mmu040"; + dstwrmw = "put_rmw_word_mmu040"; + dstlrmw = "put_rmw_long_mmu040"; } else if (using_mmu) { // 68060 MMU disp020 = "x_get_disp_ea_020"; @@ -1702,6 +1854,12 @@ static void gen_opcode (unsigned long int opcode) dstw = "put_word_mmu060"; srcb = "get_byte_mmu060"; dstb = "put_byte_mmu060"; + srcbrmw = "get_rmw_byte_mmu060"; + srcwrmw = "get_rmw_word_mmu060"; + srclrmw = "get_rmw_long_mmu060"; + dstbrmw = "put_rmw_byte_mmu060"; + dstwrmw = "put_rmw_word_mmu060"; + dstlrmw = "put_rmw_long_mmu060"; } else if (using_ce) { // 68000 ce prefetch_word = "get_word_ce000_prefetch"; @@ -1747,6 +1905,14 @@ static void gen_opcode (unsigned long int opcode) srcld = srcl; if (!srcwd) srcwd = srcw; + if (!srcbrmw) { + srcbrmw = srcb; + srcwrmw = srcw; + srclrmw = srcl; + dstbrmw = dstb; + dstwrmw = dstw; + dstlrmw = dstl; + } insn_n_cycles020 = 0; @@ -3303,10 +3469,14 @@ static void gen_opcode (unsigned long int opcode) case i_CAS: { int old_brace_level; - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, 0); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, GF_LRMW); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_LRMW); if (cpu_level == 5 && curi->size > 0) { - printf ("\tif ((dsta & %d) && currprefs.cpu_compatible && get_cpu_model () == 68060) {\n", curi->size == 1 ? 1 : 3); + if (!using_mmu) { + printf ("\tif ((dsta & %d) && currprefs.cpu_compatible && get_cpu_model () == 68060) {\n", curi->size == 1 ? 1 : 3); + } else { + printf ("\tif ((dsta & %d) && currprefs.cpu_compatible) {\n", curi->size == 1 ? 1 : 3); + } if (curi->dmode == Aipi || curi->dmode == Apdi) printf ("\t\tm68k_areg (regs, dstreg) %c= %d;\n", curi->dmode == Aipi ? '-' : '+', 1 << curi->size); printf ("\t\top_unimpl ();\n"); @@ -3320,40 +3490,49 @@ static void gen_opcode (unsigned long int opcode) printf ("\tint rc = src & 7;\n"); genflags (flag_cmp, curi->size, "newv", "m68k_dreg (regs, rc)", "dst"); sync_m68k_pc (); + gen_set_fault_pc (); printf ("\tif (GET_ZFLG ())"); old_brace_level = n_braces; start_brace (); - genastore ("(m68k_dreg (regs, ru))", curi->dmode, "dstreg", curi->size, "dst"); + printf ("\n\t"); + genastore_cas ("(m68k_dreg (regs, ru))", curi->dmode, "dstreg", curi->size, "dst"); + printf ("\t"); pop_braces (old_brace_level); printf ("else"); start_brace (); + printf ("\n"); switch (curi->size) { case sz_byte: - printf ("\tm68k_dreg(regs, rc) = (m68k_dreg(regs, rc) & ~0xff) | (dst & 0xff);\n"); + printf ("\t\tm68k_dreg(regs, rc) = (m68k_dreg(regs, rc) & ~0xff) | (dst & 0xff);\n"); break; case sz_word: - printf ("\tm68k_dreg(regs, rc) = (m68k_dreg(regs, rc) & ~0xffff) | (dst & 0xffff);\n"); + printf ("\t\tm68k_dreg(regs, rc) = (m68k_dreg(regs, rc) & ~0xffff) | (dst & 0xffff);\n"); break; default: - printf ("\tm68k_dreg(regs, rc) = dst;\n"); + printf ("\t\tm68k_dreg(regs, rc) = dst;\n"); break; } + if (cpu_level >= 4) { + // apparently 68040/060 needs to always write at the end of RMW cycle + printf ("\t"); + genastore_cas ("dst", curi->dmode, "dstreg", curi->size, "dst"); + } pop_braces (old_brace_level); } break; case i_CAS2: - genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0, 0); + genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0, GF_LRMW); printf ("\tuae_u32 rn1 = regs.regs[(extra >> 28) & 15];\n"); printf ("\tuae_u32 rn2 = regs.regs[(extra >> 12) & 15];\n"); if (curi->size == sz_word) { int old_brace_level = n_braces; - printf ("\tuae_u16 dst1 = %s (rn1), dst2 = %s (rn2);\n", srcw, srcw); + printf ("\tuae_u16 dst1 = %s (rn1), dst2 = %s (rn2);\n", srcwrmw, srcwrmw); genflags (flag_cmp, curi->size, "newv", "m68k_dreg (regs, (extra >> 16) & 7)", "dst1"); printf ("\tif (GET_ZFLG ()) {\n"); genflags (flag_cmp, curi->size, "newv", "m68k_dreg (regs, extra & 7)", "dst2"); printf ("\tif (GET_ZFLG ()) {\n"); - printf ("\t%s (rn1, m68k_dreg (regs, (extra >> 22) & 7));\n", dstw); - printf ("\t%s (rn2, m68k_dreg (regs, (extra >> 6) & 7));\n", dstw); + printf ("\t%s (rn1, m68k_dreg (regs, (extra >> 22) & 7));\n", dstwrmw); + printf ("\t%s (rn2, m68k_dreg (regs, (extra >> 6) & 7));\n", dstwrmw); printf ("\t}}\n"); pop_braces (old_brace_level); printf ("\tif (! GET_ZFLG ()) {\n"); @@ -3362,13 +3541,13 @@ static void gen_opcode (unsigned long int opcode) printf ("\t}\n"); } else { int old_brace_level = n_braces; - printf ("\tuae_u32 dst1 = %s (rn1), dst2 = %s (rn2);\n", srcl, srcl); + printf ("\tuae_u32 dst1 = %s (rn1), dst2 = %s (rn2);\n", srclrmw, srclrmw); genflags (flag_cmp, curi->size, "newv", "m68k_dreg (regs, (extra >> 16) & 7)", "dst1"); printf ("\tif (GET_ZFLG ()) {\n"); genflags (flag_cmp, curi->size, "newv", "m68k_dreg (regs, extra & 7)", "dst2"); printf ("\tif (GET_ZFLG ()) {\n"); - printf ("\t%s (rn1, m68k_dreg (regs, (extra >> 22) & 7));\n", dstl); - printf ("\t%s (rn2, m68k_dreg (regs, (extra >> 6) & 7));\n", dstl); + printf ("\t%s (rn1, m68k_dreg (regs, (extra >> 22) & 7));\n", dstlrmw); + printf ("\t%s (rn2, m68k_dreg (regs, (extra >> 6) & 7));\n", dstlrmw); printf ("\t}}\n"); pop_braces (old_brace_level); printf ("\tif (! GET_ZFLG ()) {\n"); @@ -3475,7 +3654,7 @@ static void gen_opcode (unsigned long int opcode) start_brace (); printf ("\tuae_u32 bdata[2];\n"); printf ("\tuae_s32 offset = extra & 0x800 ? m68k_dreg(regs, (extra >> 6) & 7) : (extra >> 6) & 0x1f;\n"); - printf ("\tint width = (((extra & 0x20 ? m68k_dreg(regs, extra & 7) : (uae_u32)extra) -1) & 0x1f) +1;\n"); + printf ("\tint width = (((extra & 0x20 ? m68k_dreg(regs, extra & 7) : extra) -1) & 0x1f) +1;\n"); if (curi->dmode == Dreg) { printf ("\tuae_u32 tmp = m68k_dreg(regs, dstreg);\n"); printf ("\toffset &= 0x1f;\n"); @@ -3578,7 +3757,7 @@ static void gen_opcode (unsigned long int opcode) } break; case i_TAS: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, GF_LRMW); genflags (flag_logical, curi->size, "src", "", ""); if (!isreg (curi->smode)) addcycles000 (2); @@ -3587,7 +3766,7 @@ static void gen_opcode (unsigned long int opcode) if (cpu_level >= 2 || curi->smode == Dreg || !using_ce) { if (next_cpu_level < 2) next_cpu_level = 2 - 1; - genastore ("src", curi->smode, "srcreg", curi->size, "src"); + genastore_tas ("src", curi->smode, "srcreg", curi->size, "src"); } else { printf ("\tif (!is_cycle_ce ()) {\n"); genastore ("src", curi->smode, "srcreg", curi->size, "src"); @@ -3665,9 +3844,9 @@ static void gen_opcode (unsigned long int opcode) printf ("\tuaecptr mems = m68k_areg (regs, srcreg) & ~15, memd;\n"); printf ("\tdstreg = (%s >> 12) & 7;\n", gen_nextiword (0)); printf ("\tmemd = m68k_areg (regs, dstreg) & ~15;\n"); - if (using_mmu == 68060) { - printf ("\tget_move16_mmu060 (mems, v);\n"); - printf ("\tput_move16_mmu060 (memd, v);\n"); + if (using_mmu >= 68040) { + printf ("\tget_move16_mmu (mems, v);\n"); + printf ("\tput_move16_mmu (memd, v);\n"); } else { printf ("\tv[0] = %s (mems);\n", srcl); printf ("\tv[1] = %s (mems + 4);\n", srcl); @@ -3688,9 +3867,9 @@ static void gen_opcode (unsigned long int opcode) genamode (curi->dmode, "dstreg", curi->size, "memd", 0, 2, 0); printf ("\tmemsa &= ~15;\n"); printf ("\tmemda &= ~15;\n"); - if (using_mmu == 68060) { - printf ("\tget_move16_mmu060 (memsa, v);\n"); - printf ("\tput_move16_mmu060 (memda, v);\n"); + if (using_mmu >= 68040) { + printf ("\tget_move16_mmu (memsa, v);\n"); + printf ("\tput_move16_mmu (memda, v);\n"); } else { printf ("\tv[0] = %s (memsa);\n", srcl); printf ("\tv[1] = %s (memsa + 4);\n", srcl); diff --git a/src/hardfile.c b/src/hardfile.c index 5fb593e..11d9cc4 100644 --- a/src/hardfile.c +++ b/src/hardfile.c @@ -1031,6 +1031,9 @@ int hdf_read (struct hardfiledata *hfd, void *buffer, uae_u64 offset, int len) { int v; + hf_log3 (_T("cmd_read: %p %04x-%08x (%d) %08x (%d)\n"), + buffer, (uae_u32)(offset >> 32), (uae_u32)offset, (uae_u32)(offset / hfd->ci.blocksize), (uae_u32)len, (uae_u32)(len / hfd->ci.blocksize)); + if (!hfd->adide) { v = hdf_cache_read (hfd, buffer, offset, len); } else { @@ -1047,6 +1050,9 @@ int hdf_write (struct hardfiledata *hfd, void *buffer, uae_u64 offset, int len) { int v; + hf_log3 (_T("cmd_write: %p %04x-%08x (%d) %08x (%d)\n"), + buffer, (uae_u32)(offset >> 32), (uae_u32)offset, (uae_u32)(offset / hfd->ci.blocksize), (uae_u32)len, (uae_u32)(len / hfd->ci.blocksize)); + if (hfd->byteswap) hdf_byteswap (buffer, len); if (!hfd->adide) { @@ -1065,8 +1071,6 @@ int hdf_write (struct hardfiledata *hfd, void *buffer, uae_u64 offset, int len) static uae_u64 cmd_readx (struct hardfiledata *hfd, uae_u8 *dataptr, uae_u64 offset, uae_u64 len) { gui_flicker_led (LED_HD, hfd->unitnum, 1); - hf_log3 (_T("cmd_read: %p %04x-%08x (%d) %08x (%d)\n"), - dataptr, (uae_u32)(offset >> 32), (uae_u32)offset, (uae_u32)(offset / hfd->ci.blocksize), (uae_u32)len, (uae_u32)(len / hfd->ci.blocksize)); return hdf_read (hfd, dataptr, offset, len); } static uae_u64 cmd_read (struct hardfiledata *hfd, uaecptr dataptr, uae_u64 offset, uae_u64 len) @@ -1079,8 +1083,6 @@ static uae_u64 cmd_read (struct hardfiledata *hfd, uaecptr dataptr, uae_u64 offs static uae_u64 cmd_writex (struct hardfiledata *hfd, uae_u8 *dataptr, uae_u64 offset, uae_u64 len) { gui_flicker_led (LED_HD, hfd->unitnum, 2); - hf_log3 (_T("cmd_write: %p %04x-%08x (%d) %08x (%d)\n"), - dataptr, (uae_u32)(offset >> 32), (uae_u32)offset, (uae_u32)(offset / hfd->ci.blocksize), (uae_u32)len, (uae_u32)(len / hfd->ci.blocksize)); return hdf_write (hfd, dataptr, offset, len); } @@ -1108,7 +1110,7 @@ static int nodisk (struct hardfiledata *hfd) return 0; } -int scsi_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, uae_u8 *cmdbuf, int scsi_cmd_len, +int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, uae_u8 *cmdbuf, int scsi_cmd_len, uae_u8 *scsi_data, int *data_len, uae_u8 *r, int *reply_len, uae_u8 *s, int *sense_len) { uae_u64 len, offset; @@ -1122,7 +1124,7 @@ int scsi_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, uae_u memset (r, 0, 256); memset (s, 0, 256); lun = cmdbuf[1] >> 5; - if (lun) { + if (cmdbuf[0] != 0x03 && cmdbuf[0] != 0x12 && lun) { status = 2; /* CHECK CONDITION */ s[0] = 0x70; s[2] = 5; /* ILLEGAL REQUEST */ @@ -1173,9 +1175,14 @@ int scsi_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, uae_u if ((cmdbuf[1] & 1) || cmdbuf[2] != 0) goto err; int alen = (cmdbuf[3] << 8) | cmdbuf[4]; - if (hfd->drive_empty) { - r[1] |= 0x80; // removable.. - r[0] |= 0x20; // not present + if (lun != 0) { + r[0] = 0x7f; + } else { + r[0] = 0; + if (hfd->drive_empty) { + r[1] |= 0x80; // removable.. + r[0] |= 0x20; // not present + } } r[2] = 2; /* supports SCSI-2 */ r[3] = 2; /* response data format */ @@ -1416,6 +1423,9 @@ int scsi_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, uae_u s[12] = 0x1c; /* DEFECT LIST NOT FOUND */ ls = 12; break; + case 0x1b: /* START/STOP UNIT */ + scsi_len = 0; + break; readprot: status = 2; /* CHECK CONDITION */ s[0] = 0x70; @@ -1433,7 +1443,7 @@ nodisk: default: err: - write_log (_T("UAEHF: unsupported scsi command 0x%02X\n"), cmdbuf[0]); + write_log (_T("UAEHF: unsupported scsi command 0x%02X LUN=%d\n"), cmdbuf[0], lun); errreq: lr = -1; status = 2; /* CHECK CONDITION */ @@ -1495,7 +1505,7 @@ static int handle_scsi (uaecptr request, struct hardfiledata *hfd) } scsi_log (_T("\n")); - status = scsi_emulate (hfd, NULL, cmdbuf, scsi_cmd_len, scsi_data_ptr, &scsi_len, reply, &reply_len, sense, &sense_len); + status = scsi_hd_emulate (hfd, NULL, cmdbuf, scsi_cmd_len, scsi_data_ptr, &scsi_len, reply, &reply_len, sense, &sense_len); put_word (acmd + 18, status != 0 ? 0 : scsi_cmd_len); /* fake scsi_CmdActual */ put_byte (acmd + 21, status); /* scsi_Status */ diff --git a/src/include/a2091.h b/src/include/a2091.h index a222599..d00edd4 100644 --- a/src/include/a2091.h +++ b/src/include/a2091.h @@ -26,6 +26,7 @@ extern struct scsi_data *scsis[8]; extern int a2091_add_scsi_unit (int ch, struct uaedev_config_info *ci); extern int a3000_add_scsi_unit (int ch, struct uaedev_config_info *ci); -extern int addscsi (int ch, struct hd_hardfiledata *hfd, struct uaedev_config_info *ci, int scsi_level); +extern int add_scsi_hd (int ch, struct hd_hardfiledata *hfd, struct uaedev_config_info *ci, int scsi_level); +extern int add_scsi_cd (int ch, int unitnum); #endif diff --git a/src/include/autoconf.h b/src/include/autoconf.h index 4e54e98..7d9bbc5 100644 --- a/src/include/autoconf.h +++ b/src/include/autoconf.h @@ -65,12 +65,17 @@ extern uaecptr need_uae_boot_rom (void); struct mountedinfo { - uae_u64 size; - bool ismounted; - bool ismedia; - int nrcyls; + uae_u64 size; + bool ismounted; + bool ismedia; + int nrcyls; + TCHAR rootdir[MAX_DPATH]; }; +extern int add_filesys_unitconfig (struct uae_prefs *p, int index, TCHAR *error); +extern int get_filesys_unitconfig (struct uae_prefs *p, int index, struct mountedinfo*); +extern int kill_filesys_unitconfig (struct uae_prefs *p, int nr); +extern int move_filesys_unitconfig (struct uae_prefs *p, int nr, int to); extern char *validatedevicename (char *s); extern char *validatevolumename (char *s); diff --git a/src/include/blkdev.h b/src/include/blkdev.h index 12d4c5d..badc8f4 100644 --- a/src/include/blkdev.h +++ b/src/include/blkdev.h @@ -174,6 +174,7 @@ 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 unitnum, int quick); extern struct device_info *sys_command_info_session (int unitnum, struct device_info *di, int, int); +extern bool blkdev_get_info (struct uae_prefs *p, int unitnum, struct device_info *di); 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); @@ -181,6 +182,9 @@ extern void scsi_atapi_fixup_post (uae_u8 *scsi_cmd, int len, uae_u8 *olddata, u 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 int scsi_cd_emulate (int unitnum, uae_u8 *cmdbuf, int scsi_cmd_len, + uae_u8 *scsi_data, int *data_len, uae_u8 *r, int *reply_len, uae_u8 *s, int *sense_len); + extern void blkdev_vsync (void); extern int msf2lsn (int msf); diff --git a/src/include/cdtv.h b/src/include/cdtv.h index c63bf69..63d2e20 100644 --- a/src/include/cdtv.h +++ b/src/include/cdtv.h @@ -14,7 +14,7 @@ uae_u8 cdtv_battram_read (int addr); extern void cdtv_loadcardmem (uae_u8*, int); extern void cdtv_savecardmem (uae_u8*, int); -extern int cdtv_add_scsi_unit (int ch, struct uaedev_config_info *ci); +extern int cdtv_add_scsi_hd_unit (int ch, struct uaedev_config_info *ci); extern void cdtv_getdmadata (uae_u32*); diff --git a/src/include/cpummu.h b/src/include/cpummu.h index 5fdcea8..016a863 100644 --- a/src/include/cpummu.h +++ b/src/include/cpummu.h @@ -47,6 +47,11 @@ static __inline void flush_internals (void) { } extern int mmu060_state; +extern uae_u16 mmu060_opcode; + +extern int mmu040_movem; +extern uaecptr mmu040_movem_ea; + extern bool mmu_pagesize_8k; struct xttrx { @@ -341,6 +346,9 @@ extern void REGPARAM3 dfc_put_byte(uaecptr addr, uae_u8 val) REGPARAM; #define dfc060_put_word dfc_put_word #define dfc060_put_byte dfc_put_byte +extern void uae_mmu_put_rmw (uaecptr addr, uae_u32 v, int size, int type); +extern uae_u32 uae_mmu_get_rmw (uaecptr addr, int size, int type); + extern void REGPARAM3 mmu_flush_atc(uaecptr addr, bool super, bool global) REGPARAM; extern void REGPARAM3 mmu_flush_atc_all(bool global) REGPARAM; extern void REGPARAM3 mmu_op_real(uae_u32 opcode, uae_u16 extra) REGPARAM; @@ -354,7 +362,7 @@ static ALWAYS_INLINE uaecptr mmu_get_real_address(uaecptr addr, struct mmu_atc_l return cl->phys | (addr & mmu_pagemask); } -static ALWAYS_INLINE void mmu060_get_move16(uaecptr addr, uae_u32 *v, bool data, int size) +static ALWAYS_INLINE void mmu_get_move16(uaecptr addr, uae_u32 *v, bool data, int size) { struct mmu_atc_line *cl; for (int i = 0; i < 4; i++) { @@ -420,7 +428,7 @@ static ALWAYS_INLINE void mmu_put_long(uaecptr addr, uae_u32 val, bool data, int mmu_put_long_slow(addr, val, regs.s != 0, data, size, cl); } -static ALWAYS_INLINE void mmu060_put_move16(uaecptr addr, uae_u32 *val, bool data, int size) +static ALWAYS_INLINE void mmu_put_move16(uaecptr addr, uae_u32 *val, bool data, int size) { struct mmu_atc_line *cl; for (int i = 0; i < 4; i++) { @@ -465,38 +473,38 @@ static ALWAYS_INLINE void mmu_put_byte(uaecptr addr, uae_u8 val, bool data, int mmu_put_byte_slow(addr, val, regs.s != 0, data, size, cl); } -static ALWAYS_INLINE uae_u32 mmu_get_user_long(uaecptr addr, bool super, bool data, int size) +static ALWAYS_INLINE uae_u32 mmu_get_user_long(uaecptr addr, bool super, bool data, bool write, int size) { struct mmu_atc_line *cl; // addr,super,data if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data)!=TTR_NO_MATCH)) return phys_get_long(addr); - if (likely(mmu_user_lookup(addr, super, data, false, &cl))) + if (likely(mmu_user_lookup(addr, super, data, write, &cl))) return phys_get_long(mmu_get_real_address(addr, cl)); return mmu_get_long_slow(addr, super, data, size, cl); } -static ALWAYS_INLINE uae_u16 mmu_get_user_word(uaecptr addr, bool super, bool data, int size) +static ALWAYS_INLINE uae_u16 mmu_get_user_word(uaecptr addr, bool super, bool data, bool write, int size) { struct mmu_atc_line *cl; // addr,super,data if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data)!=TTR_NO_MATCH)) return phys_get_word(addr); - if (likely(mmu_user_lookup(addr, super, data, false, &cl))) + if (likely(mmu_user_lookup(addr, super, data, write, &cl))) return phys_get_word(mmu_get_real_address(addr, cl)); return mmu_get_word_slow(addr, super, data, size, cl); } -static ALWAYS_INLINE uae_u8 mmu_get_user_byte(uaecptr addr, bool super, bool data, int size) +static ALWAYS_INLINE uae_u8 mmu_get_user_byte(uaecptr addr, bool super, bool data, bool write, int size) { struct mmu_atc_line *cl; // addr,super,data if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data)!=TTR_NO_MATCH)) return phys_get_byte(addr); - if (likely(mmu_user_lookup(addr, super, data, false, &cl))) + if (likely(mmu_user_lookup(addr, super, data, write, &cl))) return phys_get_byte(mmu_get_real_address(addr, cl)); return mmu_get_byte_slow(addr, super, data, size, cl); } @@ -657,10 +665,10 @@ static ALWAYS_INLINE uae_u8 uae_mmu060_get_byte(uaecptr addr) { return mmu_get_byte(addr, true, sz_byte); } -static ALWAYS_INLINE void uae_mmu060_get_move16(uaecptr addr, uae_u32 *val) +static ALWAYS_INLINE void uae_mmu_get_move16(uaecptr addr, uae_u32 *val) { // move16 is always aligned - mmu060_get_move16(addr, val, true, 16); + mmu_get_move16(addr, val, true, 16); } static ALWAYS_INLINE void uae_mmu060_put_long(uaecptr addr, uae_u32 val) @@ -681,10 +689,10 @@ static ALWAYS_INLINE void uae_mmu060_put_byte(uaecptr addr, uae_u8 val) { mmu_put_byte(addr, val, true, sz_byte); } -static ALWAYS_INLINE void uae_mmu060_put_move16(uaecptr addr, uae_u32 *val) +static ALWAYS_INLINE void uae_mmu_put_move16(uaecptr addr, uae_u32 *val) { // move16 is always aligned - mmu060_put_move16(addr, val, true, 16); + mmu_put_move16(addr, val, true, 16); } @@ -738,13 +746,63 @@ STATIC_INLINE uae_u32 get_long_mmu060 (uaecptr addr) return uae_mmu060_get_long (addr); } -STATIC_INLINE void get_move16_mmu060 (uaecptr addr, uae_u32 *v) +STATIC_INLINE void get_move16_mmu (uaecptr addr, uae_u32 *v) { - return uae_mmu060_get_move16 (addr, v); + return uae_mmu_get_move16 (addr, v); } -STATIC_INLINE void put_move16_mmu060 (uaecptr addr, uae_u32 *v) +STATIC_INLINE void put_move16_mmu (uaecptr addr, uae_u32 *v) { - return uae_mmu060_put_move16 (addr, v); + return uae_mmu_put_move16 (addr, v); +} + +STATIC_INLINE void put_rmw_byte_mmu060 (uaecptr addr, uae_u32 v) +{ + uae_mmu_put_rmw (addr, v, sz_byte, 1); +} +STATIC_INLINE void put_rmw_word_mmu060 (uaecptr addr, uae_u32 v) +{ + uae_mmu_put_rmw (addr, v, sz_word, 1); +} +STATIC_INLINE void put_rmw_long_mmu060 (uaecptr addr, uae_u32 v) +{ + uae_mmu_put_rmw (addr, v, sz_long, 1); +} +STATIC_INLINE uae_u32 get_rmw_byte_mmu060 (uaecptr addr) +{ + return uae_mmu_get_rmw (addr, sz_byte, 1); +} +STATIC_INLINE uae_u32 get_rmw_word_mmu060 (uaecptr addr) +{ + return uae_mmu_get_rmw (addr, sz_word, 1); +} +STATIC_INLINE uae_u32 get_rmw_long_mmu060 (uaecptr addr) +{ + return uae_mmu_get_rmw (addr, sz_long, 1); +} + +STATIC_INLINE void put_rmw_byte_mmu040 (uaecptr addr, uae_u32 v) +{ + uae_mmu_put_rmw (addr, v, sz_byte, 0); +} +STATIC_INLINE void put_rmw_word_mmu040 (uaecptr addr, uae_u32 v) +{ + uae_mmu_put_rmw (addr, v, sz_word, 0); +} +STATIC_INLINE void put_rmw_long_mmu040 (uaecptr addr, uae_u32 v) +{ + uae_mmu_put_rmw (addr, v, sz_long, 0); +} +STATIC_INLINE uae_u32 get_rmw_byte_mmu040 (uaecptr addr) +{ + return uae_mmu_get_rmw (addr, sz_byte, 0); +} +STATIC_INLINE uae_u32 get_rmw_word_mmu040 (uaecptr addr) +{ + return uae_mmu_get_rmw (addr, sz_word, 0); +} +STATIC_INLINE uae_u32 get_rmw_long_mmu040 (uaecptr addr) +{ + return uae_mmu_get_rmw (addr, sz_long, 0); } STATIC_INLINE uae_u32 get_ibyte_mmu040 (int o) diff --git a/src/include/cpummu030.h b/src/include/cpummu030.h index 9ba1b82..0ae8b85 100644 --- a/src/include/cpummu030.h +++ b/src/include/cpummu030.h @@ -71,89 +71,95 @@ void mmu030_reset(int hardreset); uaecptr mmu030_translate(uaecptr addr, bool super, bool data, bool write); int mmu030_match_ttr(uaecptr addr, uae_u32 fc, bool write); +int mmu030_match_ttr_access(uaecptr addr, uae_u32 fc, bool write); +int mmu030_match_rmw_ttr(uaecptr addr, uae_u32 fc); int mmu030_do_match_ttr(uae_u32 tt, TT_info masks, uaecptr addr, uae_u32 fc, bool write); +int mmu030_do_match_rmw_ttr(uae_u32 tt, TT_info masks, uaecptr addr, uae_u32 fc); -void mmu030_put_long(uaecptr addr, uae_u32 val, uae_u32 fc, int size); -void mmu030_put_word(uaecptr addr, uae_u16 val, uae_u32 fc, int size); -void mmu030_put_byte(uaecptr addr, uae_u8 val, uae_u32 fc, int size); -uae_u32 mmu030_get_long(uaecptr addr, uae_u32 fc, int size); -uae_u16 mmu030_get_word(uaecptr addr, uae_u32 fc, int size); -uae_u8 mmu030_get_byte(uaecptr addr, uae_u32 fc, int size); +void mmu030_put_long(uaecptr addr, uae_u32 val, uae_u32 fc); +void mmu030_put_word(uaecptr addr, uae_u16 val, uae_u32 fc); +void mmu030_put_byte(uaecptr addr, uae_u8 val, uae_u32 fc); +uae_u32 mmu030_get_long(uaecptr addr, uae_u32 fc); +uae_u16 mmu030_get_word(uaecptr addr, uae_u32 fc); +uae_u8 mmu030_get_byte(uaecptr addr, uae_u32 fc); -void mmu030_page_fault(uaecptr addr, bool read, int size, uae_u32 fc); +uae_u32 uae_mmu030_get_rmw(uaecptr addr, int size); +void uae_mmu030_put_rmw(uaecptr addr, uae_u32 val, int size); -extern uae_u16 REGPARAM3 mmu030_get_word_unaligned(uaecptr addr, uae_u32 fc) REGPARAM; -extern uae_u32 REGPARAM3 mmu030_get_long_unaligned(uaecptr addr, uae_u32 fc) REGPARAM; -extern void REGPARAM3 mmu030_put_word_unaligned(uaecptr addr, uae_u16 val, uae_u32 fc) REGPARAM; -extern void REGPARAM3 mmu030_put_long_unaligned(uaecptr addr, uae_u32 val, uae_u32 fc) REGPARAM; +extern uae_u16 REGPARAM3 mmu030_get_word_unaligned(uaecptr addr, uae_u32 fc, int flags) REGPARAM; +extern uae_u32 REGPARAM3 mmu030_get_long_unaligned(uaecptr addr, uae_u32 fc, int flags) REGPARAM; +extern uae_u16 REGPARAM3 mmu030_get_rmw_word_unaligned(uaecptr addr, uae_u32 fc, int flags) REGPARAM; +extern uae_u32 REGPARAM3 mmu030_get_rmw_long_unaligned(uaecptr addr, uae_u32 fc, int flags) REGPARAM; +extern void REGPARAM3 mmu030_put_word_unaligned(uaecptr addr, uae_u16 val, uae_u32 fc, int flags) REGPARAM; +extern void REGPARAM3 mmu030_put_long_unaligned(uaecptr addr, uae_u32 val, uae_u32 fc, int flags) REGPARAM; static ALWAYS_INLINE uae_u32 uae_mmu030_get_ilong(uaecptr addr) { uae_u32 fc = (regs.s ? 4 : 0) | 2; if (unlikely(is_unaligned(addr, 4))) - return mmu030_get_long_unaligned(addr, fc); - return mmu030_get_long(addr, fc, sz_long); + return mmu030_get_long_unaligned(addr, fc, 0); + return mmu030_get_long(addr, fc); } static ALWAYS_INLINE uae_u16 uae_mmu030_get_iword(uaecptr addr) { uae_u32 fc = (regs.s ? 4 : 0) | 2; if (unlikely(is_unaligned(addr, 2))) - return mmu030_get_word_unaligned(addr, fc); - return mmu030_get_word(addr, fc, sz_word); + return mmu030_get_word_unaligned(addr, fc, 0); + return mmu030_get_word(addr, fc); } static ALWAYS_INLINE uae_u16 uae_mmu030_get_ibyte(uaecptr addr) { uae_u32 fc = (regs.s ? 4 : 0) | 2; - return mmu030_get_byte(addr, fc, sz_byte); + return mmu030_get_byte(addr, fc); } static ALWAYS_INLINE uae_u32 uae_mmu030_get_long(uaecptr addr) { uae_u32 fc = (regs.s ? 4 : 0) | 1; if (unlikely(is_unaligned(addr, 4))) - return mmu030_get_long_unaligned(addr, fc); - return mmu030_get_long(addr, fc, sz_long); + return mmu030_get_long_unaligned(addr, fc, 0); + return mmu030_get_long(addr, fc); } static ALWAYS_INLINE uae_u16 uae_mmu030_get_word(uaecptr addr) { uae_u32 fc = (regs.s ? 4 : 0) | 1; if (unlikely(is_unaligned(addr, 2))) - return mmu030_get_word_unaligned(addr, fc); - return mmu030_get_word(addr, fc, sz_word); + return mmu030_get_word_unaligned(addr, fc, 0); + return mmu030_get_word(addr, fc); } static ALWAYS_INLINE uae_u8 uae_mmu030_get_byte(uaecptr addr) { uae_u32 fc = (regs.s ? 4 : 0) | 1; - return mmu030_get_byte(addr, fc, sz_byte); + return mmu030_get_byte(addr, fc); } static ALWAYS_INLINE void uae_mmu030_put_long(uaecptr addr, uae_u32 val) { uae_u32 fc = (regs.s ? 4 : 0) | 1; if (unlikely(is_unaligned(addr, 4))) - mmu030_put_long_unaligned(addr, val, fc); + mmu030_put_long_unaligned(addr, val, fc, 0); else - mmu030_put_long(addr, val, fc, sz_long); + mmu030_put_long(addr, val, fc); } static ALWAYS_INLINE void uae_mmu030_put_word(uaecptr addr, uae_u16 val) { uae_u32 fc = (regs.s ? 4 : 0) | 1; if (unlikely(is_unaligned(addr, 2))) - mmu030_put_word_unaligned(addr, val, fc); + mmu030_put_word_unaligned(addr, val, fc, 0); else - mmu030_put_word(addr, val, fc, sz_word); + mmu030_put_word(addr, val, fc); } static ALWAYS_INLINE void uae_mmu030_put_byte(uaecptr addr, uae_u8 val) { uae_u32 fc = (regs.s ? 4 : 0) | 1; - mmu030_put_byte(addr, val, fc, sz_byte); + mmu030_put_byte(addr, val, fc); } static ALWAYS_INLINE uae_u32 sfc030_get_long(uaecptr addr) @@ -163,8 +169,8 @@ static ALWAYS_INLINE uae_u32 sfc030_get_long(uaecptr addr) write_log(_T("sfc030_get_long: FC = %i\n"),fc); #endif if (unlikely(is_unaligned(addr, 4))) - return mmu030_get_long_unaligned(addr, fc); - return mmu030_get_long(addr, fc, sz_long); + return mmu030_get_long_unaligned(addr, fc, 0); + return mmu030_get_long(addr, fc); } static ALWAYS_INLINE uae_u16 sfc030_get_word(uaecptr addr) @@ -174,8 +180,8 @@ static ALWAYS_INLINE uae_u16 sfc030_get_word(uaecptr addr) write_log(_T("sfc030_get_word: FC = %i\n"),fc); #endif if (unlikely(is_unaligned(addr, 2))) - return mmu030_get_word_unaligned(addr, fc); - return mmu030_get_word(addr, fc, sz_word); + return mmu030_get_word_unaligned(addr, fc, 0); + return mmu030_get_word(addr, fc); } static ALWAYS_INLINE uae_u8 sfc030_get_byte(uaecptr addr) @@ -184,7 +190,7 @@ static ALWAYS_INLINE uae_u8 sfc030_get_byte(uaecptr addr) #if MMUDEBUG > 1 write_log(_T("sfc030_get_byte: FC = %i\n"),fc); #endif - return mmu030_get_byte(addr, fc, sz_byte); + return mmu030_get_byte(addr, fc); } static ALWAYS_INLINE void dfc030_put_long(uaecptr addr, uae_u32 val) @@ -194,9 +200,9 @@ static ALWAYS_INLINE void dfc030_put_long(uaecptr addr, uae_u32 val) write_log(_T("dfc030_put_long: FC = %i\n"),fc); #endif if (unlikely(is_unaligned(addr, 4))) - mmu030_put_long_unaligned(addr, val, fc); + mmu030_put_long_unaligned(addr, val, fc, 0); else - mmu030_put_long(addr, val, fc, sz_long); + mmu030_put_long(addr, val, fc); } static ALWAYS_INLINE void dfc030_put_word(uaecptr addr, uae_u16 val) @@ -206,9 +212,9 @@ static ALWAYS_INLINE void dfc030_put_word(uaecptr addr, uae_u16 val) write_log(_T("dfc030_put_word: FC = %i\n"),fc); #endif if (unlikely(is_unaligned(addr, 2))) - mmu030_put_word_unaligned(addr, val, fc); + mmu030_put_word_unaligned(addr, val, fc, 0); else - mmu030_put_word(addr, val, fc, sz_word); + mmu030_put_word(addr, val, fc); } static ALWAYS_INLINE void dfc030_put_byte(uaecptr addr, uae_u8 val) @@ -217,7 +223,7 @@ static ALWAYS_INLINE void dfc030_put_byte(uaecptr addr, uae_u8 val) #if MMUDEBUG > 1 write_log(_T("dfc030_put_byte: FC = %i\n"),fc); #endif - mmu030_put_byte(addr, val, fc, sz_byte); + mmu030_put_byte(addr, val, fc); } #define ACCESS_CHECK_PUT \ @@ -260,18 +266,37 @@ STATIC_INLINE void put_byte_mmu030_state (uaecptr addr, uae_u32 v) uae_mmu030_put_byte (addr, v); ACCESS_EXIT_PUT } +STATIC_INLINE void put_rmw_byte_mmu030_state (uaecptr addr, uae_u32 v) +{ + ACCESS_CHECK_PUT + uae_mmu030_put_rmw (addr, v, sz_byte); + ACCESS_EXIT_PUT +} STATIC_INLINE void put_word_mmu030_state (uaecptr addr, uae_u32 v) { ACCESS_CHECK_PUT uae_mmu030_put_word (addr, v); ACCESS_EXIT_PUT } +STATIC_INLINE void put_rmw_word_mmu030_state (uaecptr addr, uae_u32 v) +{ + ACCESS_CHECK_PUT + uae_mmu030_put_rmw (addr, v, sz_word); + ACCESS_EXIT_PUT +} STATIC_INLINE void put_long_mmu030_state (uaecptr addr, uae_u32 v) { ACCESS_CHECK_PUT uae_mmu030_put_long (addr, v); ACCESS_EXIT_PUT } +STATIC_INLINE void put_rmw_long_mmu030_state (uaecptr addr, uae_u32 v) +{ + ACCESS_CHECK_PUT + uae_mmu030_put_rmw (addr, v, sz_long); + ACCESS_EXIT_PUT +} + STATIC_INLINE uae_u32 get_byte_mmu030_state (uaecptr addr) { uae_u32 v; @@ -280,6 +305,15 @@ STATIC_INLINE uae_u32 get_byte_mmu030_state (uaecptr addr) ACCESS_EXIT_GET return v; } +STATIC_INLINE uae_u32 get_rmw_byte_mmu030_state (uaecptr addr) +{ + uae_u32 v; + ACCESS_CHECK_GET + v = uae_mmu030_get_rmw (addr, sz_byte); + ACCESS_EXIT_GET + return v; +} + STATIC_INLINE uae_u32 get_word_mmu030_state (uaecptr addr) { uae_u32 v; @@ -288,6 +322,14 @@ STATIC_INLINE uae_u32 get_word_mmu030_state (uaecptr addr) ACCESS_EXIT_GET return v; } +STATIC_INLINE uae_u32 get_rmw_word_mmu030_state (uaecptr addr) +{ + uae_u32 v; + ACCESS_CHECK_GET + v = uae_mmu030_get_rmw (addr, sz_word); + ACCESS_EXIT_GET + return v; +} STATIC_INLINE uae_u32 get_long_mmu030_state (uaecptr addr) { uae_u32 v; @@ -296,6 +338,15 @@ STATIC_INLINE uae_u32 get_long_mmu030_state (uaecptr addr) ACCESS_EXIT_GET return v; } +STATIC_INLINE uae_u32 get_rmw_long_mmu030_state (uaecptr addr) +{ + uae_u32 v; + ACCESS_CHECK_GET + v = uae_mmu030_get_rmw (addr, sz_long); + ACCESS_EXIT_GET + return v; +} + STATIC_INLINE uae_u32 get_ibyte_mmu030_state (int o) { uae_u32 v; diff --git a/src/include/disk.h b/src/include/disk.h index 45db754..0f06b70 100644 --- a/src/include/disk.h +++ b/src/include/disk.h @@ -29,7 +29,7 @@ extern void DISK_hsync (void); extern void DISK_reset (void); extern int disk_getwriteprotect (struct uae_prefs *p, const TCHAR *name); extern int disk_setwriteprotect (struct uae_prefs *p, int num, const TCHAR *name, bool writeprotected); -//extern bool disk_creatediskfile (const TCHAR *name, int type, drive_type adftype, const TCHAR *disk_name, bool ffs, bool bootable, struct zfile *copyfrom); +extern bool disk_creatediskfile (const TCHAR *name, int type, drive_type adftype, const TCHAR *disk_name, bool ffs, bool bootable, struct zfile *copyfrom); extern void dumpdisk (void); extern int DISK_history_add (const TCHAR *name, int idx, int type, int donotcheck); extern TCHAR *DISK_history_get (int idx, int type); diff --git a/src/include/filesys.h b/src/include/filesys.h index 6e2140e..61e5671 100644 --- a/src/include/filesys.h +++ b/src/include/filesys.h @@ -121,7 +121,7 @@ extern struct uaedev_mount_info options_mountinfo; extern struct hardfiledata *get_hardfile_data (int nr); #define FILESYS_MAX_BLOCKSIZE 2048 -extern int hdf_open (struct hardfiledata *hfd, const TCHAR *name); +extern int hdf_open (struct hardfiledata *hfd, const TCHAR *altname); extern int hdf_dup (struct hardfiledata *dhfd, const struct hardfiledata *shfd); extern void hdf_close (struct hardfiledata *hfd); extern int hdf_read_rdb (struct hardfiledata *hfd, void *buffer, uae_u64 offset, int len); diff --git a/src/include/mmu_common.h b/src/include/mmu_common.h index a6bc8ed..0392794 100644 --- a/src/include/mmu_common.h +++ b/src/include/mmu_common.h @@ -54,55 +54,59 @@ typedef int m68k_exception; #define MMU_FSLW_LK 0x02000000 #define MMU_FSLW_R 0x01000000 #define MMU_FSLW_W 0x00800000 -#define MMU_FSLW_SIZE_B 0x00000000 -#define MMU_FSLW_SIZE_W 0x00400000 -#define MMU_FSLW_SIZE_L 0x00200000 -#define MMU_FSLW_SIZE_D 0x00600000 +#define MMU_FSLW_SIZE_L 0x00000000 /* Note: wrong in mc68060 manual! */ +#define MMU_FSLW_SIZE_B 0x00200000 +#define MMU_FSLW_SIZE_W 0x00400000 +#define MMU_FSLW_SIZE_D 0x00600000 #define MMU_FSLW_TT 0x00180000 -#define MMU_FSLW_TM 0x00070000 +#define MMU_FSLW_TT_N 0x00000000 /* Normal access */ +#define MMU_FSLW_TT_16 0x00080000 /* MOVE16 */ +#define MMU_FSLW_TM 0x00070000 /* = function code */ #define MMU_FSLW_IO 0x00008000 -#define MMU_FSLW_PBE 0x00004000 -#define MMU_FSLW_SBE 0x00002000 -#define MMU_FSLW_PTA 0x00001000 -#define MMU_FSLW_PTB 0x00000800 +#define MMU_FSLW_PBE 0x00004000 +#define MMU_FSLW_SBE 0x00002000 +#define MMU_FSLW_PTA 0x00001000 +#define MMU_FSLW_PTB 0x00000800 #define MMU_FSLW_IL 0x00000400 #define MMU_FSLW_PF 0x00000200 #define MMU_FSLW_SP 0x00000100 #define MMU_FSLW_WP 0x00000080 -#define MMU_FSLW_TWE 0x00000040 +#define MMU_FSLW_TWE 0x00000040 #define MMU_FSLW_RE 0x00000020 #define MMU_FSLW_WE 0x00000010 -#define MMU_FSLW_TTR 0x00000008 -#define MMU_FSLW_BPE 0x00000004 -#define MMU_FSLW_SEE 0x00000001 +#define MMU_FSLW_TTR 0x00000008 +#define MMU_FSLW_BPE 0x00000004 +#define MMU_FSLW_SEE 0x00000001 /* 68040 */ #define MMU_SSW_TM 0x0007 #define MMU_SSW_TT 0x0018 -#define MMU_SSW_SIZE 0x0060 -#define MMU_SSW_SIZE_B 0x0020 -#define MMU_SSW_SIZE_W 0x0040 -#define MMU_SSW_SIZE_L 0x0000 +#define MMU_SSW_TT1 0x0010 +#define MMU_SSW_TT0 0x0008 +#define MMU_SSW_SIZE 0x0060 +#define MMU_SSW_SIZE_B 0x0020 +#define MMU_SSW_SIZE_W 0x0040 +#define MMU_SSW_SIZE_L 0x0000 #define MMU_SSW_RW 0x0100 #define MMU_SSW_LK 0x0200 #define MMU_SSW_ATC 0x0400 #define MMU_SSW_MA 0x0800 -#define MMU_SSW_CM 0x1000 -#define MMU_SSW_CT 0x2000 -#define MMU_SSW_CU 0x4000 -#define MMU_SSW_CP 0x8000 +#define MMU_SSW_CM 0x1000 +#define MMU_SSW_CT 0x2000 +#define MMU_SSW_CU 0x4000 +#define MMU_SSW_CP 0x8000 /* 68030 */ -#define MMU030_SSW_FC 0x8000 -#define MMU030_SSW_FB 0x4000 -#define MMU030_SSW_RC 0x2000 -#define MMU030_SSW_RB 0x1000 -#define MMU030_SSW_DF 0x0100 -#define MMU030_SSW_RM 0x0080 -#define MMU030_SSW_RW 0x0040 -#define MMU030_SSW_SIZE_MASK 0x0030 -#define MMU030_SSW_SIZE_B 0x0010 -#define MMU030_SSW_SIZE_W 0x0020 -#define MMU030_SSW_SIZE_L 0x0000 -#define MMU030_SSW_FC_MASK 0x0007 +#define MMU030_SSW_FC 0x8000 +#define MMU030_SSW_FB 0x4000 +#define MMU030_SSW_RC 0x2000 +#define MMU030_SSW_RB 0x1000 +#define MMU030_SSW_DF 0x0100 +#define MMU030_SSW_RM 0x0080 +#define MMU030_SSW_RW 0x0040 +#define MMU030_SSW_SIZE_MASK 0x0030 +#define MMU030_SSW_SIZE_B 0x0010 +#define MMU030_SSW_SIZE_W 0x0020 +#define MMU030_SSW_SIZE_L 0x0000 +#define MMU030_SSW_FC_MASK 0x0007 #define ALWAYS_INLINE __inline diff --git a/src/include/newcpu.h b/src/include/newcpu.h index ec6ec6f..0784f95 100644 --- a/src/include/newcpu.h +++ b/src/include/newcpu.h @@ -417,6 +417,7 @@ extern int getDivu68kCycles (uae_u32 dividend, uae_u16 divisor); extern int getDivs68kCycles (uae_s32 dividend, uae_s16 divisor); extern void m68k_do_rte (void); extern void protect_roms (bool); +extern void unprotect_maprom (void); extern void mmu_op (uae_u32, uae_u32); extern void mmu_op30 (uaecptr, uae_u32, uae_u16, uaecptr); diff --git a/src/include/options.h b/src/include/options.h index 2796c02..0b13414 100644 --- a/src/include/options.h +++ b/src/include/options.h @@ -127,10 +127,11 @@ struct wh { }; #define MOUNT_CONFIG_SIZE 30 -#ifndef HAS_UAEDEV_CONFIG_INFO -# define HAS_UAEDEV_CONFIG_INFO 1 -#endif // HAS_UAEDEV_CONFIG_INFO +#define UAEDEV_DIR 0 +#define UAEDEV_HDF 1 +#define UAEDEV_CD 2 struct uaedev_config_info { + int type; TCHAR devname[MAX_DPATH]; TCHAR volname[MAX_DPATH]; TCHAR rootdir[MAX_DPATH]; @@ -160,6 +161,8 @@ struct uaedev_config_info { int unit; int interleave; int sectorsperblock; + int forceload; + int cd_emu_unit; }; @@ -167,7 +170,6 @@ struct uaedev_config_data { struct uaedev_config_info ci; int configoffset; - bool ishdf; }; enum { CP_GENERIC = 1, CP_CDTV, CP_CD32, CP_A500, CP_A500P, CP_A600, CP_A1000, @@ -641,7 +643,7 @@ extern void cfgfile_target_write_str (struct zfile *f, const TCHAR *option, cons extern void cfgfile_target_dwrite_str (struct zfile *f, const TCHAR *option, const TCHAR *value); extern void cfgfile_backup (const TCHAR *path); -extern struct uaedev_config_data *add_filesys_config (struct uae_prefs *p, int index, struct uaedev_config_info*, bool hdf); +extern struct uaedev_config_data *add_filesys_config (struct uae_prefs *p, int index, struct uaedev_config_info*); extern bool get_hd_geometry (struct uaedev_config_info *); extern void uci_set_defaults (struct uaedev_config_info *uci, bool rdb); diff --git a/src/include/savestate.h b/src/include/savestate.h index 742de89..beeba4a 100644 --- a/src/include/savestate.h +++ b/src/include/savestate.h @@ -134,8 +134,13 @@ extern uae_u8 *restore_cdtv (uae_u8 *src); extern uae_u8 *save_cdtv (int *len, uae_u8*); extern void restore_cdtv_finish (void); -extern uae_u8 *restore_dmac (uae_u8 *src); -extern uae_u8 *save_dmac (int *len, uae_u8*); +extern uae_u8 *restore_cdtv_dmac (uae_u8 *src); +extern uae_u8 *save_cdtv_dmac (int *len, uae_u8*); +extern uae_u8 *restore_scsi_dmac (uae_u8 *src); +extern uae_u8 *save_scsi_dmac (int *len, uae_u8*); + +extern uae_u8 *save_scsi_hd (int num, int *len, uae_u8 *dstptr); +extern uae_u8 *restore_scsi_hd (uae_u8 *src); extern uae_u8 *restore_filesys (uae_u8 *src); extern uae_u8 *save_filesys (int num, int *len); @@ -155,7 +160,7 @@ extern void restore_cd_finish (void); extern uae_u8 *save_configuration (int *len, bool fullconfig); extern uae_u8 *restore_configuration (uae_u8 *src); extern uae_u8 *save_log (int, int *len); -extern uae_u8 *restore_log (uae_u8 *src); +//extern uae_u8 *restore_log (uae_u8 *src); extern uae_u8 *restore_input (uae_u8 *src); extern uae_u8 *save_input (int *len, uae_u8 *dstptr); diff --git a/src/include/scsi.h b/src/include/scsi.h index db47e17..7c79e74 100644 --- a/src/include/scsi.h +++ b/src/include/scsi.h @@ -2,37 +2,36 @@ #define SCSI_DATA_BUFFER_SIZE (512 * 512) struct scsi_data { - int id; - int len; - uae_u8 *data; - int data_len; - int status; - uae_u8 sense[256]; - int sense_len; - uae_u8 reply[256]; - uae_u8 cmd[16]; - int reply_len; - int direction; + int id; + int cmd_len; + uae_u8 *data; + int data_len; + int status; + uae_u8 sense[256]; + int sense_len; + uae_u8 reply[256]; + uae_u8 cmd[16]; + int reply_len; + int direction; - int offset; - uae_u8 buffer[SCSI_DATA_BUFFER_SIZE]; - struct hd_hardfiledata *hfd; - int nativescsiunit; + int offset; + uae_u8 buffer[SCSI_DATA_BUFFER_SIZE]; + struct hd_hardfiledata *hfd; + int nativescsiunit; + int cd_emu_unit; }; -extern struct scsi_data *scsi_alloc(int,struct hd_hardfiledata*); +extern struct scsi_data *scsi_alloc_hd(int, struct hd_hardfiledata*); +extern struct scsi_data *scsi_alloc_cd(int, int); extern struct scsi_data *scsi_alloc_native(int,int); extern void scsi_free(struct scsi_data*); extern void scsi_reset(void); -extern void scsi_start_transfer(struct scsi_data*,int); +extern void scsi_start_transfer(struct scsi_data*); extern int scsi_send_data(struct scsi_data*, uae_u8); extern int scsi_receive_data(struct scsi_data*, uae_u8*); extern void scsi_emulate_cmd(struct scsi_data *sd); -extern int scsi_data_dir(struct scsi_data *sd); - -extern int scsi_emulate(struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, uae_u8 *cmdbuf, int scsi_cmd_len, +extern int scsi_hd_emulate(struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, uae_u8 *cmdbuf, int scsi_cmd_len, uae_u8 *scsi_data, int *data_len, uae_u8 *r, int *reply_len, uae_u8 *s, int *sense_len); - - +extern void scsi_emulate_analyze (struct scsi_data*); \ No newline at end of file diff --git a/src/include/zfile.h b/src/include/zfile.h index bdaa08f..8f2725d 100644 --- a/src/include/zfile.h +++ b/src/include/zfile.h @@ -121,7 +121,7 @@ extern struct zvolume *zfile_fopen_archive_flags (const TCHAR *filename, int fla extern struct zvolume *zfile_fopen_archive_root (const TCHAR *filename, int flags); extern void zfile_fclose_archive (struct zvolume *zv); extern int zfile_fs_usage_archive (const TCHAR *path, const TCHAR *disk, struct fs_usage *fsp); -extern int zfile_stat_archive (const TCHAR *path, struct mystat *s); +extern int zfile_stat_archive (const TCHAR *path, struct mystat *statbuf); extern struct zdirectory *zfile_opendir_archive (const TCHAR *path); extern struct zdirectory *zfile_opendir_archive2 (const TCHAR *path, int flags); extern void zfile_closedir_archive (struct zdirectory *); diff --git a/src/newcpu.c b/src/newcpu.c index c8fd507..fa467e6 100644 --- a/src/newcpu.c +++ b/src/newcpu.c @@ -4295,7 +4295,7 @@ retry: for (;;) { pc = regs.instruction_pc = m68k_getpc (); mmu060_state = 0; - opcode = x_prefetch (0); + mmu060_opcode = opcode = x_prefetch (0); mmu060_state = 1; count_instr (opcode); do_cycles (cpu_cycles); @@ -4403,8 +4403,8 @@ insretry: pc = regs.instruction_pc = m68k_getpc (); mmu030_state[0] = mmu030_state[1] = mmu030_state[2] = 0; -#if 1 - if (pc == 0x1000) { +#if 0 + if (pc == 0x00109FFC) { write_log (_T("*")); //activate_debugger (); } @@ -5090,13 +5090,16 @@ void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cn } pc += 2; } else if (lookup->mnemo == i_MVMEL) { + uae_u16 mask = get_word_debug (pc); + pc += 2; pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode); _tcscat (instrname, _T(",")); - movemout (instrname, get_word_debug (pc), dp->dmode); + movemout (instrname, mask, dp->dmode); pc += 2; } else if (lookup->mnemo == i_MVMLE) { - movemout (instrname, get_word_debug (pc), dp->dmode); + uae_u16 mask = get_word_debug (pc); pc += 2; + movemout (instrname, mask, dp->dmode); _tcscat (instrname, _T(",")); pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode); } else { @@ -5123,12 +5126,13 @@ void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cn buf = buf_out (buf, &bufsize, _T(" ]")); if (ccpt != 0) { + uaecptr addr2 = deaddr2 ? deaddr2 : seaddr2; if (deaddr) *deaddr = pc; if (cctrue (dp->cc)) - buf = buf_out (buf, &bufsize, _T(" == $%08x (T)"), seaddr2); + buf = buf_out (buf, &bufsize, _T(" == $%08x (T)"), addr2); else - buf = buf_out (buf, &bufsize, _T(" == $%08x (F)"), seaddr2); + buf = buf_out (buf, &bufsize, _T(" == $%08x (F)"), addr2); } else if ((opcode & 0xff00) == 0x6100) { /* BSR */ if (deaddr) *deaddr = pc; diff --git a/src/od-generic/memory.c b/src/od-generic/memory.c index c283293..3f48dec 100644 --- a/src/od-generic/memory.c +++ b/src/od-generic/memory.c @@ -404,8 +404,8 @@ bool preinit_shm (void) } natmem_size = (max_allowed_mman + 1) * 1024 * 1024; - if (natmem_size < 256 * 1024 * 1024) - natmem_size = 256 * 1024 * 1024; + if (natmem_size < 17 * 1024 * 1024) + natmem_size = 17 * 1024 * 1024; write_log (_T("Total physical RAM %lluM, all RAM %lluM. Attempting to reserve: %uM.\n"), totalphys64 >> 20, total64 >> 20, natmem_size >> 20); natmem_offset = 0; @@ -429,12 +429,23 @@ bool preinit_shm (void) break; natmem_size -= 128 * 1024 * 1024; if (!natmem_size) { - write_log (_T("Can't allocate 256M of virtual address space!?\n")); - return false; + write_log (_T("Can't allocate 257M of virtual address space!?\n")); + natmem_size = 17 * 1024 * 1024; + natmem_offset = (uae_u8*)VirtualAlloc (NULL, natmem_size, MEM_RESERVE, PAGE_READWRITE); +// natmem_offset = (uae_u8*)VirtualAlloc (NULL, natmem_size, MEM_RESERVE | (VAMODE == 1 ? MEM_WRITE_WATCH : 0), PAGE_READWRITE); + if (!natmem_size) { + write_log (_T("Can't allocate 17M of virtual address space!? Something is seriously wrong\n")); + return false; + } + break; } } } - max_z3fastmem = natmem_size; + if (natmem_size <= 257 * 1024 * 1024) + max_z3fastmem = 0; + else + max_z3fastmem = natmem_size; + write_log (_T("Reserved: 0x%08X-0x%08X (%08x %dM)\n"), natmem_offset, (uae_u8*)natmem_offset + natmem_size, natmem_size, natmem_size >> 20); @@ -822,6 +833,8 @@ void *my_shmat (int shmid, void *shmaddr, int shmflg) size += BARRIER; } else if(!_tcscmp (shmids[shmid].name, _T("ramsey_low"))) { shmaddr=natmem_offset + a3000lmem_start; + if (!a3000hmem_start) + size += BARRIER; got = true; } else if(!_tcscmp (shmids[shmid].name, _T("ramsey_high"))) { shmaddr=natmem_offset + a3000hmem_start; diff --git a/src/rommgr.c b/src/rommgr.c index 45d4110..c57fb33 100644 --- a/src/rommgr.c +++ b/src/rommgr.c @@ -177,7 +177,7 @@ static struct romdata roms[] = { { _T("Freezer: X-Power Professional 500 v1.3"), 1, 2, 1, 2, _T("XPOWER\0"), 131072, 68, 0, 0, ROMTYPE_XPOWER, 0, 1, NULL, 0x31e057f0, { 0x84650266, 0x465d1859, 0x7fd71dee, 0x00775930, 0xb7e450ee }, NULL }, { _T("Freezer: Nordic Power v1.5"), 1, 5, 1, 5, _T("NPOWER\0"), 65536, 69, 0, 0, ROMTYPE_NORDIC, 0, 1, NULL, 0x83b4b21c, { 0xc56ced25, 0x506a5aab, 0x3fa13813, 0x4fc9e5ae, 0x0f9d3709 }, NULL }, { _T("Freezer: Nordic Power v3.0"), 3, 0, 3, 0, _T("NPOWER\0"), 65536, 70, 0, 0, ROMTYPE_NORDIC, 0, 1, NULL, 0x72850aef, { 0x59c91d1f, 0xa8f118f9, 0x0bdba05a, 0x9ae788d7, 0x7a6cc7c9 }, NULL }, - { _T("KS ROM v2.04 (A3000)"), 2, 4, 37, 175, _T("A3000\0"), 524288, 71, 3, 0, ROMTYPE_KICK, 0, 0, NULL, 0x234a7233, { 0xd82ebb59, 0xafc53540, 0xddf2d718, 0x7ecf239b, 0x7ea91590 }, NULL }, + { _T("KS ROM v2.04 (A3000)"), 2, 4, 37, 175, _T("A3000\0"), 524288, 71, 8, 0, ROMTYPE_KICK, 0, 0, NULL, 0x234a7233, { 0xd82ebb59, 0xafc53540, 0xddf2d718, 0x7ecf239b, 0x7ea91590 }, NULL }, { _T("The Diagnostic 2.0 (Logica)"), 2, 0, 2, 0, _T("LOGICA\0"), 524288, 72, 0, 0, ROMTYPE_KICK_SPC, 0, 0, NULL, 0x8484f426, { 0xba10d161, 0x66b2e2d6, 0x177c979c, 0x99edf846, 0x2b21651e }, NULL }, { _T("Cloanto Amiga Forever 2010 ROM key"), 0, 0, 0, 0, NULL, 1544, 73, 0, 1, ROMTYPE_KEY, 0, 0, NULL, 0x8c4dd05c, { 0x05034f62, 0x0b5bb7b2, 0x86954ea9, 0x164fdb90, 0xfb2897a4 }, NULL }, /* Format of the ALTROMPN() macro: (Please keep valid!) diff --git a/src/scsi.c b/src/scsi.c index a012cfd..8169d4f 100644 --- a/src/scsi.c +++ b/src/scsi.c @@ -16,8 +16,8 @@ #include "blkdev.h" static int outcmd[] = { 0x0a, 0x2a, 0x2f, 0xaa, -1 }; -static int incmd[] = { 0x03, 0x08, 0x12, 0x1a, 0x25, 0x28, 0x37, 0x42, 0x43, 0xa8, -1 }; -static int nonecmd[] = { 0x00, 0x35, -1 }; +static int incmd[] = { 0x03, 0x08, 0x12, 0x1a, 0x25, 0x28, 0x37, 0x42, 0x43, 0xa8, 0x51, 0x52, -1 }; +static int nonecmd[] = { 0x00, 0x1b, 0x1e, 0x35, -1 }; static int scsi_data_dir(struct scsi_data *sd) { @@ -40,8 +40,8 @@ static int scsi_data_dir(struct scsi_data *sd) return 0; } } - write_log (_T("SCSI command %02X, no direction specified (IN?)!\n"), sd->cmd[0]); - return -2; + write_log (_T("SCSI command %02X, no direction specified!\n"), sd->cmd[0]); + return 0; } void scsi_emulate_analyze (struct scsi_data *sd) @@ -67,6 +67,9 @@ void scsi_emulate_analyze (struct scsi_data *sd) case 0x25: case 0x28: case 0x35: + case 0x51: + case 0x52: + case 0x43: cmd_len = 10; break; case 0xa8: @@ -84,19 +87,36 @@ void scsi_emulate_analyze (struct scsi_data *sd) void scsi_emulate_cmd(struct scsi_data *sd) { sd->status = 0; - if (sd->cmd[0] == 0x03) { /* REQUEST SENSE */ - int len = sd->cmd[4]; - memset (sd->buffer, 0, len); - memcpy (sd->buffer, sd->sense, sd->sense_len > len ? len : sd->sense_len); - sd->data_len = len; - sd->status = 0; + //write_log (_T("CMD=%02x\n"), sd->cmd[0]); + if (sd->cd_emu_unit >= 0) { + if (sd->cmd[0] == 0x03) { /* REQUEST SENSE */ + int len = sd->cmd[4]; + memset (sd->buffer, 0, len); + memcpy (sd->buffer, sd->sense, sd->sense_len > len ? len : sd->sense_len); + sd->data_len = len; + } else { + sd->status = scsi_cd_emulate(sd->cd_emu_unit, sd->cmd, sd->cmd_len, sd->buffer, &sd->data_len, sd->reply, &sd->reply_len, sd->sense, &sd->sense_len); + if (sd->status == 0) { + if (sd->reply_len > 0) { + memset(sd->buffer, 0, 256); + memcpy(sd->buffer, sd->reply, sd->reply_len); + } + } + } } else if (sd->nativescsiunit < 0) { - sd->status = scsi_emulate(&sd->hfd->hfd, sd->hfd, - sd->cmd, sd->cmd_len, sd->buffer, &sd->data_len, sd->reply, &sd->reply_len, sd->sense, &sd->sense_len); - if (sd->status == 0) { - if (sd->reply_len > 0) { - memset(sd->buffer, 0, 256); - memcpy(sd->buffer, sd->reply, sd->reply_len); + if (sd->cmd[0] == 0x03) { /* REQUEST SENSE */ + int len = sd->cmd[4]; + memset (sd->buffer, 0, len); + memcpy (sd->buffer, sd->sense, sd->sense_len > len ? len : sd->sense_len); + sd->data_len = len; + } else { + sd->status = scsi_hd_emulate(&sd->hfd->hfd, sd->hfd, + sd->cmd, sd->cmd_len, sd->buffer, &sd->data_len, sd->reply, &sd->reply_len, sd->sense, &sd->sense_len); + if (sd->status == 0) { + if (sd->reply_len > 0) { + memset(sd->buffer, 0, 256); + memcpy(sd->buffer, sd->reply, sd->reply_len); + } } } } else { @@ -124,12 +144,27 @@ void scsi_emulate_cmd(struct scsi_data *sd) sd->offset = 0; } -struct scsi_data *scsi_alloc(int id, struct hd_hardfiledata *hfd) +struct scsi_data *scsi_alloc_hd(int id, struct hd_hardfiledata *hfd) { struct scsi_data *sd = xcalloc (struct scsi_data, 1); sd->hfd = hfd; sd->id = id; sd->nativescsiunit = -1; + sd->cd_emu_unit = -1; + return sd; +} + +struct scsi_data *scsi_alloc_cd(int id, int unitnum) +{ + struct scsi_data *sd; + if (!sys_command_open (unitnum)) { + write_log (_T("SCSI: CD EMU scsi unit %d failed to open\n"), unitnum); + return NULL; + } + sd = xcalloc (struct scsi_data, 1); + sd->id = id; + sd->cd_emu_unit = unitnum; + sd->nativescsiunit = -1; return sd; } @@ -143,6 +178,7 @@ struct scsi_data *scsi_alloc_native(int id, int nativeunit) sd = xcalloc (struct scsi_data, 1); sd->id = id; sd->nativescsiunit = nativeunit; + sd->cd_emu_unit = -1; return sd; } @@ -157,6 +193,11 @@ void scsi_free(struct scsi_data *sd) return; if (sd->nativescsiunit >= 0) { sys_command_close (sd->nativescsiunit); + sd->nativescsiunit = -1; + } + if (sd->cd_emu_unit >= 0) { + sys_command_close (sd->cd_emu_unit); + sd->cd_emu_unit = -1; } xfree(sd); }