#define XT_DEBUG 0
#define A3000_DEBUG 0
#define A3000_DEBUG_IO 0
+
#define WD33C93_DEBUG 0
#define WD33C93_DEBUG_PIO 0
static struct wd_state *wd_gvps1[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct wd_state *wd_gvps2[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct wd_state *wd_gvps2accel;
+static struct wd_state *wd_comspec[MAX_DUPLICATE_EXPANSION_BOARDS];
struct wd_state *wd_cdtv;
static struct wd_state *scsi_units[MAX_SCSI_UNITS + 1];
if ((wd->cdmac.dmac_cntr & CNTR_INTEN) && (wd->cdmac.dmac_istr & ISTR_INTS))
return true;
break;
+ case COMSPEC_CHIP:
+#if 0
+ if (wd->wc.auxstatus & ASR_INT)
+ return true;
+#endif
+ break;
}
return false;
}
return tc == 0;
}
-static bool canwddma(struct wd_state *wds)
+static int canwddma(struct wd_state *wds)
{
struct wd_chip_state *wd = &wds->wc;
uae_u8 mode = wd->wdregs[WD_CONTROL] >> 5;
write_log (_T("%s weird DMA mode %d!!\n"), WD33C93, mode);
}
return mode == 2;
+ case COMSPEC_CHIP:
+ return -1;
default:
- return false;
+ return 0;
}
}
return true;
}
+static void set_pio_data_irq(struct wd_chip_state *wd, struct wd_state *wds)
+{
+ if (!wd->wd_data_avail)
+ return;
+ switch(wds->dmac_type)
+ {
+ case COMSPEC_CHIP:
+ if (wds->comspec.status & 0x10) {
+ wds->comspec.status |= 0x08;
+ INTREQ_0(0x8000 | 0x2000);
+ }
+ break;
+ }
+}
+
+
static void wd_cmd_sel_xfer (struct wd_chip_state *wd, struct wd_state *wds, bool atn)
{
int i, tmp_tc;
set_status (wd, wd->wd_phase, 1);
return;
}
- if (canwddma (wds)) {
+ if (canwddma (wds) > 0) {
if (scsi->direction <= 0) {
do_dma(wds);
if (scsi->offset < scsi->data_len) {
scsi_emulate_cmd (scsi);
}
}
+ } else if (canwddma (wds) < 0) {
+ // pio
+ wd->wd_data_avail = 1;
+ set_pio_data_irq(wd, wds);
+ return;
} else {
// no dma = Service Request
wd->wd_phase = CSR_SRV_REQ;
wd->scsi->direction = 0;
wd->wd_data_avail = 0;
} else {
- if (canwddma (wds)) {
+ if (canwddma (wds) > 0) {
wd->wd_data_avail = -1;
} else {
wd->wd_data_avail = 1;
wd->auxstatus = 0;
wd->wd_data_avail = 0;
if (irq) {
- set_status (wd, (wd->wdregs[0] & 0x08) ? 1 : 0, 50);
+ uae_u8 status = (wd->wdregs[0] & 0x08) ? 1 : 0;
+ set_status (wd, status, 50);
}
}
wd_check_interrupt(wds, false);
}
+static void scsi_hsync2_comspec(struct wd_state *wds)
+{
+ if (!wds || !wds->enabled)
+ return;
+ wd_check_interrupt(wds, false);
+}
+
void scsi_hsync (void)
{
for (int i = 0; i < MAX_DUPLICATE_EXPANSION_BOARDS; i++) {
scsi_hsync2_a2091(wd_a2090[i]);
scsi_hsync2_gvp(wd_gvps1[i]);
scsi_hsync2_gvp(wd_gvps2[i]);
+ scsi_hsync2_comspec(wd_comspec[i]);
}
scsi_hsync2_gvp(wd_gvps2accel);
scsi_hsync2_a2091(wd_a3000);
wd->wd_data_avail = 0;
write_comm_pipe_u32 (&wds->requests, makecmd (wd->scsi, 2, 0), 1);
}
+ set_pio_data_irq(wd, wds);
} else if (wd->sasr == WD_COMMAND) {
wd->wd_busy = true;
- write_comm_pipe_u32(&wds->requests, makecmd(wds->scsis[wd->wdregs[WD_DESTINATION_ID] & 7], 0, d), 1);
+ if (wd->resetnodelay && d == WD_CMD_RESET) {
+ // stupid cpu loops that fail if CPU is too fast..
+ wd_master_reset(wds, true);
+ } else {
+ write_comm_pipe_u32(&wds->requests, makecmd(wds->scsis[wd->wdregs[WD_DESTINATION_ID] & 7], 0, d), 1);
+ }
if (wd->scsi && wd->scsi->cd_emu_unit >= 0)
gui_flicker_led (LED_CD, wd->scsi->id, 1);
}
incsasr (wd, 1);
}
+static void wdscsi_put_data(struct wd_chip_state *wd, struct wd_state *wds, uae_u8 v)
+{
+ uae_u8 sasr = wd->sasr;
+ wd->sasr = WD_DATA;
+ wdscsi_put(wd, wds, v);
+ wd->sasr = sasr;
+}
+
void wdscsi_sasr (struct wd_chip_state *wd, uae_u8 b)
{
wd->sasr = b;
wd->wd_data_avail = 0;
write_comm_pipe_u32 (&wds->requests, makecmd (wd->scsi, 3, 0), 1);
}
+ set_pio_data_irq(wd, wds);
} else if (wd->sasr == WD_SCSI_STATUS) {
wd->auxstatus &= ~0x80;
if (wds->cdtv)
return v;
}
+uae_u8 wdscsi_get_data(struct wd_chip_state *wd, struct wd_state *wds)
+{
+ uae_u8 sasr = wd->sasr;
+ wd->sasr = WD_DATA;
+ uae_u8 v = wdscsi_get(wd, wds);
+ wd->sasr = sasr;
+ return v;
+}
+
/* A590 XT */
static void xt_default_geometry(struct wd_state *wds)
ABFLAG_IO | ABFLAG_SAFE | ABFLAG_PPCIOSPACE, S_READ, S_WRITE
};
+static bool comspec_wd_aux(uaecptr addr)
+{
+ return addr == 0xc1;
+}
+static bool comspec_wd_data(uaecptr addr)
+{
+ return addr == 0xc3;
+}
+static uae_u8 comspec_status(struct wd_state *wd)
+{
+ uae_u8 v = wd->comspec.status;
+ v &= ~0x80;
+ if (wd->wc.wd_data_avail)
+ v |= 0x80;
+ return v;
+}
+
+static uae_u8 comspec_read_byte(struct wd_state *wd, uaecptr addr)
+{
+ uae_u8 v = 0;
+ addr &= 65535;
+ if (!(addr & 0x8000)) {
+ v = wd->rom[addr];
+ } else {
+ addr &= 0x7fff;
+ if ((addr & 0xf1) == 0x80) {
+ v = comspec_status(wd);
+ } else if ((addr & 0xf1) == 0x81) {
+ v = wdscsi_get_data(&wd->wc, wd);
+ } else {
+ if (comspec_wd_aux(addr)) {
+ v = wdscsi_getauxstatus(&wd->wc);
+ } else if (comspec_wd_data(addr)) {
+ v = wdscsi_get (&wd->wc, wd);
+ }
+ }
+ //write_log(_T("COMSPEC BGET %08x %02x %08x\n"), addr, v, M68K_GETPC);
+ }
+ return v;
+}
+static void comspec_write_byte(struct wd_state *wd, uaecptr addr, uae_u8 v)
+{
+ if (addr & 0x8000) {
+ addr &= 0x7fff;
+ if ((addr & 0xf0) == 0x80) {
+ wd->comspec.status = v & 0x7f;
+ if (!(v & 0x40)) {
+ wd_master_reset(wd, true);
+ }
+ } else if ((addr & 0xf1) == 0xe1) {
+ wdscsi_put_data(&wd->wc, wd, v);
+ } else {
+ if (comspec_wd_aux(addr)) {
+ wdscsi_sasr(&wd->wc, v);
+ } else if (comspec_wd_data(addr)) {
+ wdscsi_put(&wd->wc, wd, v);
+ }
+ }
+ }
+ write_log(_T("COMSPEC BPUT %08x %02x %08x\n"), addr, v, M68K_GETPC);
+}
+
+static uae_u16 comspec_read_word(struct wd_state *wd, uaecptr addr)
+{
+ uae_u16 v = 0;
+ addr &= 65535;
+ if (!(addr & 0x8000)) {
+ v = (wd->rom[addr] << 8) | wd->rom[addr + 1];
+ } else {
+ addr &= 0x7fff;
+ if ((addr & 0xf0) == 0x80) {
+ v = comspec_status(wd) << 8;
+ v |= wdscsi_get_data(&wd->wc, wd);
+ }
+ //write_log(_T("COMSPEC WGET %08x %04x %08x\n"), addr, v, M68K_GETPC);
+ }
+ return v;
+}
+static void comspec_write_word(struct wd_state *wd, uaecptr addr, uae_u16 v)
+{
+ if (addr & 0x8000) {
+ write_log(_T("COMSPEC BWUT %08x %04x %08x\n"), addr, v, M68K_GETPC);
+ }
+}
+
+static int REGPARAM2 comspec_check(struct wd_state *wd, uaecptr addr, uae_u32 size)
+{
+ return 1;
+}
+
+static uae_u8 *REGPARAM2 comspec_xlate(struct wd_state *wd, uaecptr addr)
+{
+ addr &= 0xffff;
+ return wd->rom + addr;
+}
+
+static uae_u32 REGPARAM2 comspec_lget (struct wd_state *wd, uaecptr addr)
+{
+ uae_u32 v;
+ addr &= 65535;
+ v = comspec_read_word(wd, addr) << 16;
+ v |= comspec_read_word(wd, addr + 2) & 0xffff;
+ return v;
+}
+
+static uae_u32 REGPARAM2 comspec_wget(struct wd_state *wd, uaecptr addr)
+{
+ uae_u32 v;
+ addr &= 65535;
+ v = comspec_read_word(wd, addr);
+ return v;
+}
+
+static uae_u32 REGPARAM2 comspec_bget(struct wd_state *wd, uaecptr addr)
+{
+ uae_u32 v;
+ addr &= 65535;
+ v = comspec_read_byte(wd, addr);
+ return v;
+}
+
+static void REGPARAM2 comspec_lput(struct wd_state *wd, uaecptr addr, uae_u32 l)
+{
+ addr &= 65535;
+ comspec_write_word(wd, addr + 0, l >> 16);
+ comspec_write_word(wd, addr + 2, l);
+}
+
+static void REGPARAM2 comspec_wput(struct wd_state *wd, uaecptr addr, uae_u32 w)
+{
+ addr &= 65535;
+ comspec_write_word(wd, addr, w);
+}
+
+extern const addrbank dmaca2091_bank;
+
+static void REGPARAM2 comspec_bput(struct wd_state *wd, uaecptr addr, uae_u32 b)
+{
+ b &= 0xff;
+ addr &= 65535;
+ comspec_write_byte(wd, addr, b);
+}
+
+static uae_u32 REGPARAM2 comspec_wgeti(struct wd_state *wd, uaecptr addr)
+{
+ uae_u32 v = 0xffff;
+ addr &= 65535;
+ if (!(addr & 0x8000))
+ v = (wd->rom[addr] << 8) | wd->rom[addr + 1];
+ return v;
+}
+static uae_u32 REGPARAM2 comspec_lgeti(struct wd_state *wd, uaecptr addr)
+{
+ uae_u32 v;
+ addr &= 65535;
+ v = comspec_wgeti(wd, addr) << 16;
+ v |= comspec_wgeti(wd, addr + 2);
+ return v;
+}
+
+
+static uae_u8 *REGPARAM2 comspec_xlate (uaecptr addr)
+{
+ struct wd_state *wd = getscsiboard(addr);
+ if (wd)
+ return comspec_xlate(wd, addr);
+ return default_xlate(0);
+}
+static int REGPARAM2 comspec_check (uaecptr addr, uae_u32 size)
+{
+ struct wd_state *wd = getscsiboard(addr);
+ if (wd)
+ return comspec_check(wd, addr, size);
+ return 0;
+}
+static uae_u32 REGPARAM2 comspec_lgeti (uaecptr addr)
+{
+ struct wd_state *wd = getscsiboard(addr);
+ if (wd)
+ return comspec_lgeti(wd, addr);
+ return 0;
+}
+static uae_u32 REGPARAM2 comspec_wgeti (uaecptr addr)
+{
+ struct wd_state *wd = getscsiboard(addr);
+ if (wd)
+ return comspec_wgeti(wd, addr);
+ return 0;
+}
+static uae_u32 REGPARAM2 comspec_bget (uaecptr addr)
+{
+ struct wd_state *wd = getscsiboard(addr);
+ if (wd)
+ return comspec_bget(wd, addr);
+ return 0;
+}
+static uae_u32 REGPARAM2 comspec_wget (uaecptr addr)
+{
+ struct wd_state *wd = getscsiboard(addr);
+ if (wd)
+ return comspec_wget(wd, addr);
+ return 0;
+}
+static uae_u32 REGPARAM2 comspec_lget (uaecptr addr)
+{
+ struct wd_state *wd = getscsiboard(addr);
+ if (wd)
+ return comspec_lget(wd, addr);
+ return 0;
+}
+static void REGPARAM2 comspec_bput (uaecptr addr, uae_u32 b)
+{
+ struct wd_state *wd = getscsiboard(addr);
+ if (wd)
+ comspec_bput(wd, addr, b);
+}
+static void REGPARAM2 comspec_wput (uaecptr addr, uae_u32 b)
+{
+ struct wd_state *wd = getscsiboard(addr);
+ if (wd)
+ comspec_wput(wd, addr, b);
+}
+static void REGPARAM2 comspec_lput (uaecptr addr, uae_u32 b)
+{
+ struct wd_state *wd = getscsiboard(addr);
+ if (wd)
+ comspec_lput(wd, addr, b);
+}
+
+static const addrbank comspec_bank = {
+ comspec_lget, comspec_wget, comspec_bget,
+ comspec_lput, comspec_wput, comspec_bput,
+ comspec_xlate, comspec_check, NULL, _T("*"), _T("COMSPEC"),
+ comspec_lgeti, comspec_wgeti,
+ ABFLAG_IO | ABFLAG_SAFE | ABFLAG_PPCIOSPACE, S_READ, S_WRITE
+};
+
/* GVP Series I and II */
add_scsi_device(&wd_cdtv->scsis[ch], ch, ci, rc);
}
+bool comspec_init (struct autoconfig_info *aci)
+{
+ ew(aci->autoconfig_raw, 0x00, 0xc0 | 0x01 | 0x10);
+ ew(aci->autoconfig_raw, 0x04, 0x11);
+ ew(aci->autoconfig_raw, 0x10, 0x03);
+ ew(aci->autoconfig_raw, 0x14, 0xee);
+ /* rom vector */
+ ew(aci->autoconfig_raw, 0x28, 0x00);
+ ew(aci->autoconfig_raw, 0x2c, 0x10);
+ /* serial number */
+ ew(aci->autoconfig_raw, 0x18, 0x00);
+ ew(aci->autoconfig_raw, 0x1c, 0x00);
+ ew(aci->autoconfig_raw, 0x20, 0x00);
+ ew(aci->autoconfig_raw, 0x24, 0x00);
+
+ aci->label = _T("COMSPEC");
+ if (!aci->doinit)
+ return true;
+
+ struct wd_state *wd = getscsi(aci->rc);
+ int slotsize;
+
+ if (!wd)
+ return false;
+
+ init_wd_scsi(wd);
+
+ wd->configured = 0;
+ wd->dmac_type = COMSPEC_CHIP;
+ wd->autoconfig = true;
+ wd->board_mask = 65535;
+ wd->wc.resetnodelay = true;
+ memcpy(&wd->bank, &comspec_bank, sizeof addrbank);
+ memcpy(wd->dmacmemory, aci->autoconfig_raw, sizeof wd->dmacmemory);
+
+ alloc_expansion_bank(&wd->bank, aci);
+
+ wd->rombank = 0;
+ wd->rom_size = 16384;
+ slotsize = 65536;
+ wd->rom = xcalloc(uae_u8, slotsize);
+ memset(wd->rom, 0xff, slotsize);
+ wd->rom_mask = wd->rom_size - 1;
+ struct zfile *z = read_device_from_romconfig(aci->rc, ROMTYPE_COMSPEC);
+ if (z) {
+ wd->rom_size = zfile_size (z);
+ zfile_fread (wd->rom, wd->rom_size, 1, z);
+ zfile_fclose (z);
+ wd->rom_mask = wd->rom_size - 1;
+ }
+
+ if (!aci->rc->autoboot_disabled)
+ map_banks(&wd->bank, 0xf00000 >> 16, 1, 0);
+
+ return true;
+}
+
+void comspec_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ struct wd_state *wd = allocscsi(&wd_comspec[ci->controller_type_unit], rc, ch);
+ if (!wd || ch < 0)
+ return;
+ add_scsi_device(&wd->scsis[ch], ch, ci, rc);
+}
+
#if 0
uae_u8 *save_scsi_dmac (int wdtype, int *len, uae_u8 *dstptr)
return NULL;
}
-#define NEXT_ROM_ID 200
+#define NEXT_ROM_ID 202
#define ALTROM(id,grp,num,size,flags,crc32,a,b,c,d,e) \
{ _T("X"), 0, 0, 0, 0, 0, size, id, 0, 0, flags, (grp << 16) | num, 0, NULL, crc32, a, b, c, d, e },
0x4fe08a5d, 0x007e5c61, 0x4048f598, 0x6d14011d, 0x23a41435, 0x5e0a2259, NULL, NULL },
{ _T("M-Tec AT500 Megabody v1.33"), 1, 33, 1, 33, _T("MTECAT\0"), 32768, 199, 0, 0, ROMTYPE_MTEC, 0, 0, NULL,
0x19715a2f, 0x124f9d10, 0x19f1b285, 0x16f33f4e, 0x2bf03ca0, 0x2f9ad772, NULL, NULL },
+ { _T("Comspec SA-1000 v34.805"), 34, 805, 34, 805, _T("COMSPEC\0"), 16384, 200, 0, 0, ROMTYPE_COMSPEC, 0, 0, NULL,
+ 0x44458e28, 0x048b8232, 0xfe54252b, 0xb81e0d06, 0x83c9e92d, 0x880f3cbf, NULL, NULL },
+ ALTROMPN(200, 1, 1, 8192, ROMTYPE_ODD | ROMTYPE_8BIT, NULL, 0xd5838a35, 0xb3d83657, 0x661a9fe1, 0xd54e6e69, 0xc8b13878, 0x0960a107)
+ ALTROMPN(200, 1, 2, 8192, ROMTYPE_EVEN | ROMTYPE_8BIT, NULL, 0x098c5529, 0x6f51827d, 0x40a79438, 0x69e2d0fb, 0x6e2e46e9, 0xb65c1244)
+ { _T("California Access Malibu v1.0"), 1, 0, 1, 0, _T("MALIBU\0"), 8192, 201, 0, 0, ROMTYPE_MALIBU, 0, 0, NULL,
+ 0xe60b1ce6, 0xa7c4b709, 0x494f4034, 0x42b8ec11, 0x090dc1d0, 0x18098ebc, NULL, NULL },
{ _T("CyberStorm MK I 68040"), 0, 0, 0, 0, _T("CSMKI\0"), 32768, 95, 0, 0, ROMTYPE_CB_CSMK1, 0, 0, NULL,
0, 0, 0, 0, 0, 0, NULL, _T("cyberstormmk1_040.rom") },
uae_u8 *newrom = NULL;
uae_u8 *tmp1 = xcalloc(uae_u8, 524288 * 2);
uae_u8 *tmp2 = xcalloc(uae_u8, 524288 * 2);
- zfile_fread(tmp1, 1, size, f);
for (;;) {
+ if (zfile_fread(tmp1, 1, size, f) != size)
+ break;
if (size == 524288 * 2) {
// Perhaps it is 1M interleaved ROM image?
mergecd32(tmp2, tmp1, 524288 * 2);
zfile_fclose(f);
f = f2;
}
+ if (f) {
+ zfile_fseek(f, 0, SEEK_SET);
+ }
return f;
}
struct zfile *read_rom_name (const TCHAR *filename)
{
- int i;
struct zfile *f;
- for (i = 0; i < romlist_cnt; i++) {
+ for (int i = 0; i < romlist_cnt; i++) {
if (my_issamepath(filename, rl[i].path)) {
struct romdata *rd = rl[i].rd;
f = read_rom (rd);
}
f = rom_fopen2(filename, _T("rb"), ZFD_NORMAL);
if (f) {
- uae_u8 tmp[11];
+ uae_u8 tmp[11] = { 0 };
zfile_fread (tmp, sizeof tmp, 1, f);
if (!memcmp (tmp, "AMIROMTYPE1", sizeof tmp)) {
struct zfile *df;