]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
53C400 emulation, RocHard RH800C SCSI support, SCSI/IDE updates.
authorToni Wilen <twilen@winuae.net>
Sat, 2 May 2015 16:15:12 +0000 (19:15 +0300)
committerToni Wilen <twilen@winuae.net>
Sat, 2 May 2015 16:15:12 +0000 (19:15 +0300)
expansion.cpp
hardfile.cpp
idecontrollers.cpp
include/autoconf.h
include/filesys.h
include/ide.h
include/idecontrollers.h
include/ncr9x_scsi.h
include/scsi.h
ncr9x_scsi.cpp
scsi.cpp

index 8d4928edec81e2814de276abf640a4d79aeb417f..07354a7cecbf8c3d6fb776bb2e7c94d94c0a790e 100644 (file)
@@ -2197,6 +2197,21 @@ static const struct expansionsubromtype masoboshi_sub[] = {
                NULL
        }
 };
+static const struct expansionsubromtype rochard_sub[] = {
+       {
+               _T("IDE"), _T("ide"),
+               2144, 2, 0,
+               { 0 },
+       },
+       {
+               _T("IDE+SCSI"), _T("scsi"),
+               2144, 2, 0,
+               { 0 },
+       },
+       {
+               NULL
+       }
+};
 static const struct expansionsubromtype supra_sub[] = {
        {
                _T("A500 ByteSync/XP"), _T("bytesync"),
@@ -2395,9 +2410,9 @@ const struct expansionromtype expansionroms[] = {
        },
        {
                _T("rochard"), _T("RocHard RH800C"), _T("Roctec"),
-               rochard_init, rochard_add_ide_unit, ROMTYPE_ROCHARD | ROMTYPE_NONE, 0, 0, 2, false,
-               NULL, 0,
-               true, EXPANSIONTYPE_IDE,
+               rochard_init, rochard_add_idescsi_unit, ROMTYPE_ROCHARD | ROMTYPE_NONE, 0, 0, 2, false,
+               rochard_sub, 0,
+               true, EXPANSIONTYPE_IDE | EXPANSIONTYPE_SCSI | EXPANSIONTYPE_IDE_PORT_DOUBLED,
                2144, 2, 0
        },
 #if 0
index 5dbfa929bae2b54abdf045e667031cb108379924..cc3613130698cf1645aca22a48413609ecbe4ce8 100644 (file)
@@ -1146,6 +1146,7 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua
        int scsi_len = -1;
        int status = 0;
        int lun;
+       uae_u8 cmd = cmdbuf[0];
 
        if (log_scsiemu) {
                write_log (_T("SCSIEMU HD %d: %02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X CMDLEN=%d DATA=%p\n"), hfd->unitnum,
@@ -1154,13 +1155,20 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua
                        scsi_cmd_len, scsi_data);
        }
 
-       if (cmdbuf[0] == 0x03) { /* REQUEST SENSE */
+       if (cmd == 0x03) { /* REQUEST SENSE */
+               if (hfd->unit_attention) {
+                       s[0] = 0x70;
+                       s[2] = 6; /* UNIT ATTENTION */
+                       s[12] = (hfd->unit_attention >> 8) & 0xff;
+                       s[13] = (hfd->unit_attention >> 0) & 0xff;
+                       *sense_len = 0x12;
+               }
                return 0;
        }
 
        *reply_len = *sense_len = 0;
        lun = cmdbuf[1] >> 5;
-       if (cmdbuf[0] != 0x03 && cmdbuf[0] != 0x12 && lun) {
+       if (cmd != 0x03 && cmd != 0x12 && lun) {
                status = 2; /* CHECK CONDITION */
                s[0] = 0x70;
                s[2] = 5; /* ILLEGAL REQUEST */
@@ -1169,6 +1177,7 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua
                write_log (_T("UAEHF: CMD=%02X LUN=%d ignored\n"), cmdbuf[0], lun);
                goto scsi_done;
        }
+
        switch (cmdbuf[0])
        {
        case 0x12: /* INQUIRY */
@@ -1218,6 +1227,7 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua
        switch (cmdbuf[0])
        {
        case 0x00: /* TEST UNIT READY */
+               hfd->unit_attention = 0;
                if (nodisk (hfd))
                        goto nodisk;
                scsi_len = 0;
index 14079090f62ba7efeb3ed377e16f5510b66ef752..a039f7993cfb84214d0d8f1c20bc8d415f0bf15b 100644 (file)
@@ -146,6 +146,7 @@ static struct ide_board *getide(struct romconfig *rc)
                if (ide_boards[i]) {
                        struct ide_board *ide = ide_boards[i];
                        if (ide->rc == rc) {
+                               ide->original_rc = rc;
                                ide->rc = NULL;
                                return ide;
                        }
@@ -588,6 +589,11 @@ static uae_u32 ide_read_byte(struct ide_board *board, uaecptr addr)
                        int regnum = get_rochard_reg(addr, board, &portnum);
                        if (regnum >= 0 && board->ide[portnum])
                                v = get_ide_reg_multi(board, regnum, portnum);
+               } else if ((addr & 0x7c00) == 0x7000) {
+                       if (board->subtype)
+                               v = rochard_scsi_get(oaddr);
+                       else
+                               v = 0;
                } else {
                        v = board->rom[addr & board->rom_mask];
                }
@@ -767,6 +773,11 @@ static void ide_write_byte(struct ide_board *board, uaecptr addr, uae_u8 v)
                        map_banks_z2(ab, v, (board->mask + 1) >> 16);
                        board->baseaddress = v << 16;
                        board->configured = 1;
+                       if (board->type == ROCHARD_IDE) {
+                               rochard_scsi_init(board->original_rc, board->baseaddress);
+                       } else if (board->type == MASOBOSHI_IDE) {
+                               ncr_masoboshi_autoconfig_init(board->original_rc, board->baseaddress);
+                       }
                        expamem_next(ab, NULL);
                        return;
                }
@@ -855,13 +866,17 @@ static void ide_write_byte(struct ide_board *board, uaecptr addr, uae_u8 v)
 
                } else if (board->type == ROCHARD_IDE) {
 
-                       if (board->configured && (addr & 0x8000)) {
-                               int portnum;
-                               int regnum = get_rochard_reg(addr, board, &portnum);
-                               if (regnum >= 0 && board->ide[portnum])
-                                       put_ide_reg_multi(board, regnum, v, portnum);
+                       if (board->configured) {
+                               if (addr & 0x8000) {
+                                       int portnum;
+                                       int regnum = get_rochard_reg(addr, board, &portnum);
+                                       if (regnum >= 0 && board->ide[portnum])
+                                               put_ide_reg_multi(board, regnum, v, portnum);
+                               } else if ((addr & 0x7c00) == 0x7000) {
+                                       if (board->subtype)
+                                               rochard_scsi_put(oaddr, v);
+                               }
                        }
-
                }
 
        }
@@ -1288,8 +1303,6 @@ addrbank *masoboshi_init(struct romconfig *rc)
        else
                memcpy(ide->acmemory, ide->rom + 0x000, sizeof ide->acmemory);
 
-       // init SCSI part
-       ncr_masoboshi_autoconfig_init(rc);
        return ide->bank;
 }
 
@@ -1384,6 +1397,7 @@ addrbank *rochard_init(struct romconfig *rc)
        ide->bank = &ide_bank_generic;
        ide->rom_size = 32768;
        ide->mask = 65536 - 1;
+       ide->subtype = rc->subtype;
 
        memset(ide->acmemory, 0xff, sizeof ide->acmemory);
 
@@ -1395,7 +1409,20 @@ addrbank *rochard_init(struct romconfig *rc)
        return ide->bank;
 }
 
-void rochard_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+static void rochard_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
 {
        add_ide_standard_unit(ch, ci, rc, rochard_board, ROCHARD_IDE, false, false, 4);
 }
+
+void rochard_add_idescsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+       if (ch < 0) {
+               rochard_add_ide_unit(ch, ci, rc);
+               rochard_add_scsi_unit(ch, ci, rc);
+       } else {
+               if (ci->controller_type < HD_CONTROLLER_TYPE_SCSI_FIRST)
+                       rochard_add_ide_unit(ch, ci, rc);
+               else
+                       rochard_add_scsi_unit(ch, ci, rc);
+       }
+}
index cdb488ca024887ab429a39d8aedc3a88f61b7808..475829060f7336db660360da73189caeea1b425c 100644 (file)
@@ -109,6 +109,7 @@ typedef bool(*E8ACCESS)(int, uae_u32*, int, bool);
 #define EXPANSIONTYPE_SCSI 1
 #define EXPANSIONTYPE_IDE 2
 #define EXPANSIONTYPE_24BIT 4
+#define EXPANSIONTYPE_IDE_PORT_DOUBLED 8
 struct expansionboardsettings
 {
        const TCHAR *name;
index 730a3330e5776006d6acffae1ab94c60e6af6cd2..401e8f41eadfba8880f0e2e374a606450c0e199e 100644 (file)
@@ -71,6 +71,7 @@ struct hardfiledata {
        int reinsertdelay;
        bool isreinsert;
        bool unit_stopped;
+       int unit_attention;
 };
 
 #define HFD_FLAGS_REALDRIVE 1
index 4a6b34a90cf4ae8e19805ad82b3cd682ac6a0f75..1fa7a87e30f893b808e5946298e3163cb3607d94 100644 (file)
@@ -43,7 +43,7 @@ struct ide_board
        int type;
        int userdata;
        int subtype;
-       struct romconfig *rc;
+       struct romconfig *rc, *original_rc;
        struct ide_board **self_ptr;
 };
 
index 9528736c1818674cf4085b881125019a0625ca51..8624f7a05dbf41c5a0c4bd02e0c5b8518ab3eabb 100644 (file)
@@ -26,7 +26,7 @@ void mtec_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *
 addrbank *mtec_init(struct romconfig *rc);
 
 addrbank *rochard_init(struct romconfig *rc);
-void rochard_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
+void rochard_add_idescsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
 
 uae_u32 REGPARAM3 apollo_ide_lget (uaecptr addr) REGPARAM;
 uae_u32 REGPARAM3 apollo_ide_wget (uaecptr addr) REGPARAM;
index 73fd6f88c331146b08d6a55d21520341cd332dfb..c0bcbafac571e2f06cac1bd875397badc4db0d68 100644 (file)
@@ -20,7 +20,7 @@ extern uae_u32 cpuboard_ncr9x_scsi_get(uaecptr);
 
 uae_u32 masoboshi_ncr9x_scsi_get(uaecptr addr, int devnum);
 void masoboshi_ncr9x_scsi_put(uaecptr addr, uae_u32 v, int devnum);
-void ncr_masoboshi_autoconfig_init(struct romconfig*);
+void ncr_masoboshi_autoconfig_init(struct romconfig*, uaecptr);
 
 #define BLIZZARD_2060_SCSI_OFFSET 0x1ff00
 #define BLIZZARD_2060_DMA_OFFSET 0x1fff0
index 99487fa46129937409d7cce809c6e71a65d3c1da..f15ab8d28795c216cba9b627e468319ec87c3deb 100644 (file)
@@ -183,3 +183,8 @@ void kronos_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfi
 
 addrbank *adscsi_init(struct romconfig *rc);
 void adscsi_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
+
+void rochard_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
+bool rochard_scsi_init(struct romconfig *rc, uaecptr baseaddress);
+uae_u8 rochard_scsi_get(uaecptr addr);
+void rochard_scsi_put(uaecptr addr, uae_u8 v);
index fbc436ce5a3d678bcd38c5f7bdd973a2de11ff51..d156004494a41a726ab91ad3b45d2ebc99d726cc 100644 (file)
@@ -1463,7 +1463,7 @@ addrbank *ncr_dkb_autoconfig_init(struct romconfig *rc)
 }
 
 
-void ncr_masoboshi_autoconfig_init(struct romconfig *rc)
+void ncr_masoboshi_autoconfig_init(struct romconfig *rc, uaecptr baseaddress)
 {
        struct ncr9x_state *ncr = getscsi(rc);
 
@@ -1471,6 +1471,7 @@ void ncr_masoboshi_autoconfig_init(struct romconfig *rc)
                return;
 
        ncr->enabled = true;
+       ncr->baseaddress = baseaddress;
 
        ncr9x_reset_board(ncr);
 }
index 326adaeaca6ce71e2714a17551d9e6a4b86a5cdb..194f9b3e037de88671de54c0b8e000e1bdb24b6d 100644 (file)
--- a/scsi.cpp
+++ b/scsi.cpp
@@ -23,7 +23,7 @@
 #include "custom.h"
 
 #define SCSI_EMU_DEBUG 0
-#define RAW_SCSI_DEBUG 2
+#define RAW_SCSI_DEBUG 1
 #define NCR5380_DEBUG 0
 
 #define NCR5380_SUPRA 1
@@ -36,7 +36,8 @@
 #define NCR5380_ADD500 8
 #define NCR5380_KRONOS 9
 #define NCR5380_ADSCSI 10
-#define NCR_LAST 11
+#define NCR5380_ROCHARD 11
+#define NCR_LAST 12
 
 extern int log_scsiemu;
 
@@ -215,6 +216,8 @@ static void copysense(struct scsi_data *sd)
        int len = sd->cmd[4];
        if (log_scsiemu)
                write_log (_T("REQUEST SENSE length %d (%d)\n"), len, sd->sense_len);
+       if (len == 0)
+               len = 4;
        memset(sd->buffer, 0, len);
        memcpy(sd->buffer, sd->sense, sd->sense_len > len ? len : sd->sense_len);
        if (sd->sense_len == 0)
@@ -232,6 +235,14 @@ static void copyreply(struct scsi_data *sd)
        }
 }
 
+void scsi_emulate_reset_device(struct scsi_data *sd)
+{
+       if (!sd)
+               return;
+       if (sd->device_type == UAEDEV_HDF && sd->nativescsiunit < 0)
+               sd->hfd->hfd.unit_attention = (0x29 << 8) | 0x02; //  SCSI bus reset occurred
+}
+
 void scsi_emulate_cmd(struct scsi_data *sd)
 {
        sd->status = 0;
@@ -257,7 +268,7 @@ void scsi_emulate_cmd(struct scsi_data *sd)
                }
        } else if (sd->device_type == UAEDEV_HDF && sd->nativescsiunit < 0) {
                if (sd->cmd[0] == 0x03) { /* REQUEST SENSE */
-                       scsi_hd_emulate(&sd->hfd->hfd, sd->hfd, sd->cmd, 0, 0, 0, 0, 0, 0, 0);
+                       scsi_hd_emulate(&sd->hfd->hfd, sd->hfd, sd->cmd, 0, 0, 0, 0, 0, sd->sense, &sd->sense_len);
                        copysense(sd);
                } else {
                        scsi_clear_sense(sd);
@@ -573,11 +584,15 @@ struct raw_scsi
        int initiator_id, target_id;
        struct scsi_data *device[MAX_TOTAL_SCSI_DEVICES];
        struct scsi_data *target;
+       int msglun;
 };
 
 struct soft_scsi
 {
        uae_u8 regs[8];
+       bool c400;
+       uae_u8 regs_400[2];
+       int c400_count;
        struct raw_scsi rscsi;
        bool irq;
        bool intena;
@@ -601,6 +616,7 @@ struct soft_scsi
        uaecptr dmac_address;
        int dmac_length;
        int dmac_active;
+       int chip_state;
 
        // add500
        uae_u16 databuffer[2];
@@ -790,6 +806,13 @@ static int countbits(uae_u8 v)
        return cnt;
 }
 
+static void raw_scsi_reset_bus(struct raw_scsi *rs)
+{
+       for (int i = 0; i < 8; i++)
+               scsi_emulate_reset_device(rs->device[i]);
+}
+
+
 static void raw_scsi_set_databus(struct raw_scsi *rs, bool databusoutput)
 {
        rs->databusoutput = databusoutput;
@@ -828,6 +851,7 @@ void raw_scsi_set_signal_phase(struct raw_scsi *rs, bool busy, bool select, bool
                break;
                case SCSI_SIGNAL_PHASE_SELECT_1:
                rs->atn = atn;
+               rs->msglun = -1;
                if (!busy) {
                        uae_u8 data = rs->data & ~(1 << rs->initiator_id);
                        rs->target_id = getbit(data);
@@ -954,13 +978,10 @@ static void raw_scsi_write_data(struct raw_scsi *rs, uae_u8 data)
                write_log(_T("raw_scsi: got command byte %02x (%d/%d)\n"), data, sd->offset, len);
 #endif
                if (sd->offset >= len) {
-#if RAW_SCSI_DEBUG
-                       write_log(_T("raw_scsi: got command %02x (%d bytes)\n"), sd->cmd[0], len);
-                       for (int i = 0; i < len; i++) {
-                               write_log(_T("%02x."), sd->cmd[i]);
+                       if (rs->msglun >= 0) {
+                               sd->cmd[1] &= ~(0x80 | 0x40 | 0x20);
+                               sd->cmd[1] |= rs->msglun << 5;
                        }
-                       write_log(_T("\n"));
-#endif
                        scsi_emulate_analyze(rs->target);
                        if (sd->direction > 0) {
 #if RAW_SCSI_DEBUG
@@ -1000,6 +1021,8 @@ static void raw_scsi_write_data(struct raw_scsi *rs, uae_u8 data)
                write_log(_T("raw_scsi_put_data got message %02x (%d/%d)\n"), data, sd->offset, len);
                if (sd->offset >= len) {
                        write_log(_T("raw_scsi_put_data got message %02x (%d bytes)\n"), sd->msgout[0], len);
+                       if ((sd->msgout[0] & (0x80 | 0x20)) == 0x80)
+                               rs->msglun = sd->msgout[0] & 7;
                        scsi_start_transfer(sd);
                        rs->bus_phase = SCSI_SIGNAL_PHASE_COMMAND;
                }
@@ -1010,10 +1033,10 @@ 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)
+void raw_scsi_put_data(struct raw_scsi *rs, uae_u8 data, bool databusoutput, bool noack)
 {
        rs->data = data;
-       if ((!rs->use_ack && (rs->bus_phase >= 0 && !(rs->io & SCSI_IO_REQ))) || !databusoutput)
+       if (((!rs->use_ack || noack) && (rs->bus_phase >= 0 && !(rs->io & SCSI_IO_REQ))) || !databusoutput)
                return;
        raw_scsi_write_data(rs, data);
 }
@@ -1039,7 +1062,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);
+               raw_scsi_put_data(rs, v, true, true);
        } else if (bank == 0xc00 && !(addr & 1)) {
                as->irq = (v & 64) != 0;
                raw_scsi_set_signal_phase(rs,
@@ -1047,7 +1070,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);
+               raw_scsi_put_data(rs, v, true, true);
                raw_scsi_set_signal_phase(rs, true, false, false);
        }
        //write_log(_T("apollo scsi put %04x = %02x\n"), addr, v);
@@ -1142,6 +1165,8 @@ void ncr80_rethink(void)
 
 static void ncr5380_set_irq(struct soft_scsi *scsi)
 {
+       if (scsi->irq && (scsi->regs[5] & (1 << 4)))
+               return;
        scsi->irq = true;
        scsi->regs[5] |= 1 << 4;
        ncr80_rethink();
@@ -1153,15 +1178,23 @@ static void ncr5380_check_phase(struct soft_scsi *scsi)
                return;
        if (scsi->regs[2] & 0x40)
                return;
-       if (scsi->regs[5] & 0x80)
-               return;
        if (scsi->rscsi.bus_phase != (scsi->regs[3] & 7)) {
                scsi->regs[5] |= 0x80; // end of dma
-               scsi->regs[3] |= 0x80;
+               scsi->regs[3] |= 0x80; // last byte sent
                ncr5380_set_irq(scsi);
        }
 }
 
+static void ncr5380_reset(struct soft_scsi *scsi)
+{
+       struct raw_scsi *r = &scsi->rscsi;
+
+       scsi->irq = true;
+       memset(scsi->regs, 0, sizeof scsi->regs);
+       raw_scsi_reset_bus(r);
+       scsi->regs[1] = 0x80;
+}
+
 uae_u8 ncr5380_bget(struct soft_scsi *scsi, int reg)
 {
        reg &= 7;
@@ -1199,7 +1232,7 @@ uae_u8 ncr5380_bget(struct soft_scsi *scsi, int reg)
                        if (scsi->irq) {
                                v |= 1 << 4;
                        }
-                       if (t & SCSI_IO_REQ) {
+                       if ((t & SCSI_IO_REQ) && !scsi->c400) {
                                v |= 1 << 6;
                        }
                }
@@ -1225,7 +1258,7 @@ void ncr5380_bput(struct soft_scsi *scsi, int reg, uae_u8 v)
        switch(reg)
        {
                case 0:
-               raw_scsi_put_data(r, v, scsi->regs[1] & 1);
+               raw_scsi_put_data(r, v, scsi->regs[1] & 1, false);
                break;
                case 1:
                scsi->regs[reg] &= ~((1 << 5) | (1 << 6));
@@ -1242,9 +1275,7 @@ void ncr5380_bput(struct soft_scsi *scsi, int reg, uae_u8 v)
 //                             raw_scsi_write_data(r, r->data);
                }
                if (v & 0x80) { // RST
-                       scsi->irq = true;
-                       memset(scsi->regs, 0, sizeof scsi->regs);
-                       scsi->regs[reg] = 0x80;
+                       ncr5380_reset(scsi);
                }
                break;
                case 2:
@@ -1286,6 +1317,96 @@ void ncr5380_bput(struct soft_scsi *scsi, int reg, uae_u8 v)
        ncr5380_check_phase(scsi);
 }
 
+static bool ncr53400_5380(struct soft_scsi *scsi)
+{
+       if (scsi->irq)
+               scsi->regs_400[1] = 0;
+       return !scsi->regs_400[1];
+}
+
+static void ncr53400_dmacount(struct soft_scsi *scsi)
+{
+       scsi->c400_count++;
+       if (scsi->c400_count == 128) {
+               scsi->c400_count = 0;
+               scsi->regs_400[1]--;
+               if (scsi->regs_400[1] == 0) {
+                       scsi->regs[5] &= ~0x40; // dma request
+                       ncr5380_check_phase(scsi);
+               }
+       }
+}
+
+static uae_u8 ncr53400_bget(struct soft_scsi *scsi, int reg)
+{
+       struct raw_scsi *rs = &scsi->rscsi;
+       uae_u8 v = 0;
+       uae_u8 csr = scsi->regs_400[0];
+
+       if (ncr53400_5380(scsi) && reg < 8) {
+               v = ncr5380_bget(scsi, reg);
+               //write_log(_T("53C80 REG GET %02x -> %02x\n"), reg, v);
+               return v;
+       }
+       if (reg & 0x80) {
+               v = raw_scsi_get_data(rs);
+               ncr53400_dmacount(scsi);
+       } else if (reg & 0x100) {
+               switch (reg) {
+                       case 0x100:
+                               if (scsi->regs_400[1]) {
+                                       v |= 0x02;
+                               } else {
+                                       v |= 0x04;
+                               }
+                               if (ncr53400_5380(scsi))
+                                       v |= 0x80;
+                               if (scsi->irq)
+                                       v |= 0x01;
+                               break;
+                       case 0x101:
+                               v = scsi->regs_400[1];
+                               break;
+               }
+               //write_log(_T("53C400 REG GET %02x -> %02x\n"), reg, v);
+       }
+       ncr5380_check_phase(scsi);
+       return v;
+}
+
+static void ncr53400_bput(struct soft_scsi *scsi, int reg, uae_u8 v)
+{
+       struct raw_scsi *rs = &scsi->rscsi;
+       uae_u8 csr = scsi->regs_400[0];
+
+       if (ncr53400_5380(scsi) && reg < 8) {
+               ncr5380_bput(scsi, reg, v);
+               //write_log(_T("53C80 REG PUT %02x -> %02x\n"), reg, v);
+               return;
+       }
+       if (reg & 0x80) {
+               raw_scsi_put_data(rs, v, true, true);
+               ncr53400_dmacount(scsi);
+       } else if (reg & 0x100) {
+               switch (reg) {
+                       case 0x100:
+                               scsi->regs_400[0] = v;
+                               if (v & 0x80) {
+                                       ncr5380_reset(scsi);
+                                       scsi->regs_400[0] = 0x80;
+                                       scsi->regs_400[1] = 0;
+                               }
+                               break;
+                       case 0x101:
+                               scsi->regs_400[1] = v;
+                               scsi->c400_count = 0;
+                               break;
+               }
+               //write_log(_T("53C400 REG PUT %02x -> %02x\n"), reg, v);
+       }
+       ncr5380_check_phase(scsi);
+}
+
 static int suprareg(struct soft_scsi *ncr, uaecptr addr, bool write)
 {
        int reg = (addr & 0x0f) >> 1;
@@ -1666,6 +1787,16 @@ static uae_u32 ncr80_bget2(struct soft_scsi *ncr, uaecptr addr, int size)
                if (addr & 0x8000) {
                        v = ncr->rom[addr & 8191];
                }
+
+       } else if (ncr->type == NCR5380_ROCHARD) {
+
+               int reg = (addr & 15) / 2;
+               if ((addr & 0x300) == 0x300)
+                       v = ncr53400_bget(ncr, reg | 0x100);
+               else if (addr & 0x200)
+                       v = ncr53400_bget(ncr, reg | 0x80);
+               else
+                       v = ncr53400_bget(ncr, reg);
        }
 
 #if NCR5380_DEBUG > 1
@@ -1717,11 +1848,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);
+                       raw_scsi_put_data(rs, val, true, true);
                        break;
                        case 0x8380:
                        {
-                               raw_scsi_put_data(rs, val, true);
+                               raw_scsi_put_data(rs, val, true, true);
                                raw_scsi_set_signal_phase(rs, false, true, false);
                                uae_u8 t = raw_scsi_get_signal_phase(rs);
                                if (t & SCSI_IO_BUSY)
@@ -1741,7 +1872,7 @@ static void ncr80_bput2(struct soft_scsi *ncr, uaecptr addr, uae_u32 val, int si
                struct raw_scsi *rs = &ncr->rscsi;
                if (!(addr & 0x8000) && (origddr & 0xf00000) != 0xf00000) {
                        if (!(addr & 8)) {
-                               raw_scsi_put_data(rs, val, true);
+                               raw_scsi_put_data(rs, val, true, true);
                        } else {
                                // select?
                                if (val & 4) {
@@ -1758,13 +1889,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);
+                               raw_scsi_put_data(rs, val, false, true);
                                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);
+                               raw_scsi_put_data(rs, val, true, true);
                                vector_scsi_status(rs);
                        }
 
@@ -1802,7 +1933,18 @@ static void ncr80_bput2(struct soft_scsi *ncr, uaecptr addr, uae_u32 val, int si
                        ;
                }
 
+       } else if (ncr->type == NCR5380_ROCHARD) {
+
+               int reg = (addr & 15) / 2;
+               if ((addr & 0x300) == 0x300)
+                       ncr53400_bput(ncr, reg | 0x100, val);
+               else if (addr & 0x200)
+                       ncr53400_bput(ncr, reg | 0x80, val);
+               else
+                       ncr53400_bput(ncr, reg, val);
+
        }
+
 #if NCR5380_DEBUG > 1
        write_log(_T("PUT %08x %02x %d %08x\n"), addr, val, reg, M68K_GETPC);
 #endif
@@ -2201,6 +2343,30 @@ void adscsi_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfi
        generic_soft_scsi_add(ch, ci, rc, NCR5380_ADSCSI, 65536, 65536, ROMTYPE_ADSCSI);
 }
 
+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->baseaddress = baseaddress;
+       return scsi != NULL;
+}
+void rochard_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+       generic_soft_scsi_add(ch, ci, rc, NCR5380_ROCHARD, 65536, -1, ROMTYPE_ROCHARD);
+}
+
+uae_u8 rochard_scsi_get(uaecptr addr)
+{
+       return soft_generic_bget(addr);
+}
+
+void rochard_scsi_put(uaecptr addr, uae_u8 v)
+{
+       soft_generic_bput(addr, v);
+}
+
 
 void soft_scsi_free(void)
 {
@@ -2216,3 +2382,5 @@ void soft_scsi_reset(void)
                raw_scsi_reset(&soft_scsi_devices[i]->rscsi);
        }
 }
+
+