/* * UAE - The Un*x Amiga Emulator * * NCR 53C9x * * (c) 2014 Toni Wilen */ #include "sysconfig.h" #include "sysdeps.h" #ifdef NCR9X #define NCR_DEBUG 0 #include "options.h" #include "uae.h" #include "memory.h" #include "rommgr.h" #include "custom.h" #include "newcpu.h" #include "ncr9x_scsi.h" #include "scsi.h" #include "filesys.h" #include "zfile.h" #include "blkdev.h" #include "cpuboard.h" #include "flashrom.h" #include "autoconf.h" #include "qemuvga/qemuuaeglue.h" #include "qemuvga/queue.h" #include "qemuvga/scsi/scsi.h" #include "qemuvga/scsi/esp.h" #include "gui.h" #include "devices.h" #define FASTLANE_BOARD_SIZE (2 * 16777216) #define FASTLANE_ROM_SIZE 32768 #define FASTLANE_HARDBITS 0x01000041 #define FASTLANE_RESETDMA 0x01000081 /* NetBSD Fastlane definitions */ #define FLSC_HB_DISABLED 0x01 #define FLSC_HB_BUSID6 0x02 #define FLSC_HB_SEAGATE 0x04 #define FLSC_HB_SLOW 0x08 #define FLSC_HB_SYNCHRON 0x10 #define FLSC_HB_CREQ 0x20 #define FLSC_HB_IACT 0x40 #define FLSC_HB_MINT 0x80 #define FLSC_PB_ESI 0x01 #define FLSC_PB_EDI 0x02 #define FLSC_PB_ENABLE_DMA 0x04 #define FLSC_PB_DMA_WRITE 0x08 #define FLSC_PB_LED 0x10 #define OKTAGON_BOARD_SIZE 65536 #define OKTAGON_ROM_SIZE 32768 #define OKTAGON_ROM_OFFSET 0x100 #define OKTAGON_ESP_ADDR 0x03000 #define OKTAGON_DMA_START 0x01000 #define OKTAGON_DMA_END 0x2000 #define OKTAGON_INTENA 0x8000 #define OKTAGON_EEPROM_SCL 0x8010 #define OKTAGON_EEPROM_SDA 0x8018 #define OKTAGON_EEPROM_SIZE 512 #define MASOBOSHI_ESP_ADDR 0xfa00 #define MASOBOSHI_DMA_START 0xf900 #define MASOBOSHI_DMA_END 0xfa00 #define DKB_BOARD_SIZE 131072 #define DKB_ROM_SIZE 32768 #define DKB_ROM_OFFSET 0x8000 struct ncr9x_state { DeviceState devobject; SCSIDevice *scsid[8]; SCSIBus scsibus; uae_u32 board_mask; uae_u32 board_mask2; uae_u8 *rom; void *flashrom; struct zfile *flashrom_file; uae_u8 acmemory[128]; int configured; uaecptr baseaddress; uaecptr baseaddress2; uae_u32 expamem_hi; uae_u32 expamem_lo; bool enabled; int rom_start, rom_end, rom_offset; bool rom_bypass_if_write; int io_start, io_end; addrbank *bank; bool chipirq, boardirq, boardirqlatch; bool intena; bool irq6; bool pcmcia; void (*irq_func)(struct ncr9x_state*); int led; uaecptr dma_ptr; bool dma_on; int dma_cnt; uae_u32 dma_mask; uae_u8 states[16]; struct romconfig *rc; struct ncr9x_state **self_ptr; uae_u8 data; bool data_valid_r, data_valid_w; void *eeprom; uae_u8 eeprom_data[512]; bool romisoddonly; bool romisevenonly; uae_u8 *fakedma_data_buf; int fakedma_data_size_allocated; int fakedma_data_size; int fakedma_data_offset; uae_u8 *fakedma_data_write_buffer; }; /* Blizzard SCSI Kit IV: scsi: 0x8000 dma: 0x10000 pa >>= 1; if (!bsc->sc_datain) pa |= 0x80000000; bsc->sc_dmabase[0x8000] = (u_int8_t)(pa >> 24); bsc->sc_dmabase[0] = (u_int8_t)(pa >> 24); bsc->sc_dmabase[0] = (u_int8_t)(pa >> 16); bsc->sc_dmabase[0] = (u_int8_t)(pa >> 8); bsc->sc_dmabase[0] = (u_int8_t)(pa); Blizzard 2060: scsi: 0x1ff00 dma: 0x1fff0 bsc->sc_reg[0xe0] = BZTZSC_PB_LED; LED pa >>= 1; if (!bsc->sc_datain) pa |= 0x80000000; bsc->sc_dmabase[12] = (u_int8_t)(pa); bsc->sc_dmabase[8] = (u_int8_t)(pa >> 8); bsc->sc_dmabase[4] = (u_int8_t)(pa >> 16); bsc->sc_dmabase[0] = (u_int8_t)(pa >> 24); */ #define MAX_NCR9X_UNITS 10 static struct ncr9x_state *ncr_blizzard_scsi; static struct ncr9x_state *ncr_fastlane_scsi[MAX_DUPLICATE_EXPANSION_BOARDS]; static struct ncr9x_state *ncr_oktagon2008_scsi[MAX_DUPLICATE_EXPANSION_BOARDS]; static struct ncr9x_state *ncr_alf3_scsi[MAX_DUPLICATE_EXPANSION_BOARDS]; static struct ncr9x_state *ncr_masoboshi_scsi[MAX_DUPLICATE_EXPANSION_BOARDS]; static struct ncr9x_state *ncr_dkb1200_scsi; static struct ncr9x_state *ncr_ematrix530_scsi; static struct ncr9x_state *ncr_multievolution_scsi; static struct ncr9x_state *ncr_typhoon2_scsi; 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_squirrel_scsi; static struct ncr9x_state *ncr_mtec_mastercard; static struct ncr9x_state *ncr_units[MAX_NCR9X_UNITS + 1]; // Only offsets 0x100 to 0x10f contains non-FF data static uae_u8 oktagon_eeprom[16] = { 0x0b, 0xf4, 0x3f, 0x0a, 0xff, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0xaf, 0xff }; static void freescsi(SCSIDevice *scsi) { if (scsi) { free_scsi((struct scsi_data*)scsi->handle); xfree(scsi); } } static void freencrunit(struct ncr9x_state *ncr) { if (!ncr) return; for (int i = 0; i < MAX_NCR9X_UNITS; i++) { if (ncr_units[i] == ncr) { ncr_units[i] = NULL; } } for (int ch = 0; ch < 8; ch++) { freescsi(ncr->scsid[ch]); ncr->scsid[ch] = NULL; } flash_free(ncr->flashrom); zfile_fclose(ncr->flashrom_file); xfree(ncr->rom); if (ncr->self_ptr) *ncr->self_ptr = NULL; xfree(ncr); } static struct ncr9x_state *allocscsi(struct ncr9x_state **ncr, struct romconfig *rc, int ch) { struct ncr9x_state *scsi; if (ch < 0) { freencrunit(*ncr); *ncr = NULL; } if ((*ncr) == NULL) { scsi = xcalloc(struct ncr9x_state, 1); for (int i = 0; i < MAX_NCR9X_UNITS; i++) { if (ncr_units[i] == NULL) { ncr_units[i] = scsi; if (rc) rc->unitdata = scsi; scsi->rc = rc; scsi->self_ptr = ncr; *ncr = scsi; return scsi; } } } return *ncr; } static struct ncr9x_state *getscsi(struct romconfig *rc) { for (int i = 0; i < MAX_NCR9X_UNITS; i++) { if (ncr_units[i]) { struct ncr9x_state *ncr = ncr_units[i]; if (ncr->rc == rc) return ncr; } } return NULL; } static void ncr9x_rethink(void) { for (int i = 0; ncr_units[i]; i++) { if (ncr_units[i]->boardirq) { if (ncr_units[i]->pcmcia) pcmcia_interrupt_set(1); else safe_interrupt_set(IRQ_SOURCE_NCR9X, i, ncr_units[i]->irq6); } } } static void set_irq2(struct ncr9x_state *ncr) { if (ncr->chipirq && !ncr->boardirq) { ncr->boardirq = true; devices_rethink_all(ncr9x_rethink); } if (!ncr->chipirq && ncr->boardirq) { ncr->boardirq = false; if (ncr->pcmcia) pcmcia_interrupt_set(0); } } static void set_irq2_dkb1200(struct ncr9x_state *ncr) { if (!(ncr->states[0] & 0x40)) ncr->boardirq = false; if (ncr->chipirq && !ncr->boardirq && (ncr->states[0] & 0x40)) { ncr->boardirq = true; devices_rethink_all(ncr9x_rethink); } } static void set_irq2_oktagon(struct ncr9x_state *ncr) { if (!(ncr->states[0] & 0x80)) ncr->boardirq = false; if (ncr->chipirq && !ncr->boardirq && (ncr->states[0] & 0x80)) { ncr->boardirq = true; devices_rethink_all(ncr9x_rethink); } } static void set_irq2_alf3(struct ncr9x_state *ncr) { if (!(ncr->states[0] & 0x01)) ncr->boardirq = false; if (ncr->chipirq && !ncr->boardirq && (ncr->states[0] & 0x01)) { ncr->boardirq = true; devices_rethink_all(ncr9x_rethink); } } static void set_irq2_fastlane(struct ncr9x_state *ncr) { if (!ncr->chipirq || !(ncr->states[0] & FLSC_PB_ESI)) { ncr->states[0] |= FLSC_HB_MINT; ncr->boardirq = false; return; } ncr->states[0] |= FLSC_HB_CREQ; ncr->states[0] &= ~FLSC_HB_MINT; if (ncr->states[0] & FLSC_PB_ESI) { if (!ncr->boardirq) { ncr->boardirq = true; devices_rethink_all(ncr9x_rethink); } } } static void set_irq2_golemfast(struct ncr9x_state *ncr) { } static void set_irq2_masoboshi(struct ncr9x_state *ncr) { if (ncr->chipirq) { ncr->boardirqlatch = true; if (1 || ncr->intena) { ncr->boardirq = true; devices_rethink_all(ncr9x_rethink); #if NCR_DEBUG > 1 write_log(_T("MASOBOSHI IRQ\n")); #endif } else { ncr->boardirq = false; } } else { ncr->boardirq = false; } } 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; ncr->chipirq = true; #if NCR_DEBUG > 1 write_log(_T("NCR9X +IRQ\n")); #endif ncr->irq_func(ncr); } void esp_irq_lower(qemu_irq irq) { struct ncr9x_state *ncr = (struct ncr9x_state*)irq; ncr->chipirq = false; #if NCR_DEBUG > 1 write_log(_T("NCR9X -IRQ\n")); #endif ncr->irq_func(ncr); } static void fakedma_buffer_size(struct ncr9x_state *ncr, int size) { size = (size + 1) & ~1; if (ncr->fakedma_data_size_allocated >= size) return; if (ncr->fakedma_data_buf) xfree(ncr->fakedma_data_buf); ncr->fakedma_data_buf = xmalloc(uae_u8, size); ncr->fakedma_data_size_allocated = size; } /* Fake DMA */ static int fake_dma_null(void *opaque, uint8_t *buf, int len) { return 0; } static int fake_dma_read_ematrix(void *opaque, uint8_t *buf, int len) { struct ncr9x_state *ncr = (struct ncr9x_state*)opaque; ncr->states[0] = 1; ncr->chipirq = true; set_irq2(ncr); ncr->fakedma_data_offset = 0; ncr->fakedma_data_write_buffer = buf; ncr->fakedma_data_size = len; fakedma_buffer_size(ncr, len); return 0; } static int fake_dma_write_ematrix(void *opaque, uint8_t *buf, int len) { struct ncr9x_state *ncr = (struct ncr9x_state*)opaque; ncr->states[0] = 1; ncr->chipirq = true; set_irq2(ncr); ncr->fakedma_data_offset = 0; fakedma_buffer_size(ncr, len); memcpy(ncr->fakedma_data_buf, buf, len); if (len & 1) ncr->fakedma_data_buf[len] = 0; ncr->fakedma_data_size = len; return 0; } static int fake_dma_read(void *opaque, uint8_t *buf, int len) { struct ncr9x_state *ncr = (struct ncr9x_state*)opaque; ncr->fakedma_data_offset = 0; ncr->fakedma_data_write_buffer = buf; ncr->fakedma_data_size = len; fakedma_buffer_size(ncr, len); return 0; } static int fake_dma_write(void *opaque, uint8_t *buf, int len) { struct ncr9x_state *ncr = (struct ncr9x_state*)opaque; ncr->fakedma_data_offset = 0; fakedma_buffer_size(ncr, len); memcpy(ncr->fakedma_data_buf, buf, len); if (len & 1) ncr->fakedma_data_buf[len] = 0; ncr->fakedma_data_size = len; return 0; } static int fake2_dma_read(void *opaque, uint8_t *buf, int len) { struct ncr9x_state *ncr = (struct ncr9x_state*)opaque; esp_dma_enable(ncr->devobject.lsistate, 0); if (ncr->data_valid_r) { *buf = ncr->data; ncr->data_valid_r = false; } return 1; } static int fake2_dma_write(void *opaque, uint8_t *buf, int len) { struct ncr9x_state *ncr = (struct ncr9x_state*)opaque; esp_dma_enable(ncr->devobject.lsistate, 0); if (!ncr->data_valid_w) { ncr->data = *buf; ncr->data_valid_w = true; return 1; } return 0; } /* Following are true DMA */ static int masoboshi_dma_read(void *opaque, uint8_t *buf, int len) { struct ncr9x_state *ncr = (struct ncr9x_state*)opaque; if (ncr->dma_on) { m68k_cancel_idle(); while (len > 0) { uae_u16 v = dma_get_word((ncr->dma_ptr & ~1) & ncr->dma_mask); *buf++ = v >> 8; len--; if (len > 0) { *buf++ = (uint8_t)v; len--; } ncr->dma_ptr += 2; } return -1; } else { esp_dma_enable(ncr->devobject.lsistate, 0); if (ncr->data_valid_r) { *buf = ncr->data; ncr->data_valid_r = false; } return 1; } } static int masoboshi_dma_write(void *opaque, uint8_t *buf, int len) { struct ncr9x_state *ncr = (struct ncr9x_state*)opaque; if (ncr->dma_on) { m68k_cancel_idle(); while (len > 0) { uae_u16 v; v = *buf++; len--; v <<= 8; if (len > 0) { v |= *buf++; len--; } dma_put_word((ncr->dma_ptr & ~1) & ncr->dma_mask, v); ncr->dma_ptr += 2; } return -1; } else { esp_dma_enable(ncr->devobject.lsistate, 0); if (!ncr->data_valid_w) { ncr->data = *buf; ncr->data_valid_w = true; return 1; } return 0; } } 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 = dma_get_word((ncr->dma_ptr & ~1) & ncr->dma_mask); *buf++ = v >> 8; len--; if (len > 0) { *buf++ = (uint8_t)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--; } dma_put_word((ncr->dma_ptr & ~1) & ncr->dma_mask, v); ncr->dma_ptr += 2; } return -1; } return 0; } static int fastlane_dma_read(void *opaque, uint8_t *buf, int len) { struct ncr9x_state *ncr = (struct ncr9x_state*)opaque; if (!(ncr->states[0] & FLSC_PB_DMA_WRITE)) { write_log(_T("fastlane_dma_read mismatched direction!\n")); return -1; } m68k_cancel_idle(); while (len > 0) { uae_u16 v = dma_get_word(ncr->dma_ptr & ~1); *buf++ = v >> 8; len--; if (len > 0) { *buf++ = (uint8_t)v; len--; } ncr->dma_ptr += 2; } return -1; } static int fastlane_dma_write(void *opaque, uint8_t *buf, int len) { struct ncr9x_state *ncr = (struct ncr9x_state*)opaque; if (ncr->states[0] & FLSC_PB_DMA_WRITE) { write_log(_T("fastlane_dma_write mismatched direction!\n")); return -1; } m68k_cancel_idle(); while (len > 0) { uae_u16 v; v = *buf++; len--; v <<= 8; if (len > 0) { v |= *buf++; len--; } dma_put_word(ncr->dma_ptr & ~1, v); ncr->dma_ptr += 2; } return -1; } static int cyberstorm_mk1_mk2_dma_read(void *opaque, uint8_t *buf, int len) { struct ncr9x_state *ncr = (struct ncr9x_state*)opaque; if (!(ncr->dma_ptr & 0x00000001)) { write_log(_T("cyberstorm_dma_read mismatched direction!\n")); return -1; } m68k_cancel_idle(); while (len > 0) { uae_u16 v = dma_get_word(ncr->dma_ptr & ~1); *buf++ = v >> 8; len--; if (len > 0) { *buf++ = (uint8_t)v; len--; } ncr->dma_ptr += 2; } return -1; } static int cyberstorm_mk1_mk2_dma_write(void *opaque, uint8_t *buf, int len) { struct ncr9x_state *ncr = (struct ncr9x_state*)opaque; if (ncr->dma_ptr & 0x00000001) { write_log(_T("cyberstorm_dma_write mismatched direction!\n")); return -1; } m68k_cancel_idle(); while (len > 0) { uae_u16 v; v = *buf++; len--; v <<= 8; if (len > 0) { v |= *buf++; len--; } dma_put_word(ncr->dma_ptr & ~1, v); ncr->dma_ptr += 2; } return -1; } static int blizzard_dma_read(void *opaque, uint8_t *buf, int len) { struct ncr9x_state *ncr = (struct ncr9x_state*)opaque; if (!(ncr->dma_ptr & 0x80000000)) { write_log(_T("blizzard_dma_read mismatched direction!\n")); return -1; } m68k_cancel_idle(); while (len > 0) { uae_u16 v = dma_get_word((ncr->dma_ptr & 0x7fffffff) * 2); *buf++ = v >> 8; len--; if (len > 0) { *buf++ = (uint8_t)v; len--; } ncr->dma_ptr++; } return -1; } static int blizzard_dma_write(void *opaque, uint8_t *buf, int len) { struct ncr9x_state *ncr = (struct ncr9x_state*)opaque; if (ncr->dma_ptr & 0x80000000) { write_log(_T("blizzard_dma_write mismatched direction!\n")); return -1; } m68k_cancel_idle(); while (len > 0) { uae_u16 v; v = *buf++; len--; v <<= 8; if (len > 0) { v |= *buf++; len--; } dma_put_word((ncr->dma_ptr & 0x7fffffff) * 2, v); ncr->dma_ptr++; } return -1; } static int get_scb_len(uae_u8 cmd) { if (cmd <= 0x1f) return 6; if (cmd >= 0x20 && cmd <= 0x5f) return 10; if (cmd >= 0x80 && cmd <= 0x9f) return 16; if (cmd >= 0xa0 && cmd <= 0xbf) return 12; return 0; } void scsiesp_req_continue(SCSIRequest *req) { struct scsi_data *sd = (struct scsi_data*)req->dev->handle; if (sd->data_len < 0) { esp_command_complete(req, sd->status, 0); } else if (sd->data_len) { esp_transfer_data(req, sd->data_len); } else { if (sd->direction > 0) scsi_emulate_cmd(sd); esp_command_complete(req, sd->status, 0); } } SCSIRequest *scsiesp_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun, uint8_t *buf, void *hba_private) { SCSIRequest *req = xcalloc(SCSIRequest, 1); struct scsi_data *sd = (struct scsi_data*)d->handle; struct ncr9x_state *ncr = (struct ncr9x_state*)sd->privdata; int len = get_scb_len(buf[0]); req->dev = d; req->hba_private = hba_private; req->bus = &ncr->scsibus; req->bus->qbus.parent = &ncr->devobject; memcpy(sd->cmd, buf, len); sd->cmd_len = len; return req; } int32_t scsiesp_req_enqueue(SCSIRequest *req) { struct scsi_data *sd = (struct scsi_data*)req->dev->handle; sd->data_len = 0; scsi_start_transfer(sd); scsi_emulate_analyze(sd); #if NCR_DEBUG write_log (_T("%02x.%02x.%02x.%02x.%02x.%02x\n"), sd->cmd[0], sd->cmd[1], sd->cmd[2], sd->cmd[3], sd->cmd[4], sd->cmd[5]); #endif if (sd->direction <= 0) scsi_emulate_cmd(sd); if (sd->direction == 0) return 1; if (sd->direction > 0) return -sd->data_len; return sd->data_len; } void scsiesp_req_unref(SCSIRequest *req) { xfree(req); } uint8_t *scsiesp_req_get_buf(SCSIRequest *req) { struct scsi_data *sd = (struct scsi_data*)req->dev->handle; sd->data_len = 0; return sd->buffer; } SCSIDevice *scsiesp_device_find(SCSIBus *bus, int channel, int target, int lun) { struct ncr9x_state *ncr = (struct ncr9x_state*)bus->privdata; if (lun != 0 || target < 0 || target >= 8) { #if NCR_DEBUG write_log(_T("Selected not supported: %d-%d-%d\n"), channel, target, lun); #endif return NULL; } #if NCR_DEBUG if (ncr->scsid[target]) write_log(_T("Selected: %d-%d-%d\n"), channel, target, lun); else write_log(_T("Selected non-existing: %d-%d-%d\n"), channel, target, lun); #endif return ncr->scsid[target]; } void scsiesp_req_cancel(SCSIRequest *req) { write_log(_T("scsi_req_cancel!?\n")); esp_request_cancelled(req); } #define IO_MASK 0x3f static uaecptr beswap(uaecptr addr) { return (addr & ~3) | (3 - (addr & 3)); } static bool isncr(struct ncr9x_state *ncr, struct ncr9x_state **arr) { for (int i = 0; i < MAX_DUPLICATE_EXPANSION_BOARDS; i++) { if (arr[i] == ncr) return true; } return false; } static void ncr9x_io_bput3(struct ncr9x_state *ncr, uaecptr addr, uae_u32 val, int *reg) { int reg_shift = 2; uaecptr oldaddr = addr; if (!ncr) return; addr &= ncr->board_mask; if (isncr(ncr, ncr_scram5394_scsi)) { if (addr >= 0x8000 && addr < 0xa000) { if (ncr->fakedma_data_offset < ncr->fakedma_data_size) { ncr->fakedma_data_buf[ncr->fakedma_data_offset++] = val; if (ncr->fakedma_data_offset == ncr->fakedma_data_size) { memcpy(ncr->fakedma_data_write_buffer, ncr->fakedma_data_buf, ncr->fakedma_data_size); esp_fake_dma_done(ncr->devobject.lsistate); } } return; } if (addr & 1) { return; } if (addr < 0x6000 || addr >= 0xc000) { return; } reg_shift = 1; } else if (ncr == ncr_multievolution_scsi) { reg_shift = 1; if (addr & 0x1000) { if (ncr->fakedma_data_offset < ncr->fakedma_data_size) { ncr->fakedma_data_buf[ncr->fakedma_data_offset++] = val; if (ncr->fakedma_data_offset == ncr->fakedma_data_size) { memcpy(ncr->fakedma_data_write_buffer, ncr->fakedma_data_buf, ncr->fakedma_data_size); esp_fake_dma_done(ncr->devobject.lsistate); } } return; } } else if (isncr(ncr, ncr_golemfast_scsi)) { reg_shift = 1; if ((addr & 0x8400) == 0x8400) { if (ncr->fakedma_data_offset < ncr->fakedma_data_size) { ncr->fakedma_data_buf[ncr->fakedma_data_offset++] = val; if (ncr->fakedma_data_offset == ncr->fakedma_data_size) { memcpy(ncr->fakedma_data_write_buffer, ncr->fakedma_data_buf, ncr->fakedma_data_size); esp_fake_dma_done(ncr->devobject.lsistate); } } return; } } else if (ncr == ncr_squirrel_scsi) { reg_shift = 0; if (addr >= 16) { ncr->data = val; ncr->data_valid_r = true; esp_dma_enable(ncr->devobject.lsistate, 1); return; } } else if (isncr(ncr, ncr_masoboshi_scsi)) { if (addr >= 0xf000 && addr < 0xf800) addr &= ~0x0700; // SCSI DMA LEN (words) if (addr >= 0xf00a && addr < 0xf00c) { if (addr == 0xf00a) { ncr->dma_cnt &= 0x00ff; ncr->dma_cnt |= val << 8; } else { ncr->dma_cnt &= 0xff00; ncr->dma_cnt |= val; } return; } // SCSI DMA PTR if (addr >= 0xf00c && addr < 0xf010) { int shift = (3 - (addr - 0xf00c)) * 8; uae_u32 mask = 0xff << shift; ncr->dma_ptr &= ~mask; ncr->dma_ptr |= val << shift; ncr->dma_ptr &= 0xffffff; return; } if (addr >= 0xf000 && addr < 0xf008) { ncr->states[addr - 0xf000] = val; if (addr == 0xf000) { ncr->boardirqlatch = false; set_irq2_masoboshi(ncr); } if (addr == 0xf007) { // scsi dma start ncr->dma_on = false; if (val & 0x80) { write_log(_T("MASOBOSHI SCSI DMA %s start %08x, %d\n"), (ncr->states[5] & 0x80) ? _T("READ") : _T("WRITE"), ncr->dma_ptr, ncr->dma_cnt); ncr->dma_on = true; esp_dma_enable(ncr->devobject.lsistate, 1); } else { esp_dma_enable(ncr->devobject.lsistate, 0); } } #if 0 write_log(_T("MASOBOSHI IO %08X PUT %02x %08x\n"), addr, val & 0xff, M68K_GETPC); #endif return; } if (addr >= MASOBOSHI_DMA_START && addr < MASOBOSHI_DMA_END) { #if NCR_DEBUG > 2 write_log(_T("MASOBOSHI DMA %08X PUT %02x %08x\n"), addr, val & 0xff, M68K_GETPC); #endif ncr->data = val; ncr->data_valid_r = true; esp_fake_dma_put(ncr->devobject.lsistate, val); return; } if (addr < MASOBOSHI_ESP_ADDR || addr >= MASOBOSHI_ESP_ADDR + 0x100) { #if NCR_DEBUG write_log(_T("MASOBOSHI IO %08X PUT %02x %08x\n"), addr, val & 0xff, M68K_GETPC); #endif return; } if (addr == MASOBOSHI_ESP_ADDR + 3 * 2 && val == 0x02) ncr->states[0] |= 0x80; 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_DEBUG if (ncr->dma_on) { write_log(_T("Trifecta DMA %08x %c\n"), ncr->dma_ptr, (val & 1) ? 'R' : 'W'); } #endif } 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); memcpy(oktagon_eeprom, ncr->eeprom_data + 0x100, 16); } else if (addr == OKTAGON_EEPROM_SDA) { eeprom_i2c_set(ncr->eeprom, BITBANG_I2C_SDA, (val & 0x80) != 0); memcpy(oktagon_eeprom, ncr->eeprom_data + 0x100, 16); } else if (addr >= OKTAGON_DMA_START && addr < OKTAGON_DMA_END) { ncr->data = val; ncr->data_valid_r = true; esp_dma_enable(ncr->devobject.lsistate, 1); return; } else if (addr == OKTAGON_INTENA) { ncr->states[0] = val; set_irq2_oktagon(ncr); return; } if (addr < OKTAGON_ESP_ADDR || addr >= OKTAGON_ESP_ADDR + 0x100) { return; } reg_shift = 1; } else if (isncr(ncr, ncr_alf3_scsi)) { if (addr >= 0xd000 && addr < 0xe000) { ncr->data = val; ncr->data_valid_r = true; esp_dma_enable(ncr->devobject.lsistate, 1); return; } else if (addr == 0xa001) { ncr->states[0] = val; set_irq2_alf3(ncr); return; } if (addr < 0x8000 || addr >= 0x8000 + 0x100) return; reg_shift = 1; } else if (isncr(ncr, ncr_fastlane_scsi)) { if (addr >= FASTLANE_HARDBITS) { if (addr == FASTLANE_HARDBITS) { int oldstate = ncr->states[0]; ncr->states[0] = val; if (!(oldstate & FLSC_PB_ENABLE_DMA) && (ncr->states[0] & FLSC_PB_ENABLE_DMA)) esp_dma_enable(ncr->devobject.lsistate, 1); else if ((oldstate & FLSC_PB_ENABLE_DMA) && !(ncr->states[0] & FLSC_PB_ENABLE_DMA)) esp_dma_enable(ncr->devobject.lsistate, 0); set_irq2_fastlane(ncr); } else if (addr == FASTLANE_RESETDMA) { ncr->dma_cnt = 4; ncr->dma_ptr = 0; } return; } else if (addr < 0x01000000) { // DMA address bits 0 to 23 comes from address bus. // DMA address bits 24 to 31 comes from data bus. ncr->dma_cnt--; if (ncr->dma_cnt == 3) { ncr->dma_ptr = val << 24; ncr->dma_ptr |= addr; } if (ncr->dma_cnt == 0 && (ncr->states[0] & FLSC_PB_ENABLE_DMA)) esp_dma_enable(ncr->devobject.lsistate, 1); return; } } else if (ISCPUBOARD(BOARD_BLIZZARD, BOARD_BLIZZARD_SUB_1230II)) { addr &= 0xffff; if (addr >= 0x20) { if (addr & 0x10) { ncr->dma_cnt = 0; ncr->dma_ptr = 0; } ncr->dma_ptr |= (val & 0xff) << ((3 - ncr->dma_cnt) * 8); ncr->dma_cnt++; if (ncr->dma_cnt == 4) esp_dma_enable(ncr->devobject.lsistate, 1); return; } reg_shift = 1; } else if (ISCPUBOARD(BOARD_BLIZZARD, BOARD_BLIZZARD_SUB_1230III)) { addr &= 0xffff; if (addr >= 0x20) { write_log(_T("BOARD_BLIZZARD_SUB_1230III WRITE %08x %08x\n"), addr, M68K_GETPC); return; } if (addr >= 0x10 && addr < 0x20) { fas408_write_fifo(ncr->devobject.lsistate, val); return; } reg_shift = 0; } else if (ISCPUBOARD(BOARD_BLIZZARD, BOARD_BLIZZARD_SUB_2060)) { if (addr >= BLIZZARD_2060_DMA_OFFSET) { //write_log (_T("Blizzard DMA PUT %08x %02X\n"), addr, (uae_u8)val); addr &= 0xf; addr >>= 2; addr = 3 - addr; ncr->dma_ptr &= ~(0xff << (addr * 8)); ncr->dma_ptr |= (val & 0xff) << (addr * 8); if (addr == 3) esp_dma_enable(ncr->devobject.lsistate, 1); return; } else if (addr >= BLIZZARD_2060_LED_OFFSET) { ncr->led = val; return; } } else if (ISCPUBOARD(BOARD_BLIZZARD, BOARD_BLIZZARD_SUB_1230IV) || ISCPUBOARD(BOARD_BLIZZARD, BOARD_BLIZZARD_SUB_1260)) { if (!is_board_enabled(&currprefs, ROMTYPE_BLIZKIT4, 0)) return; if (addr >= BLIZZARD_SCSI_KIT4_DMA_OFFSET) { addr &= 0x18000; if (addr == 0x18000) { ncr->dma_ptr = 0; ncr->dma_cnt = 4; } else { ncr->dma_ptr <<= 8; ncr->dma_ptr |= (uae_u8)val; ncr->dma_cnt--; if (ncr->dma_cnt == 0) esp_dma_enable(ncr->devobject.lsistate, 1); } //write_log(_T("Blizzard DMA PUT %08x %02X\n"), oldaddr, (uae_u8)val); return; } } else if (ISCPUBOARD(BOARD_CYBERSTORM, BOARD_CYBERSTORM_SUB_MK1)) { if (addr >= CYBERSTORM_MK1_JUMPER_OFFSET) { if (addr == CYBERSTORM_MK1_JUMPER_OFFSET) esp_dma_enable(ncr->devobject.lsistate, 1); } else if (addr >= CYBERSTORM_MK1_DMA_OFFSET) { addr &= 7; addr >>= 1; addr = 3 - addr; ncr->dma_ptr &= ~(0xff << (addr * 8)); ncr->dma_ptr |= (val & 0xff) << (addr * 8); return; } else if (addr >= CYBERSTORM_MK2_LED_OFFSET) { ncr->led = val; return; } } else if (ISCPUBOARD(BOARD_CYBERSTORM, BOARD_CYBERSTORM_SUB_MK2)) { if (addr >= CYBERSTORM_MK2_DMA_OFFSET) { addr &= 0xf; addr >>= 2; addr = 3 - addr; ncr->dma_ptr &= ~(0xff << (addr * 8)); ncr->dma_ptr |= (val & 0xff) << (addr * 8); if (addr == 0) esp_dma_enable(ncr->devobject.lsistate, 1); return; } else if (addr >= CYBERSTORM_MK2_LED_OFFSET) { ncr->led = val; return; } } else if (isncr(ncr, ncr_rapidfire_scsi)) { reg_shift = 1; if (addr == 0x10040) { ncr->states[0] = val; esp_dma_enable(ncr->devobject.lsistate, 1); //write_log(_T("DKB IO PUT %02x %08x\n"), val & 0xff, M68K_GETPC); return; } if (addr >= 0x10020 && addr < 0x10028) { //write_log(_T("DKB PUT BYTE %02x\n"), val & 0xff); if (ncr->fakedma_data_offset < ncr->fakedma_data_size) { ncr->fakedma_data_buf[ncr->fakedma_data_offset++] = val; if (ncr->fakedma_data_offset == ncr->fakedma_data_size) { memcpy(ncr->fakedma_data_write_buffer, ncr->fakedma_data_buf, ncr->fakedma_data_size); esp_fake_dma_done(ncr->devobject.lsistate); } } return; } if (addr < 0x10000 || addr >= 0x10020) { write_log(_T("DKB IO %08X PUT %02x %08x\n"), addr, val & 0xff, M68K_GETPC); return; } } else if (ISCPUBOARD(BOARD_DKB, BOARD_DKB_SUB_12x0)) { if (!(currprefs.cpuboard_settings & 1)) return; if (addr == 0x10100) { ncr->states[0] = val; esp_dma_enable(ncr->devobject.lsistate, 1); //write_log(_T("DKB IO PUT %02x %08x\n"), val & 0xff, M68K_GETPC); return; } if (addr >= 0x10080 && addr < 0x10088) { //write_log(_T("DKB PUT BYTE %02x\n"), val & 0xff); if (ncr->fakedma_data_offset < ncr->fakedma_data_size) { ncr->fakedma_data_buf[ncr->fakedma_data_offset++] = val; if (ncr->fakedma_data_offset == ncr->fakedma_data_size) { memcpy(ncr->fakedma_data_write_buffer, ncr->fakedma_data_buf, ncr->fakedma_data_size); esp_fake_dma_done(ncr->devobject.lsistate); } } return; } if (addr < 0x10000 || addr >= 0x10040) { write_log(_T("DKB IO %08X PUT %02x %08x\n"), addr, val & 0xff, M68K_GETPC); return; } } else if (ISCPUBOARD(BOARD_MTEC, BOARD_MTEC_SUB_EMATRIX530) || ISCPUBOARD(BOARD_DCE, BOARD_DCE_SUB_TYPHOON2) || ncr == ncr_mtec_mastercard) { if ((addr & 0xf000) >= 0xe000) { if ((addr & 0x3ff) <= 7) { if (ncr->fakedma_data_offset < ncr->fakedma_data_size) { ncr->fakedma_data_buf[ncr->fakedma_data_offset++] = val; if (ncr->fakedma_data_offset == ncr->fakedma_data_size) { memcpy(ncr->fakedma_data_write_buffer, ncr->fakedma_data_buf, ncr->fakedma_data_size); esp_fake_dma_done(ncr->devobject.lsistate); ncr->states[0] = 0; } } } return; } if (addr < 0xc000 || addr >= 0xe000) return; if (addr & 1) return; if ((currprefs.cpuboard_settings & 1) && ncr != ncr_mtec_mastercard) return; reg_shift = 3; } if (!ncr->devobject.lsistate) return; addr >>= reg_shift; addr &= IO_MASK; esp_reg_write(ncr->devobject.lsistate, (addr), val); *reg = addr; } static void ncr9x_io_bput(struct ncr9x_state *ncr, uaecptr addr, uae_u32 val) { int reg = -1; ncr9x_io_bput3(ncr, addr, val, ®); #if NCR_DEBUG > 1 if (ncr) write_log(_T("ESP write %02X (%08X) %02X %08X\n"), reg & 0xff, addr, val & 0xff, M68K_GETPC); #endif } static uae_u32 ncr9x_io_bget3(struct ncr9x_state *ncr, uaecptr addr, int *reg) { uae_u8 v = 0xff; int reg_shift = 2; uaecptr oldaddr = addr; if (!ncr) return v; addr &= ncr->board_mask; if (isncr(ncr, ncr_scram5394_scsi)) { if (addr >= 0x8000 && addr < 0xa000) { if (ncr->fakedma_data_offset >= ncr->fakedma_data_size) return 0; v = ncr->fakedma_data_buf[ncr->fakedma_data_offset++]; if (ncr->fakedma_data_offset == ncr->fakedma_data_size) { esp_fake_dma_done(ncr->devobject.lsistate); } return v; } if (addr & 1) return v; if (addr == 0) { v = ncr->rom[0]; v |= !ncr->chipirq ? 0x80 : 0x00; return v; } if (addr < 0x4000 || addr >= 0xc000) { v = ncr->rom[(addr >> 1) & 8191]; return v; } if (addr < 0x6000) return v; reg_shift = 1; } else if (ncr == ncr_multievolution_scsi) { reg_shift = 1; if (addr & 0x1000) { if (ncr->fakedma_data_offset >= ncr->fakedma_data_size) return 0; v = ncr->fakedma_data_buf[ncr->fakedma_data_offset++]; if (ncr->fakedma_data_offset == ncr->fakedma_data_size) { esp_fake_dma_done(ncr->devobject.lsistate); //write_log(_T("MultiEvolution fake dma finished\n")); } //write_log(_T("MultiEvolution fake dma %02x %d/%d\n"), v, ncr->fakedma_data_offset, ncr->fakedma_data_size); return v; } } else if (isncr(ncr, ncr_golemfast_scsi)) { reg_shift = 1; if ((addr & 0x8400) == 0x8400) { if (ncr->fakedma_data_offset >= ncr->fakedma_data_size) return 0; v = ncr->fakedma_data_buf[ncr->fakedma_data_offset++]; if (ncr->fakedma_data_offset == ncr->fakedma_data_size) { esp_fake_dma_done(ncr->devobject.lsistate); } //write_log(_T("FAKEDMA READ %08x %02X %08x (%d/%d)\n"), addr, v, M68K_GETPC, ncr->fakedma_data_offset, ncr->fakedma_data_size); return v; } } else if (ncr == ncr_squirrel_scsi) { reg_shift = 0; if (addr >= 16) { esp_dma_enable(ncr->devobject.lsistate, 1); v = ncr->data; ncr->data_valid_w = false; return v; } } else if (isncr(ncr, ncr_masoboshi_scsi)) { if (addr == MASOBOSHI_ESP_ADDR + 3 * 2 && (ncr->states[0] & 0x80)) return 2; if (addr >= 0xf000 && addr < 0xf800) addr &= ~0x0700; if (ncr->states[0] & 0x80) ncr->states[0] &= ~0x80; if (addr >= 0xf00c && addr < 0xf010) { int shift = (3 - (addr - 0xf00c)) * 8; uae_u32 mask = 0xff << shift; if (addr == 0xf04f) write_log(_T("MASOBOSHI SCSI DMA PTR READ = %08x %08x\n"), ncr->dma_ptr, M68K_GETPC); return ncr->dma_ptr >> shift; } if (addr >= 0xf008 && addr < 0xf00c) { if (addr == 0xf00b) write_log(_T("MASOBOSHI SCSI DMA LEN READ = %04x %08x\n"), ncr->dma_cnt, v, M68K_GETPC); if (addr == 0xf00a) return ncr->dma_cnt >> 8; if (addr == 0xf00b) return ncr->dma_cnt >> 0; return v; } if (addr >= 0xf000 && addr <= 0xf007) { int idx = addr - 0xf000; if (addr == 0xf000) { ncr->states[0] |= 2; ncr->states[0] |= 1; if (esp_dreq(&ncr->devobject)) { ncr->states[0] &= ~1; // data request } if (ncr->boardirqlatch) { ncr->states[0] &= ~2; // scsi interrupt } #if 0 if (ncr->chipirq) { ncr->states[0] &= ~1; } #endif } v = ncr->states[idx]; #if 0 write_log(_T("MASOBOSHI IO %08X GET %02x %08x\n"), addr, v, M68K_GETPC); #endif return v; } #if 0 if (addr == 0xf007) { v = ncr->states[0]; } #endif if (addr >= MASOBOSHI_DMA_START && addr < MASOBOSHI_DMA_END) { esp_dma_enable(ncr->devobject.lsistate, 1); v = ncr->data; ncr->data_valid_w = false; #if NCR_DEBUG > 2 write_log(_T("MASOBOSHI DMA %08X GET %02x %08x\n"), addr, v, M68K_GETPC); #endif return v; } if (addr < MASOBOSHI_ESP_ADDR || addr >= MASOBOSHI_ESP_ADDR + 0x100) { #if NCR_DEBUG write_log(_T("MASOBOSHI IO %08X GET %02x %08x\n"), addr, v, M68K_GETPC); #endif return v; } 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; } else if (addr == OKTAGON_EEPROM_SDA) { return eeprom_i2c_set(ncr->eeprom, BITBANG_I2C_SDA, -1) ? 0x80 : 0x00; } else if (addr >= OKTAGON_DMA_START && addr < OKTAGON_DMA_END) { esp_dma_enable(ncr->devobject.lsistate, 1); v = ncr->data; ncr->data_valid_w = false; return v; } else if (addr == OKTAGON_INTENA) { return ncr->states[0]; } if (addr < OKTAGON_ESP_ADDR || addr >= OKTAGON_ESP_ADDR + 0x100) return 0xff; reg_shift = 1; } else if (isncr(ncr, ncr_alf3_scsi)) { if (addr >= 0xd000 && addr < 0xe000) { esp_dma_enable(ncr->devobject.lsistate, 1); v = ncr->data; ncr->data_valid_w = false; return v; } else if (addr == 0xa000) { v = 0; if (ncr->rc->device_settings & 1) v |= 1 << 4; if (ncr->rc->device_settings & 2) v |= 1 << 5; if (ncr->rc->device_settings & 4) v |= 1 << 3; if (ncr->rc->device_settings & 8) v |= 1 << 7; if (ncr->rc->device_settings & 16) v |= 1 << 6; v |= ncr->rc->device_id & 7; return v; } else if (addr == 0xa001) { v = ncr->boardirq ? 1 : 0; if (ncr->rc->device_settings & (1 << 5)) v |= 2; return v; } if (addr < 0x8000 || addr >= 0x8000 + 0x100) return 0xff; reg_shift = 1; } else if (isncr(ncr, ncr_fastlane_scsi)) { if (addr >= FASTLANE_HARDBITS) { if (addr == FASTLANE_HARDBITS) { uae_u8 v = ncr->states[0]; v &= ~(FLSC_HB_DISABLED | FLSC_HB_BUSID6 | FLSC_HB_SEAGATE | FLSC_HB_SLOW | FLSC_HB_SYNCHRON); return v; } return 0; } } else if (ISCPUBOARD(BOARD_BLIZZARD, BOARD_BLIZZARD_SUB_1230II)) { addr &= 0xffff; if (addr >= 0x20) { return 0; } reg_shift = 1; } else if (ISCPUBOARD(BOARD_BLIZZARD, BOARD_BLIZZARD_SUB_1230III)) { addr &= 0xffff; if (addr >= 0x10 && addr < 0x20) { v = (uae_u8)fas408_read_fifo(ncr->devobject.lsistate); return v; } if (addr >= 0x20) { write_log(_T("BOARD_BLIZZARD_SUB_1230III %08x %08x\n"), addr, M68K_GETPC); return 0; } reg_shift = 0; } else if (ISCPUBOARD(BOARD_BLIZZARD, BOARD_BLIZZARD_SUB_2060)) { if (addr >= BLIZZARD_2060_DMA_OFFSET) { write_log(_T("Blizzard DMA GET %08x\n"), addr); return 0; } else if (addr >= BLIZZARD_2060_LED_OFFSET) { return ncr->led; } } else if (ISCPUBOARD(BOARD_BLIZZARD, BOARD_BLIZZARD_SUB_1230IV) || ISCPUBOARD(BOARD_BLIZZARD, BOARD_BLIZZARD_SUB_1260)) { if (!is_board_enabled(&currprefs, ROMTYPE_BLIZKIT4, 0)) return 0; if (addr >= BLIZZARD_SCSI_KIT4_DMA_OFFSET) return 0; } else if (ISCPUBOARD(BOARD_CYBERSTORM, BOARD_CYBERSTORM_SUB_MK1)) { if (addr >= CYBERSTORM_MK1_JUMPER_OFFSET) { return 0xff; } else if (addr >= CYBERSTORM_MK1_DMA_OFFSET) { return 0; } else if (addr >= CYBERSTORM_MK1_LED_OFFSET) { return ncr->led; } } else if (ISCPUBOARD(BOARD_CYBERSTORM, BOARD_CYBERSTORM_SUB_MK2)) { if (addr >= CYBERSTORM_MK2_DMA_OFFSET) { return 0; } else if (addr >= CYBERSTORM_MK2_LED_OFFSET) { return ncr->led; } } else if (isncr(ncr, ncr_rapidfire_scsi)) { reg_shift = 1; if (addr == 0x10040) { uae_u8 v = 0; if (ncr->chipirq || ncr->boardirq) v |= 0x40; if (ncr->fakedma_data_offset < ncr->fakedma_data_size) v |= 0x80; ncr->boardirq = false; //write_log(_T("DKB IO GET %02x %08x\n"), v, M68K_GETPC); return v; } if (addr >= 0x10020 && addr < 0x10028) { //write_log(_T("DKB GET BYTE %02x %08x\n"), ncr->fakedma_data_buf[ncr->fakedma_data_offset], M68K_GETPC); if (ncr->fakedma_data_offset >= ncr->fakedma_data_size) return 0; v = ncr->fakedma_data_buf[ncr->fakedma_data_offset++]; if (ncr->fakedma_data_offset == ncr->fakedma_data_size) { esp_fake_dma_done(ncr->devobject.lsistate); //write_log(_T("DKB fake dma finished\n")); } return v; } if (addr < 0x10000 || addr >= 0x10020) { write_log(_T("DKB IO GET %08x %08x\n"), addr, M68K_GETPC); return 0; } } else if (ISCPUBOARD(BOARD_DKB, BOARD_DKB_SUB_12x0)) { if (!(currprefs.cpuboard_settings & 1)) return 0x00; if (addr == 0x10100) { uae_u8 v = 0; if (ncr->chipirq || ncr->boardirq) v |= 0x40; if (ncr->fakedma_data_offset < ncr->fakedma_data_size) v |= 0x80; ncr->boardirq = false; //write_log(_T("DKB IO GET %02x %08x\n"), v, M68K_GETPC); return v; } if (addr >= 0x10080 && addr < 0x10088) { //write_log(_T("DKB GET BYTE %02x\n"), ncr->fakedma_data_buf[ncr->fakedma_data_offset]); if (ncr->fakedma_data_offset >= ncr->fakedma_data_size) return 0; v = ncr->fakedma_data_buf[ncr->fakedma_data_offset++]; if (ncr->fakedma_data_offset == ncr->fakedma_data_size) { esp_fake_dma_done(ncr->devobject.lsistate); //write_log(_T("DKB fake dma finished\n")); } return v; } if (addr < 0x10000 || addr >= 0x10040) { write_log(_T("DKB IO GET %08x %08x\n"), addr, M68K_GETPC); return 0; } } else if (ISCPUBOARD(BOARD_MTEC, BOARD_MTEC_SUB_EMATRIX530) || ISCPUBOARD(BOARD_DCE, BOARD_DCE_SUB_TYPHOON2) || ncr == ncr_mtec_mastercard) { if ((addr & 0xf000) >= 0xe000) { if ((addr & 0x3ff) <= 7) { if (ncr->fakedma_data_offset >= ncr->fakedma_data_size) { ncr->states[0] = 0; return 0; } v = ncr->fakedma_data_buf[ncr->fakedma_data_offset++]; if (ncr->fakedma_data_offset == ncr->fakedma_data_size) { esp_fake_dma_done(ncr->devobject.lsistate); ncr->states[0] = 0; } return v; } return 0xff; } if ((addr & 1) && !(addr & 0x0800)) { // dma request return ncr->states[0] ? 0xff : 0x7f; } if ((addr & 1) && (addr & 0x0800)) { // hardware revision? return 0x7f; } if (addr & 1) return 0x7f; if ((currprefs.cpuboard_settings & 1) && ncr != ncr_mtec_mastercard) return 0x7f; if (addr < 0xc000 || addr >= 0xe000) return 0x7f; reg_shift = 3; } if (!ncr->devobject.lsistate) return v; addr >>= reg_shift; addr &= IO_MASK; v = (uae_u8)esp_reg_read(ncr->devobject.lsistate, (addr)); *reg = addr; return v; } static uae_u32 ncr9x_io_bget(struct ncr9x_state *ncr, uaecptr addr) { int reg = -1; uae_u8 v = ncr9x_io_bget3(ncr, addr, ®); #if NCR_DEBUG > 1 if (ncr) write_log(_T("ESP read %02X (%08X) %02X %08X\n"), reg & 0xff, addr, v, M68K_GETPC); #endif return v; } static uae_u8 read_rombyte(struct ncr9x_state *ncr, uaecptr addr) { uae_u8 v = 0xff; if (ncr->flashrom) { if ((!ncr->romisoddonly && !ncr->romisevenonly) || (ncr->romisoddonly && (addr & 1)) || (ncr->romisevenonly && !(addr & 1))) v = flash_read(ncr->flashrom, addr >> 1); } else { v = ncr->rom[addr]; } return v; } static void write_rombyte(struct ncr9x_state *ncr, uaecptr addr, uae_u8 v) { if (!ncr->flashrom) return; if ((!ncr->romisoddonly && !ncr->romisevenonly) || (ncr->romisoddonly && (addr & 1)) || (ncr->romisevenonly && !(addr & 1))) flash_write(ncr->flashrom, addr >> 1, v); } static uae_u32 ncr9x_bget2(struct ncr9x_state *ncr, uaecptr addr) { uae_u32 v = 0; addr &= ncr->board_mask; if (ncr->rom && addr >= ncr->rom_start && addr < ncr->rom_end) { if (addr < ncr->io_start || (!ncr->romisoddonly && !ncr->romisevenonly) || (ncr->romisoddonly && (addr & 1)) || (ncr->romisevenonly && !(addr & 1))) return read_rombyte (ncr, addr - ncr->rom_offset); } if (ncr->io_end && (addr < ncr->io_start || addr >= ncr->io_end)) return v; v = ncr9x_io_bget(ncr, addr); #if NCR_DEBUG > 5 write_log(_T("ncr9x_bget2 %08x %02x %08x\n"), addr, (uae_u8)v, M68K_GETPC); #endif return v; } static void ncr9x_bput2(struct ncr9x_state *ncr, uaecptr addr, uae_u32 val) { uae_u32 v = val; #if NCR_DEBUG > 5 write_log(_T("ncr9x_bput %08x %02x %08x\n"), addr, (uae_u8)val, M68K_GETPC); #endif addr &= ncr->board_mask; if (ncr->rom && addr >= ncr->rom_start && addr < ncr->rom_end && !ncr->rom_bypass_if_write) { if (addr < ncr->io_start || (!ncr->romisoddonly && !ncr->romisevenonly) || (ncr->romisoddonly && (addr & 1)) || (ncr->romisevenonly && !(addr & 1))) { write_rombyte(ncr, addr, val); return; } } if (ncr->io_end && (addr < ncr->io_start || addr >= ncr->io_end)) return; ncr9x_io_bput(ncr, addr, val); } static uae_u32 REGPARAM2 ncr9x_lget(struct ncr9x_state *ncr, uaecptr addr) { uae_u32 v; addr &= ncr->board_mask; if (isncr(ncr, ncr_oktagon2008_scsi)) { v = ncr9x_io_bget(ncr, addr + 0) << 24; v |= ncr9x_io_bget(ncr, addr + 1) << 16; v |= ncr9x_io_bget(ncr, addr + 2) << 8; v |= ncr9x_io_bget(ncr, addr + 3) << 0; } else { v = ncr9x_bget2(ncr, addr + 0) << 24; v |= ncr9x_bget2(ncr, addr + 1) << 16; v |= ncr9x_bget2(ncr, addr + 2) << 8; v |= ncr9x_bget2(ncr, addr + 3) << 0; } return v; } static uae_u32 REGPARAM2 ncr9x_wget(struct ncr9x_state *ncr, uaecptr addr) { uae_u32 v; addr &= ncr->board_mask; if (isncr(ncr, ncr_oktagon2008_scsi)) { v = ncr9x_io_bget(ncr, addr) << 8; v |= ncr9x_io_bget(ncr, addr + 1); } else { v = ncr9x_bget2(ncr, addr) << 8; v |= ncr9x_bget2(ncr, addr + 1); } return v; } static uae_u32 REGPARAM2 ncr9x_bget(struct ncr9x_state *ncr, uaecptr addr) { uae_u32 v; addr &= ncr->board_mask; if (!ncr->configured) { addr &= 65535; if (addr >= sizeof ncr->acmemory) return 0; return ncr->acmemory[addr]; } v = ncr9x_bget2(ncr, addr); return v; } static void REGPARAM2 ncr9x_lput(struct ncr9x_state *ncr, uaecptr addr, uae_u32 l) { addr &= ncr->board_mask; if (isncr(ncr, ncr_oktagon2008_scsi)) { ncr9x_io_bput(ncr, addr + 0, l >> 24); ncr9x_io_bput(ncr, addr + 1, l >> 16); ncr9x_io_bput(ncr, addr + 2, l >> 8); ncr9x_io_bput(ncr, addr + 3, l >> 0); } else { ncr9x_bput2(ncr, addr + 0, l >> 24); ncr9x_bput2(ncr, addr + 1, l >> 16); ncr9x_bput2(ncr, addr + 2, l >> 8); ncr9x_bput2(ncr, addr + 3, l >> 0); } } static void REGPARAM2 ncr9x_wput(struct ncr9x_state *ncr, uaecptr addr, uae_u32 w) { w &= 0xffff; addr &= ncr->board_mask; if (!ncr->configured) { addr &= 65535; switch (addr) { case 0x44: map_banks_z3(ncr->bank, expamem_board_pointer >> 16, FASTLANE_BOARD_SIZE >> 16); ncr->baseaddress = expamem_board_pointer; ncr->configured = 1; expamem_next (ncr->bank, NULL); break; } return; } if (isncr(ncr, ncr_oktagon2008_scsi)) { ncr9x_io_bput(ncr, addr, w >> 8); ncr9x_io_bput(ncr, addr + 1, w); } else { ncr9x_bput2(ncr, addr, w >> 8); ncr9x_bput2(ncr, addr + 1, w); } } static void REGPARAM2 ncr9x_bput(struct ncr9x_state *ncr, uaecptr addr, uae_u32 b) { b &= 0xff; addr &= ncr->board_mask; if (!ncr->configured) { addr &= 65535; switch (addr) { case 0x48: if (isncr(ncr, ncr_fastlane_scsi)) return; map_banks_z2(ncr->bank, expamem_board_pointer >> 16, expamem_board_size >> 16); ncr->configured = 1; ncr->baseaddress = expamem_board_pointer; expamem_next (ncr->bank, NULL); break; case 0x4c: ncr->configured = 1; expamem_shutup(ncr->bank); break; } return; } ncr9x_bput2(ncr, addr, b); } static struct ncr9x_state *getscsiboard(uaecptr addr) { for (int i = 0; ncr_units[i]; i++) { if (!ncr_units[i]->baseaddress) return ncr_units[i]; if ((addr & ~ncr_units[i]->board_mask) == ncr_units[i]->baseaddress) return ncr_units[i]; if (ncr_units[i]->baseaddress2 && (addr & ~ncr_units[i]->board_mask2) == ncr_units[i]->baseaddress2) return ncr_units[i]; } return NULL; } static void REGPARAM2 ncr9x_generic_bput (uaecptr addr, uae_u32 b) { struct ncr9x_state *ncr = getscsiboard(addr); if (ncr) ncr9x_bput(ncr, addr, b); } static void REGPARAM2 ncr9x_generic_wput (uaecptr addr, uae_u32 b) { struct ncr9x_state *ncr = getscsiboard(addr); if (ncr) ncr9x_wput(ncr, addr, b); } static void REGPARAM2 ncr9x_generic_lput (uaecptr addr, uae_u32 b) { struct ncr9x_state *ncr = getscsiboard(addr); if (ncr) ncr9x_lput(ncr, addr, b); } static uae_u32 REGPARAM2 ncr9x_generic_bget (uaecptr addr) { struct ncr9x_state *ncr = getscsiboard(addr); if (ncr) return ncr9x_bget(ncr, addr); return 0; } static uae_u32 REGPARAM2 ncr9x_generic_wget (uaecptr addr) { struct ncr9x_state *ncr = getscsiboard(addr); if (ncr) return ncr9x_wget(ncr, addr); return 0; } static uae_u32 REGPARAM2 ncr9x_generic_lget (uaecptr addr) { struct ncr9x_state *ncr = getscsiboard(addr); if (ncr) return ncr9x_lget(ncr, addr); return 0; } static uae_u8 *REGPARAM2 ncr9x_generic_xlate(uaecptr addr) { struct ncr9x_state *ncr = getscsiboard(addr); if (!ncr) return NULL; addr &= ncr->board_mask; return ncr->rom + addr; } static int REGPARAM2 ncr9x_generic_check(uaecptr a, uae_u32 b) { struct ncr9x_state *ncr = getscsiboard(a); if (!ncr) return 0; a &= ncr->board_mask; if (a >= ncr->rom_start && a + b < ncr->rom_end) return 1; return 0; } static addrbank ncr9x_bank_generic = { ncr9x_generic_lget, ncr9x_generic_wget, ncr9x_generic_bget, ncr9x_generic_lput, ncr9x_generic_wput, ncr9x_generic_bput, ncr9x_generic_xlate, ncr9x_generic_check, NULL, NULL, _T("53C94/FAS216"), ncr9x_generic_lget, ncr9x_generic_wget, ABFLAG_IO | ABFLAG_SAFE, S_READ, S_WRITE }; uae_u32 cpuboard_ncr9x_scsi_get(uaecptr addr) { return ncr9x_io_bget(ncr_blizzard_scsi, addr); } void cpuboard_ncr9x_scsi_put(uaecptr addr, uae_u32 v) { ncr9x_io_bput(ncr_blizzard_scsi, addr, v); } uae_u32 masoboshi_ncr9x_scsi_get(uaecptr addr, int devnum) { return ncr9x_io_bget(ncr_masoboshi_scsi[devnum], addr); } void masoboshi_ncr9x_scsi_put(uaecptr addr, uae_u32 v, int devnum) { 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); } void golemfast_ncr9x_scsi_put(uaecptr addr, uae_u32 v, int devnum) { ncr9x_io_bput(ncr_golemfast_scsi[devnum], addr, v); } uae_u32 squirrel_ncr9x_scsi_get(uaecptr addr, int devnum) { return ncr9x_io_bget(ncr_squirrel_scsi, addr); } void squirrel_ncr9x_scsi_put(uaecptr addr, uae_u32 v, int devnum) { ncr9x_io_bput(ncr_squirrel_scsi, addr, v); } static void ew(struct ncr9x_state *ncr, int addr, uae_u8 value) { if (addr == 00 || addr == 02 || addr == 0x40 || addr == 0x42) { ncr->acmemory[addr] = (value & 0xf0); ncr->acmemory[addr + 2] = (value & 0x0f) << 4; } else { ncr->acmemory[addr] = ~(value & 0xf0); ncr->acmemory[addr + 2] = ~((value & 0x0f) << 4); } } static void ncr9x_reset_board(struct ncr9x_state *ncr); static void ncr9x_reset(int hardreset) { for (int i = 0; ncr_units[i]; i++) { ncr9x_reset_board(ncr_units[i]); ncr_units[i]->enabled = false; } } static void ncr9x_free(void) { for (int i = 0; ncr_units[i]; i++) { freencrunit(ncr_units[i]); } } static void ncr9x_reset_board(struct ncr9x_state *ncr) { if (!ncr) return; ncr->configured = 0; ncr->boardirq = false; ncr->chipirq = false; device_add_rethink(ncr9x_rethink); device_add_reset(ncr9x_reset); device_add_exit(ncr9x_free, NULL); } void ncr_squirrel_init(struct romconfig *rc, uaecptr baseaddress) { struct ncr9x_state *ncr = getscsi(rc); if (!ncr) return; ncr->enabled = true; ncr->pcmcia = true; ncr->baseaddress = baseaddress; ncr9x_reset_board(ncr); } void ncr_golemfast_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_multievolution_init(struct autoconfig_info *aci) { device_add_reset(ncr9x_reset); if (!aci->doinit) return true; struct ncr9x_state *ncr = getscsi(aci->rc); xfree(ncr->rom); ncr->rom = NULL; if (!ncr) return false; ncr->bank = &ncr9x_bank_generic; ncr->enabled = true; ncr->rom = xcalloc(uae_u8, 65536); ncr->configured = -1; ncr->board_mask = 0x1ffff; ncr->board_mask2 = 0xffff; ncr->baseaddress = 0xf00000; ncr->baseaddress2 = 0xef0000; ncr->rom_start = 0; ncr->rom_offset = 0; ncr->rom_end = 0x10000; ncr->io_start = 0x1e000; ncr->io_end = ncr->io_start + 0x2000; ncr->irq6 = true; load_rom_rc(aci->rc, ROMTYPE_MEVOLUTION, 65536, 0, ncr->rom, 65536, 0); map_banks(ncr->bank, ncr->baseaddress2 >> 16, (ncr->board_mask + 1) >> 16, 0); aci->addrbank = &expamem_null; return true; } bool ncr_fastlane_autoconfig_init(struct autoconfig_info *aci) { struct zfile *z = read_device_from_romconfig(aci->rc, ROMTYPE_FASTLANE); uae_u8 *rom = xcalloc(uae_u8, FASTLANE_ROM_SIZE * 4); if (z) { // memory board at offset 0x100 int autoconfig_offset = 0; memset(rom, 0xff, FASTLANE_ROM_SIZE * 4); for (int i = 0; i < FASTLANE_ROM_SIZE; i++) { int ia = i - autoconfig_offset; uae_u8 b; zfile_fread(&b, 1, 1, z); rom[i * 4 + 0] = b | 0x0f; rom[i * 4 + 2] = (b << 4) | 0x0f; if (ia >= 0 && ia < 0x20) { aci->autoconfig_raw[ia * 4 + 0] = b; } else if (ia >= 0x40 && ia < 0x60) { aci->autoconfig_raw[(ia - 0x40) * 4 + 2] = b; } } zfile_fclose(z); } device_add_reset(ncr9x_reset); if (!aci->doinit) { xfree(rom); return true; } struct ncr9x_state *ncr = getscsi(aci->rc); xfree(ncr->rom); ncr->rom = rom; if (!ncr) return false; ncr->enabled = true; memcpy(ncr->acmemory, aci->autoconfig_raw, sizeof ncr->acmemory); ncr->rom_start = 0x800; ncr->rom_offset = 0; ncr->rom_bypass_if_write = true; // DMA pointer set can write to ROM space ncr->rom_end = FASTLANE_ROM_SIZE * 4; ncr->io_start = 0; ncr->io_end = 0; ncr->bank = &ncr9x_bank_generic; ncr9x_reset_board(ncr); aci->addrbank = ncr->bank; return true; } static const uae_u8 oktagon_autoconfig[16] = { 0xd1, 0x05, 0x00, 0x00, 0x08, 0x2c, 0x00, 0x00, 0x00, 0x00, OKTAGON_ROM_OFFSET >> 8, OKTAGON_ROM_OFFSET & 0xff }; bool ncr_oktagon_autoconfig_init(struct autoconfig_info *aci) { device_add_reset(ncr9x_reset); aci->autoconfigp = oktagon_autoconfig; if (!aci->doinit) return true; struct ncr9x_state *ncr = getscsi(aci->rc); if (!ncr) return false; xfree(ncr->rom); ncr->rom = NULL; eeprom_free(ncr->eeprom); ncr->eeprom = NULL; ncr->enabled = true; memset (ncr->acmemory, 0xff, sizeof ncr->acmemory); ncr->rom_start = 0; ncr->rom_offset = 0; ncr->rom_end = OKTAGON_ROM_SIZE * 2; ncr->io_start = 0x2000; ncr->io_end = ncr->rom_end; ncr->romisoddonly = true; ncr->bank = &ncr9x_bank_generic; memset(ncr->eeprom_data, 0xff, OKTAGON_EEPROM_SIZE); memcpy(ncr->eeprom_data + 0x100, oktagon_eeprom, 16); ncr->eeprom = eeprom_new(ncr->eeprom_data, OKTAGON_EEPROM_SIZE, NULL); ncr->rom = xcalloc (uae_u8, OKTAGON_ROM_SIZE * 6); memset(ncr->rom, 0xff, OKTAGON_ROM_SIZE * 6); ncr9x_reset_board(ncr); if (!aci->rc->autoboot_disabled) { struct zfile *z = read_device_from_romconfig(aci->rc, ROMTYPE_OKTAGON); if (z) { // memory board at offset 0x100 memset(ncr->rom, 0xff, OKTAGON_ROM_SIZE * 4); for (int i = 0; i < 0x1000 / 2; i++) { uae_u8 b; zfile_fread(&b, 1, 1, z); ncr->rom[OKTAGON_ROM_OFFSET + i * 4 + 0] = b; zfile_fread(&b, 1, 1, z); ncr->rom[OKTAGON_ROM_OFFSET + i * 4 + 2] = b; } for (int i = 0; i < OKTAGON_ROM_SIZE - 0x1000; i++) { uae_u8 b; zfile_fread(&b, 1, 1, z); ncr->rom[0x2000 + i * 4 + 1] = b; zfile_fread(&b, 1, 1, z); ncr->rom[0x2000 + i * 4 + 3] = b; } zfile_fclose(z); } } for (int i = 0; i < 16; i++) { uae_u8 b = oktagon_autoconfig[i]; ew(ncr, i * 4, b); } aci->addrbank = ncr->bank; return true; } static const uae_u8 alf3_autoconfig[16] = { 0xd1, 0x03, 0x40, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xC0, 0x16, 0x68 }; bool ncr_alf3_autoconfig_init(struct autoconfig_info *aci) { struct zfile *z = read_device_from_romconfig(aci->rc, ROMTYPE_ALF3); if (z) { zfile_fread(aci->autoconfig_raw, 128, 1, z); zfile_fclose(z); } else { memcpy(aci->autoconfig_bytes, alf3_autoconfig, 16); aci->autoconfigp = aci->autoconfig_bytes; } device_add_reset(ncr9x_reset); if (!aci->doinit) { return true; } struct ncr9x_state *ncr = getscsi(aci->rc); if (!ncr) return false; xfree(ncr->rom); ncr->rom = NULL; eeprom_free(ncr->eeprom); ncr->eeprom = NULL; ncr->enabled = true; memset(ncr->acmemory, 0xff, sizeof ncr->acmemory); ncr->rom_start = 0; ncr->rom_offset = 0; ncr->rom_end = 0x8000; ncr->io_start = 0x8000; ncr->io_end = ncr->io_start + 0x8000; ncr->romisoddonly = true; ncr->bank = &ncr9x_bank_generic; ncr->irq6 = (ncr->rc->device_settings & (1 << 5)) == 0; ncr->rom = xcalloc(uae_u8, 65536); memset(ncr->rom, 0xff, 65536); ncr9x_reset_board(ncr); z = read_device_from_romconfig(aci->rc, ROMTYPE_ALF3); if (z) { zfile_fread(ncr->rom, 32768, 1, z); zfile_fclose(z); } if (!z) { for (int i = 0; i < 16; i++) { uae_u8 v = alf3_autoconfig[i]; if (ncr->rc->autoboot_disabled && i == 0) v &= ~0x10; ew(ncr, i * 4, v); } } else { if (ncr->rc->autoboot_disabled) ncr->rom[0] &= ~0x10; for (int i = 0; i < 128; i++) { ncr->acmemory[i] = ncr->rom[i]; } } aci->addrbank = ncr->bank; return true; } static const uae_u8 dkb_autoconfig[16] = { 0xd2, 0x12, 0x40, 0x00, 0x07, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 }; bool ncr_dkb_autoconfig_init(struct autoconfig_info *aci) { const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_RAPIDFIRE); device_add_reset(ncr9x_reset); aci->autoconfigp = dkb_autoconfig; if (!aci->doinit) return true; struct ncr9x_state *ncr = getscsi(aci->rc); if (!ncr) return false; xfree(ncr->rom); ncr->rom = NULL; ncr->enabled = true; memset (ncr->acmemory, 0xff, sizeof ncr->acmemory); ncr->rom_start = 0; ncr->rom_offset = 0; ncr->rom_end = DKB_ROM_SIZE * 2; ncr->io_start = 0x10000; ncr->io_end = 0x20000; ncr->bank = &ncr9x_bank_generic; ncr->board_mask = 131071; ncr->romisevenonly = true; ncr9x_reset_board(ncr); ncr->rom = xcalloc (uae_u8, DKB_ROM_SIZE); load_rom_rc(aci->rc, ROMTYPE_CB_DKB, 32768, 0, ncr->rom, 32768, LOADROM_ONEFILL); for (int i = 0; i < 16; i++) { uae_u8 b = dkb_autoconfig[i]; ew(ncr, i * 4, b); } ncr->flashrom_file = flashromfile_open(aci->rc->romfile); if (ncr->flashrom_file) { zfile_fread(ncr->rom, 32768, 1, ncr->flashrom_file); } ncr->flashrom = flash_new(ncr->rom, 32768, 32768, 0x1f, 0xdc, ncr->flashrom_file, FLASHROM_PARALLEL_EEPROM); aci->addrbank = ncr->bank; return true; } bool typhoon2scsi_init(struct autoconfig_info *aci) { uae_u8 *rom = xcalloc(uae_u8, 65536); load_rom_rc(aci->rc, ROMTYPE_CB_TYPHOON2, 32768, 32768, rom, 65536, LOADROM_EVENONLY_ODDONE); memcpy(aci->autoconfig_raw, aci->rc->autoboot_disabled ? rom + 256 : rom, 128); device_add_reset(ncr9x_reset); if (!aci->doinit) { xfree(rom); return true; } struct ncr9x_state *ncr = getscsi(aci->rc); if (!ncr) { xfree(rom); return false; } xfree(ncr->rom); ncr->rom = rom; ncr->enabled = true; memcpy(ncr->acmemory, aci->autoconfig_raw, sizeof aci->autoconfig_raw); ncr->rom_start = 0; ncr->rom_offset = 0; ncr->rom_end = 0x8000; ncr->io_start = 0x8000; ncr->io_end = 0x10000; ncr->bank = &ncr9x_bank_generic; ncr->board_mask = 65535; ncr9x_reset_board(ncr); aci->addrbank = ncr->bank; return true; } bool ncr_ematrix_autoconfig_init(struct autoconfig_info *aci) { uae_u8 *rom = xcalloc(uae_u8, 65536); load_rom_rc(aci->rc, ROMTYPE_CB_EMATRIX, 32768, 32768, rom, 65536, LOADROM_EVENONLY_ODDONE); memcpy(aci->autoconfig_raw, aci->rc->autoboot_disabled ? rom + 256 : rom, 128); device_add_reset(ncr9x_reset); if (!aci->doinit) { xfree(rom); return true; } struct ncr9x_state *ncr = getscsi(aci->rc); if (!ncr) { xfree(rom); return false; } xfree(ncr->rom); ncr->rom = rom; ncr->enabled = true; memcpy(ncr->acmemory, aci->autoconfig_raw, sizeof aci->autoconfig_raw); ncr->rom_start = 0; ncr->rom_offset = 0; ncr->rom_end = 0x8000; ncr->io_start = 0x8000; ncr->io_end = 0x10000; ncr->bank = &ncr9x_bank_generic; ncr->board_mask = 65535; ncr9x_reset_board(ncr); aci->addrbank = ncr->bank; return true; } void ncr_masoboshi_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); } 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); device_add_reset(ncr9x_reset); if (!aci->doinit) { aci->autoconfigp = ert->autoconfig; return true; } struct ncr9x_state *ncr = getscsi(aci->rc); if (!ncr) return false; ncr->enabled = true; ncr->bank = &ncr9x_bank_generic; ncr->board_mask = 65535; xfree(ncr->rom); ncr->rom = xcalloc(uae_u8, 8192); load_rom_rc(aci->rc, ROMTYPE_SCRAM5394, 8192, 0, ncr->rom, 8192, 0); for (int i = 0; i < 16; i++) { uae_u8 b = ert->autoconfig[i]; ew(ncr, i * 4, b); } ncr9x_reset_board(ncr); aci->addrbank = ncr->bank; return true; } bool ncr_mtecmastercard_init(struct autoconfig_info *aci) { uae_u8 *rom = xcalloc(uae_u8, 65536); load_rom_rc(aci->rc, ROMTYPE_MASTERCARD, 32768, 0, rom, 65536, LOADROM_EVENONLY_ODDONE); memcpy(aci->autoconfig_raw, aci->rc->autoboot_disabled ? rom + 256 : rom, 128); device_add_reset(ncr9x_reset); if (!aci->doinit) { xfree(rom); return true; } struct ncr9x_state *ncr = getscsi(aci->rc); if (!ncr) { xfree(rom); return false; } xfree(ncr->rom); ncr->rom = rom; ncr->enabled = true; memcpy(ncr->acmemory, aci->autoconfig_raw, sizeof aci->autoconfig_raw); ncr->rom_start = 0; ncr->rom_offset = 0; ncr->rom_end = 0x8000; ncr->io_start = 0x8000; ncr->io_end = 0x10000; ncr->bank = &ncr9x_bank_generic; ncr->board_mask = 65535; ncr9x_reset_board(ncr); aci->addrbank = ncr->bank; return true; } bool ncr_rapidfire_init(struct autoconfig_info *aci) { const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_RAPIDFIRE); device_add_reset(ncr9x_reset); if (!aci->doinit) { aci->autoconfigp = ert->autoconfig; return true; } struct ncr9x_state *ncr = getscsi(aci->rc); if (!ncr) return false; ncr->enabled = true; memset (ncr->acmemory, 0xff, sizeof ncr->acmemory); ncr->rom_start = 0; ncr->rom_offset = 0; ncr->rom_end = DKB_ROM_SIZE * 2; ncr->io_start = 0x10000; ncr->io_end = 0x20000; ncr->bank = &ncr9x_bank_generic; ncr->board_mask = 131071; ncr->romisevenonly = true; ncr9x_reset_board(ncr); ncr->rom = xcalloc (uae_u8, DKB_ROM_SIZE); load_rom_rc(aci->rc, ROMTYPE_RAPIDFIRE, 32768, 0, ncr->rom, 32768, LOADROM_ONEFILL); for (int i = 0; i < 16; i++) { uae_u8 b = ert->autoconfig[i]; ew(ncr, i * 4, b); } ncr->flashrom_file = flashromfile_open(aci->rc->romfile); if (ncr->flashrom_file) { zfile_fread(ncr->rom, 32768, 1, ncr->flashrom_file); } ncr->flashrom = flash_new(ncr->rom, 32768, 32768, 0x1f, 0xdc, ncr->flashrom_file, FLASHROM_PARALLEL_EEPROM); aci->addrbank = ncr->bank; return true; } static void ncr9x_esp_scsi_init(struct ncr9x_state *ncr, ESPDMAMemoryReadWriteFunc read, ESPDMAMemoryReadWriteFunc write, void (*irq_func)(struct ncr9x_state*), int mode) { ncr->board_mask = 0xffff; ncr->irq_func = irq_func ? irq_func : set_irq2; if (!ncr->devobject.lsistate) esp_scsi_init(&ncr->devobject, read, write, mode > 0 ? mode : 0); esp_scsi_reset(&ncr->devobject, ncr); } static void allocscsidevice(struct ncr9x_state *ncr, int ch, struct scsi_data *handle, int uae_unitnum) { handle->privdata = ncr; ncr->scsid[ch] = xcalloc (SCSIDevice, 1); ncr->scsid[ch]->id = ch; ncr->scsid[ch]->handle = handle; handle->uae_unitnum = uae_unitnum; } static void add_ncr_scsi_hd(struct ncr9x_state *ncr, int ch, struct hd_hardfiledata *hfd, struct uaedev_config_info *ci, int uae_unitnum) { struct scsi_data *handle = NULL; freescsi(ncr->scsid[ch]); ncr->scsid[ch] = NULL; if (!add_scsi_hd(&handle, ch, hfd, ci)) return; allocscsidevice(ncr, ch, handle, uae_unitnum); ncr->enabled = true; } static void add_ncr_scsi_cd(struct ncr9x_state *ncr, int ch, int unitnum, int uae_unitnum) { struct scsi_data *handle = NULL; freescsi(ncr->scsid[ch]); ncr->scsid[ch] = NULL; if (!add_scsi_cd(&handle, ch, unitnum)) return; allocscsidevice(ncr, ch, handle, uae_unitnum); ncr->enabled = true; } static void add_ncr_scsi_tape(struct ncr9x_state *ncr, int ch, const TCHAR *tape_directory, bool readonly, int uae_unitnum) { struct scsi_data *handle = NULL; freescsi(ncr->scsid[ch]); ncr->scsid[ch] = NULL; if (!add_scsi_tape(&handle, ch, tape_directory, readonly)) return; allocscsidevice(ncr, ch, handle, uae_unitnum); ncr->enabled = true; } static void ncr9x_add_scsi_unit(struct ncr9x_state **ncrp, int ch, struct uaedev_config_info *ci, struct romconfig *rc) { struct ncr9x_state *ncr = allocscsi(ncrp, rc, ch); if (ch >= 0 && ncr) { ncr->dma_mask = rc->dma24bit ? 0x00ffffff : 0xffffffff; if (ci->type == UAEDEV_CD) add_ncr_scsi_cd (ncr, ch, ci->device_emu_unit, ci->uae_unitnum); else if (ci->type == UAEDEV_TAPE) add_ncr_scsi_tape (ncr, ch, ci->rootdir, ci->readonly, ci->uae_unitnum); else if (ci->type == UAEDEV_HDF) add_ncr_scsi_hd (ncr, ch, NULL, ci, ci->uae_unitnum); } } void cpuboard_ncr9x_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc) { ncr9x_add_scsi_unit(&ncr_blizzard_scsi, ch, ci, rc); ncr_blizzard_scsi->configured = -1; ncr_blizzard_scsi->enabled = true; if (ISCPUBOARD(BOARD_CYBERSTORM, BOARD_CYBERSTORM_SUB_MK1) || ISCPUBOARD(BOARD_CYBERSTORM, BOARD_CYBERSTORM_SUB_MK2)) { ncr9x_esp_scsi_init(ncr_blizzard_scsi, cyberstorm_mk1_mk2_dma_read, cyberstorm_mk1_mk2_dma_write, NULL, 0); } else if (ISCPUBOARD(BOARD_BLIZZARD, BOARD_BLIZZARD_SUB_1230III)) { ncr9x_esp_scsi_init(ncr_blizzard_scsi, fake_dma_null, fake_dma_null, NULL, 1); } else { ncr9x_esp_scsi_init(ncr_blizzard_scsi, blizzard_dma_read, blizzard_dma_write, NULL, 0); } if (ISCPUBOARD(BOARD_CYBERSTORM, BOARD_CYBERSTORM_SUB_MK1)) ncr_blizzard_scsi->board_mask = 0xffff; else ncr_blizzard_scsi->board_mask = 0x1ffff; } void cpuboard_dkb_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc) { ncr9x_add_scsi_unit(&ncr_dkb1200_scsi, ch, ci, rc); ncr9x_esp_scsi_init(ncr_dkb1200_scsi, fake_dma_read, fake_dma_write, set_irq2_dkb1200, 2); } void fastlane_add_scsi_unit (int ch, struct uaedev_config_info *ci, struct romconfig *rc) { ncr9x_add_scsi_unit(&ncr_fastlane_scsi[ci->controller_type_unit], ch, ci, rc); ncr9x_esp_scsi_init(ncr_fastlane_scsi[ci->controller_type_unit], fastlane_dma_read, fastlane_dma_write, set_irq2_fastlane, 0); ncr_fastlane_scsi[ci->controller_type_unit]->board_mask = 32 * 1024 * 1024 - 1; } void oktagon_add_scsi_unit (int ch, struct uaedev_config_info *ci, struct romconfig *rc) { ncr9x_add_scsi_unit(&ncr_oktagon2008_scsi[ci->controller_type_unit], ch, ci, rc); ncr9x_esp_scsi_init(ncr_oktagon2008_scsi[ci->controller_type_unit], fake2_dma_read, fake2_dma_write, set_irq2_oktagon, 0); } void alf3_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc) { ncr9x_add_scsi_unit(&ncr_alf3_scsi[ci->controller_type_unit], ch, ci, rc); ncr9x_esp_scsi_init(ncr_alf3_scsi[ci->controller_type_unit], fake2_dma_read, fake2_dma_write, set_irq2_alf3, 0); } void masoboshi_add_scsi_unit (int ch, struct uaedev_config_info *ci, struct romconfig *rc) { ncr9x_add_scsi_unit(&ncr_masoboshi_scsi[ci->controller_type_unit], ch, ci, rc); 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); ncr9x_esp_scsi_init(ncr_ematrix530_scsi, fake_dma_read_ematrix, fake_dma_write_ematrix, set_irq2, 0); esp_dma_enable(ncr_ematrix530_scsi->devobject.lsistate, 1); } void multievolution_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc) { ncr9x_add_scsi_unit(&ncr_multievolution_scsi, ch, ci, rc); ncr9x_esp_scsi_init(ncr_multievolution_scsi, fake_dma_read, fake_dma_write, set_irq2, 0); esp_dma_enable(ncr_multievolution_scsi->devobject.lsistate, 1); } void golemfast_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc) { ncr9x_add_scsi_unit(&ncr_golemfast_scsi[ci->controller_type_unit], ch, ci, rc); ncr9x_esp_scsi_init(ncr_golemfast_scsi[ci->controller_type_unit], fake_dma_read, fake_dma_write, set_irq2_golemfast, 0); esp_dma_enable(ncr_golemfast_scsi[ci->controller_type_unit]->devobject.lsistate, 1); } void scram5394_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc) { ncr9x_add_scsi_unit(&ncr_scram5394_scsi[ci->controller_type_unit], ch, ci, rc); ncr9x_esp_scsi_init(ncr_scram5394_scsi[ci->controller_type_unit], fake_dma_read, fake_dma_write, set_irq2, 0); esp_dma_enable(ncr_scram5394_scsi[ci->controller_type_unit]->devobject.lsistate, 1); } void rapidfire_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc) { ncr9x_add_scsi_unit(&ncr_rapidfire_scsi[ci->controller_type_unit], ch, ci, rc); ncr9x_esp_scsi_init(ncr_rapidfire_scsi[ci->controller_type_unit], fake_dma_read, fake_dma_write, set_irq2, 2); esp_dma_enable(ncr_rapidfire_scsi[ci->controller_type_unit]->devobject.lsistate, 1); } void typhoon2scsi_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc) { ncr9x_add_scsi_unit(&ncr_typhoon2_scsi, ch, ci, rc); ncr9x_esp_scsi_init(ncr_typhoon2_scsi, fake_dma_read_ematrix, fake_dma_write_ematrix, set_irq2, 0); esp_dma_enable(ncr_typhoon2_scsi->devobject.lsistate, 1); } void squirrel_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc) { ncr9x_add_scsi_unit(&ncr_squirrel_scsi, ch, ci, rc); ncr9x_esp_scsi_init(ncr_squirrel_scsi, fake2_dma_read, fake2_dma_write, set_irq2, 0); esp_dma_enable(ncr_squirrel_scsi->devobject.lsistate, 1); } void mtecmastercard_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc) { ncr9x_add_scsi_unit(&ncr_mtec_mastercard, ch, ci, rc); ncr9x_esp_scsi_init(ncr_mtec_mastercard, fake_dma_read_ematrix, fake_dma_write_ematrix, set_irq2, 0); esp_dma_enable(ncr_mtec_mastercard->devobject.lsistate, 1); } #endif