WinUAE/ncr9x_scsi.cpp
2023-09-17 11:09:17 +03:00

2632 lines
68 KiB
C++

/*
* 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, &reg);
#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, &reg);
#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