]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
53C80 emulation improvements, C-Ltd A1000/A2000, Preferred Technologies Nexus and...
authorToni Wilen <twilen@winuae.net>
Tue, 12 May 2015 16:10:32 +0000 (19:10 +0300)
committerToni Wilen <twilen@winuae.net>
Tue, 12 May 2015 16:10:32 +0000 (19:10 +0300)
a2091.cpp
expansion.cpp
gayle.cpp
include/gayle.h
include/rommgr.h
include/scsi.h
rommgr.cpp
scsi.cpp

index 4213b1f52609bd3b7885ee6c3048c683a427a4f3..0d12c4792d6d39e96914c6177de0022bdaf19564 100644 (file)
--- a/a2091.cpp
+++ b/a2091.cpp
@@ -642,9 +642,9 @@ static bool do_dma_commodore_8727(struct wd_state *wd, struct scsi_data *scsi)
                for (;;) {
                        uae_u8 v1 = 0, v2 = 0;
                        int status;
-                       status = scsi_receive_data (scsi, &v1);
+                       status = scsi_receive_data (scsi, &v1, true);
                        if (!status)
-                               status = scsi_receive_data (scsi, &v2);
+                               status = scsi_receive_data(scsi, &v2, true);
                        put_word((wd->cdmac.dmac_acr << 1) & 0xffffff, (v1 << 8) | v2);
                        if (wd->wc.wd_dataoffset < sizeof wd->wc.wd_data) {
                                wd->wc.wd_data[wd->wc.wd_dataoffset++] = v1;
@@ -709,7 +709,7 @@ static bool do_dma_commodore(struct wd_state *wd, struct scsi_data *scsi)
                bool run = true;
                while (run) {
                        uae_u8 v;
-                       int status = scsi_receive_data (scsi, &v);
+                       int status = scsi_receive_data(scsi, &v, true);
                        put_byte(wd->cdmac.dmac_acr, v);
                        if (wd->wc.wd_dataoffset < sizeof wd->wc.wd_data)
                                wd->wc.wd_data[wd->wc.wd_dataoffset++] = v;
@@ -755,7 +755,7 @@ static bool do_dma_gvp_s1(struct wd_state *wd, struct scsi_data *scsi)
        if (scsi->direction < 0) {
                for (;;) {
                        uae_u8 v;
-                       int status = scsi_receive_data (scsi, &v);
+                       int status = scsi_receive_data(scsi, &v, true);
                        wd->gdmac.buffer[wd->wc.wd_dataoffset++] = v;
                        wd->wc.wd_dataoffset &= wd->gdmac.s1_rammask;
                        if (decreasetc (&wd->wc))
@@ -803,7 +803,7 @@ static bool do_dma_gvp_s2(struct wd_state *wd, struct scsi_data *scsi)
                }
                for (;;) {
                        uae_u8 v;
-                       int status = scsi_receive_data (scsi, &v);
+                       int status = scsi_receive_data(scsi, &v, true);
                        put_byte(wd->gdmac.addr, v);
                        if (wd->wc.wd_dataoffset < sizeof wd->wc.wd_data)
                                wd->wc.wd_data[wd->wc.wd_dataoffset++] = v;
@@ -1517,7 +1517,7 @@ uae_u8 wdscsi_get (struct wd_chip_state *wd, struct wd_state *wds)
                        write_log (_T("%s WD_DATA READ without data request!?\n"), WD33C93);
                        return 0;
                }
-               int status = scsi_receive_data (wd->scsi, &v);
+               int status = scsi_receive_data(wd->scsi, &v, true);
 #if WD33C93_DEBUG_PIO
                write_log (_T("%s WD_DATA READ %02x %d/%d\n"), WD33C93, v, wd->scsi->offset, wd->scsi->data_len);
 #endif
index 07354a7cecbf8c3d6fb776bb2e7c94d94c0a790e..6f6a6bce9d3c2e99af94fbff4199c42e6f142c16 100644 (file)
@@ -2242,7 +2242,26 @@ static const struct expansionsubromtype supra_sub[] = {
                NULL
        }
 };
-
+static const struct expansionsubromtype nexus_sub[] = {
+       {
+               _T("2M Fast (Product ID 2)"), _T("fast2m"),
+               2102, 2, 0,
+               { 0xd1, 0x01, 0x00, 0x00, 0x08, 0x36, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 },
+       },
+       {
+               _T("4M Fast (Product ID 4)"), _T("fast4m"),
+               2102, 4, 0,
+               { 0xd1, 0x01, 0x00, 0x00, 0x08, 0x36, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 },
+       },
+       {
+               _T("8M Fast (Product ID 8)"), _T("fast8m"),
+               2102, 8, 0,
+               { 0xd1, 0x01, 0x00, 0x00, 0x08, 0x36, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 },
+       },
+       {
+               NULL
+       }
+};
 static const struct expansionboardsettings adscsi2000_settings[] = {
        {
                _T("Cache (B)"),
@@ -2415,6 +2434,30 @@ const struct expansionromtype expansionroms[] = {
                true, EXPANSIONTYPE_IDE | EXPANSIONTYPE_SCSI | EXPANSIONTYPE_IDE_PORT_DOUBLED,
                2144, 2, 0
        },
+       {
+               _T("a1000scsi"), _T("A1000/A2000 SCSI"), _T("C-Ltd"),
+               cltda1000scsi_init, cltda1000scsi_add_scsi_unit, ROMTYPE_CLTDSCSI | ROMTYPE_NONE, 0, 0, 2, false,
+               NULL, 0,
+               false, EXPANSIONTYPE_SCSI,
+               0, 0, 0,
+               false, NULL,
+               { 0xc1, 0x0c, 0x00, 0x00, 0x03, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+       },
+       {
+               _T("ptnexus"), _T("Nexus"), _T("Preferred Technologies"),
+               ptnexus_init, ptnexus_add_scsi_unit, ROMTYPE_PTNEXUS | ROMTYPE_NONE, 0, 0, 2, false,
+               nexus_sub, 0,
+               false, EXPANSIONTYPE_SCSI,
+               2102, 4, 0,
+               false, NULL,
+               { 0xd1, 0x01, 0x00, 0x00, 0x08, 0x36, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 },
+       },
+       {
+               _T("dataflyerscsiplus"), _T("DataFlyer SCSI+"), _T("Expansion Systems"),
+               dataflyer_init, dataflyer_add_scsi_unit, ROMTYPE_DATAFLYER | ROMTYPE_NONE, 0, 0, 1, true,
+               NULL, 0,
+               false, EXPANSIONTYPE_SCSI,
+       },
 #if 0
        {
                _T("kronos"), _T("Kronos"), _T("C-Ltd"),
index 60c8a9a885ad9527693d90dec7667aedf6a447da..a9fb69a55267321671527e5b6c70dae9a85ed898 100644 (file)
--- a/gayle.cpp
+++ b/gayle.cpp
@@ -29,6 +29,8 @@
 #include "blkdev.h"
 #include "scsi.h"
 #include "ide.h"
+#include "idecontrollers.h"
+#include "debug.h"
 
 #define PCMCIA_SRAM 1
 #define PCMCIA_IDE 2
@@ -153,6 +155,10 @@ static int ide_splitter;
 
 static struct ide_thread_state gayle_its;
 
+static int dataflyer_state;
+static int dataflyer_disable_irq;
+static uae_u8 dataflyer_byte;
+
 static void pcmcia_reset (void)
 {
        memset (pcmcia_configuration, 0, sizeof pcmcia_configuration);
@@ -177,6 +183,10 @@ static uae_u8 checkgayleideirq (void)
        int i;
        bool irq = false;
 
+       if (dataflyer_disable_irq) {
+               gayle_irq &= ~GAYLE_IRQ_IDE;
+               return 0;
+       }
        for (i = 0; i < 2; i++) {
                if (idedrive[i]) {
                        if (!(idedrive[i]->regs.ide_devcon & 2) && (idedrive[i]->irq || (idedrive[i + 2] && idedrive[i + 2]->irq)))
@@ -390,7 +400,7 @@ static void gayle_write2 (uaecptr addr, uae_u32 val)
        struct ide_hdf *ide = NULL;
        int ide_reg;
 
-       if ((GAYLE_LOG > 3 && (addr != 0x2000 && addr != 0x2001 && addr != 0x2020 && addr != 0x2021 && addr != GAYLE_IRQ_1200)) || GAYLE_LOG > 5)
+       if ((GAYLE_LOG > 3 && (addr != 0x2000 && addr != 0x2001 && addr != 0x3020 && addr != 0x3021 && addr != GAYLE_IRQ_1200)) || GAYLE_LOG > 5)
                write_log (_T("IDE_WRITE %08X=%02X PC=%X\n"), addr, (uae_u32)val & 0xff, M68K_GETPC);
        if (currprefs.cs_ide <= 0)
                return;
@@ -501,6 +511,77 @@ addrbank gayle_bank = {
        dummy_lgeti, dummy_wgeti, ABFLAG_IO
 };
 
+void gayle_dataflyer_enable(bool enable)
+{
+       if (!enable) {
+               dataflyer_state = 0;
+               dataflyer_disable_irq = 0;
+               return;
+       }
+       dataflyer_state = 1;
+}
+
+static bool isdataflyerscsiplus(uaecptr addr, uae_u32 *v, int size)
+{
+       if (!dataflyer_state)
+               return false;
+       uaecptr addrmask = addr & 0xffff;
+       if (addrmask >= GAYLE_IRQ_4000 && addrmask <= GAYLE_IRQ_4000 + 1 && currprefs.cs_ide == IDE_A4000)
+               return false;
+       uaecptr addrbase = (addr & ~0xff) & ~0x1020;
+       int reg = ((addr & 0xffff) & ~0x2020) >> 2;
+       if (reg >= IDE_SECONDARY) {
+               reg &= ~IDE_SECONDARY;
+               if (reg >= 6) // normal IDE registers
+                       return false;
+               if (size < 0) {
+                       switch (reg)
+                       {
+                               case 0: // 53C80 fake dma port
+                               soft_scsi_put(addrbase | 8, 1, *v);
+                               break;
+                               case 3:
+                               dataflyer_byte = *v;
+                               break;
+                       }
+               } else {
+                       switch (reg)
+                       {
+                               case 0: // 53C80 fake dma port
+                               *v = soft_scsi_get(addrbase | 8, 1);
+                               break;
+                               case 3:
+                               *v = 0;
+                               if (ide_irq_check(idedrive[0]))
+                                       *v = dataflyer_byte;
+                               break;
+                               case 4: // select SCSI
+                               dataflyer_disable_irq = 1;
+                               dataflyer_state |= 2;
+                               break;
+                               case 5: // select IDE
+                               dataflyer_disable_irq = 1;
+                               dataflyer_state &= ~2;
+                               break;
+                       }
+               }
+#if 0
+               if (size < 0)
+                       write_log(_T("SECONDARY BASE PUT(%d) %08x %08x PC=%08x\n"), -size, addr, *v, M68K_GETPC);
+               else
+                       write_log(_T("SECONDARY BASE GET(%d) %08x PC=%08x\n"), size, addr, M68K_GETPC);
+#endif
+               return true;
+       }
+       if (!(dataflyer_state & 2))
+               return false;
+       if (size < 0)
+               soft_scsi_put(addrbase | reg, -size, *v);
+       else
+               *v = soft_scsi_get(addrbase | reg, size);
+       return true;
+}
+
 static bool isa4000t (uaecptr *paddr)
 {
        if (currprefs.cs_mbdmac != 2)
@@ -524,6 +605,9 @@ static uae_u32 REGPARAM2 gayle_lget (uaecptr addr)
 #ifdef NCR
        if (currprefs.cs_mbdmac == 2 && (addr & 0xffff) == 0x3000)
                return 0xffffffff; // NCR DIP BANK
+       if (isdataflyerscsiplus(addr, &v, 4)) {
+               return v;
+       }
        if (isa4000t (&addr)) {
                if (addr >= NCR_ALT_OFFSET) {
                        addr &= NCR_MASK;
@@ -551,14 +635,17 @@ static uae_u32 REGPARAM2 gayle_wget (uaecptr addr)
 {
        struct ide_hdf *ide = NULL;
        int ide_reg;
-       uae_u16 v;
+       uae_u32 v;
 #ifdef JIT
        special_mem |= S_READ;
 #endif
 #ifdef NCR
        if (currprefs.cs_mbdmac == 2 && (addr & (0xffff - 1)) == 0x3000)
                return 0xffff; // NCR DIP BANK
-       if (isa4000t (&addr)) {
+       if (isdataflyerscsiplus(addr, &v, 2)) {
+               return v;
+       }
+       if (isa4000t(&addr)) {
                if (addr >= NCR_OFFSET) {
                        addr &= NCR_MASK;
                        v = (ncr710_io_bget_a4000t(addr) << 8) | ncr710_io_bget_a4000t(addr + 1);
@@ -575,13 +662,17 @@ static uae_u32 REGPARAM2 gayle_wget (uaecptr addr)
 }
 static uae_u32 REGPARAM2 gayle_bget (uaecptr addr)
 {
+       uae_u32 v;
 #ifdef JIT
        special_mem |= S_READ;
 #endif
 #ifdef NCR
        if (currprefs.cs_mbdmac == 2 && (addr & (0xffff - 3)) == 0x3000)
                return 0xff; // NCR DIP BANK
-       if (isa4000t (&addr)) {
+       if (isdataflyerscsiplus(addr, &v, 1)) {
+               return v;
+       }
+       if (isa4000t(&addr)) {
                if (addr >= NCR_OFFSET) {
                        addr &= NCR_MASK;
                        return ncr710_io_bget_a4000t(addr);
@@ -589,7 +680,8 @@ static uae_u32 REGPARAM2 gayle_bget (uaecptr addr)
                return 0;
        }
 #endif
-       return gayle_read (addr);
+       v = gayle_read (addr);
+       return v;
 }
 
 static void REGPARAM2 gayle_lput (uaecptr addr, uae_u32 value)
@@ -599,7 +691,10 @@ static void REGPARAM2 gayle_lput (uaecptr addr, uae_u32 value)
 #ifdef JIT
        special_mem |= S_WRITE;
 #endif
-       if (isa4000t (&addr)) {
+       if (isdataflyerscsiplus(addr, &value, -4)) {
+               return;
+       }
+       if (isa4000t(&addr)) {
                if (addr >= NCR_ALT_OFFSET) {
                        addr &= NCR_MASK;
                        ncr710_io_bput_a4000t(addr + 3, value >> 0);
@@ -632,7 +727,10 @@ static void REGPARAM2 gayle_wput (uaecptr addr, uae_u32 value)
        special_mem |= S_WRITE;
 #endif
 #ifdef NCR
-       if (isa4000t (&addr)) {
+       if (isdataflyerscsiplus(addr, &value, -2)) {
+               return;
+       }
+       if (isa4000t(&addr)) {
                if (addr >= NCR_OFFSET) {
                        addr &= NCR_MASK;
                        ncr710_io_bput_a4000t(addr, value >> 8);
@@ -656,7 +754,10 @@ static void REGPARAM2 gayle_bput (uaecptr addr, uae_u32 value)
        special_mem |= S_WRITE;
 #endif
 #ifdef NCR
-       if (isa4000t (&addr)) {
+       if (isdataflyerscsiplus(addr, &value, -1)) {
+               return;
+       }
+       if (isa4000t(&addr)) {
                if (addr >= NCR_OFFSET) {
                        addr &= NCR_MASK;
                        ncr710_io_bput_a4000t(addr, value);
@@ -1687,6 +1788,7 @@ void gayle_reset (int hardreset)
        }
 #endif
        gayle_bank.name = bankname;
+       gayle_dataflyer_enable(false);
 }
 
 uae_u8 *restore_gayle (uae_u8 *src)
index 06b17d5a41e55a3fba90b3e84eb2f7f646dca2ce..3cb18f9a418ed0828628e96016cf9904b31ba4e6 100644 (file)
@@ -16,3 +16,5 @@ extern int gary_timeout; // non-existing memory access = delay
 
 #define PCMCIA_COMMON_START 0x600000
 #define PCMCIA_COMMON_SIZE 0x400000
+
+extern void gayle_dataflyer_enable(bool);
\ No newline at end of file
index d77b23885067ab7af2cbc66908877aaf52275023..e1d21313c20916b88be942b60d2c2cd8eaa3ccce 100644 (file)
@@ -69,6 +69,9 @@ extern int decode_cloanto_rom_do (uae_u8 *mem, int size, int real_size);
 #define ROMTYPE_KRONOS         0x00100018
 #define ROMTYPE_ADSCSI         0x00100019
 #define ROMTYPE_ROCHARD                0x0010001a
+#define ROMTYPE_CLTDSCSI       0x0010001b
+#define ROMTYPE_PTNEXUS                0x0010001c
+#define ROMTYPE_DATAFLYER      0x0010001d
 
 #define ROMTYPE_QUAD           0x01000000
 #define ROMTYPE_EVEN           0x02000000
index f15ab8d28795c216cba9b627e468319ec87c3deb..358c900e3e8791aa81223e2aef4ec76db9019e0a 100644 (file)
@@ -56,7 +56,7 @@ extern void scsi_reset(void);
 
 extern void scsi_start_transfer(struct scsi_data*);
 extern int scsi_send_data(struct scsi_data*, uae_u8);
-extern int scsi_receive_data(struct scsi_data*, uae_u8*);
+extern int scsi_receive_data(struct scsi_data*, uae_u8*, bool next);
 extern void scsi_emulate_cmd(struct scsi_data *sd);
 extern void scsi_illegal_lun(struct scsi_data *sd);
 extern void scsi_clear_sense(struct scsi_data *sd);
@@ -148,6 +148,9 @@ static uae_u32 REGPARAM2 x ## _lget(uaecptr addr) \
 return y ## _lget(& ## z, addr); \
 }
 
+void soft_scsi_put(uaecptr addr, int size, uae_u32 v);
+uae_u32 soft_scsi_get(uaecptr addr, int size);
+
 void ncr80_rethink(void);
 
 void apollo_scsi_bput(uaecptr addr, uae_u8 v);
@@ -188,3 +191,12 @@ void rochard_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconf
 bool rochard_scsi_init(struct romconfig *rc, uaecptr baseaddress);
 uae_u8 rochard_scsi_get(uaecptr addr);
 void rochard_scsi_put(uaecptr addr, uae_u8 v);
+
+addrbank *cltda1000scsi_init(struct romconfig *rc);
+void cltda1000scsi_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
+
+addrbank *ptnexus_init(struct romconfig *rc);
+void ptnexus_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
+
+addrbank *dataflyer_init(struct romconfig *rc);
+void dataflyer_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
index f609b6d96c2c366ba16d00c63c06e9e50f6df8df..3bf63280773ff6f8c2da15ce9406a5fa5d8f4c95 100644 (file)
@@ -95,7 +95,7 @@ struct romdata *getromdatabypath (const TCHAR *path)
        return NULL;
 }
 
-#define NEXT_ROM_ID 139
+#define NEXT_ROM_ID 140
 
 static struct romheader romheaders[] = {
        { _T("Freezer Cartridges"), 1 },
@@ -369,8 +369,10 @@ static struct romdata roms[] = {
        { _T("Kupke Golem 030"), 0, 0, 0, 0, _T("GOLEM030\0"), 8192, 126, 0, 0, ROMTYPE_CB_GOLEM030, 0, 0, NULL,
        0x05d473f4, 0x574ec567,0xcc67e06f,0x91dcecb9,0x8c204399,0x5fe2a09f, NULL, NULL },
 
+       { _T("Preferred Technologies Nexus"), 1, 0, 1, 0, _T("PTNEXUS\0"), 8192, 139, 0, 0, ROMTYPE_PTNEXUS, 0, 0, NULL,
+       0xf495879a, 0xa3bd0202, 0xe14aa5b6, 0x49d3ce88, 0x22975950, 0x6500dbc2, NULL, NULL },
        { _T("ICD AdSCSI 2000"), 1, 6, 1, 6, _T("ADSCSI\0"), 32768, 133, 0, 0, ROMTYPE_ADSCSI, 0, 0, NULL,
-       0x7dba3e1f, 0x1e05f284,0xd59a1e5d,0x4e4de44e,0x6f075175,0x625cd6c0, NULL, NULL },
+       0x7dba3e1f, 0x1e05f284, 0xd59a1e5d, 0x4e4de44e, 0x6f075175, 0x625cd6c0, NULL, NULL },
        { _T("Archos ADD-500"), 1, 21, 1, 21, _T("ADD\0"), 16384, 132, 0, 0, ROMTYPE_ADD500, 0, 0, NULL,
        0x3f4e4a74, 0x9ed96fc0,0xd6381dc3,0x3192b0af,0xdfae4b74,0x576c3a69, NULL, NULL },
        { _T("Protar A500HD"), 1, 193, 1, 193, _T("PROTAR\0"), 32768, 131, 0, 0, ROMTYPE_PROTAR, 0, 0, NULL,
@@ -1705,6 +1707,8 @@ struct boardromconfig *get_device_rom(struct uae_prefs *p, int romtype, int devn
        *index = ert->parentromtype ? 1 : 0;
        for (int i = 0; i < MAX_EXPANSION_BOARDS; i++) {
                struct boardromconfig *brc = &p->expansionboard[i];
+               if (!brc->device_type)
+                       continue;
                if ((brc->device_type & ROMTYPE_MASK) == (parentrom & ROMTYPE_MASK) && brc->device_num == devnum)
                        return brc;
        }
@@ -1778,6 +1782,8 @@ struct boardromconfig *get_boardromconfig(struct uae_prefs *p, int romtype, int
 {
        for (int i = 0; i < MAX_EXPANSION_BOARDS; i++) {
                struct boardromconfig *brc = &p->expansionboard[i];
+               if (!brc->device_type)
+                       continue;
                if ((brc->device_type & ROMTYPE_MASK) == (romtype & ROMTYPE_MASK)) {
                        for (int j = 0; j < MAX_BOARD_ROMS; j++) {
                                if (brc->roms[j].romfile[0]) {
@@ -1842,4 +1848,4 @@ bool load_rom_rc(struct romconfig *rc, const int *roms, int maxfilesize, int fil
                        oldpos = 0;
        }
        return true;
-}
\ No newline at end of file
+}
index 194f9b3e037de88671de54c0b8e000e1bdb24b6d..79437b7d4e054d757cc8d4aa019b9531750a2099 100644 (file)
--- a/scsi.cpp
+++ b/scsi.cpp
 #include "rommgr.h"
 #include "newcpu.h"
 #include "custom.h"
+#include "gayle.h"
 
 #define SCSI_EMU_DEBUG 0
 #define RAW_SCSI_DEBUG 1
 #define NCR5380_DEBUG 0
+#define NCR5380_DEBUG_IRQ 0
 
 #define NCR5380_SUPRA 1
 #define NONCR_GOLEM 2
 #define NCR5380_KRONOS 9
 #define NCR5380_ADSCSI 10
 #define NCR5380_ROCHARD 11
-#define NCR_LAST 12
+#define NCR5380_CLTD 12
+#define NCR5380_PTNEXUS 13
+#define NCR5380_DATAFLYER 14
+#define NCR_LAST 15
 
 extern int log_scsiemu;
 
@@ -171,8 +176,20 @@ bool scsi_emulate_analyze (struct scsi_data *sd)
                        sd->direction = 0;
                }
                return true;
+       case 0x15: // MODE SELECT
+       case 0x55: 
+       if (sd->device_type != UAEDEV_CD && sd->device_type != UAEDEV_TAPE)
+               goto nocmd;
+       break;
+       }
+       if (data_len < 0) {
+               if (cmd_len == 6)
+                       sd->data_len = sd->cmd[4];
+               else
+                       sd->data_len = (sd->cmd[7] << 8) | sd->cmd[8];
+       } else {
+               sd->data_len = data_len;
        }
-       sd->data_len = data_len;
        sd->direction = scsi_data_dir (sd);
        return true;
 nocmd:
@@ -434,13 +451,16 @@ int scsi_send_data(struct scsi_data *sd, uae_u8 b)
        return 0;
 }
 
-int scsi_receive_data(struct scsi_data *sd, uae_u8 *b)
+int scsi_receive_data(struct scsi_data *sd, uae_u8 *b, bool next)
 {
        if (!sd->data_len)
                return -1;
-       *b = sd->buffer[sd->offset++];
-       if (sd->offset == sd->data_len)
-               return 1; // requested length got
+       *b = sd->buffer[sd->offset];
+       if (next) {
+               sd->offset++;
+               if (sd->offset == sd->data_len)
+                       return 1; // requested length got
+       }
        return 0;
 }
 
@@ -576,9 +596,8 @@ struct raw_scsi
        int bus_phase;
        bool atn;
        bool ack;
-       bool use_ack;
        bool wait_ack;
-       uae_u8 data;
+       uae_u8 data_write;
        uae_u8 status;
        bool databusoutput;
        int initiator_id, target_id;
@@ -589,14 +608,14 @@ struct raw_scsi
 
 struct soft_scsi
 {
-       uae_u8 regs[8];
-       bool c400;
+       uae_u8 regs[8 + 1];
        uae_u8 regs_400[2];
        int c400_count;
        struct raw_scsi rscsi;
        bool irq;
        bool intena;
        bool enabled;
+       bool delayed_irq;
        bool configured;
        uae_u8 acmemory[128];
        uaecptr baseaddress;
@@ -609,6 +628,8 @@ struct soft_scsi
        int type;
        int subtype;
        int dma_direction;
+       bool dma_active;
+       bool dma_controller;
        struct romconfig *rc;
        struct soft_scsi **self_ptr;
 
@@ -824,22 +845,30 @@ void raw_scsi_set_signal_phase(struct raw_scsi *rs, bool busy, bool select, bool
        {
                case SCSI_SIGNAL_PHASE_FREE:
                if (busy && !select && !rs->databusoutput) {
+                       if (countbits(rs->data_write) != 1) {
+#if RAW_SCSI_DEBUG
+                               write_log(_T("raw_scsi: invalid arbitration scsi id mask! (%02x)\n"), rs->data_write);
+#endif
+                               return;
+                       }
                        rs->bus_phase = SCSI_SIGNAL_PHASE_ARBIT;
-                       rs->initiator_id = getbit(rs->data);
+                       rs->initiator_id = getbit(rs->data_write);
 #if RAW_SCSI_DEBUG
-                       write_log(_T("raw_scsi: arbitration initiator id %d\n"), rs->initiator_id);
+                       write_log(_T("raw_scsi: arbitration initiator id %d (%02x)\n"), rs->initiator_id, rs->data_write);
 #endif
                } else if (!busy && select) {
-                       if (countbits(rs->data) == 1) {
-                               // In SCSI-1 initiator ID is optional.
-                               rs->data |= 0x80;
+                       if (countbits(rs->data_write) > 2 || rs->data_write == 0) {
+#if RAW_SCSI_DEBUG
+                               write_log(_T("raw_scsi: invalid scsi id selected mask (%02x)\n"), rs->data_write);
+#endif
+                               return;
                        }
-                       rs->initiator_id = getbit(rs->data);
+                       rs->initiator_id = -1;
                        rs->bus_phase = SCSI_SIGNAL_PHASE_SELECT_1;
-                       raw_scsi_set_signal_phase(rs, busy, select, atn);
 #if RAW_SCSI_DEBUG
-                       write_log(_T("raw_scsi: selected initiator id %d\n"), rs->initiator_id);
+                       write_log(_T("raw_scsi: selected scsi id mask (%02x)\n"), rs->data_write);
 #endif
+                       raw_scsi_set_signal_phase(rs, busy, select, atn);
                }
                break;
                case SCSI_SIGNAL_PHASE_ARBIT:
@@ -852,23 +881,31 @@ void raw_scsi_set_signal_phase(struct raw_scsi *rs, bool busy, bool select, bool
                case SCSI_SIGNAL_PHASE_SELECT_1:
                rs->atn = atn;
                rs->msglun = -1;
+               rs->target_id = -1;
                if (!busy) {
-                       uae_u8 data = rs->data & ~(1 << rs->initiator_id);
-                       rs->target_id = getbit(data);
-                       if (rs->target_id >= 0) {
-                               rs->target = rs->device[rs->target_id];
-                               if (rs->target) {
+                       for (int i = 0; i < 8; i++) {
+                               if (i == rs->initiator_id)
+                                       continue;
+                               if ((rs->data_write & (1 << i)) && rs->device[i]) {
+                                       rs->target_id = i;
+                                       rs->target = rs->device[rs->target_id];
 #if RAW_SCSI_DEBUG
                                        write_log(_T("raw_scsi: selected id %d\n"), rs->target_id);
 #endif
                                        rs->io |= SCSI_IO_BUSY;
-                               } else {
+                               }
+                       }
 #if RAW_SCSI_DEBUG
-                                       write_log(_T("raw_scsi: selected non-existing id %d\n"), rs->target_id);
-#endif
-                                       rs->target_id = -1;
+                       if (rs->target_id < 0) {
+                               for (int i = 0; i < 8; i++) {
+                                       if (i == rs->initiator_id)
+                                               continue;
+                                       if ((rs->data_write & (1 << i)) && !rs->device[i]) {
+                                               write_log(_T("raw_scsi: selected non-existing id %d\n"), i);
+                                       }
                                }
                        }
+#endif
                        if (rs->target_id >= 0) {
                                rs->bus_phase = SCSI_SIGNAL_PHASE_SELECT_2;
                        } else {
@@ -888,7 +925,7 @@ void raw_scsi_set_signal_phase(struct raw_scsi *rs, bool busy, bool select, bool
        }
 }
 
-uae_u8 raw_scsi_get_signal_phase(struct raw_scsi *rs)
+static uae_u8 raw_scsi_get_signal_phase(struct raw_scsi *rs)
 {
        uae_u8 v = rs->io;
        if (rs->bus_phase >= 0)
@@ -898,7 +935,7 @@ uae_u8 raw_scsi_get_signal_phase(struct raw_scsi *rs)
        return v;
 }
 
-uae_u8 raw_scsi_get_data(struct raw_scsi *rs)
+static uae_u8 raw_scsi_get_data_2(struct raw_scsi *rs, bool next, bool nodebug)
 {
        struct scsi_data *sd = rs->target;
        uae_u8 v = 0;
@@ -912,31 +949,39 @@ uae_u8 raw_scsi_get_data(struct raw_scsi *rs)
 #if RAW_SCSI_DEBUG
                write_log(_T("raw_scsi: arbitration\n"));
 #endif
-               v = rs->data;
+               v = rs->data_write;
                break;
                case SCSI_SIGNAL_PHASE_DATA_IN:
-               if (scsi_receive_data(sd, & v)) {
-                       rs->bus_phase = SCSI_SIGNAL_PHASE_STATUS;
-#if RAW_SCSI_DEBUG
-                       write_log(_T("raw_scsi: data in finished, %d bytes: status phase\n"), sd->offset);
+#if RAW_SCSI_DEBUG > 2
+               scsi_receive_data(sd, &v, false);
+               write_log(_T("raw_scsi: read data byte %02x (%d/%d)\n"), v, sd->offset, sd->data_len);
 #endif
+               if (scsi_receive_data(sd, &v, next)) {
+                       write_log(_T("raw_scsi: data in finished, %d bytes: status phase\n"), sd->offset);
+                       rs->bus_phase = SCSI_SIGNAL_PHASE_STATUS;
                }
                break;
                case SCSI_SIGNAL_PHASE_STATUS:
 #if RAW_SCSI_DEBUG
-               write_log(_T("raw_scsi: status byte read %02x\n"), sd->status);
+               if (!nodebug)
+                       write_log(_T("raw_scsi: status byte read %02x\n"), sd->status);
 #endif
                v = sd->status;
-               sd->status = 0;
-               rs->bus_phase = SCSI_SIGNAL_PHASE_MESSAGE_IN;
+               if (next) {
+                       sd->status = 0;
+                       rs->bus_phase = SCSI_SIGNAL_PHASE_MESSAGE_IN;
+               }
                break;
                case SCSI_SIGNAL_PHASE_MESSAGE_IN:
 #if RAW_SCSI_DEBUG
-               write_log(_T("raw_scsi: message byte read %02x\n"), sd->status);
+               if (!nodebug)
+                       write_log(_T("raw_scsi: message byte read %02x\n"), sd->status);
 #endif
                v = sd->status;
                rs->status = v;
-               bus_free(rs);
+               if (next) {
+                       bus_free(rs);
+               }
                break;
                default:
                write_log(_T("raw_scsi_get_data but bus phase is %d!\n"), rs->bus_phase);
@@ -946,6 +991,12 @@ uae_u8 raw_scsi_get_data(struct raw_scsi *rs)
        return v;
 }
 
+uae_u8 raw_scsi_get_data(struct raw_scsi *rs, bool next)
+{
+       return raw_scsi_get_data_2(rs, next, true);
+}
+
+
 static int getmsglen(uae_u8 *msgp, int len)
 {
        uae_u8 msg = msgp[0];
@@ -1007,6 +1058,9 @@ static void raw_scsi_write_data(struct raw_scsi *rs, uae_u8 data)
                }
                break;
                case SCSI_SIGNAL_PHASE_DATA_OUT:
+#if RAW_SCSI_DEBUG > 2
+               write_log(_T("raw_scsi: write data byte %02x (%d/%d)\n"), data, sd->offset, sd->data_len);
+#endif
                if (scsi_send_data(sd, data)) {
 #if RAW_SCSI_DEBUG
                        write_log(_T("raw_scsi: data out finished, %d bytes\n"), sd->data_len);
@@ -1033,20 +1087,28 @@ static void raw_scsi_write_data(struct raw_scsi *rs, uae_u8 data)
        }
 }
 
-void raw_scsi_put_data(struct raw_scsi *rs, uae_u8 data, bool databusoutput, bool noack)
+static void raw_scsi_put_data(struct raw_scsi *rs, uae_u8 data, bool databusoutput)
 {
-       rs->data = data;
-       if (((!rs->use_ack || noack) && (rs->bus_phase >= 0 && !(rs->io & SCSI_IO_REQ))) || !databusoutput)
+       rs->data_write = data;
+       if (!databusoutput)
                return;
        raw_scsi_write_data(rs, data);
 }
 
-void raw_scsi_set_ack(struct raw_scsi *rs, bool ack)
+static void raw_scsi_set_ack(struct raw_scsi *rs, bool ack)
 {
        if (rs->ack != ack) {
                rs->ack = ack;
-               if (ack && rs->use_ack && rs->bus_phase >= 0 && (rs->io & SCSI_IO_REQ) && !(rs->bus_phase & 1)) {
-                       raw_scsi_write_data(rs, rs->data);
+               if (!ack)
+                       return;
+               if (rs->bus_phase < 0)
+                       return;
+               if (!(rs->bus_phase & SCSI_IO_DIRECTION)) {
+                       if (rs->databusoutput) {
+                               raw_scsi_write_data(rs, rs->data_write);
+                       }
+               } else {
+                       raw_scsi_get_data_2(rs, true, false);
                }
        }
 }
@@ -1062,7 +1124,7 @@ void apollo_scsi_bput(uaecptr addr, uae_u8 v)
        struct raw_scsi *rs = &as->rscsi;
        addr &= 0x3fff;
        if (bank == 0) {
-               raw_scsi_put_data(rs, v, true, true);
+               raw_scsi_put_data(rs, v, true);
        } else if (bank == 0xc00 && !(addr & 1)) {
                as->irq = (v & 64) != 0;
                raw_scsi_set_signal_phase(rs,
@@ -1070,7 +1132,7 @@ void apollo_scsi_bput(uaecptr addr, uae_u8 v)
                        (v & 32) != 0,
                        false);
        } else if (bank == 0x400 && (addr & 1)) {
-               raw_scsi_put_data(rs, v, true, true);
+               raw_scsi_put_data(rs, v, true);
                raw_scsi_set_signal_phase(rs, true, false, false);
        }
        //write_log(_T("apollo scsi put %04x = %02x\n"), addr, v);
@@ -1086,7 +1148,7 @@ uae_u8 apollo_scsi_bget(uaecptr addr)
        uae_u8 v = 0xff;
        addr &= 0x3fff;
        if (bank == 0) {
-               v = raw_scsi_get_data(rs);
+               v = raw_scsi_get_data(rs, true);
        } else if (bank == 0x800 && (addr & 1)) {
                uae_u8 t = raw_scsi_get_signal_phase(rs);
                v = 1; // disable switch off
@@ -1165,11 +1227,30 @@ void ncr80_rethink(void)
 
 static void ncr5380_set_irq(struct soft_scsi *scsi)
 {
-       if (scsi->irq && (scsi->regs[5] & (1 << 4)))
+       if (scsi->irq)
                return;
        scsi->irq = true;
-       scsi->regs[5] |= 1 << 4;
        ncr80_rethink();
+       if (scsi->delayed_irq)
+               x_do_cycles(2 * CYCLE_UNIT);
+#if NCR5380_DEBUG_IRQ
+       write_log(_T("IRQ\n"));
+#endif
+}
+
+static void ncr5380_databusoutput(struct soft_scsi *scsi)
+{
+       bool databusoutput = (scsi->regs[1] & 1) != 0;
+       struct raw_scsi *r = &scsi->rscsi;
+
+       if (r->bus_phase >= 0 && (r->bus_phase & SCSI_IO_DIRECTION))
+               databusoutput = false;
+       raw_scsi_set_databus(r, databusoutput);
+}
+
+static void ncr5380_check(struct soft_scsi *scsi)
+{
+       ncr5380_databusoutput(scsi);
 }
 
 static void ncr5380_check_phase(struct soft_scsi *scsi)
@@ -1179,8 +1260,10 @@ static void ncr5380_check_phase(struct soft_scsi *scsi)
        if (scsi->regs[2] & 0x40)
                return;
        if (scsi->rscsi.bus_phase != (scsi->regs[3] & 7)) {
-               scsi->regs[5] |= 0x80; // end of dma
-               scsi->regs[3] |= 0x80; // last byte sent
+               if (scsi->dma_controller) {
+                       scsi->regs[5] |= 0x80; // end of dma
+                       scsi->regs[3] |= 0x80; // last byte sent
+               }
                ncr5380_set_irq(scsi);
        }
 }
@@ -1197,7 +1280,8 @@ static void ncr5380_reset(struct soft_scsi *scsi)
 
 uae_u8 ncr5380_bget(struct soft_scsi *scsi, int reg)
 {
-       reg &= 7;
+       if (reg > 8)
+               return 0;
        uae_u8 v = scsi->regs[reg];
        struct raw_scsi *r = &scsi->rscsi;
        switch(reg)
@@ -1232,47 +1316,64 @@ uae_u8 ncr5380_bget(struct soft_scsi *scsi, int reg)
                        if (scsi->irq) {
                                v |= 1 << 4;
                        }
-                       if ((t & SCSI_IO_REQ) && !scsi->c400) {
+                       if (scsi->dma_active && !scsi->dma_controller) {
                                v |= 1 << 6;
                        }
                }
                break;
                case 0:
+               v = raw_scsi_get_data(r, false);
+               break;
                case 6:
-               v = raw_scsi_get_data(r);
+               v = raw_scsi_get_data(r, scsi->dma_active);
+               ncr5380_check_phase(scsi);
                break;
                case 7:
                scsi->irq = false;
                break;
+               case 8: // fake dma port
+               v = raw_scsi_get_data(r, true);
+               ncr5380_check_phase(scsi);
+               break;
        }
-       ncr5380_check_phase(scsi);
+       ncr5380_check(scsi);
        return v;
 }
 
 void ncr5380_bput(struct soft_scsi *scsi, int reg, uae_u8 v)
 {
+       if (reg > 8)
+               return;
        struct raw_scsi *r = &scsi->rscsi;
-       reg &= 7;
        uae_u8 old = scsi->regs[reg];
        scsi->regs[reg] = v;
        switch(reg)
        {
                case 0:
-               raw_scsi_put_data(r, v, scsi->regs[1] & 1, false);
+               {
+                       r->data_write = v;
+                       // assert data bus can be only active if direction is out
+                       // and bus phase matches
+                       if (r->databusoutput) {
+                               if (((scsi->regs[2] & 2) && scsi->dma_active) || r->bus_phase < 0) {
+                                       raw_scsi_write_data(r, v);
+                                       ncr5380_check_phase(scsi);
+                               }
+                       }
+               }
                break;
                case 1:
                scsi->regs[reg] &= ~((1 << 5) | (1 << 6));
                scsi->regs[reg] |= old & ((1 << 5) | (1 << 6)); // AIP, LA
                if (!(v & 0x80)) {
                        bool init = r->bus_phase < 0;
-                       raw_scsi_set_databus(r, (v & 1) != 0);
+                       ncr5380_databusoutput(scsi);
                        raw_scsi_set_signal_phase(r,
                                (v & (1 << 3)) != 0,
                                (v & (1 << 2)) != 0,
                                (v & (1 << 1)) != 0);
-                       raw_scsi_set_ack(r, (v & (1 << 4)) != 0);
-//                     if ((v & 1) && !(old & 1) && !(scsi->regs[2] & 2) && !init && !r->use_ack)
-//                             raw_scsi_write_data(r, r->data);
+                       if (!(scsi->regs[2] & 2))
+                               raw_scsi_set_ack(r, (v & (1 << 4)) != 0);
                }
                if (v & 0x80) { // RST
                        ncr5380_reset(scsi);
@@ -1288,33 +1389,48 @@ void ncr5380_bput(struct soft_scsi *scsi, int reg, uae_u8 v)
                        scsi->regs[1] &= ~(1 << 6);
                }
                if (!(v & 2)) {
-                       scsi->regs[2] &= ~(0x80 | 0x40);
+                       // end of dma and dma request
+                       scsi->regs[5] &= ~(0x80 | 0x40);
                        scsi->dma_direction = 0;
+                       scsi->dma_active = false;
                }
                break;
                case 5:
                scsi->regs[reg] = old;
-               scsi->dma_direction = 1;
+               if (scsi->regs[2] & 2) {
+                       scsi->dma_direction = 1;
+                       scsi->dma_active = true;
+                       dma_check(scsi);
+               }
 #if NCR5380_DEBUG
                write_log(_T("DMA send\n"));
 #endif
-               dma_check(scsi);
                break;
                case 6:
-               scsi->dma_direction = 1;
+               if (scsi->regs[2] & 2) {
+                       scsi->dma_direction = 1;
+                       scsi->dma_active = true;
+               }
 #if NCR5380_DEBUG
                write_log(_T("DMA target recv\n"));
 #endif
                break;
                case 7:
-               scsi->dma_direction = -1;
+               if (scsi->regs[2] & 2) {
+                       scsi->dma_direction = -1;
+                       scsi->dma_active = true;
+                       dma_check(scsi);
+               }
 #if NCR5380_DEBUG
                write_log(_T("DMA initiator recv\n"));
 #endif
-               dma_check(scsi);
+               break;
+               case 8: // fake dma port
+               raw_scsi_put_data(r, v, true);
+               ncr5380_check_phase(scsi);
                break;
        }
-       ncr5380_check_phase(scsi);
+       ncr5380_check(scsi);
 }
 
 static bool ncr53400_5380(struct soft_scsi *scsi)
@@ -1349,7 +1465,7 @@ static uae_u8 ncr53400_bget(struct soft_scsi *scsi, int reg)
                return v;
        }
        if (reg & 0x80) {
-               v = raw_scsi_get_data(rs);
+               v = raw_scsi_get_data(rs, true);
                ncr53400_dmacount(scsi);
        } else if (reg & 0x100) {
                switch (reg) {
@@ -1385,7 +1501,7 @@ static void ncr53400_bput(struct soft_scsi *scsi, int reg, uae_u8 v)
                return;
        }
        if (reg & 0x80) {
-               raw_scsi_put_data(rs, v, true, true);
+               raw_scsi_put_data(rs, v, true);
                ncr53400_dmacount(scsi);
        } else if (reg & 0x100) {
                switch (reg) {
@@ -1412,10 +1528,7 @@ static int suprareg(struct soft_scsi *ncr, uaecptr addr, bool write)
        int reg = (addr & 0x0f) >> 1;
        if ((addr & 0x20) && ncr->subtype == 0) {
                // "dma" data in/out space
-               if (!write)
-                       reg = 6;
-               else
-                       reg = 0;
+               reg = 8;
                if (!(ncr->regs[2] & 2))
                        cpu_halt(6);
        }
@@ -1426,7 +1539,7 @@ static int stardrivereg(struct soft_scsi *ncr, uaecptr addr)
 {
        if ((addr & 0x0191) == 0x191) {
                // "dma" data in/out register
-               return 0;
+               return 8;
        }
        if ((addr & 0x0181) != 0x181)
                return -1;
@@ -1434,12 +1547,21 @@ static int stardrivereg(struct soft_scsi *ncr, uaecptr addr)
        return reg;
 }
 
+static int cltdreg(struct soft_scsi *ncr, uaecptr addr)
+{
+       if (!(addr & 1)) {
+               return -1;
+       }
+       int reg = (addr >> 1) & 7;
+       return reg;
+}
+
 static int protarreg(struct soft_scsi *ncr, uaecptr addr)
 {
        int reg = -1;
        if ((addr & 0x24) == 0x20) {
                // "fake dma" data port
-               reg = 0;
+               reg = 8;
        } else if ((addr & 0x20) == 0x00) {
                reg = (addr >> 2) & 7;
        }
@@ -1450,7 +1572,7 @@ static int add500reg(struct soft_scsi *ncr, uaecptr addr)
 {
        int reg = -1;
        if ((addr & 0x8048) == 0x8000) {
-               reg = 0;
+               reg = 8;
        } else if ((addr & 0x8040) == 0x8040) {
                reg = (addr >> 1) & 7;
        }
@@ -1461,15 +1583,24 @@ static int adscsireg(struct soft_scsi *ncr, uaecptr addr, bool write)
 {
        int reg = -1;
        if ((addr == 0x38 || addr == 0x39) && !write) {
-               reg = 0;
+               reg = 8;
        } else if ((addr == 0x20 || addr == 0x21) && write) {
-               reg = 0;
+               reg = 8;
        } else  if (addr < 0x20) {
                reg = (addr >> 2) & 7;
        }
        return reg;
 }
 
+static int ptnexusreg(struct soft_scsi *ncr, uaecptr addr)
+{
+       int reg = -1;
+       if ((addr & 0x8ff0) == 0) {
+               reg = (addr >> 1) & 7;
+       }
+       return reg;
+}
+
 
 static uae_u8 read_supra_dma(struct soft_scsi *ncr, uaecptr addr)
 {
@@ -1532,7 +1663,7 @@ static void vector_scsi_status(struct raw_scsi *rs)
 {
        // Vector Falcon 8000 FPGA seems to handle this internally
        while (rs->bus_phase == SCSI_SIGNAL_PHASE_STATUS || rs->bus_phase == SCSI_SIGNAL_PHASE_MESSAGE_IN) {
-               raw_scsi_get_data(rs);
+               raw_scsi_get_data(rs, true);
        }
 }
 
@@ -1585,10 +1716,10 @@ static uae_u32 ncr80_bget2(struct soft_scsi *ncr, uaecptr addr, int size)
                        case 0x8001:
                        case 0x8002:
                        case 0x8003:
-                       v = raw_scsi_get_data(rs);
+                       v = raw_scsi_get_data(rs, true);
                        // message is not retrieved by driver, perhaps hardware does it?
                        if (rs->bus_phase == SCSI_SIGNAL_PHASE_MESSAGE_IN)
-                               raw_scsi_get_data(rs);
+                               raw_scsi_get_data(rs, true);
                        break;
                        case 0x8200:
                        {
@@ -1637,6 +1768,34 @@ static uae_u32 ncr80_bget2(struct soft_scsi *ncr, uaecptr addr, int size)
                        }
                }
 
+       } else if (ncr->type == NCR5380_CLTD) {
+
+               struct raw_scsi *rs = &ncr->rscsi;
+               if (!ncr->configured && addr < sizeof ncr->acmemory) {
+                       v = ncr->acmemory[addr];
+               } else {
+                       reg = cltdreg(ncr, addr);
+                       if (reg >= 0)
+                               v = ncr5380_bget(ncr, reg);
+               }
+
+       } else if (ncr->type == NCR5380_PTNEXUS) {
+
+               struct raw_scsi *rs = &ncr->rscsi;
+               if (!ncr->configured && addr < sizeof ncr->acmemory) {
+                       v = ncr->acmemory[addr];
+               } else if (addr & 0x8000) {
+                       v = ncr->rom[addr & 16383];
+               } else {
+                       reg = ptnexusreg(ncr, addr);
+                       if (reg >= 0) {
+                               v = ncr5380_bget(ncr, reg);
+                       } else if (addr == 0x11) {
+                               // fake dma status
+                               v = 0;
+                       }
+               }
+
        } else if (ncr->type == NONCR_KOMMOS) {
 
                struct raw_scsi *rs = &ncr->rscsi;
@@ -1644,7 +1803,7 @@ static uae_u32 ncr80_bget2(struct soft_scsi *ncr, uaecptr addr, int size)
                        v = ncr->rom[addr & 0x7fff];
                } else if ((origddr & 0xf00000) != 0xf00000) {
                        if (!(addr & 8)) {
-                               v = raw_scsi_get_data(rs);
+                               v = raw_scsi_get_data(rs, true);
                        } else {
                                uae_u8 t = raw_scsi_get_signal_phase(rs);
                                v = 0;
@@ -1686,7 +1845,7 @@ static uae_u32 ncr80_bget2(struct soft_scsi *ncr, uaecptr addr, int size)
 
                        } else if ((addr & 0x300) == 0x000) {
                                if (size > 1) {
-                                       v = raw_scsi_get_data(rs);
+                                       v = raw_scsi_get_data(rs, true);
                                        vector_scsi_status(rs);
                                } else {
                                        v = rs->status >= 2 ? 2 : 0;
@@ -1721,12 +1880,12 @@ static uae_u32 ncr80_bget2(struct soft_scsi *ncr, uaecptr addr, int size)
                                if (!(addr & 1)) {
                                        if (t & SCSI_IO_REQ) {
                                                ncr->databuffer[0] = ncr->databuffer[1];
-                                               ncr->databuffer[1] = raw_scsi_get_data(rs) << 8;
-                                               ncr->databuffer[1] |= raw_scsi_get_data(rs);
+                                               ncr->databuffer[1] = raw_scsi_get_data(rs, true) << 8;
+                                               ncr->databuffer[1] |= raw_scsi_get_data(rs, true);
                                                if (ncr->databuffer_empty) {
                                                        ncr->databuffer[0] = ncr->databuffer[1];
-                                                       ncr->databuffer[1] = raw_scsi_get_data(rs) << 8;
-                                                       ncr->databuffer[1] |= raw_scsi_get_data(rs);
+                                                       ncr->databuffer[1] = raw_scsi_get_data(rs, true) << 8;
+                                                       ncr->databuffer[1] |= raw_scsi_get_data(rs, true);
                                                }
                                                ncr->databuffer_empty = false;
                                        } else {
@@ -1773,7 +1932,6 @@ static uae_u32 ncr80_bget2(struct soft_scsi *ncr, uaecptr addr, int size)
                        }
                }
 
-
        } else if (ncr->type == NCR5380_KRONOS) {
 
                struct raw_scsi *rs = &ncr->rscsi;
@@ -1797,11 +1955,17 @@ static uae_u32 ncr80_bget2(struct soft_scsi *ncr, uaecptr addr, int size)
                        v = ncr53400_bget(ncr, reg | 0x80);
                else
                        v = ncr53400_bget(ncr, reg);
+
+       } else if (ncr->type == NCR5380_DATAFLYER) {
+
+               reg = addr & 0xff;
+               v = ncr5380_bget(ncr, reg);
+
        }
 
 #if NCR5380_DEBUG > 1
        //if (addr >= 0x8000)
-               write_log(_T("GET %08x %02x %d %08x\n"), addr, v, reg, M68K_GETPC);
+               write_log(_T("GET %08x %02x %d %08x %d\n"), addr, v, reg, M68K_GETPC, regs.intmask);
 #endif
 
        return v;
@@ -1848,11 +2012,11 @@ static void ncr80_bput2(struct soft_scsi *ncr, uaecptr addr, uae_u32 val, int si
                        case 0x8081:
                        case 0x8082:
                        case 0x8083:
-                       raw_scsi_put_data(rs, val, true, true);
+                       raw_scsi_put_data(rs, val, true);
                        break;
                        case 0x8380:
                        {
-                               raw_scsi_put_data(rs, val, true, true);
+                               raw_scsi_put_data(rs, val, true);
                                raw_scsi_set_signal_phase(rs, false, true, false);
                                uae_u8 t = raw_scsi_get_signal_phase(rs);
                                if (t & SCSI_IO_BUSY)
@@ -1867,12 +2031,31 @@ static void ncr80_bput2(struct soft_scsi *ncr, uaecptr addr, uae_u32 val, int si
                if (reg >= 0)
                        ncr5380_bput(ncr, reg, val);
 
+       } else if (ncr->type == NCR5380_CLTD) {
+
+               if (ncr->configured) {
+                       reg = cltdreg(ncr, addr);
+                       if (reg >= 0)
+                               ncr5380_bput(ncr, reg, val);
+               }
+
+       } else if (ncr->type == NCR5380_PTNEXUS) {
+
+               if (ncr->configured) {
+                       reg = ptnexusreg(ncr, addr);
+                       if (reg >= 0) {
+                               ncr5380_bput(ncr, reg, val);
+                       } else if (addr == 0x11) {
+                               ncr->chip_state = val;
+                       }
+               }
+
        } else if (ncr->type == NONCR_KOMMOS) {
 
                struct raw_scsi *rs = &ncr->rscsi;
                if (!(addr & 0x8000) && (origddr & 0xf00000) != 0xf00000) {
                        if (!(addr & 8)) {
-                               raw_scsi_put_data(rs, val, true, true);
+                               raw_scsi_put_data(rs, val, true);
                        } else {
                                // select?
                                if (val & 4) {
@@ -1889,13 +2072,13 @@ static void ncr80_bput2(struct soft_scsi *ncr, uaecptr addr, uae_u32 val, int si
                struct raw_scsi *rs = &ncr->rscsi;
                if (addr & 0x8000) {
                        if ((addr & 0x300) == 0x300) {
-                               raw_scsi_put_data(rs, val, false, true);
+                               raw_scsi_put_data(rs, val, false);
                                raw_scsi_set_signal_phase(rs, false, true, false);
                                uae_u8 t = raw_scsi_get_signal_phase(rs);
                                if (t & SCSI_IO_BUSY)
                                        raw_scsi_set_signal_phase(rs, true, false, false);
                        } else if ((addr & 0x300) == 0x000) {
-                               raw_scsi_put_data(rs, val, true, true);
+                               raw_scsi_put_data(rs, val, true);
                                vector_scsi_status(rs);
                        }
 
@@ -1943,10 +2126,15 @@ static void ncr80_bput2(struct soft_scsi *ncr, uaecptr addr, uae_u32 val, int si
                else
                        ncr53400_bput(ncr, reg, val);
 
+       } else if (ncr->type == NCR5380_DATAFLYER) {
+
+               reg = addr & 0xff;
+               ncr5380_bput(ncr, reg, val);
+
        }
 
 #if NCR5380_DEBUG > 1
-       write_log(_T("PUT %08x %02x %d %08x\n"), addr, val, reg, M68K_GETPC);
+       write_log(_T("PUT %08x %02x %d %08x %d\n"), addr, val, reg, M68K_GETPC, regs.intmask);
 #endif
 }
 
@@ -2107,7 +2295,26 @@ addrbank soft_bank_generic = {
        soft_generic_lget, soft_generic_wget, ABFLAG_IO | ABFLAG_SAFE
 };
 
-
+void soft_scsi_put(uaecptr addr, int size, uae_u32 v)
+{
+       if (size == 4)
+               soft_generic_lput(addr, v);
+       else if (size == 2)
+               soft_generic_wput(addr, v);
+       else
+               soft_generic_bput(addr, v);
+}
+uae_u32 soft_scsi_get(uaecptr addr, int size)
+{
+       uae_u32 v;
+       if (size == 4)
+               v = soft_generic_lget(addr);
+       else if (size == 2)
+               v = soft_generic_wget(addr);
+       else
+               v = soft_generic_bget(addr);
+       return v;
+}
 
 /*
        $8380 select unit (unit mask)
@@ -2186,8 +2393,6 @@ addrbank *stardrive_init(struct romconfig *rc)
        if (!scsi)
                return &expamem_null;
 
-       scsi->rscsi.use_ack = true;
-
        const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_STARDRIVE);
        for (int i = 0; i < 16; i++) {
                uae_u8 b = ert->autoconfig[i];
@@ -2288,8 +2493,6 @@ addrbank *add500_init(struct romconfig *rc)
        roms[0] = 132;
        roms[1] = -1;
 
-       scsi->rscsi.use_ack = true;
-
        load_rom_rc(rc, roms, 16384, 0, scsi->rom, 32768, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
        memcpy(scsi->acmemory, scsi->rom, sizeof scsi->acmemory);
        return scsi->bank;
@@ -2347,8 +2550,7 @@ bool rochard_scsi_init(struct romconfig *rc, uaecptr baseaddress)
 {
        struct soft_scsi *scsi = getscsi(rc);
        scsi->configured = 1;
-       scsi->rscsi.use_ack = true;
-       scsi->c400 = true;
+       scsi->dma_controller = true;
        scsi->baseaddress = baseaddress;
        return scsi != NULL;
 }
@@ -2367,6 +2569,76 @@ void rochard_scsi_put(uaecptr addr, uae_u8 v)
        soft_generic_bput(addr, v);
 }
 
+addrbank *cltda1000scsi_init(struct romconfig *rc) {
+       struct soft_scsi *scsi = getscsi(rc);
+
+       if (!scsi)
+               return &expamem_null;
+
+       scsi->intena = true;
+       scsi->delayed_irq = true;
+
+       const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_CLTDSCSI);
+       for (int i = 0; i < 16; i++) {
+               uae_u8 b = ert->autoconfig[i];
+               ew(scsi, i * 4, b);
+       }
+       return scsi->bank;
+}
+
+void cltda1000scsi_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc) {
+       generic_soft_scsi_add(ch, ci, rc, NCR5380_CLTD, 65536, 0, ROMTYPE_CLTDSCSI);
+}
+
+addrbank *ptnexus_init(struct romconfig *rc)
+{
+       struct soft_scsi *scsi = getscsi(rc);
+       int roms[2];
+
+       if (!scsi)
+               return &expamem_null;
+
+       roms[0] = -1;
+       roms[1] = -1;
+
+       scsi->intena = true;
+       scsi->delayed_irq = true;
+
+       const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_PTNEXUS);
+       for (int i = 0; i < 16; i++) {
+               uae_u8 b = ert->autoconfig[i];
+               ew(scsi, i * 4, b);
+       }
+
+       load_rom_rc(rc, roms, 8192, 0, scsi->rom, 65536, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
+       return scsi->bank;
+}
+
+void ptnexus_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+       generic_soft_scsi_add(ch, ci, rc, NCR5380_PTNEXUS, 65536, 65536, ROMTYPE_PTNEXUS);
+}
+
+addrbank *dataflyer_init(struct romconfig *rc)
+{
+       struct soft_scsi *scsi = getscsi(rc);
+
+       if (!scsi)
+               return &expamem_null;
+
+       scsi->baseaddress = (currprefs.cs_ide == IDE_A4000) ? 0xdd2000 : 0xda0000;
+       scsi->configured = true;
+
+       gayle_dataflyer_enable(true);
+
+       return NULL;
+}
+
+void dataflyer_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+       generic_soft_scsi_add(ch, ci, rc, NCR5380_DATAFLYER, 4096, 0, ROMTYPE_DATAFLYER);
+}
+
 
 void soft_scsi_free(void)
 {
@@ -2382,5 +2654,3 @@ void soft_scsi_reset(void)
                raw_scsi_reset(&soft_scsi_devices[i]->rscsi);
        }
 }
-
-