From: Toni Wilen Date: Sun, 20 Jan 2013 13:37:53 +0000 (+0200) Subject: 2600b2 X-Git-Tag: 2600~19 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=84c86102a73d81bdc0d72f78e3db765945e45b77;p=francis%2Fwinuae.git 2600b2 --- diff --git a/a2091.cpp b/a2091.cpp index d19dcfcf..e9b1c3b6 100644 --- a/a2091.cpp +++ b/a2091.cpp @@ -9,7 +9,7 @@ #define A2091_DEBUG 0 #define A3000_DEBUG 0 -#define WD33C93_DEBUG 1 +#define WD33C93_DEBUG 0 #define WD33C93_DEBUG_PIO 0 #include "sysconfig.h" @@ -340,7 +340,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++; @@ -418,7 +418,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 */ @@ -775,6 +775,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); } @@ -840,7 +843,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); @@ -913,7 +916,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; @@ -1532,7 +1535,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; @@ -1543,7 +1546,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; } @@ -1605,7 +1616,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) @@ -1621,7 +1635,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); } @@ -1759,6 +1776,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 @@ -1794,7 +1813,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 (); @@ -1812,7 +1831,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/blkdev.cpp b/blkdev.cpp index a8d62c04..3b1490b9 100644 --- a/blkdev.cpp +++ b/blkdev.cpp @@ -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) @@ -324,16 +325,16 @@ static int getunitinfo (int unitnum, int drive, cd_standard_unit csu, int *isaud return 0; } -static int get_standard_cd_unit2 (cd_standard_unit csu) +static int get_standard_cd_unit2 (struct uae_prefs *p, cd_standard_unit 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 { @@ -371,7 +372,7 @@ fallback: int get_standard_cd_unit (cd_standard_unit csu) { - int unitnum = get_standard_cd_unit2 (csu); + int unitnum = get_standard_cd_unit2 (&currprefs, csu); if (unitnum < 0) return -1; #ifdef RETROPLATFORM @@ -396,6 +397,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; @@ -449,6 +456,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++) { @@ -1121,7 +1145,7 @@ static int scsi_read_cd (int unitnum, uae_u8 *cmd, uae_u8 *data, struct device_i return sys_command_cd_rawread (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; @@ -1150,14 +1174,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 */ @@ -1414,6 +1445,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)) @@ -1425,6 +1511,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; @@ -1458,23 +1545,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; @@ -1524,10 +1612,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; @@ -1635,7 +1719,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); @@ -1762,7 +1846,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/blkdev_cdimage.cpp b/blkdev_cdimage.cpp index 23c527a2..ffdbfafe 100644 --- a/blkdev_cdimage.cpp +++ b/blkdev_cdimage.cpp @@ -86,8 +86,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; @@ -1705,7 +1704,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); @@ -1718,6 +1717,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; } @@ -1737,8 +1739,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; @@ -1752,6 +1756,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/cdtv.cpp b/cdtv.cpp index d8254914..e49c9a80 100644 --- a/cdtv.cpp +++ b/cdtv.cpp @@ -1656,9 +1656,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/cfgfile.cpp b/cfgfile.cpp index 09e4acea..b9437a63 100644 --- a/cfgfile.cpp +++ b/cfgfile.cpp @@ -533,7 +533,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); @@ -542,7 +542,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, @@ -556,7 +556,8 @@ static void write_filesys_config (struct uae_prefs *p, struct zfile *f) _stprintf (s, _T(",%d/%d/%d"), ci->pcyls, ci->pheads, ci->psecs); } } - cfgfile_write_str (f, _T("hardfile2"), tmp); + if (ci->type == UAEDEV_HDF) + cfgfile_write_str (f, _T("hardfile2"), tmp); #if 0 _stprintf (tmp2, _T("hardfile=%s,%d,%d,%d,%d,%s"), uci->readonly ? "ro" : "rw", uci->sectors, @@ -565,7 +566,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); } } @@ -2309,7 +2314,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; @@ -2320,8 +2325,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 { @@ -2331,18 +2346,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")); @@ -2358,7 +2372,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); @@ -2496,6 +2510,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; @@ -2540,7 +2556,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; @@ -2563,7 +2579,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; @@ -2585,7 +2602,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; @@ -2624,6 +2641,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; @@ -2637,13 +2664,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; } @@ -2656,21 +2683,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; + } + } else if (_tcsicmp (value, _T("dir")) != 0) { + type = 0; + return 1; /* ignore for now */ } -#if 0 // not yet - return cfgfile_parse_newfilesys (p, i, hdf, tmpp); -#else + 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)] == '_') { @@ -2744,7 +2779,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; @@ -2755,9 +2791,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; } @@ -3749,7 +3785,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")); diff --git a/consolehook.cpp b/consolehook.cpp index a81f8e18..28f76f44 100644 --- a/consolehook.cpp +++ b/consolehook.cpp @@ -54,7 +54,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/cpummu.cpp b/cpummu.cpp index a65db594..64b52a94 100644 --- a/cpummu.cpp +++ b/cpummu.cpp @@ -42,11 +42,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); @@ -247,7 +253,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; @@ -258,21 +264,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; @@ -286,24 +316,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); } @@ -351,10 +396,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; @@ -375,7 +417,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(); @@ -398,14 +440,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); } @@ -536,6 +578,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 @@ -559,6 +602,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) { @@ -682,13 +782,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) { @@ -699,12 +799,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) { @@ -725,12 +825,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) { @@ -748,7 +848,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) @@ -842,13 +942,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); } @@ -959,8 +1059,9 @@ void REGPARAM2 mmu_set_tc(uae_u16 tc) { regs.mmu_enabled = (tc & 0x8000) != 0; mmu_pagesize_8k = (tc & 0x4000) != 0; - mmu_tagmask = mmu_pagesize_8k ? 0xFFFF0000 : 0xFFFF8000; + 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); @@ -984,6 +1085,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) @@ -1016,6 +1121,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/cpummu30.cpp b/cpummu30.cpp index 584cc255..a056e6a7 100644 --- a/cpummu30.cpp +++ b/cpummu30.cpp @@ -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,10 +515,12 @@ 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")); write_log(_T("TRANSPARENT TRANSLATION: %08X\n"), TT); @@ -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,22 @@ 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); + addr, regs.mmu_ssw, read, (flags & MMU030_SSW_SIZE_B) ? 1 : (flags & MMU030_SSW_SIZE_W) ? 2 : 4, fc, regs.instruction_pc); #endif + +// extern void activate_debugger(void); +// activate_debugger (); + THROW(2); } @@ -1537,7 +1582,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 +1601,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 +1620,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 +1639,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 +1658,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 +1677,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 +1796,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 +1814,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 +1832,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 +1850,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 +1867,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 +1884,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 +1902,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 +2033,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 +2049,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 +2066,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 +2088,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 +2112,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 +2133,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 +2170,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 +2183,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 +2215,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/custom.cpp b/custom.cpp index a1256a44..0aec4b1d 100644 --- a/custom.cpp +++ b/custom.cpp @@ -2977,7 +2977,7 @@ void compute_framesync (void) int start = hbstrt; int stop = hbstop; - gfxvidinfo.drawbuffer.inwidth = (((start > stop ? (maxhpos - (maxhpos - start + stop)) : (maxhpos - (stop - start) + 2)) * 2) << res2); + gfxvidinfo.drawbuffer.inwidth = (((start > stop ? (maxhpos - (maxhpos - start + stop)) : (maxhpos - (stop - start) + 2)) * 2) << res2); gfxvidinfo.drawbuffer.inxoffset = ((stop + 1) & ~1) * 2; gfxvidinfo.drawbuffer.extrawidth = 0; diff --git a/debug.cpp b/debug.cpp index cd3416f3..42c74411 100644 --- a/debug.cpp +++ b/debug.cpp @@ -188,9 +188,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) { } @@ -208,9 +208,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) { } @@ -228,9 +228,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) { } diff --git a/expansion.cpp b/expansion.cpp index dbeb9cf5..df2b5472 100644 --- a/expansion.cpp +++ b/expansion.cpp @@ -953,7 +953,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/filesys.cpp b/filesys.cpp index 8f18ba0c..73f099da 100644 --- a/filesys.cpp +++ b/filesys.cpp @@ -295,9 +295,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; @@ -309,7 +310,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)) { @@ -326,23 +327,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) @@ -499,6 +518,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) @@ -757,7 +777,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 } @@ -6051,6 +6071,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; } @@ -6563,8 +6591,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); @@ -6603,17 +6633,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) { @@ -6623,8 +6654,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); @@ -6637,6 +6670,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")); @@ -6645,6 +6679,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; @@ -6764,6 +6799,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/gayle.cpp b/gayle.cpp index 17be2859..a9671e37 100644 --- a/gayle.cpp +++ b/gayle.cpp @@ -26,6 +26,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 @@ -75,7 +77,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 */ @@ -84,12 +86,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 @@ -97,6 +100,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 @@ -165,13 +173,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; @@ -179,14 +190,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 @@ -194,7 +210,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; @@ -251,22 +267,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) @@ -405,26 +429,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) @@ -436,7 +459,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 (); @@ -445,8 +468,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) @@ -457,7 +480,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; } @@ -477,8 +500,11 @@ static void ide_identify_drive (void) pw (20, 3); pw (21, ide->blocksize); pw (22, 4); - ps (23, _T("0.4"), 8); /* firmware revision */ - _stprintf (tmp, _T("UAE-IDE %s"), ide->hdhfd.hfd.product_id); + 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 */ pw (48, 1); @@ -492,9 +518,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); @@ -527,27 +553,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; @@ -555,8 +585,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); @@ -564,33 +594,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; } } @@ -599,22 +629,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; } } @@ -622,21 +652,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) { @@ -647,11 +677,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; } } } @@ -660,7 +690,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) @@ -702,7 +732,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 (); } @@ -718,7 +748,7 @@ static void ide_write_sectors (int flags) ide_fail (); return; } - check_maxtransfer(1); + check_maxtransfer (1); gui_flicker_led (LED_HD, ide->num, 2); nsec = get_nsec (lba48); get_lbachs (ide, &lba, &cyl, &head, &sec, lba48); @@ -738,18 +768,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) @@ -758,63 +794,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); } - } - 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 + } 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 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); + } + } +} + +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 { - ide_fail (); - write_log (_T("IDE%d: unknown command %x\n"), ide->num, cmd); + // 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) @@ -829,49 +922,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 (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; } - 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; + 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 (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); } if (irq) { ide_interrupt (); @@ -898,28 +1007,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->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) { + if (ide->data_size == 0) { + 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 (); @@ -929,7 +1054,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; @@ -940,74 +1065,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_STATUS_DRDY | IDE_STATUS_DSC; + 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; @@ -1015,7 +1150,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) @@ -1023,39 +1158,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; } } @@ -1066,7 +1207,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 @@ -1092,7 +1233,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; @@ -1104,7 +1245,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; @@ -1562,8 +1703,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; + } } } @@ -1575,14 +1718,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; } @@ -1610,7 +1777,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 @@ -2260,8 +2427,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); @@ -2296,11 +2468,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; @@ -2340,19 +2507,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")); } @@ -2440,19 +2608,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); @@ -2481,19 +2649,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/gencpu.cpp b/gencpu.cpp index 2858dac1..d58a05a9 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -52,6 +52,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 @@ -78,6 +80,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; @@ -472,6 +476,26 @@ static void sync_m68k_pc (void) m68k_pc_offset = 0; } +static void addmmufixup (char *reg) +{ + if (!using_mmu) + return; + if (using_mmu == 68040 && (mmufixupstate || mmufixupcnt > 0)) + return; + printf ("\tmmufixup[%d].reg = %s;\n", mmufixupcnt, reg); + printf ("\tmmufixup[%d].value = m68k_areg (regs, %s);\n", mmufixupcnt, reg); + mmufixupstate |= 1 << mmufixupcnt; + mmufixupcnt++; +} + +static void clearmmufixup (int cnt) +{ + if (mmufixupstate & (1 << cnt)) { + printf ("\tmmufixup[%d].reg = -1;\n", cnt); + mmufixupstate &= ~(1 << cnt); + } +} + static void gen_set_fault_pc (void) { if (using_mmu != 68040) @@ -479,8 +503,20 @@ static void gen_set_fault_pc (void) 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 @@ -494,26 +530,6 @@ static void syncmovepc (int getv, int flags) } -static void addmmufixup (char *reg) -{ - if (!using_mmu) - return; - if (using_mmu == 68040 && (mmufixupstate || mmufixupcnt > 0)) - return; - printf ("\tmmufixup[%d].reg = %s;\n", mmufixupcnt, reg); - printf ("\tmmufixup[%d].value = m68k_areg (regs, %s);\n", mmufixupcnt, reg); - mmufixupstate |= 1 << mmufixupcnt; - mmufixupcnt++; -} - -static void clearmmufixup (int cnt) -{ - if (mmufixupstate & (1 << cnt)) { - printf ("\tmmufixup[%d].reg = -1;\n", cnt); - mmufixupstate &= ~(1 << cnt); - } -} - /* 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 */ @@ -618,6 +634,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; @@ -633,7 +650,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) @@ -643,6 +662,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; @@ -774,9 +794,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 (); } } @@ -817,6 +837,10 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g default: break; } + + if (movem == 3) { + close_brace (); + } } @@ -869,7 +893,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: @@ -922,7 +947,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; @@ -931,7 +956,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; @@ -940,7 +965,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 (); @@ -987,6 +1012,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); @@ -996,6 +1029,93 @@ 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; + if (apdi) { + dphase = 1; aphase = 0; + index = "movem_index2"; + } else { + dphase = 0; aphase = 1; + index = "movem_index1"; + } + + for (int 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; + + 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 (int 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) */ @@ -1057,10 +1177,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); @@ -1117,14 +1241,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"); @@ -1132,9 +1261,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", @@ -1523,6 +1655,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 @@ -1621,6 +1759,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"; @@ -1641,6 +1785,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"; @@ -1657,6 +1807,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"; @@ -1702,6 +1858,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; @@ -3258,10 +3422,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"); @@ -3275,40 +3443,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 (); - printf ("\tif (GET_ZFLG ())"); + 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"); @@ -3317,13 +3494,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"); @@ -3533,7 +3710,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); @@ -3542,7 +3719,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"); @@ -3618,9 +3795,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); @@ -3641,9 +3818,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/hardfile.cpp b/hardfile.cpp index 350dcfd5..ddbe7a71 100644 --- a/hardfile.cpp +++ b/hardfile.cpp @@ -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/include/a2091.h b/include/a2091.h index a2225999..d00edd49 100644 --- a/include/a2091.h +++ b/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/include/autoconf.h b/include/autoconf.h index 6638e56b..6162786d 100644 --- a/include/autoconf.h +++ b/include/autoconf.h @@ -52,10 +52,11 @@ extern uaecptr need_uae_boot_rom (void); struct mountedinfo { - uae_u64 size; + uae_s64 size; bool ismounted; bool ismedia; int nrcyls; + TCHAR rootdir[MAX_DPATH]; }; extern int add_filesys_unitconfig (struct uae_prefs *p, int index, TCHAR *error); diff --git a/include/blkdev.h b/include/blkdev.h index 52f13e4e..a3d72927 100644 --- a/include/blkdev.h +++ b/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/include/cdtv.h b/include/cdtv.h index c63bf69e..63d2e206 100644 --- a/include/cdtv.h +++ b/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/include/cpummu.h b/include/cpummu.h index 0e5d25b4..7c8fe43b 100644 --- a/include/cpummu.h +++ b/include/cpummu.h @@ -44,6 +44,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; //typedef uae_u8 flagtype; @@ -342,6 +347,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; @@ -355,7 +363,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++) { @@ -421,7 +429,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++) { @@ -466,38 +474,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); } @@ -658,10 +666,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) @@ -682,10 +690,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); } @@ -739,13 +747,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_mmu_get_move16 (addr, v); +} +STATIC_INLINE void put_move16_mmu (uaecptr addr, uae_u32 *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_mmu060_get_move16 (addr, v); + return uae_mmu_get_rmw (addr, sz_word, 0); } -STATIC_INLINE void put_move16_mmu060 (uaecptr addr, uae_u32 *v) +STATIC_INLINE uae_u32 get_rmw_long_mmu040 (uaecptr addr) { - return uae_mmu060_put_move16 (addr, v); + return uae_mmu_get_rmw (addr, sz_long, 0); } STATIC_INLINE uae_u32 get_ibyte_mmu040 (int o) diff --git a/include/cpummu030.h b/include/cpummu030.h index 565e37da..0ae8b857 100644 --- a/include/cpummu030.h +++ b/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 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/include/gui.h b/include/gui.h index be46aa46..fe7a0342 100644 --- a/include/gui.h +++ b/include/gui.h @@ -79,6 +79,7 @@ typedef enum { NUMSG_MODRIP_NOTFOUND, NUMSG_MODRIP_FINISHED, NUMSG_MODRIP_SAVE, NUMSG_KS68EC020, NUMSG_KS68020, NUMSG_KS68030, NUMSG_ROMNEED, NUMSG_EXPROMNEED, NUMSG_NOZLIB, NUMSG_STATEHD, - NUMSG_NOCAPS, NUMSG_OLDCAPS, NUMSG_KICKREP, NUMSG_KICKREPNO + NUMSG_NOCAPS, NUMSG_OLDCAPS, NUMSG_KICKREP, NUMSG_KICKREPNO, + NUMSG_KS68030PLUS } notify_user_msg; diff --git a/include/mmu_common.h b/include/mmu_common.h index 2738f460..a681a131 100644 --- a/include/mmu_common.h +++ b/include/mmu_common.h @@ -49,12 +49,14 @@ 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_L 0x00000000 /* Note: wrong in mc68060 manual! */ +#define MMU_FSLW_SIZE_B 0x00200000 #define MMU_FSLW_SIZE_W 0x00400000 -#define MMU_FSLW_SIZE_L 0x00200000 #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 @@ -73,6 +75,8 @@ typedef int m68k_exception; /* 68040 */ #define MMU_SSW_TM 0x0007 #define MMU_SSW_TT 0x0018 +#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 diff --git a/include/options.h b/include/options.h index c69892c0..0680b784 100644 --- a/include/options.h +++ b/include/options.h @@ -108,7 +108,11 @@ struct wh { }; #define MOUNT_CONFIG_SIZE 30 +#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]; @@ -138,6 +142,8 @@ struct uaedev_config_info { int unit; int interleave; int sectorsperblock; + int forceload; + int cd_emu_unit; }; @@ -145,7 +151,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, @@ -571,7 +576,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/include/scsi.h b/include/scsi.h index 9e80cf02..b6152c04 100644 --- a/include/scsi.h +++ b/include/scsi.h @@ -18,10 +18,12 @@ struct scsi_data 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_native(int,int); +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); @@ -30,6 +32,6 @@ 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_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/memory.cpp b/memory.cpp index 6afcd6df..8c2d6e6d 100644 --- a/memory.cpp +++ b/memory.cpp @@ -2490,7 +2490,10 @@ void memory_reset (void) struct romdata *rd = getromdatabydata (kickmemory, kickmem_size); if (rd) { write_log (_T("Known ROM '%s' loaded\n"), rd->name); - if ((rd->cpu & 3) == 3 && changed_prefs.cpu_model != 68030) { + if ((rd->cpu & 8) && changed_prefs.cpu_model < 68030) { + notify_user (NUMSG_KS68030PLUS); + uae_restart (-1, NULL); + } else if ((rd->cpu & 3) == 3 && changed_prefs.cpu_model != 68030) { notify_user (NUMSG_KS68030); uae_restart (-1, NULL); } else if ((rd->cpu & 3) == 1 && changed_prefs.cpu_model < 68020) { diff --git a/newcpu.cpp b/newcpu.cpp index aadbdc17..376ba923 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -4267,7 +4267,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); @@ -4317,6 +4317,14 @@ retry: TRY (prb) { for (;;) { pc = regs.instruction_pc = m68k_getpc (); + +#if 0 + if (pc == 0x000fa01c) { + write_log (_T("*")); + //activate_debugger (); + } +#endif + opcode = x_prefetch (0); count_instr (opcode); do_cycles (cpu_cycles); @@ -4375,8 +4383,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 (); } @@ -5052,13 +5060,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 { @@ -5085,12 +5096,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/od-win32/gencomp_msvc/gencomp_msvc.vcxproj b/od-win32/gencomp_msvc/gencomp_msvc.vcxproj index 263c93e7..b55431e0 100644 --- a/od-win32/gencomp_msvc/gencomp_msvc.vcxproj +++ b/od-win32/gencomp_msvc/gencomp_msvc.vcxproj @@ -45,7 +45,7 @@ Application false false - Unicode + MultiByte v110 diff --git a/od-win32/mman.cpp b/od-win32/mman.cpp index 7c63a1c1..526c9acd 100644 --- a/od-win32/mman.cpp +++ b/od-win32/mman.cpp @@ -180,8 +180,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; @@ -203,12 +203,21 @@ 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 | (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%p-0x%p (%08x %dM)\n"), natmem_offset, (uae_u8*)natmem_offset + natmem_size, natmem_size, natmem_size >> 20); @@ -737,6 +746,8 @@ void *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/od-win32/resources/RCa02620 b/od-win32/resources/RCa02620 new file mode 100644 index 00000000..9bdff419 Binary files /dev/null and b/od-win32/resources/RCa02620 differ diff --git a/od-win32/resources/RCa06412 b/od-win32/resources/RCa06412 new file mode 100644 index 00000000..c953cbcb Binary files /dev/null and b/od-win32/resources/RCa06412 differ diff --git a/od-win32/resources/RCb02620 b/od-win32/resources/RCb02620 new file mode 100644 index 00000000..9bdff419 Binary files /dev/null and b/od-win32/resources/RCb02620 differ diff --git a/od-win32/resources/RCb06412 b/od-win32/resources/RCb06412 new file mode 100644 index 00000000..c953cbcb Binary files /dev/null and b/od-win32/resources/RCb06412 differ diff --git a/od-win32/resources/resource.h b/od-win32/resources/resource.h index e7416216..93f4ed6f 100644 --- a/od-win32/resources/resource.h +++ b/od-win32/resources/resource.h @@ -27,6 +27,7 @@ #define IDS_CHIPSET2 20 #define IDS_GAMEPORTS 21 #define IDS_EXPANSION 22 +#define IDS_STRING23 23 #define IDS_EXTTEXT 100 #define IDS_EXTACTUAL 101 #define IDS_SOUND 102 @@ -367,9 +368,11 @@ #define IDD_LIST 386 #define IDS_MISCLISTITEMS1 386 #define IDS_MISCLISTITEMS2 387 +#define IDD_CDDRIVE 387 #define IDS_MISCLISTITEMS3 388 #define IDS_WHEELMOUSE 389 #define IDS_JOYMODE_WHEELMOUSE 389 +#define IDS_NUMSG_KS68030PLUS 390 #define IDS_QS_MODELS 1000 #define IDS_QS_MODEL_A500 1001 #define IDS_QS_MODEL_A500P 1002 @@ -575,6 +578,7 @@ #define IDC_PORT0 1342 #define IDC_NEW_FSARCH 1342 #define IDC_PORT1 1343 +#define IDC_NEW_CD 1344 #define IDC_PATH_NAME 1362 #define IDC_SELECTOR 1363 #define IDC_VOLUME_NAME 1364 @@ -1166,7 +1170,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NO_MFC 1 #define _APS_3D_CONTROLS 1 -#define _APS_NEXT_RESOURCE_VALUE 387 +#define _APS_NEXT_RESOURCE_VALUE 388 #define _APS_NEXT_COMMAND_VALUE 40050 #define _APS_NEXT_CONTROL_VALUE 1815 #define _APS_NEXT_SYMED_VALUE 101 diff --git a/od-win32/resources/winuae.rc b/od-win32/resources/winuae.rc index 5c6e0ba5..056a6f7e 100644 --- a/od-win32/resources/winuae.rc +++ b/od-win32/resources/winuae.rc @@ -321,6 +321,7 @@ BEGIN COMBOBOX IDC_CD_TYPE,282,279,71,50,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "Eject",IDC_CD_EJECT,360,278,30,15 COMBOBOX IDC_CD_TEXT,5,297,386,75,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Add SCSI/IDE CD Drive",IDC_NEW_CD,135,176,126,15 END IDD_SOUND DIALOGEX 0, 0, 396, 288 @@ -1107,6 +1108,17 @@ BEGIN CONTROL "",IDC_LISTDIALOG_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,7,302,171 END +IDD_CDDRIVE DIALOGEX 0, 0, 396, 109 +STYLE DS_LOCALEDIT | DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | DS_CENTERMOUSE | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "CD Settings" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + RTEXT "HD Controller:",IDC_STATIC,12,90,65,10,SS_CENTERIMAGE + COMBOBOX IDC_HDF_CONTROLLER,91,89,61,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP + DEFPUSHBUTTON "Add CD Drive",IDOK,236,87,73,14 + PUSHBUTTON "Cancel",IDCANCEL,316,87,73,14 +END + ///////////////////////////////////////////////////////////////////////////// // @@ -1262,12 +1274,10 @@ GUIDELINES DESIGNINFO BEGIN IDD_KICKSTART, DIALOG BEGIN - BOTTOMMARGIN, 214 END IDD_DISPLAY, DIALOG BEGIN - BOTTOMMARGIN, 270 END IDD_MEMORY, DIALOG @@ -1296,7 +1306,6 @@ BEGIN IDD_IOPORTS, DIALOG BEGIN - BOTTOMMARGIN, 293 END IDD_GAMEPORTS, DIALOG @@ -1345,12 +1354,10 @@ BEGIN IDD_FILTER, DIALOG BEGIN - BOTTOMMARGIN, 286 END IDD_HARDDRIVE, DIALOG BEGIN - BOTTOMMARGIN, 108 END IDD_MISC2, DIALOG @@ -1399,7 +1406,6 @@ BEGIN IDD_INPUTMAP, DIALOG BEGIN - TOPMARGIN, 1 END IDD_INFOBOX, DIALOG @@ -1408,10 +1414,10 @@ BEGIN IDD_LIST, DIALOG BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 309 - TOPMARGIN, 7 - BOTTOMMARGIN, 199 + END + + IDD_CDDRIVE, DIALOG + BEGIN END END #endif // APSTUDIO_INVOKED @@ -1803,6 +1809,7 @@ BEGIN IDS_MISCLISTITEMS2 "Always on top\nDisable screensaver\nSynchronize clock\nFaster RTG\nClipboard sharing\nAllow native code\n" IDS_MISCLISTITEMS3 "Native on-screen display\nRTG on-screen display\nCreate winuaelog.txt log\nLog illegal memory accesses\nBlank unused displays\nStart mouse uncaptured\nStart minimized\nMinimize when focus is lost\n" IDS_JOYMODE_WHEELMOUSE "Wheel Mouse" + IDS_NUMSG_KS68030PLUS "The selected system ROM requires a 68030 or higher CPU." END #endif // English resources diff --git a/od-win32/win32.h b/od-win32/win32.h index 734fab4b..b962759d 100644 --- a/od-win32/win32.h +++ b/od-win32/win32.h @@ -19,11 +19,11 @@ #define LANG_DLL 1 #if WINUAEPUBLICBETA -#define WINUAEBETA _T("1") +#define WINUAEBETA _T("2") #else #define WINUAEBETA _T("") #endif -#define WINUAEDATE MAKEBD(2013, 1, 12) +#define WINUAEDATE MAKEBD(2013, 1, 20) #define WINUAEEXTRA _T("") //#define WINUAEEXTRA _T("AmiKit Preview") #define WINUAEREV _T("") diff --git a/od-win32/win32gui.cpp b/od-win32/win32gui.cpp index 30ea5373..f654266b 100644 --- a/od-win32/win32gui.cpp +++ b/od-win32/win32gui.cpp @@ -1968,6 +1968,8 @@ static UINT_PTR CALLBACK ofnhook (HWND hDlg, UINT message, WPARAM wParam, LPARAM static void eject_cd (void) { workprefs.cdslots[0].name[0] = 0; + if (full_property_sheet) + workprefs.cdslots[0].type = SCSI_UNIT_DEFAULT; quickstart_cddrive[0] = 0; workprefs.cdslots[0].inuse = false; if (full_property_sheet) { @@ -3878,19 +3880,23 @@ void InitializeListView (HWND hDlg) } else if (lv_type == LV_HARDDISK) { #ifdef FILESYS + listview_column_width[1] = 60; for(i = 0; i < workprefs.mountitems; i++) { struct uaedev_config_data *uci = &workprefs.mountconfig[i]; struct uaedev_config_info *ci = &uci->ci; int nosize = 0, type; struct mountedinfo mi; - TCHAR *rootdir = ci->rootdir; + TCHAR *rootdir; type = get_filesys_unitconfig (&workprefs, i, &mi); if (type < 0) { - type = uci->ishdf ? FILESYS_HARDFILE : FILESYS_VIRTUAL; + type = ci->type == UAEDEV_HDF || ci->type == UAEDEV_CD ? FILESYS_HARDFILE : FILESYS_VIRTUAL; nosize = 1; } + if (mi.size < 0) + nosize = 1; + rootdir = mi.rootdir; if (nosize) _tcscpy (size_str, _T("n/a")); @@ -3949,7 +3955,7 @@ void InitializeListView (HWND hDlg) WIN32GUI_LoadUIString (ci->readonly ? IDS_NO : IDS_YES, readwrite_str, sizeof (readwrite_str) / sizeof (TCHAR)); lvstruct.mask = LVIF_TEXT | LVIF_PARAM; - lvstruct.pszText = mi.ismedia == false ? _T("E") : (nosize ? _T("X") : (mi.ismounted ? _T("*") : _T(" "))); + lvstruct.pszText = mi.ismedia == false ? _T("E") : (nosize && mi.size >= 0 ? _T("X") : (mi.ismounted ? _T("*") : _T(" "))); if (ci->controller && mi.ismedia) lvstruct.pszText = _T(" "); lvstruct.lParam = 0; @@ -3958,7 +3964,7 @@ void InitializeListView (HWND hDlg) result = ListView_InsertItem (list, &lvstruct); if (result != -1) { - listview_column_width[0] = 15; + listview_column_width[0] = 20; ListView_SetItemText(list, result, 1, devname_str); width = ListView_GetStringWidth(list, devname_str) + 10; @@ -4009,8 +4015,10 @@ void InitializeListView (HWND hDlg) } } // Adjust our column widths so that we can see the contents... - for(i = 0; i < listview_num_columns; i++) - ListView_SetColumnWidth (list, i, listview_column_width[i]); + for(i = 0; i < listview_num_columns; i++) { + if (ListView_GetColumnWidth (list, i) < listview_column_width[i]) + ListView_SetColumnWidth (list, i, listview_column_width[i]); + } // Redraw the items in the list... items = ListView_GetItemCount (list); ListView_RedrawItems (list, 0, items); @@ -5422,6 +5430,8 @@ static INT_PTR CALLBACK QuickstartDlgProc (HWND hDlg, UINT msg, WPARAM wParam, L val = SendDlgItemMessage (hDlg, IDC_CD0Q_TYPE, CB_GETCURSEL, 0, 0); if (val != CB_ERR) { quickstart_cdtype = val; + if (full_property_sheet) + workprefs.cdslots[0].type = SCSI_UNIT_DEFAULT; if (quickstart_cdtype >= 2) { int len = sizeof quickstart_cddrive / sizeof (TCHAR); quickstart_cdtype = 2; @@ -9141,6 +9151,10 @@ static INT_PTR CALLBACK SoundDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM #ifdef FILESYS +struct cddlg_vals +{ + struct uaedev_config_info ci; +}; struct fsvdlg_vals { struct uaedev_config_info ci; @@ -9156,6 +9170,7 @@ struct hfdlg_vals bool rdb; }; +static struct cddlg_vals current_cddlg; static struct fsvdlg_vals current_fsvdlg; static struct hfdlg_vals current_hfdlg; static int archivehd; @@ -9164,15 +9179,16 @@ static void default_fsvdlg (struct fsvdlg_vals *f) { memset (f, 0, sizeof (struct fsvdlg_vals)); f->ci.autoboot = true; + f->ci.type = UAEDEV_DIR; } static void default_hfdlg (struct hfdlg_vals *f, bool rdb) { memset (f, 0, sizeof (struct hfdlg_vals)); uci_set_defaults (&f->ci, rdb); f->original = true; + f->ci.type = UAEDEV_HDF; } - static void volumeselectfile (HWND hDlg) { TCHAR directory_path[MAX_DPATH]; @@ -9549,6 +9565,45 @@ static void hardfilecreatehdf (HWND hDlg, TCHAR *newpath) sethardfile (hDlg); } +static INT_PTR CALLBACK CDDriveSettingsProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static int recursive = 0; + int posn; + + switch (msg) { + + case WM_INITDIALOG: + recursive++; + inithdcontroller (hDlg); + SendDlgItemMessage (hDlg, IDC_HDF_CONTROLLER, CB_SETCURSEL, current_cddlg.ci.controller, 0); + recursive--; + customDlgType = IDD_CDDRIVE; + customDlg = hDlg; + return TRUE; + case WM_COMMAND: + if (recursive) + break; + recursive++; + switch (LOWORD (wParam)) + { + case IDOK: + EndDialog (hDlg, 1); + break; + case IDCANCEL: + EndDialog (hDlg, 0); + break; + case IDC_HDF_CONTROLLER: + posn = SendDlgItemMessage (hDlg, IDC_HDF_CONTROLLER, CB_GETCURSEL, 0, 0); + if (posn != CB_ERR) + current_cddlg.ci.controller = posn; + break; + } + recursive--; + break; + } + return FALSE; +} + static INT_PTR CALLBACK HardfileSettingsProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { static int recursive = 0; @@ -9887,7 +9942,7 @@ static void new_filesys (HWND hDlg, int entry) int bp = tweakbootpri (current_fsvdlg.ci.bootpri, current_fsvdlg.ci.autoboot, current_fsvdlg.ci.donotmount); memcpy (&ci, ¤t_fsvdlg.ci, sizeof (struct uaedev_config_info)); ci.bootpri = bp; - uci = add_filesys_config (&workprefs, entry, &ci, false); + uci = add_filesys_config (&workprefs, entry, &ci); if (uci) { if (uci->ci.rootdir[0]) filesys_media_change (uci->ci.rootdir, 1, uci); @@ -9896,6 +9951,17 @@ static void new_filesys (HWND hDlg, int entry) } } +static void new_cddrive (HWND hDlg, int entry) +{ + struct uaedev_config_info ci = { 0 }; + ci.cd_emu_unit = 0; + ci.controller = current_cddlg.ci.controller; + ci.type = UAEDEV_CD; + ci.readonly = true; + ci.blocksize = 2048; + add_filesys_config (&workprefs, entry, &ci); +} + static void new_hardfile (HWND hDlg, int entry) { struct uaedev_config_data *uci; @@ -9903,7 +9969,7 @@ static void new_hardfile (HWND hDlg, int entry) int bp = tweakbootpri (current_hfdlg.ci.bootpri, current_hfdlg.ci.autoboot, current_hfdlg.ci.donotmount); memcpy (&ci, ¤t_hfdlg.ci, sizeof (struct uaedev_config_info)); ci.bootpri = bp; - uci = add_filesys_config (&workprefs, entry, &ci, true); + uci = add_filesys_config (&workprefs, entry, &ci); if (uci) { struct hardfiledata *hfd = get_hardfile_data (uci->configoffset); hardfile_media_change (hfd, &ci, true, false); @@ -9914,7 +9980,7 @@ static void new_harddrive (HWND hDlg, int entry) { struct uaedev_config_data *uci; - uci = add_filesys_config (&workprefs, entry, ¤t_hfdlg.ci, true); + uci = add_filesys_config (&workprefs, entry, ¤t_hfdlg.ci); if (uci) { struct hardfiledata *hfd = get_hardfile_data (uci->configoffset); hardfile_media_change (hfd, ¤t_hfdlg.ci, true, false); @@ -9950,9 +10016,15 @@ static void harddisk_edit (HWND hDlg) type = get_filesys_unitconfig (&workprefs, entry, &mi); if (type < 0) - type = uci->ishdf ? FILESYS_HARDFILE : FILESYS_VIRTUAL; + type = uci->ci.type == UAEDEV_HDF ? FILESYS_HARDFILE : FILESYS_VIRTUAL; - if(type == FILESYS_HARDFILE || type == FILESYS_HARDFILE_RDB) + if (uci->ci.type == UAEDEV_CD) { + memcpy (¤t_cddlg.ci, uci, sizeof (struct uaedev_config_info)); + if (CustomDialogBox (IDD_CDDRIVE, hDlg, CDDriveSettingsProc)) { + new_cddrive (hDlg, entry); + } + } + else if(type == FILESYS_HARDFILE || type == FILESYS_HARDFILE_RDB) { current_hfdlg.forcedcylinders = uci->ci.highcyl; memcpy (¤t_hfdlg.ci, uci, sizeof (struct uaedev_config_info)); @@ -10018,6 +10090,11 @@ static int harddiskdlg_button (HWND hDlg, WPARAM wParam) new_hardfile (hDlg, -1); return 1; + case IDC_NEW_CD: + if (CustomDialogBox (IDD_CDDRIVE, hDlg, CDDriveSettingsProc)) + new_cddrive (hDlg, -1); + return 1; + case IDC_NEW_HD: memset (¤t_hfdlg, 0, sizeof (current_hfdlg)); if (hdf_init_target () == 0) { @@ -10180,13 +10257,19 @@ static INT_PTR CALLBACK HarddiskDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPA getfloppyname (hDlg, 0, 1, IDC_CD_TEXT); quickstart_cdtype = 1; workprefs.cdslots[0].inuse = true; + if (full_property_sheet) + workprefs.cdslots[0].type = SCSI_UNIT_DEFAULT; addcdtype (hDlg, IDC_CD_TYPE); addfloppyhistory_2 (hDlg, 0, IDC_CD_TEXT, HISTORY_CD); + InitializeListView (hDlg); + hilitehd (hDlg); break; case IDC_CD_TYPE: int val = SendDlgItemMessage (hDlg, IDC_CD_TYPE, CB_GETCURSEL, 0, 0); if (val != CB_ERR) { quickstart_cdtype = val; + if (full_property_sheet) + workprefs.cdslots[0].type = SCSI_UNIT_DEFAULT; if (quickstart_cdtype >= 2) { int len = sizeof quickstart_cddrive / sizeof (TCHAR); quickstart_cdtype = 2; @@ -10208,6 +10291,8 @@ static INT_PTR CALLBACK HarddiskDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPA } addcdtype (hDlg, IDC_CD_TYPE); addfloppyhistory_2 (hDlg, 0, IDC_CD_TEXT, HISTORY_CD); + InitializeListView (hDlg); + hilitehd (hDlg); } break; } @@ -14999,7 +15084,6 @@ static void centerWindow (HWND hDlg) y = mdc->rect.top; } } - SetForegroundWindow (hDlg); pt1.x = x + 100; pt1.y = y + (GetSystemMetrics (SM_CYMENU) + GetSystemMetrics (SM_CYBORDER)) / 2; pt2.x = x + gui_width - 100; @@ -15200,7 +15284,7 @@ int dragdrop (HWND hDlg, HDROP hd, struct uae_prefs *prefs, int currentpage) } else if (currentpage == HARDDISK_ID) { default_fsvdlg (¤t_fsvdlg); _tcscpy (current_fsvdlg.ci.rootdir, file); - add_filesys_config (&workprefs, -1, ¤t_fsvdlg.ci, false); + add_filesys_config (&workprefs, -1, ¤t_fsvdlg.ci); } else { drv = floppyslot_addfile (prefs, file, drv, firstdrv, i); if (drv < 0) @@ -15226,18 +15310,18 @@ int dragdrop (HWND hDlg, HDROP hd, struct uae_prefs *prefs, int currentpage) } else { default_fsvdlg (¤t_fsvdlg); _tcscpy (current_fsvdlg.ci.rootdir, file); - add_filesys_config (&workprefs, -1, ¤t_fsvdlg.ci, false); + add_filesys_config (&workprefs, -1, ¤t_fsvdlg.ci); } } else { uci_set_defaults (¤t_hfdlg.ci, false); current_hfdlg.forcedcylinders = 0; updatehdfinfo (NULL, true, true); - add_filesys_config (&workprefs, -1, ¤t_hfdlg.ci, true); + add_filesys_config (&workprefs, -1, ¤t_hfdlg.ci); } break; case ZFILE_HDFRDB: default_hfdlg (¤t_hfdlg, true); - add_filesys_config (&workprefs, -1, ¤t_hfdlg.ci, true); + add_filesys_config (&workprefs, -1, ¤t_hfdlg.ci); break; case ZFILE_NVR: _tcscpy (prefs->flashfile, file); @@ -15269,7 +15353,7 @@ int dragdrop (HWND hDlg, HDROP hd, struct uae_prefs *prefs, int currentpage) default_fsvdlg (¤t_fsvdlg); _tcscpy (current_fsvdlg.ci.rootdir, file); _tcscpy (current_fsvdlg.ci.volname, filepart); - add_filesys_config (&workprefs, -1, ¤t_fsvdlg.ci, false); + add_filesys_config (&workprefs, -1, ¤t_fsvdlg.ci); if (!full_property_sheet) do_filesys_insert (file); } else { @@ -16331,6 +16415,7 @@ static int transla[] = { NUMSG_NOCAPS, IDS_NUMSG_NOCAPS, NUMSG_KICKREP, IDS_NUMSG_KICKREP, NUMSG_KICKREPNO, IDS_NUMSG_KICKREPNO, + NUMSG_KS68030PLUS, IDS_NUMSG_KS68030PLUS, -1 }; diff --git a/od-win32/winuaechangelog.txt b/od-win32/winuaechangelog.txt index 50616346..46e17d2f 100644 --- a/od-win32/winuaechangelog.txt +++ b/od-win32/winuaechangelog.txt @@ -1,6 +1,31 @@ - restore only single input target to default. +Beta 2: + +- 030/040/060 MMU TAS and CAS/CAS2 Read-Modify-Write cycle special handling emulated, RMW read access + part is internally considered a write access and it will cause access fault if address is write protected. +- 040 MMU MOVEM special handling (SSR CM-bit) emulated. +- Some 040/060 MMU emulation bug fixes. (It still isn't fully compatible) +- A3000 2.04 ROM requires 68030 or higher, it is not 68030-only. (Only 1.4b is 68030-only) +- Bogus filesystem.resource entry was added if RDB HDF had more than one partition with custom filesystem (b1) +- Fixed stuck IDE emulation interrupt that hangs the emulated system, happened randomly during A4000 IDE detection. (Old bug) +- Geometry file FORCELOAD parameter added, forceload=1: do not re-use already loaded filesystem(s). +- A590/A2091/A3000 SCSI CDROM emulation added, uses SCSI emulation originally made for uaescsi.device. +- Gayle/A4000 ATAPI CDROM emulation added (uses uaescsi.device SCSI emulation, ATAPI = IDE CROM SCSI command support) +- CD image mounter SCSI emulation inquiry command's vendor/product/revision data was blank. +- Ultra-minimal "Add CD Drive" GUI added. Only IDE or SCSI and only one CD entry can be added. Use hardddrives panel bottom + CD drive/image selection select menu to select mounted CD. uaescsi.device still works as previously but note that + same CD drive/image slot (internally there is more but they are not available in GUI yet) is shared = it may not be good + idea to enable both uaescsi.device and hardware IDE/SCSI CD emulation at the same time. +- Added more emulated SCSI CD commands, READ TRACK INFORMATION, READ DISC INFORMATION and PREVENT/ALLOW MEDIUM REMOVAL + (which does nothing). READ TOC allocation length check fixed. + +Note: Curently SCSI and IDE CD is single threaded = whole emulation pauses while waiting for CD command to finish = better +not to use real CD drives. Only uaescsi.device runs in background. + +Beta 1: + Big MMU emulation update: - Previous (Next emulator) 68030 MMU added (+missing bus error exception stuff implemented by me), diff --git a/rommgr.cpp b/rommgr.cpp index 242345de..c14cb382 100644 --- a/rommgr.cpp +++ b/rommgr.cpp @@ -139,7 +139,7 @@ static struct romdata roms[] = { 0x64466c2a, 0xF72D8914,0x8DAC39C6,0x96E30B10,0x859EBC85,0x9226637B }, { _T("KS ROM v2.05 (A600HD)"), 2, 5, 37, 350, _T("A600HD\0A600\0"), 524288, 10, 0, 0, ROMTYPE_KICK, 0, 0, _T("391304-02"), 0x43b0df7b, 0x02843C42,0x53BBD29A,0xBA535B0A,0xA3BD9A85,0x034ECDE4 }, - { _T("KS ROM v2.04 (A3000)"), 2, 4, 37, 175, _T("A3000\0"), 524288, 71, 3, 0, ROMTYPE_KICK, 0, 0, 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 }, ALTROMPN(71, 1, 1, 262144, ROMTYPE_EVEN, _T("390629-03"), 0xa245dbdf,0x83bab8e9,0x5d378b55,0xb0c6ae65,0x61385a96,0xf638598f) ALTROMPN(71, 1, 2, 262144, ROMTYPE_ODD , _T("390630-03"), 0x7db1332b,0x48f14b31,0x279da675,0x7848df6f,0xeb531881,0x8f8f576c) diff --git a/scsi.cpp b/scsi.cpp index cf512ddd..0237e27a 100644 --- a/scsi.cpp +++ b/scsi.cpp @@ -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: @@ -85,19 +88,35 @@ void scsi_emulate_cmd(struct scsi_data *sd) { sd->status = 0; //write_log (_T("CMD=%02x\n"), sd->cmd[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; + 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 { @@ -125,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; } @@ -144,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; } @@ -158,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); }