]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
HardFrame and A-Team HD controllers.
authorToni Wilen <twilen@winuae.net>
Sun, 13 Nov 2016 13:13:47 +0000 (15:13 +0200)
committerToni Wilen <twilen@winuae.net>
Sun, 13 Nov 2016 13:13:47 +0000 (15:13 +0200)
expansion.cpp
ide.cpp
idecontrollers.cpp
include/idecontrollers.h
include/rommgr.h
include/scsi.h
rommgr.cpp
scsi.cpp

index 94a4354f013e75d528f9ffe2247793d020a7637e..ba86c4270711e0935ee151db64dd13b6fb81a7a5 100644 (file)
@@ -245,6 +245,7 @@ static bool ks11orolder(void)
 
 /* Autoconfig address space at 0xE80000 */
 static uae_u8 expamem[65536];
+static uae_u8 expamem_write_space[65536];
 #define AUTOMATIC_AUTOCONFIG_MAX_ADDRESS 0x80
 static int expamem_autoconfig_mode;
 static addrbank*(*expamem_map)(struct autoconfig_info*);
@@ -331,6 +332,14 @@ static void addextrachip (uae_u32 sysbase)
 
 addrbank expamem_null, expamem_none;
 
+DECLARE_MEMORY_FUNCTIONS(expamem_write);
+addrbank expamem_write_bank = {
+       expamem_write_lget, expamem_write_wget, expamem_write_bget,
+       expamem_write_lput, expamem_write_wput, expamem_write_bput,
+       default_xlate, default_check, NULL, NULL, _T("Autoconfig Z2 WRITE"),
+       dummy_lgeti, dummy_wgeti,
+       ABFLAG_IO | ABFLAG_SAFE | ABFLAG_PPCIOSPACE, S_READ, S_WRITE
+};
 DECLARE_MEMORY_FUNCTIONS(expamem);
 addrbank expamem_bank = {
        expamem_lget, expamem_wget, expamem_bget,
@@ -509,6 +518,10 @@ static void call_card_init(int index)
                }
        }
 
+       if (aci->write_bank_address && aci->write_bank_address != 0xffffffff) {
+               map_banks(&expamem_write_bank, aci->write_bank_address >> 16, aci->size >> 16, 0);
+       }
+
        if (ab) {
                // non-NULL: not using expamem_bank
                expamem_bank_current = ab;
@@ -601,6 +614,42 @@ void expamem_next(addrbank *mapped, addrbank *next)
        }
 }
 
+// only for custom autoconfig device development purposes, not in use in any normal config
+static uae_u32 REGPARAM2 expamem_write_lget(uaecptr addr)
+{
+       addr &= 0xffff;
+       return (expamem_write_space[addr + 0] << 24) | (expamem_write_space[addr + 1] << 16) | (expamem_write_space[addr + 2] << 8) | (expamem_write_space[addr + 3] << 0);
+}
+static uae_u32 REGPARAM2 expamem_write_wget(uaecptr addr)
+{
+       addr &= 0xffff;
+       return (expamem_write_space[addr + 0] << 8) | (expamem_write_space[addr + 1] << 0);
+}
+static uae_u32 REGPARAM2 expamem_write_bget(uaecptr addr)
+{
+       addr &= 0xffff;
+       return expamem_write_space[addr];
+}
+static void REGPARAM2 expamem_write_lput(uaecptr addr, uae_u32 value)
+{
+       addr &= 0xffff;
+       expamem_write_space[addr + 0] = value >> 24;
+       expamem_write_space[addr + 1] = value >> 16;
+       expamem_write_space[addr + 2] = value >>  8;
+       expamem_write_space[addr + 3] = value >>  0;
+}
+static void REGPARAM2 expamem_write_wput(uaecptr addr, uae_u32 value)
+{
+       addr &= 0xffff;
+       expamem_write_space[addr + 0] = value >> 8;
+       expamem_write_space[addr + 1] = value;
+}
+static void REGPARAM2 expamem_write_bput(uaecptr addr, uae_u32 value)
+{
+       addr &= 0xffff;
+       expamem_write_space[addr] = value;
+}
+
 static uae_u32 REGPARAM2 expamem_lget (uaecptr addr)
 {
        if (expamem_bank_current && expamem_bank_current != &expamem_bank) {
@@ -1621,6 +1670,7 @@ static bool expamem_init_fastcard_2(struct autoconfig_info *aci, int zorro)
                type |= Z2_MEM_8MB;
 
        aci->addrbank = bank;
+       aci->write_bank_address = p->fastmem[aci->devnum].write_address;
 
        if (aci->devnum == 0) {
                if (ISCPUBOARDP(p, BOARD_COMMODORE, BOARD_COMMODORE_SUB_A26x0)) {
@@ -1639,6 +1689,11 @@ static bool expamem_init_fastcard_2(struct autoconfig_info *aci, int zorro)
                aci->zorro = -1;
        }
 
+       if (expamem_write_space[0] != 0x00 && expamem_write_space[0] != 0xff && aci->write_bank_address) {
+               memcpy(expamem, expamem_write_space, 65536);
+               memcpy(bank->baseaddr, expamem_write_space, 65536);
+       }
+
        memcpy(aci->autoconfig_raw, expamem, sizeof aci->autoconfig_raw);
        return true;
 }
@@ -4525,6 +4580,12 @@ const struct expansionromtype expansionroms[] = {
                NULL, 0,
                true, EXPANSIONTYPE_SCSI | EXPANSIONTYPE_PARALLEL_ADAPTER
        },
+       {
+               _T("ateam"), _T("A-Team"), _T("Mainhattan Data"),
+               ateam_init, NULL, ateam_add_ide_unit, ROMTYPE_ATEAM, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+               NULL, 0,
+               true, EXPANSIONTYPE_IDE
+       },
        {
                _T("mtecat"), _T("AT 500"), _T("M-Tec"),
                mtec_init, NULL, mtec_add_ide_unit, ROMTYPE_MTEC, 0, 0, BOARD_AUTOCONFIG_Z2, false,
@@ -4537,6 +4598,14 @@ const struct expansionromtype expansionroms[] = {
                masoboshi_sub, 0,
                true, EXPANSIONTYPE_SCSI | EXPANSIONTYPE_IDE
        },
+       {
+               _T("hardframe"), _T("HardFrame"), _T("Microbotics"),
+               hardframe_init, NULL, hardframe_add_scsi_unit, ROMTYPE_HARDFRAME, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+               NULL, 0,
+               true, EXPANSIONTYPE_SCSI,
+               0, 0, 0, false, NULL,
+               true
+       },
        {
                _T("stardrive"), _T("StarDrive"), _T("Microbotics"),
                stardrive_init, NULL, stardrive_add_scsi_unit, ROMTYPE_STARDRIVE | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, true,
diff --git a/ide.cpp b/ide.cpp
index f4e11411cc57a6aaf4f148ac5c5c58f72279e050..f51693f1141d2b556cfb01dbd67a1daef2f27312 100644 (file)
--- a/ide.cpp
+++ b/ide.cpp
@@ -619,7 +619,7 @@ static void process_rw_command (struct ide_hdf *ide)
 static void process_packet_command (struct ide_hdf *ide)
 {
        setbsy (ide);
-       write_comm_pipe_u32 (&ide->its->requests, ide->num | 0x80, 1);
+       write_comm_pipe_u32 (&ide->its->requests, ide->num | 0x100, 1);
 }
 
 static void atapi_data_done (struct ide_hdf *ide)
@@ -1297,8 +1297,8 @@ static void *ide_thread (void *idedata)
                struct ide_hdf *ide;
                if (its->state == 0 || unit == 0xfffffff)
                        break;
-               ide = its->idetable[unit & 0x7f];
-               if (unit & 0x80)
+               ide = its->idetable[unit & 0xff];
+               if (unit & 0x100)
                        do_process_packet_command (ide);
                else
                        do_process_rw_command (ide);
index 3922c192ba0960025b53a927be3bf1a476191209..57cc23f6424be09c55602ad2bd5596f3642485fe 100644 (file)
@@ -46,7 +46,8 @@
 #define GOLEMFAST_IDE (x86_AT_IDE + 2 * MAX_DUPLICATE_EXPANSION_BOARDS)
 #define BUDDHA_IDE (GOLEMFAST_IDE + 2 * MAX_DUPLICATE_EXPANSION_BOARDS)
 #define DATAFLYERPLUS_IDE (BUDDHA_IDE + 3 * MAX_DUPLICATE_EXPANSION_BOARDS)
-#define TOTAL_IDE (DATAFLYERPLUS_IDE + MAX_DUPLICATE_EXPANSION_BOARDS)
+#define ATEAM_IDE (DATAFLYERPLUS_IDE + MAX_DUPLICATE_EXPANSION_BOARDS)
+#define TOTAL_IDE (ATEAM_IDE + MAX_DUPLICATE_EXPANSION_BOARDS)
 
 #define ALF_ROM_OFFSET 0x0100
 #define GVP_IDE_ROM_OFFSET 0x8000
@@ -99,6 +100,7 @@ static struct ide_board *x86_at_ide_board[MAX_DUPLICATE_EXPANSION_BOARDS];
 static struct ide_board *golemfast_board[MAX_DUPLICATE_EXPANSION_BOARDS];
 static struct ide_board *buddha_board[MAX_DUPLICATE_EXPANSION_BOARDS];
 static struct ide_board *dataflyerplus_board[MAX_DUPLICATE_EXPANSION_BOARDS];
+static struct ide_board *ateam_board[MAX_DUPLICATE_EXPANSION_BOARDS];
 
 static struct ide_hdf *idecontroller_drive[TOTAL_IDE * 2];
 static struct ide_thread_state idecontroller_its;
@@ -489,6 +491,22 @@ static int get_golemfast_reg(uaecptr addr, struct ide_board *board)
        return reg;
 }
 
+static int get_ateam_reg(uaecptr addr, struct ide_board *board)
+{
+       if (!(addr & 1))
+               return -1;
+       if ((addr & 0xf000) != 0xf000)
+               return -1;
+       addr >>= 7;
+       addr &= 15;
+       if (addr >= 8) {
+               addr &= 7;
+               addr |= IDE_SECONDARY;
+       }
+       return addr;
+}
+
+
 static int getidenum(struct ide_board *board, struct ide_board **arr)
 {
        for (int i = 0; i < MAX_DUPLICATE_EXPANSION_BOARDS; i++) {
@@ -738,6 +756,18 @@ static uae_u32 ide_read_byte(struct ide_board *board, uaecptr addr)
                        v = board->rom[addr & board->rom_mask];
                }
 
+       } else if (board->type == ATEAM_IDE) {
+
+               if (addr == 1) {
+                       v = ide_irq_check(board->ide[0], false) ? 0x00 : 0x80;
+               } else {
+                       int reg = get_ateam_reg(addr, board);
+                       if (reg >= 0) {
+                               v = get_ide_reg(board, reg);
+                       } else {
+                               v = board->rom[addr & board->rom_mask];
+                       }
+               }
 
        }
 
@@ -928,6 +958,12 @@ static uae_u32 ide_read_word(struct ide_board *board, uaecptr addr)
                                v = get_ide_reg_multi(board, IDE_DATA, (addr & 0x4000) ? 1 : 0, 1);
                        }
 
+               } else if (board->type == ATEAM_IDE) {
+
+                       if (board->configured && (addr & 0xf800) == 0xf800) {
+                               v = get_ide_reg_multi(board, IDE_DATA, 0, 1);
+                       }
+
                }
 
        }
@@ -1104,6 +1140,22 @@ static void ide_write_byte(struct ide_board *board, uaecptr addr, uae_u8 v)
                                                idescsi_scsi_put(oaddr, v);
                                }
                        }
+
+               } else if (board->type == ATEAM_IDE) {
+
+                       if ((addr & 0xff01) == 0x0101) {
+                               // disable interrupt strobe address
+                               board->intena = false;
+                       } else if ((addr & 0xff01) == 0x0201) {
+                               // enable interrupt strobe address
+                               board->intena = true;
+                       } else {
+                               int reg = get_ateam_reg(addr, board);
+                               if (reg >= 0) {
+                                       put_ide_reg(board, reg, v);
+                               }
+                       }
+
                }
 
        }
@@ -1241,6 +1293,12 @@ static void ide_write_word(struct ide_board *board, uaecptr addr, uae_u16 v)
                                put_ide_reg_multi(board, IDE_DATA, v, (addr & 0x4000) ? 1 : 0, 1);
                        }
 
+               } else if (board->type == ATEAM_IDE) {
+               
+                       if (board->configured && (addr & 0xf800) == 0xf800) {
+                               put_ide_reg_multi(board, IDE_DATA, v, 0, 1);
+                       }
+               
                }
        }
 }
@@ -1918,6 +1976,43 @@ void dataflyerplus_add_idescsi_unit(int ch, struct uaedev_config_info *ci, struc
        }
 }
 
+bool ateam_init(struct autoconfig_info *aci)
+{
+       uae_u8 *rom;
+       int rom_size = 32768;
+
+       rom = xcalloc(uae_u8, rom_size);
+       memset(rom, 0xff, rom_size);
+       load_rom_rc(aci->rc, ROMTYPE_ATEAM, 16384, !aci->rc->autoboot_disabled ? 0xc000 : 0x8000, rom, 32768, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
+
+       if (!aci->doinit) {
+               memcpy(aci->autoconfig_raw, rom, sizeof aci->autoconfig_raw);
+               xfree(rom);
+               return true;
+       }
+
+       struct ide_board *ide = getide(aci->rc);
+
+       ide->configured = 0;
+       ide->keepautoconfig = false;
+       ide->bank = &ide_bank_generic;
+       ide->mask = 65536 - 1;
+
+       ide->rom = rom;
+       ide->rom_size = rom_size;
+       ide->rom_mask = rom_size - 1;
+       memcpy(ide->acmemory, ide->rom, sizeof ide->acmemory);
+
+       aci->addrbank = ide->bank;
+       return true;
+}
+
+void ateam_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+       add_ide_standard_unit(ch, ci, rc, ateam_board, ATEAM_IDE, true, false, 2);
+}
+
+
 extern void x86_xt_ide_bios(struct zfile*, struct romconfig*);
 static bool x86_at_hd_init(struct autoconfig_info *aci, int type)
 {
index 38d5e222d8c1d4ff500654ad3ca29447b27e1785..a0ada8526cf6771289fbcc89e1da8a44ed7a6f07 100644 (file)
@@ -42,6 +42,9 @@ void buddha_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig
 bool dataflyerplus_init(struct autoconfig_info *aci);
 void dataflyerplus_add_idescsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
 
+bool ateam_init(struct autoconfig_info *aci);
+void ateam_add_ide_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;
 uae_u32 REGPARAM3 apollo_ide_bget (uaecptr addr) REGPARAM;
index 68625360fc928617e64ac59df446620ee59c33ef..5fa4af7b2a493caf1e0246095828f2ce6600d7cc 100644 (file)
@@ -144,6 +144,8 @@ extern int decode_cloanto_rom_do (uae_u8 *mem, int size, int real_size);
 #define ROMTYPE_HYDRA          0x0010005b
 #define ROMTYPE_LANROVER       0x0010005c
 #define ROMTYPE_ARIADNE                0x0010005d
+#define ROMTYPE_HARDFRAME      0x0010005e
+#define ROMTYPE_ATEAM          0x0010005f
 
 #define ROMTYPE_NOT                    0x00800000
 #define ROMTYPE_QUAD           0x01000000
index 3705297306c96d9d990927d4e3bedcdca00dad7d..0636614bfaef9d469533293c674c8cbd29ea8681 100644 (file)
@@ -258,6 +258,9 @@ void scram5380_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romco
 bool ossi_init(struct autoconfig_info*);
 void ossi_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
 
+bool hardframe_init(struct autoconfig_info*);
+void hardframe_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
+
 uae_u8 idescsi_scsi_get(uaecptr addr);
 void idescsi_scsi_put(uaecptr addr, uae_u8 v);
 
index e710e99de89fce912f55378da3f1c68928ad1d6e..67854fe179d702cebb0433e9588f81a65fff92c4 100644 (file)
@@ -95,7 +95,7 @@ struct romdata *getromdatabypath (const TCHAR *path)
        return NULL;
 }
 
-#define NEXT_ROM_ID 173
+#define NEXT_ROM_ID 175
 
 #define ALTROM(id,grp,num,size,flags,crc32,a,b,c,d,e) \
 { _T("X"), 0, 0, 0, 0, 0, size, id, 0, 0, flags, (grp << 16) | num, 0, NULL, crc32, a, b, c, d, e },
@@ -475,6 +475,10 @@ static struct romdata roms[] = {
        0xb0814aca, 0xb817672c, 0x1beb86c6, 0x840aa4bd, 0xf4640835, 0x1ed103f4, NULL, NULL },
        { _T("Expansion Systems Dataflyer+ v2.1"), 2, 1, 2, 1, _T("DATAFLYERPLUS\0"), 32768, 169, 0, 0, ROMTYPE_DATAFLYER, 0, 0, NULL,
        0xc49daa65, 0x20275716, 0xdc7eb00e, 0x5dc53680, 0xb5c8a90a, 0x7c00e390, NULL, NULL },
+       { _T("Microbotics HardFrame v1.5"), 1, 5, 1, 5, _T("HARDFRAME\0"), 32768, 173, 0, 0, ROMTYPE_HARDFRAME, 0, 0, NULL,
+       0x8d144212, 0xc5a4f497, 0x5216c1b1, 0xe08760d0, 0x0bd579ef, 0xea226354, NULL, NULL },
+       { _T("Mainhattan Data A-Team v1.8"), 1, 8, 1, 8, _T("ATEAM\0"), 65536, 174, 0, 0, ROMTYPE_ATEAM, 0, 0, NULL,
+       0x4fe08a5d, 0x007e5c61, 0x4048f598, 0x6d14011d, 0x23a41435, 0x5e0a2259, NULL, NULL },
 
        { _T("CyberStorm MK I 68040"), 0, 0, 0, 0, _T("CSMKI\0"), 32768, 95, 0, 0, ROMTYPE_CB_CSMK1, 0, 0, NULL,
          0, 0, 0, 0, 0, 0, NULL, _T("cyberstormmk1_040.rom") },
index 8c08940005238fc1473ce0572458260159de050c..b6f917f2038aae988bd28f4ef77e51cd0701575a 100644 (file)
--- a/scsi.cpp
+++ b/scsi.cpp
@@ -59,7 +59,8 @@
 #define NCR5380_SCRAM 28
 #define NCR5380_OSSI 29
 #define NCR5380_DATAFLYERPLUS 30
-#define NCR_LAST 31
+#define NONCR_HARDFRAME 31
+#define NCR_LAST 32
 
 extern int log_scsiemu;
 
@@ -731,9 +732,10 @@ struct raw_scsi
 
 struct soft_scsi
 {
-       uae_u8 regs[8 + 1];
+       uae_u8 regs[32];
        uae_u8 regs_400[2];
        int c400_count;
+       uae_u8 aic_reg;
        struct raw_scsi rscsi;
        bool irq;
        bool intena;
@@ -1220,9 +1222,13 @@ static void raw_scsi_write_data(struct raw_scsi *rs, uae_u8 data)
                case SCSI_SIGNAL_PHASE_MESSAGE_OUT:
                sd->msgout[sd->offset++] = data;
                len = getmsglen(sd->msgout, sd->offset);
+#if RAW_SCSI_DEBUG
                write_log(_T("raw_scsi_put_data got message %02x (%d/%d)\n"), data, sd->offset, len);
+#endif
                if (sd->offset >= len) {
+#if RAW_SCSI_DEBUG
                        write_log(_T("raw_scsi_put_data got message %02x (%d bytes)\n"), sd->msgout[0], len);
+#endif
                        if ((sd->msgout[0] & (0x80 | 0x20)) == 0x80)
                                rs->msglun = sd->msgout[0] & 7;
                        scsi_start_transfer(sd);
@@ -1356,6 +1362,30 @@ static void supra_do_dma(struct soft_scsi *ncr)
        }
 }
 
+uae_u8 aic_bget_dma(struct soft_scsi *scsi, bool *phaseerr);
+void aic_bput_dma(struct soft_scsi *scsi, uae_u8 v, bool *phaseerr);
+
+static void hardframe_do_dma(struct soft_scsi *ncr)
+{
+       int len = ncr->dmac_length;
+       for (int i = 0; i < len; i++) {
+               bool phaseerr;
+               if (ncr->dmac_direction < 0) {
+                       uae_u8 v = aic_bget_dma(ncr, &phaseerr);
+                       if (phaseerr)
+                               break;
+                       x_put_byte(ncr->dmac_address, v);
+               } else if (ncr->dmac_direction > 0) {
+                       uae_u8 v = x_get_byte(ncr->dmac_address);
+                       aic_bput_dma(ncr, v, &phaseerr);
+                       if (phaseerr)
+                               break;
+               }
+               ncr->dmac_length--;
+               ncr->dmac_address++;
+       }
+}
+
 static void xebec_do_dma(struct soft_scsi *ncr)
 {
        struct raw_scsi *rs = &ncr->rscsi;
@@ -1387,10 +1417,242 @@ static void dma_check(struct soft_scsi *ncr)
                        xebec_do_dma(ncr);
 
                }
+
+               if (ncr->type == NONCR_HARDFRAME) {
+
+                       hardframe_do_dma(ncr);
+
+               }
+
                ncr->dmac_active = 0;
        }
 }
 
+// AIC-6250
+
+static void aic_int(struct soft_scsi *scsi, uae_u8 mask)
+{
+       scsi->regs[16 + 8] |= mask;
+       if ((scsi->regs[16 + 8] & scsi->regs[3]) & 0x1f) {
+               scsi->irq = true;
+               ncr80_rethink();
+       } else {
+               scsi->irq = false;
+       }
+}
+
+static bool aic_phase_match(struct soft_scsi *scsi)
+{
+       struct raw_scsi *r = &scsi->rscsi;
+       uae_u8 phase = r->bus_phase;
+       bool cd = (phase & SCSI_IO_COMMAND) != 0;
+       bool io = (phase & SCSI_IO_DIRECTION) != 0;
+       bool msg = (phase & SCSI_IO_MESSAGE) != 0;
+       if (phase >= 0 &&
+               ((scsi->regs[9] >> 5) & 1) == msg &&
+               ((scsi->regs[9] >> 6) & 1) == io &&
+               ((scsi->regs[9] >> 7) & 1) == cd) {
+                       return true;
+       }
+       return false;
+}
+
+static void aic_reg_inc(struct soft_scsi *scsi)
+{
+       if (scsi->aic_reg >= 8)
+               return;
+       scsi->aic_reg++;
+}
+
+static uae_u8 aic_bget_reg(struct soft_scsi *scsi)
+{
+       return scsi->aic_reg & 15;
+}
+
+static uae_u8 aic_bget_dma(struct soft_scsi *scsi, bool *phaseerr)
+{
+       struct raw_scsi *r = &scsi->rscsi;
+       if (!aic_phase_match(scsi)) {
+               *phaseerr = true;
+               return 0;
+       }
+       *phaseerr = false;
+       return raw_scsi_get_data(r, true);
+}
+
+static uae_u8 aic_bget_data(struct soft_scsi *scsi)
+{
+       struct raw_scsi *r = &scsi->rscsi;
+       int reg = scsi->aic_reg;
+       uae_u8 v = scsi->regs[reg];
+
+       aic_reg_inc(scsi);
+
+       switch (reg)
+       {
+               case 0:
+               v = (scsi->dmac_length >> 0) & 0xff;
+               break;
+               case 1:
+               v = (scsi->dmac_length >> 8) & 0xff;
+               break;
+               case 2:
+               v = (scsi->dmac_length >> 16) & 0xff;
+               break;
+               case 6: // REVISION CONTROL
+               v = 2;
+               break;
+               case 7: // STATUS 0
+               {
+                       v = scsi->regs[reg + 16] & 2;
+                       if (r->bus_phase == SCSI_SIGNAL_PHASE_FREE)
+                               v |= 0x10; // BUS FREE
+                       if (raw_scsi_get_signal_phase(r) & SCSI_IO_REQ)
+                               v |= 0x04; // SCSI REQ ON
+                       if (scsi->dmac_length == 0)
+                               v |= 0x01; // DMA BYTE COUNT ZERO
+                       if ((raw_scsi_get_signal_phase(r) & SCSI_IO_REQ) && !aic_phase_match(scsi))
+                               v |= 0x20; // PHASE MISMATCH
+               }
+               break;
+               case 8: // STATUS 1
+               {
+                       v = scsi->regs[reg + 16] | 0x40;
+                       if (scsi->regs[8] & 2) { // SCSI RESET OUT
+                               v |= 0x20; // SCSI RESET IN
+                       } else {
+                               v &= ~0x20;
+                       }
+                       scsi->regs[reg + 16] = v;
+               }
+               break;
+               case 9: // SCSI SIGNAL
+               {
+                       uae_u8 t = raw_scsi_get_signal_phase(r);
+                       v = 0;
+                       if (t & SCSI_IO_BUSY)
+                               v |= 0x04;
+                       if (t & SCSI_IO_ATN)
+                               v |= 0x10;
+                       if (t & SCSI_IO_SEL)
+                               v |= 0x08;
+                       if (t & SCSI_IO_REQ)
+                               v |= 0x02;
+                       if (t & SCSI_IO_DIRECTION)
+                               v |= 0x40;
+                       if (t & SCSI_IO_COMMAND)
+                               v |= 0x80;
+                       if (t & SCSI_IO_MESSAGE)
+                               v |= 0x20;
+                       if (r->ack)
+                               v |= 0x01;
+               }
+               break;
+               case 10: // SCSI ID DATA
+                       v = scsi->regs[16 + 10];
+               break;
+               case 13:
+               {
+                       // SCSI ID (4 to 7 only)
+                       int vv = scsi->rc->device_id - 4;
+                       if (vv < 0)
+                               vv = 0;
+                       vv ^= 3;
+                       vv = (vv >> 1) | (vv << 1);
+                       v = (vv & 3) << 5;
+               }
+               break;
+       }
+       return v;
+}
+
+static void aic_bput_reg(struct soft_scsi *scsi, uae_u8 v)
+{
+       scsi->aic_reg = v & 15;
+}
+
+static void aic_bput_dma(struct soft_scsi *scsi, uae_u8 v, bool *phaseerr)
+{
+       struct raw_scsi *r = &scsi->rscsi;
+       if (!aic_phase_match(scsi)) {
+               *phaseerr = true;
+               return;
+       }
+       *phaseerr = false;
+       raw_scsi_put_data(r, v, true);
+}
+
+static void aic_bput_data(struct soft_scsi *scsi, uae_u8 v)
+{
+       struct raw_scsi *r = &scsi->rscsi;
+       int reg = scsi->aic_reg;
+
+       aic_reg_inc(scsi);
+
+       switch (reg)
+       {
+               case 0:
+               scsi->dmac_length &= 0xffff00;
+               scsi->dmac_length |= v << 0;
+               break;
+               case 1:
+               scsi->dmac_length &= 0xff00ff;
+               scsi->dmac_length |= v << 8;
+               break;
+               case 2:
+               scsi->dmac_length &= 0x00ffff;
+               scsi->dmac_length |= v << 16;
+               break;
+               case 3: // INT MSK
+               // cleared interrupt mask clears request
+               scsi->regs[16 + 8] &= v | ~0x1f;
+               if (v & 0x40) { // ARB/SEL START
+                       raw_scsi_put_data(r, scsi->regs[10], false);
+                       raw_scsi_set_signal_phase(r, false, true, (v & 0x20) != 0);
+                       raw_scsi_set_signal_phase(r, true, false, false);
+                       aic_int(scsi, 0x08); // COMMAND DONE
+                       scsi->regs[11] = scsi->regs[10]; // SOURCE AND DESTINATION ID = DATA
+                       v &= ~0x40;
+               }
+               aic_int(scsi, 0);
+               break;
+               case 5:
+               if (v & 1) { // DMA XFER EN
+                       scsi->dma_direction = (v & 2) ? 1 : -1;
+                       dma_check(scsi);
+                       aic_int(scsi, 0x08); // COMMAND DONE
+               }
+               break;
+               case 8: // CONTROL
+               if (v & 2) { // SCSI RESET OUT
+                       raw_scsi_reset(r);
+               }
+               if (v & 0x80) { // AUTO SCSI PIO REQ
+                       if (aic_phase_match(scsi)) {
+                               int phase = r->bus_phase;
+                               bool io = (phase & SCSI_IO_DIRECTION) != 0;
+                               scsi->regs[16 + 7] &= ~0x02;
+                               if (!io) {
+                                       raw_scsi_put_data(r, scsi->regs[10], true);
+                               } else {
+                                       scsi->regs[16 + 10] = raw_scsi_get_data(r, true);
+                               }
+                               aic_int(scsi, 0x08); // COMMAND DONE
+                               if (phase != r->bus_phase)
+                                       scsi->regs[16 + 7] |= 0x02; // SCSI PHASE CHG/ATN
+                               v &= ~0x80;
+                       } else {
+                               aic_int(scsi, 0x10); // ERROR
+                       }
+               }
+               break;
+               case 9: // SCSI SIGNAL
+
+               break;
+       }
+       scsi->regs[reg] = v;
+}
+
 // NCR 53C80/MISC SCSI-LIKE
 
 void x86_doirq(uint8_t irqnum);
@@ -2171,11 +2433,11 @@ static int dataflyerplus_reg(uaecptr addr)
        return (addr >> 1) & 7;
 }
 
-static uae_u8 read_supra_dma(struct soft_scsi *ncr, uaecptr addr)
+static uae_u8 read_684xx_dma(struct soft_scsi *ncr, uaecptr addr)
 {
        uae_u8 val = 0;
 
-       addr &= 0x1f;
+       addr &= 0x3f;
        switch (addr)
        {
                case 0:
@@ -2185,16 +2447,19 @@ static uae_u8 read_supra_dma(struct soft_scsi *ncr, uaecptr addr)
                val = 0;
                break;
        }
-
-       write_log(_T("SUPRA DMA GET %08x %02x %08x\n"), addr, val, M68K_GETPC);
+#if NCR5380_DEBUG > 0
+       write_log(_T("684xx DMA GET %08x %02x %08x\n"), addr, val, M68K_GETPC);
+#endif
        return val;
 }
 
-static void write_supra_dma(struct soft_scsi *ncr, uaecptr addr, uae_u8 val)
+static void write_684xx_dma(struct soft_scsi *ncr, uaecptr addr, uae_u8 val)
 {
-       write_log(_T("SUPRA DMA PUT %08x %02x %08x\n"), addr, val, M68K_GETPC);
+#if NCR5380_DEBUG > 0
+       write_log(_T("684xx DMA PUT %08x %02x %08x\n"), addr, val, M68K_GETPC);
+#endif
 
-       addr &= 0x1f;
+       addr &= 0x3f;
        switch (addr)
        {
                case 5: // OCR
@@ -2312,11 +2577,27 @@ static uae_u32 ncr80_bget2(struct soft_scsi *ncr, uaecptr addr, int size)
 
        addr &= ncr->board_mask;
 
-       if (ncr->type == NCR5380_SUPRA) {
+       if (ncr->type == NONCR_HARDFRAME) {
+
+               if (addr == 0xc0) {
+                       v = aic_bget_reg(ncr);
+               } else if (addr == 0xc2) {
+                       v = aic_bget_data(ncr);
+               } else if (addr == 0x40) {
+                       v = ncr->irq ? 0x80 : 0x00;
+               } else if (addr == 0x42) {
+                       v = ncr->intena ? 0x10 : 0x00;
+               } else if (addr >= 0x80 && addr <= 0x9f) {
+                       v = read_684xx_dma(ncr, addr & 31);
+               } else {
+                       v = ncr->rom[addr];
+               }
+
+       } else if (ncr->type == NCR5380_SUPRA) {
 
                if (ncr->subtype == 4) {
                        if ((addr & 0xc000) == 0xc000) {
-                               v = read_supra_dma(ncr, addr);
+                               v = read_684xx_dma(ncr, addr);
                        } else if (addr & 0x8000) {
                                addresstype = (addr & 1) ? 0 : 1;
                        }
@@ -2747,7 +3028,7 @@ static uae_u32 ncr80_bget2(struct soft_scsi *ncr, uaecptr addr, int size)
        }
 
 #if NCR5380_DEBUG > 1
-       if (1 || origaddr >= 0x8000)
+       if (origaddr < 0x100)
                write_log(_T("GET %08x %02x %d %08x %d\n"), origaddr, v, reg, M68K_GETPC, regs.intmask);
 #endif
 
@@ -2762,11 +3043,23 @@ static void ncr80_bput2(struct soft_scsi *ncr, uaecptr addr, uae_u32 val, int si
 
        addr &= ncr->board_mask;
 
-       if (ncr->type == NCR5380_SUPRA) {
+       if (ncr->type == NONCR_HARDFRAME) {
+               
+               if (addr == 0xc0) {
+                       aic_bput_reg(ncr, val);
+               } else if (addr == 0xc2) {
+                       aic_bput_data(ncr, val);
+               } else if (addr == 0x42) {
+                       ncr->intena = (val & 0x10) != 0;
+               } else if (addr >= 0x80 && addr <= 0x9f) {
+                       write_684xx_dma(ncr, addr & 31, val);
+               }
+
+       } else if (ncr->type == NCR5380_SUPRA) {
 
                if (ncr->subtype == 4) {
                        if ((addr & 0xc000) == 0xc000) {
-                               write_supra_dma(ncr, addr, val);
+                               write_684xx_dma(ncr, addr, val);
                        } else if (addr & 0x8000) {
                                addresstype = (addr & 1) ? 0 : 1;
                        }
@@ -4143,3 +4436,27 @@ void dataflyerplus_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct r
 {
        generic_soft_scsi_add(ch, ci, rc, NCR5380_DATAFLYERPLUS, 65536, -1, ROMTYPE_DATAFLYER);
 }
+
+bool hardframe_init(struct autoconfig_info *aci)
+{
+       if (!aci->doinit) {
+               load_rom_rc(aci->rc, ROMTYPE_HARDFRAME, 32768, aci->rc->autoboot_disabled ? 64 : 0, aci->autoconfig_raw, 128, LOADROM_EVENONLY_ODDONE);
+               return true;
+       }
+
+       struct soft_scsi *scsi = getscsi(aci->rc);
+       if (!scsi)
+               return false;
+
+       load_rom_rc(aci->rc, ROMTYPE_HARDFRAME, 32768, 0, scsi->rom, 65536, LOADROM_EVENONLY_ODDONE);
+       if (aci->rc->autoboot_disabled)
+               memcpy(scsi->rom, scsi->rom + 128, 128);
+       memcpy(scsi->acmemory, scsi->rom, sizeof scsi->acmemory);
+       aci->addrbank = scsi->bank;
+       return true;
+}
+
+void hardframe_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+       generic_soft_scsi_add(ch, ci, rc, NONCR_HARDFRAME, 65536, 65536, ROMTYPE_HARDFRAME);
+}