#define A2091_DEBUG 0
#define A3000_DEBUG 0
-#define WD33C93_DEBUG 1
+#define WD33C93_DEBUG 0
#define WD33C93_DEBUG_PIO 0
#include "sysconfig.h"
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++;
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 */
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);
}
#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);
}
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;
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;
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;
}
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)
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);
}
if (!scsis[num])
return NULL;
s = scsis[num];
+ if (s->hfd == NULL)
+ return NULL;
if (dstptr)
dstbak = dst = dstptr;
else
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 ();
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;
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)
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 {
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
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;
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++) {
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;
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 */
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))
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;
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;
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;
goto nodisk;
int start = rl (cmdbuf + 2);
int len;
- if (cmd = 0xa5)
+ if (cmd == 0xa5)
len = rl (cmdbuf + 6);
else
len = rw (cmdbuf + 7);
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) {
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;
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);
} else {
_tcscpy (di->label, _T("IMG:<EMPTY>"));
}
+ _tcscpy (di->vendorid, _T("UAE"));
+ _stprintf (di->productid, _T("SCSICD%d"), unitnum);
+ _tcscpy (di->revision, _T("1.0"));
di->backend = _T("IMAGE");
return di;
}
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;
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;
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)
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);
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,
_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,
#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);
}
}
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;
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 {
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"));
_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);
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;
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;
goto invalid_fs;
value = tmpp;
- if (!hdf) {
+ if (type == 0) {
+ uci.type = UAEDEV_DIR;
tmpp = _tcschr (value, ':');
if (tmpp == 0)
goto empty_fs;
_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;
}
}
}
+ 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;
_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;
}
_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)] == '_') {
}
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;
}
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;
}
_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"));
_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)
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);
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;
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;
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);
}
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;
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();
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);
}
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_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)
{
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) {
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) {
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) {
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)
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);
}
{
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);
// 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)
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;
#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;
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)
*
*/
-
-#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
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);
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 */
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:
#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);
}
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;
}
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;
}
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;
}
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;
}
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;
}
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
* 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;
}
}
}
-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;
}
}
}
-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;
}
}
}
-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);
}
}
}
-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);
}
}
}
-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);
}
}
-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) {
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) {
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) {
}
-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;
}
} 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) {
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;
}
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 */
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++) {
// 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 {
} else {
m68k_areg (regs, 7) += 32;
}
- // Rerun "mmu030_opcode" using restored state.
- mmu030_retry = true;
}
void flush_mmu030 (uaecptr addr, int n)
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;
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) {
}
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) {
}
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) {
}
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)
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;
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)) {
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)
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)
#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
}
}
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;
}
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);
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) {
} 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);
}
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"));
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;
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;
#include "gui.h"
#include "a2091.h"
#include "ncr_scsi.h"
+#include "blkdev.h"
+#include "scsi.h"
#define PCMCIA_SRAM 1
#define PCMCIA_IDE 2
/* 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 */
#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
#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
{
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;
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
#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;
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)
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)
{
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 ();
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)
TCHAR tmp[100];
bool atapi = ide->atapi;
- if (ide->hdhfd.size == 0) {
+ if (!isdrive (ide)) {
ide_fail ();
return;
}
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);
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);
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;
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);
}
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;
}
}
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;
}
}
{
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) {
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;
}
}
}
{
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)
}
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 ();
}
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);
}
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)
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)
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 ();
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 ();
{
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;
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;
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)
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;
}
}
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
}
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;
{
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;
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;
+ }
}
}
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;
}
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
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);
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;
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"));
}
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);
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 ();
#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
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;
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)
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
}
-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 */
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;
}
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)
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;
}
} 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 ();
}
}
default:
break;
}
+
+ if (movem == 3) {
+ close_brace ();
+ }
}
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:
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;
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;
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 ();
{
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);
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)
*/
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);
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");
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",
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
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";
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";
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";
srcld = srcl;
if (!srcwd)
srcwd = srcw;
+ if (!srcbrmw) {
+ srcbrmw = srcb;
+ srcwrmw = srcw;
+ srclrmw = srcl;
+ dstbrmw = dstb;
+ dstwrmw = dstw;
+ dstlrmw = dstl;
+ }
insn_n_cycles020 = 0;
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");
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");
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");
}
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);
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");
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);
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);
{
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 {
{
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) {
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)
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);
}
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;
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 */
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 */
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;
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 */
}
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 */
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
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);
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);
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);
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*);
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;
#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;
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++) {
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++) {
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);
}
{
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)
{
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);
}
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)
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)
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)
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)
#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)
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)
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)
#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 \
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;
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;
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;
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;
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;
#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
/* 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
};
#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];
int unit;
int interleave;
int sectorsperblock;
+ int forceload;
+ int cd_emu_unit;
};
{
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,
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);
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);
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
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) {
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);
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);
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 ();
}
}
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 {
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;
<ConfigurationType>Application</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<UseOfAtl>false</UseOfAtl>
- <CharacterSet>Unicode</CharacterSet>
+ <CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
}
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;
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);
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;
#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
#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
#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
#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
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
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
+
/////////////////////////////////////////////////////////////////////////////
//
BEGIN
IDD_KICKSTART, DIALOG
BEGIN
- BOTTOMMARGIN, 214
END
IDD_DISPLAY, DIALOG
BEGIN
- BOTTOMMARGIN, 270
END
IDD_MEMORY, DIALOG
IDD_IOPORTS, DIALOG
BEGIN
- BOTTOMMARGIN, 293
END
IDD_GAMEPORTS, DIALOG
IDD_FILTER, DIALOG
BEGIN
- BOTTOMMARGIN, 286
END
IDD_HARDDRIVE, DIALOG
BEGIN
- BOTTOMMARGIN, 108
END
IDD_MISC2, DIALOG
IDD_INPUTMAP, DIALOG
BEGIN
- TOPMARGIN, 1
END
IDD_INFOBOX, DIALOG
IDD_LIST, DIALOG
BEGIN
- LEFTMARGIN, 7
- RIGHTMARGIN, 309
- TOPMARGIN, 7
- BOTTOMMARGIN, 199
+ END
+
+ IDD_CDDRIVE, DIALOG
+ BEGIN
END
END
#endif // APSTUDIO_INVOKED
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
#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("")
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) {
} 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"));
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;
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;
}
}
// 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);
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;
#ifdef FILESYS
+struct cddlg_vals
+{
+ struct uaedev_config_info ci;
+};
struct fsvdlg_vals
{
struct uaedev_config_info ci;
bool rdb;
};
+static struct cddlg_vals current_cddlg;
static struct fsvdlg_vals current_fsvdlg;
static struct hfdlg_vals current_hfdlg;
static int archivehd;
{
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];
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;
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);
}
}
+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;
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);
{
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);
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));
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) {
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;
}
addcdtype (hDlg, IDC_CD_TYPE);
addfloppyhistory_2 (hDlg, 0, IDC_CD_TEXT, HISTORY_CD);
+ InitializeListView (hDlg);
+ hilitehd (hDlg);
}
break;
}
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;
} 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)
} 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);
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 {
NUMSG_NOCAPS, IDS_NUMSG_NOCAPS,
NUMSG_KICKREP, IDS_NUMSG_KICKREP,
NUMSG_KICKREPNO, IDS_NUMSG_KICKREPNO,
+ NUMSG_KS68030PLUS, IDS_NUMSG_KS68030PLUS,
-1
};
- 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),
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)
#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)
{
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)
case 0x25:
case 0x28:
case 0x35:
+ case 0x51:
+ case 0x52:
+ case 0x43:
cmd_len = 10;
break;
case 0xa8:
{
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 {
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;
}
sd = xcalloc (struct scsi_data, 1);
sd->id = id;
sd->nativescsiunit = nativeunit;
+ sd->cd_emu_unit = -1;
return 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);
}