NULL
}
};
+static const struct expansionsubromtype trifecta_sub[] = {
+ {
+ _T("EC"), _T("ec"), 0, // IDE-only
+ 2071, 32, 0, false,
+ { 0 }
+ },
+ {
+ _T("LX"), _T("lx"), 0, // IDE+SCSI
+ 2071, 32, 0, false,
+ { 0 }
+ },
+ {
+ NULL
+ }
+};
static const struct expansionsubromtype supra_sub[] = {
{
_T("A500 ByteSync/XP"), _T("bytesync"), ROMTYPE_NONE | ROMTYPE_SUPRA,
2071, 4, 0, false, NULL,
true, 0, adscsi2000_settings
},
+ {
+ _T("trifecta"), _T("Trifecta"), _T("ICD"),
+ NULL, trifecta_init, NULL, trifecta_add_idescsi_unit, ROMTYPE_TRIFECTA | ROMTYPE_NONE, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+ trifecta_sub, 0,
+ false, EXPANSIONTYPE_SCSI | EXPANSIONTYPE_IDE,
+ 2071, 32, 0, false, NULL,
+ true, 0, NULL,
+ },
{
_T("buddha"), _T("Buddha"), _T("Individual Computers"),
NULL, buddha_init, NULL, buddha_add_ide_unit, ROMTYPE_BUDDHA, 0, 0, BOARD_AUTOCONFIG_Z2, false,
#define ELSATHD_IDE (FASTATA4K_IDE + 2 * MAX_DUPLICATE_EXPANSION_BOARDS)
#define ACCESSX_IDE (ELSATHD_IDE + MAX_DUPLICATE_EXPANSION_BOARDS)
#define IVST500AT_IDE (ACCESSX_IDE + 2 * MAX_DUPLICATE_EXPANSION_BOARDS)
-#define TOTAL_IDE (IVST500AT_IDE + MAX_DUPLICATE_EXPANSION_BOARDS)
+#define TRIFECTA_IDE (IVST500AT_IDE + MAX_DUPLICATE_EXPANSION_BOARDS)
+#define TOTAL_IDE (TRIFECTA_IDE + MAX_DUPLICATE_EXPANSION_BOARDS)
#define ALF_ROM_OFFSET 0x0100
#define GVP_IDE_ROM_OFFSET 0x8000
#define MASOBOSHI_SCSI_OFFSET 0xf800
#define MASOBOSHI_SCSI_OFFSET_END 0xfc00
+#define TRIFECTA_SCSI_OFFSET 0x0000
+#define TRIFECTA_SCSI_OFFSET_END 0x0100
+
/* masoboshi:
IDE
static struct ide_board *elsathd_board[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct ide_board *accessx_board[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct ide_board *ivst500at_board[MAX_DUPLICATE_EXPANSION_BOARDS];
+static struct ide_board *trifecta_board[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct ide_hdf *idecontroller_drive[TOTAL_IDE * 2];
static struct ide_thread_state idecontroller_its;
board->state2[0] |= 0x80;
}
+static int get_trifecta_reg(uaecptr addr, struct ide_board *board)
+{
+ int reg;
+ if (!(addr & 0x800))
+ return -1;
+ reg = (addr >> 6) & 7;
+ if (addr & 0x200)
+ reg |= IDE_SECONDARY;
+ return reg;
+}
+
static int get_adide_reg(uaecptr addr, struct ide_board *board)
{
int reg;
if (!rom)
write_log(_T("MASOBOSHI BYTE GET %08x %02x %d %08x\n"), addr, v, regnum, M68K_GETPC);
#endif
+
+ } else if (board->type == TRIFECTA_IDE) {
+
+ if (addr & 1) {
+ int regnum = get_trifecta_reg(addr, board);
+ if (regnum >= 0) {
+ v = get_ide_reg(board, regnum);
+ }
+ }
+ if (addr >= TRIFECTA_SCSI_OFFSET && addr < TRIFECTA_SCSI_OFFSET_END) {
+ if (board->subtype)
+ v = trifecta_ncr9x_scsi_get(oaddr, getidenum(board, trifecta_board));
+ else
+ v = 0xff;
+ }
+ if (addr == 0x401) {
+ if (board->subtype)
+ v = (board->aci->rc->device_id ^ 7) & 7; // inverted SCSI ID
+ else
+ v = 0xff;
+ } else if (addr & 0x8000) {
+ if (board->rom)
+ v = board->rom[addr & board->rom_mask];
+ }
+ if (addr >= 0x400 && addr <= 0x7ff) {
+ write_log(_T("trifecta get %08x\n"), addr);
+ }
+
+
} else if (board->type == APOLLO_IDE) {
if (addr >= APOLLO_ROM_OFFSET) {
}
}
+ } else if (board->type == TRIFECTA_IDE) {
+
+ if (addr & 0x8000) {
+ if (board->rom) {
+ v = board->rom[addr & board->rom_mask] << 8;
+ v |= board->rom[(addr + 1) & board->rom_mask];
+ }
+ } else {
+ int regnum = get_trifecta_reg(addr, board);
+ if (regnum == IDE_DATA) {
+ v = get_ide_reg(board, IDE_DATA);
+ } else {
+ v = ide_read_byte(board, addr) << 8;
+ v |= ide_read_byte(board, addr + 1);
+ }
+ }
+
} else if (board->type == APOLLO_IDE) {
if ((addr & 0xc000) == 0x4000) {
ncr_golemfast_autoconfig_init(board->original_rc, board->baseaddress);
} else if (board->type == DATAFLYERPLUS_IDE) {
dataflyerplus_scsi_init(board->original_rc, board->baseaddress);
+ } else if (board->type == TRIFECTA_IDE) {
+ ncr_trifecta_autoconfig_init(board->original_rc, board->baseaddress);
}
expamem_next(ab, NULL);
}
}
}
+ } else if (board->type == TRIFECTA_IDE) {
+
+ if (addr & 1) {
+ int regnum = get_trifecta_reg(addr, board);
+ if (regnum >= 0) {
+ put_ide_reg(board, regnum, v);
+ }
+ }
+ if (addr >= TRIFECTA_SCSI_OFFSET && addr < TRIFECTA_SCSI_OFFSET_END) {
+ if (board->subtype)
+ trifecta_ncr9x_scsi_put(oaddr, v, getidenum(board, trifecta_board));
+ }
+ if (addr >= 0x400 && addr <= 0x407) {
+ trifecta_ncr9x_scsi_put(oaddr, v, getidenum(board, trifecta_board));
+ }
+
} else if (board->type == APOLLO_IDE) {
if ((addr & 0xc000) == 0x4000) {
#if DEBUG_IDE_MASOBOSHI
write_log(_T("MASOBOSHI IO WORD WRITE %08x %04x %08x\n"), addr, v, M68K_GETPC);
#endif
-
+ } else if (board->type == TRIFECTA_IDE) {
+
+ int regnum = get_trifecta_reg(addr, board);
+ if (regnum == IDE_DATA) {
+ put_ide_reg(board, IDE_DATA, v);
+ } else {
+ ide_write_byte(board, addr, v >> 8);
+ ide_write_byte(board, addr + 1, v);
+ }
+
} else if (board->type == APOLLO_IDE) {
if ((addr & 0xc000) == 0x4000) {
}
}
+static const uae_u8 trifecta_autoconfig[16] = { 0xc1, 0x23, 0x00, 0x00, 0x08, 0x17, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 };
+
+bool trifecta_init(struct autoconfig_info *aci)
+{
+ int rom_size = 65536;
+ uae_u8 *rom = xcalloc(uae_u8, rom_size);
+ memset(rom, 0xff, rom_size);
+
+ if (!aci->doinit) {
+ aci->autoconfigp = trifecta_autoconfig;
+ return true;
+ }
+
+ struct ide_board *ide = getide(aci);
+
+ if (!ide)
+ return false;
+
+ ide->configured = 0;
+ ide->bank = &ide_bank_generic;
+ ide->type = TRIFECTA_IDE;
+ ide->rom_size = rom_size;
+ ide->rom_mask = ide->mask = rom_size - 1;
+ ide->rom = rom;
+ ide->subtype = aci->rc->subtype;
+ ide->keepautoconfig = false;
+ ide->intena = true;
+
+ load_rom_rc(aci->rc, ROMTYPE_TRIFECTA, 32768, 0, rom, 65536, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
+
+ for (int i = 0; i < 16; i++) {
+ uae_u8 b = trifecta_autoconfig[i];
+ ew(ide, i * 4, b);
+ }
+
+ aci->addrbank = ide->bank;
+ return true;
+}
+
+static void trifecta_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ add_ide_standard_unit(ch, ci, rc, trifecta_board, TRIFECTA_IDE, true, false, 2);
+}
+
+void trifecta_add_idescsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ if (ch < 0) {
+ trifecta_add_ide_unit(ch, ci, rc);
+ trifecta_add_scsi_unit(ch, ci, rc);
+ } else {
+ if (ci->controller_type < HD_CONTROLLER_TYPE_SCSI_FIRST)
+ trifecta_add_ide_unit(ch, ci, rc);
+ else
+ trifecta_add_scsi_unit(ch, ci, rc);
+ }
+}
+
+
static const uae_u8 adide_autoconfig[16] = { 0xd1, 0x02, 0x00, 0x00, 0x08, 0x17, 0x00, 0x00, 0x00, 0x00, ADIDE_ROM_OFFSET >> 8, ADIDE_ROM_OFFSET & 0xff };
bool adide_init(struct autoconfig_info *aci)
void masoboshi_add_idescsi_unit (int ch, struct uaedev_config_info *ci, struct romconfig *rc);
bool masoboshi_init(struct autoconfig_info *aci);
+void trifecta_add_idescsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
+bool trifecta_init(struct autoconfig_info *aci);
+
void adide_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
bool adide_init(struct autoconfig_info *aci);
extern void fastlane_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
extern void oktagon_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
extern void masoboshi_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
+extern void trifecta_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
extern void ematrix_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
extern void multievolution_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
extern void golemfast_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
void masoboshi_ncr9x_scsi_put(uaecptr addr, uae_u32 v, int devnum);
void ncr_masoboshi_autoconfig_init(struct romconfig*, uaecptr);
+uae_u32 trifecta_ncr9x_scsi_get(uaecptr addr, int devnum);
+void trifecta_ncr9x_scsi_put(uaecptr addr, uae_u32 v, int devnum);
+void ncr_trifecta_autoconfig_init(struct romconfig*, uaecptr);
+
uae_u32 golemfast_ncr9x_scsi_get(uaecptr addr, int devnum);
void golemfast_ncr9x_scsi_put(uaecptr addr, uae_u32 v, int devnum);
void ncr_golemfast_autoconfig_init(struct romconfig*, uaecptr);
#define ROMTYPE_OVERDRIVE 0x00100078
#define ROMTYPE_IVSTC 0x00100079
#define ROMTYPE_IVST500AT 0x0010007a
+#define ROMTYPE_TRIFECTA 0x0010007b
#define ROMTYPE_NOT 0x00800000
#define ROMTYPE_QUAD 0x01000000
bool adscsi_init(struct autoconfig_info *aci);
void adscsi_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
+bool trifecta_init(struct autoconfig_info *aci);
+void trifecta_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
+
void rochard_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
bool rochard_scsi_init(struct romconfig *rc, uaecptr baseaddress);
static struct ncr9x_state *ncr_golemfast_scsi[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct ncr9x_state *ncr_scram5394_scsi[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct ncr9x_state *ncr_rapidfire_scsi[MAX_DUPLICATE_EXPANSION_BOARDS];
+static struct ncr9x_state *ncr_trifecta_scsi[MAX_DUPLICATE_EXPANSION_BOARDS];
static struct ncr9x_state *ncr_units[MAX_NCR9X_UNITS + 1];
}
}
+static void set_irq2_trifecta(struct ncr9x_state *ncr)
+{
+ if (ncr->chipirq) {
+ ncr->boardirqlatch = true;
+ if (ncr->intena) {
+ ncr->boardirq = true;
+ devices_rethink_all(ncr9x_rethink);
+#if NCR_DEBUG > 1
+ write_log(_T("TRIFECTA IRQ\n"));
+#endif
+ } else {
+ ncr->boardirq = false;
+ }
+ } else {
+ ncr->boardirq = false;
+ }
+}
+
void esp_irq_raise(qemu_irq irq)
{
struct ncr9x_state *ncr = (struct ncr9x_state*)irq;
}
}
+/* Trifecta is true DMA only to/from its onboard Fast RAM expansion */
+
+static int trifecta_dma_read(void *opaque, uint8_t *buf, int len)
+{
+ struct ncr9x_state *ncr = (struct ncr9x_state*)opaque;
+ if (ncr->dma_on) {
+ write_log(_T("Trifecta DMA from %08x, %d bytes\n"), ncr->dma_ptr, len);
+ m68k_cancel_idle();
+ while (len > 0) {
+ uae_u16 v = get_word(ncr->dma_ptr & ~1);
+ *buf++ = v >> 8;
+ len--;
+ if (len > 0) {
+ *buf++ = v;
+ len--;
+ }
+ ncr->dma_ptr += 2;
+ }
+ return -1;
+ }
+ return 0;
+}
+static int trifecta_dma_write(void *opaque, uint8_t *buf, int len)
+{
+ struct ncr9x_state *ncr = (struct ncr9x_state*)opaque;
+ if (ncr->dma_on) {
+ write_log(_T("Trifecta DMA to %08x, %d bytes\n"), ncr->dma_ptr, len);
+ m68k_cancel_idle();
+ while (len > 0) {
+ uae_u16 v;
+ v = *buf++;
+ len--;
+ v <<= 8;
+ if (len > 0) {
+ v |= *buf++;
+ len--;
+ }
+ put_word(ncr->dma_ptr & ~1, v);
+ ncr->dma_ptr += 2;
+ }
+ return -1;
+ }
+ return 0;
+}
+
static int fastlane_dma_read(void *opaque, uint8_t *buf, int len)
{
reg_shift = 1;
addr &= 0x3f;
+ } else if (isncr(ncr, ncr_trifecta_scsi)) {
+
+ if (addr == 0x400) {
+ ncr->intena = (val & 8) != 0;
+ ncr->dma_on = (val & 4) != 0;
+ esp_dma_enable(ncr->devobject.lsistate, ncr->dma_on);
+ ncr->states[0] = val;
+ ncr->dma_cnt = 0;
+ if (ncr->dma_on) {
+ write_log(_T("Trifecta DMA %08x %c\n"), ncr->dma_ptr, (val & 1) ? 'R' : 'W');
+ }
+ } else if (addr == 0x402) {
+ ncr->dma_ptr &= 0xffff00;
+ ncr->dma_ptr |= val;
+ } else if (addr == 0x404) {
+ ncr->dma_ptr &= 0xff00ff;
+ ncr->dma_ptr |= val << 8;
+ } else if (addr == 0x406) {
+ ncr->dma_ptr &= 0x00ffff;
+ ncr->dma_ptr |= val << 16;
+ }
+
+ if (addr >= 0x200)
+ return;
+
+ if (!(addr & 1))
+ return;
+
+ reg_shift = 1;
+ addr &= 0x3f;
+
} else if (isncr(ncr, ncr_oktagon2008_scsi)) {
if (addr == OKTAGON_EEPROM_SCL) {
eeprom_i2c_set(ncr->eeprom, BITBANG_I2C_SCL, (val & 0x80) != 0);
reg_shift = 1;
addr &= 0x3f;
+ } else if (isncr(ncr, ncr_trifecta_scsi)) {
+
+ if (addr >= 0x200)
+ return v;
+
+ if (!(addr & 1))
+ return v;
+
+ reg_shift = 1;
+ addr &= 0x3f;
+
} else if (isncr(ncr, ncr_oktagon2008_scsi)) {
if (addr == OKTAGON_EEPROM_SCL) {
return eeprom_i2c_set(ncr->eeprom, BITBANG_I2C_SCL, -1) ? 0x80 : 0x00;
ncr9x_io_bput(ncr_masoboshi_scsi[devnum], addr, v);
}
+uae_u32 trifecta_ncr9x_scsi_get(uaecptr addr, int devnum)
+{
+ return ncr9x_io_bget(ncr_trifecta_scsi[devnum], addr);
+}
+void trifecta_ncr9x_scsi_put(uaecptr addr, uae_u32 v, int devnum)
+{
+ ncr9x_io_bput(ncr_trifecta_scsi[devnum], addr, v);
+}
+
uae_u32 golemfast_ncr9x_scsi_get(uaecptr addr, int devnum)
{
return ncr9x_io_bget(ncr_golemfast_scsi[devnum], addr);
ncr9x_reset_board(ncr);
}
+void ncr_trifecta_autoconfig_init(struct romconfig *rc, uaecptr baseaddress)
+{
+ struct ncr9x_state *ncr = getscsi(rc);
+
+ if (!ncr)
+ return;
+
+ ncr->enabled = true;
+ ncr->baseaddress = baseaddress;
+
+ ncr9x_reset_board(ncr);
+}
+
+
bool ncr_scram5394_init(struct autoconfig_info *aci)
{
const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_SCRAM5394);
ncr9x_esp_scsi_init(ncr_masoboshi_scsi[ci->controller_type_unit], masoboshi_dma_read, masoboshi_dma_write, set_irq2_masoboshi, 0);
}
+void trifecta_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+ ncr9x_add_scsi_unit(&ncr_trifecta_scsi[ci->controller_type_unit], ch, ci, rc);
+ ncr9x_esp_scsi_init(ncr_trifecta_scsi[ci->controller_type_unit], trifecta_dma_read, trifecta_dma_write, set_irq2_trifecta, 0);
+}
+
void ematrix_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
{
ncr9x_add_scsi_unit(&ncr_ematrix530_scsi, ch, ci, rc);
}
} else {
s->rregs[ESP_FIFO] = s->ti_buf[s->ti_rptr++];
- esp_raise_irq(s);
+ if (s->pio_on)
+ esp_raise_irq(s);
}
}
if (s->ti_size == 0) {
}
}
#if ESPLOG
- write_log("<FIFO %02x %d %d %d\n", s->rregs[ESP_FIFO], s->pio_on, s->ti_size, s->ti_rptr);
+ write_log("<-FIFO %02x %d %d %d\n", s->rregs[ESP_FIFO], s->pio_on, s->ti_size, s->ti_rptr);
#endif
break;
case ESP_RINTR:
case ESP_TCMID:
case ESP_TCHI:
s->rregs[ESP_RSTAT] &= ~STAT_TC;
+ if (!(s->wregs[ESP_CFG2] & 0x40))
+ val = 0;
break;
case ESP_FIFO:
#if ESPLOG
s->rregs[ESP_RINTR] = INTR_DC;
s->rregs[ESP_RSEQ] = 0;
//s->rregs[ESP_RFLAGS] = 0;
- // Masoboshi driver expects phase=0!
- s->rregs[ESP_RSTAT] &= ~7;
+ // Features enable
+ if (!(s->wregs[ESP_CFG2] & 0x40)) {
+ // Masoboshi driver expects phase=0!
+ s->rregs[ESP_RSTAT] &= ~7;
+ }
esp_raise_irq(s);
break;
case CMD_PAD:
s->rregs[ESP_RSTAT] = STAT_TC;
s->rregs[ESP_RINTR] = INTR_FC;
s->rregs[ESP_RSEQ] = 0;
- break;
+ if (s->current_req) {
+ scsiesp_req_continue(s->current_req);
+ }
+ break;
case CMD_SATN:
break;
case CMD_RSTATN: