]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
SASI emulation, Tecmar and Xebec.
authorToni Wilen <twilen@winuae.net>
Fri, 26 Jun 2015 15:54:28 +0000 (18:54 +0300)
committerToni Wilen <twilen@winuae.net>
Fri, 26 Jun 2015 15:54:28 +0000 (18:54 +0300)
expansion.cpp
hardfile.cpp
include/autoconf.h
include/scsi.h
scsi.cpp

index 417212db21c67283e558ed06b264b261e8c625da..67f8e37999c875eca80b159a67f758b4f4bdb438 100644 (file)
 #include "specialmonitors.h"
 #include "pci.h"
 
+// More information in first revision HRM Appendix_G
+#define BOARD_PROTOAUTOCONFIG 1
+
+#define BOARD_AUTOCONFIG_Z2 2
+#define BOARD_AUTOCONFIG_Z3 3
+#define BOARD_NONAUTOCONFIG 4
+
 #define EXP_DEBUG 0
 
 #define MAX_EXPANSION_BOARD_SPACE 16
@@ -69,7 +76,9 @@
 #define rom_card       0x10 /* ROM vector is valid */
 #define add_memory     0x20 /* Link RAM into free memory list */
 
-#define zorroII                0xc0 /* Type of Expansion Card */
+/* Type of Expansion Card */
+#define protoautoconfig 0x40
+#define zorroII                0xc0
 #define zorroIII       0x80
 
 /* ********************************************************** */
@@ -386,7 +395,7 @@ static void call_card_init(int index)
        }
 
        code = expamem_read(0);
-       if ((code & 0xc0) == 0xc0) {
+       if ((code & 0xc0) == zorroII) {
                // Z2
                code &= 7;
                if (code == 0)
@@ -397,7 +406,7 @@ static void call_card_init(int index)
                expamem_board_size = expamem_z2_size;
                expamem_board_pointer = expamem_z2_pointer;
 
-       } else {
+       } else if ((code & 0xc0) == zorroIII) {
                // Z3
                if (expamem_z3_sum < Z3BASE_UAE) {
                        expamem_z3_sum = currprefs.z3autoconfig_start;
@@ -428,6 +437,16 @@ static void call_card_init(int index)
 
                expamem_board_size = expamem_z3_size;
                expamem_board_pointer = expamem_z3_pointer;
+
+       } else if ((code & 0xc0) == 0x40) {
+               // 0x40 = "Box without init/diagnostic code"
+               // proto autoconfig "box" size.
+               //expamem_z2_size = (1 << ((code >> 3) & 7)) * 4096;
+               // much easier this way, all old-style boards were made for
+               // A1000 and didn't have passthrough connector.
+               expamem_z2_size = 65536;
+               expamem_board_size = expamem_z2_size;
+               expamem_board_pointer = expamem_z2_pointer;
        }
 
        if (ab) {
@@ -467,7 +486,7 @@ static void boardmessage(addrbank *mapped, bool success)
                size /= 1024;
        }
        write_log (_T("Card %d: Z%d 0x%08x %4d%c %s %s%s\n"),
-               ecard + 1, (type & 0xc0) == zorroII ? 2 : 3,
+               ecard + 1, (type & 0xc0) == zorroII ? 2 : ((type & 0xc0) == zorroIII ? 3 : 1),
                expamem_board_pointer, size, sizemod,
                type & rom_card ? _T("ROM") : (type & add_memory ? _T("RAM") : _T("IO ")),
                mapped->name,
@@ -642,34 +661,47 @@ static void REGPARAM2 expamem_bput (uaecptr addr, uae_u32 value)
        }
        if (ecard >= cardno)
                return;
-       switch (addr & 0xff) {
-       case 0x48:
-               if (expamem_type() == zorroII) {
-                       expamem_hi = value & 0xff;
-                       expamem_z2_pointer = (expamem_hi | (expamem_lo >> 4)) << 16; 
+       if (expamem_type() == protoautoconfig) {
+               switch (addr & 0xff) {
+               case 0x22:
+                       expamem_hi = value & 0x7f;
+                       expamem_z2_pointer = 0xe80000 | (expamem_hi * 4096);
                        expamem_board_pointer = expamem_z2_pointer;
                        if (cards[ecard].map) {
                                expamem_next(cards[ecard].map(), NULL);
                                return;
                        }
-               } else {
-                       expamem_lo = value & 0xff;
+                       break;
                }
-               break;
+       } else {
+               switch (addr & 0xff) {
+               case 0x48:
+                       if (expamem_type() == zorroII) {
+                               expamem_hi = value & 0xff;
+                               expamem_z2_pointer = (expamem_hi | (expamem_lo >> 4)) << 16; 
+                               expamem_board_pointer = expamem_z2_pointer;
+                               if (cards[ecard].map) {
+                                       expamem_next(cards[ecard].map(), NULL);
+                                       return;
+                               }
+                       } else {
+                               expamem_lo = value & 0xff;
+                       }
+                       break;
 
-       case 0x4a:
-               if (expamem_type () == zorroII)
-                       expamem_lo = value & 0xff;
-               break;
+               case 0x4a:
+                       if (expamem_type () == zorroII)
+                               expamem_lo = value & 0xff;
+                       break;
 
-       case 0x4c:
-               if (cards[ecard].map) {
-                       expamem_next(expamem_bank_current, NULL);
-                       return;
+               case 0x4c:
+                       if (cards[ecard].map) {
+                               expamem_next(expamem_bank_current, NULL);
+                               return;
+                       }
+                       break;
                }
-               break;
        }
-
        if (expamem_bank_current && expamem_bank_current != &expamem_bank)
                expamem_bank_current->bput(addr, value);
 }
@@ -1842,11 +1874,11 @@ void expamem_reset (void)
        }
 
        // add possible non-autoconfig boards
-       add_cpu_expansions(1);
+       add_cpu_expansions(BOARD_NONAUTOCONFIG);
 
        bool fastmem_after = false;
        if (currprefs.fastmem_autoconfig) {
-               fastmem_after = add_fastram_after_expansion(2);
+               fastmem_after = add_fastram_after_expansion(BOARD_AUTOCONFIG_Z2);
                if (!fastmem_after && fastmem_bank.baseaddr != NULL && (fastmem_bank.allocated <= 262144 || currprefs.chipmem_size <= 2 * 1024 * 1024)) {
                        cards[cardno].flags = 0;
                        cards[cardno].name = _T("Z2Fast");
@@ -1871,8 +1903,8 @@ void expamem_reset (void)
        }
 
        // immediately after Z2Fast so that they can be emulated as A590/A2091 with fast ram.
-       add_cpu_expansions(2);
-       add_expansions(2);
+       add_cpu_expansions(BOARD_AUTOCONFIG_Z2);
+       add_expansions(BOARD_AUTOCONFIG_Z2);
 
        if (fastmem_after && currprefs.fastmem_autoconfig) {
                if (fastmem_bank.baseaddr != NULL && (fastmem_bank.allocated <= 262144 || currprefs.chipmem_size <= 2 * 1024 * 1024)) {
@@ -1964,7 +1996,7 @@ void expamem_reset (void)
        /* Z3 boards last */
        if (!currprefs.address_space_24) {
 
-               add_cpu_expansions(3);
+               add_cpu_expansions(BOARD_AUTOCONFIG_Z3);
 
                if (z3fastmem_bank.baseaddr != NULL) {
                        z3num = 0;
@@ -2004,15 +2036,15 @@ void expamem_reset (void)
                }
 #endif
 
-               add_expansions(3);
+               add_expansions(BOARD_AUTOCONFIG_Z3);
 
        }
 
-       // zorro == 1: non-autoconfig/hardwired
-       add_expansions(1);
+       add_expansions(BOARD_NONAUTOCONFIG);
 
        expamem_z3_pointer = 0;
        expamem_z3_sum = 0;
+       expamem_z2_pointer = 0;
        if (cardno == 0 || savestate_state)
                expamem_init_clear_zero ();
        else
@@ -2410,125 +2442,131 @@ const struct expansionromtype expansionroms[] = {
                NULL, 0,
                false, EXPANSIONTYPE_SCSI | EXPANSIONTYPE_IDE
        },
-       {
-               _T("cpuboard_ext"), _T("SCSI Kit IV"), _T("Blizzard"),
-               NULL, NULL, NULL, ROMTYPE_CPUBOARDEXT, ROMTYPE_CPUBOARD, 0, 0, true,
-               NULL, 0,
-               false, EXPANSIONTYPE_SCSI
-       },
        {
                _T("grex"), _T("G-REX"), _T("DCE"),
-               grex_init, NULL, NULL, ROMTYPE_GREX | ROMTYPE_NOT, 0, 0, 1, true,
-       },
-       {
-               _T("prometheus"), _T("Prometheus"), _T("Matay"),
-               prometheus_init, NULL, NULL, ROMTYPE_PROMETHEUS | ROMTYPE_NOT, 0, 0, 3, false,
+               grex_init, NULL, NULL, ROMTYPE_GREX | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG, true,
+               NULL, 0,
+               false, EXPANSIONTYPE_PCI_BRIDGE
        },
        {
                _T("mediator"), _T("Mediator"), _T("Elbox"),
-               mediator_init, mediator_init2, NULL, ROMTYPE_MEDIATOR | ROMTYPE_NOT, 0, 0, 3, false,
+               mediator_init, mediator_init2, NULL, ROMTYPE_MEDIATOR | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z3, false,
                mediator_sub, 0,
-               false, 0,
+               false, EXPANSIONTYPE_PCI_BRIDGE,
                0, 0, 0, false, NULL,
                false,
                mediator_settings
        },
        {
-               _T("a2090a"), _T("A2090a"), _T("Commodore"),
-               a2090_init, NULL, a2090_add_scsi_unit, ROMTYPE_A2090 | ROMTYPE_NONE, 0, 0, 2, false,
+               _T("prometheus"), _T("Prometheus"), _T("Matay"),
+               prometheus_init, NULL, NULL, ROMTYPE_PROMETHEUS | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z3, false,
                NULL, 0,
-               true, EXPANSIONTYPE_SCSI
-       },
-       {
-               _T("a2091"), _T("A590/A2091"), _T("Commodore"),
-               a2091_init, NULL, a2091_add_scsi_unit, ROMTYPE_A2091 | ROMTYPE_NONE, 0, 0, 2, false,
-               a2091_sub, 1,
-               true, EXPANSIONTYPE_SCSI,
-               0, 0, 0, true, NULL
+               false, EXPANSIONTYPE_PCI_BRIDGE
        },
        {
-               _T("a4091"), _T("A4091"), _T("Commodore"),
-               ncr710_a4091_autoconfig_init, NULL, a4091_add_scsi_unit, ROMTYPE_A4091, 0, 0, 3, false,
+               _T("apollo"), _T("Apollo"), _T("ACT"),
+               apollo_init_hd, NULL, apollo_add_scsi_unit, ROMTYPE_APOLLO, 0, 0, BOARD_AUTOCONFIG_Z2, false,
                NULL, 0,
-               false, EXPANSIONTYPE_SCSI,
-               0, 0, 0, false, NULL,
-               true
+               false, EXPANSIONTYPE_SCSI | EXPANSIONTYPE_IDE,
+               8738, 0, 0
        },
        {
-               _T("fastlane"), _T("Fastlane"), _T("Phase 5"),
-               ncr_fastlane_autoconfig_init, NULL, fastlane_add_scsi_unit, ROMTYPE_FASTLANE, 0, 0, 3, false,
+               _T("add500"), _T("ADD-500"), _T("Archos"),
+               add500_init, NULL, add500_add_scsi_unit, ROMTYPE_ADD500, 0, 0, BOARD_AUTOCONFIG_Z2, false,
                NULL, 0,
                false, EXPANSIONTYPE_SCSI,
-               8512, 10, 0, false, fastlane_memory_callback
-       },
-       {
-               _T("gvp1"), _T("Series I"), _T("GVP"),
-               gvp_init_s1, NULL, gvp_s1_add_scsi_unit, ROMTYPE_GVPS1 | ROMTYPE_NONE, ROMTYPE_GVPS12, 0, 2, false,
-               gvp1_sub, 1,
-               true, EXPANSIONTYPE_SCSI
+               8498, 27, 0, true, NULL
        },
        {
-               _T("gvp"), _T("Series II"), _T("GVP"),
-               gvp_init_s2, NULL, gvp_s2_add_scsi_unit, ROMTYPE_GVPS2 | ROMTYPE_NONE, ROMTYPE_GVPS12, 0, 2, false,
+               _T("blizzardscsikitiv"), _T("SCSI Kit IV"), _T("Blizzard"),
+               NULL, NULL, cpuboard_ncr9x_add_scsi_unit, ROMTYPE_BLIZKIT4, 0, 0, 0, true,
                NULL, 0,
-               true, EXPANSIONTYPE_SCSI,
-               2017, 10, 0
+               false, EXPANSIONTYPE_SCSI
        },
        {
                _T("oktagon2008"), _T("Oktagon 2008"), _T("BSC/Alfa Data"),
-               ncr_oktagon_autoconfig_init, NULL, oktagon_add_scsi_unit, ROMTYPE_OKTAGON, 0, 0, 2, false,
+               ncr_oktagon_autoconfig_init, NULL, oktagon_add_scsi_unit, ROMTYPE_OKTAGON, 0, 0, BOARD_AUTOCONFIG_Z2, false,
                NULL, 0,
                true, EXPANSIONTYPE_SCSI
        },
        {
                _T("alfapower"), _T("AlfaPower/AT-Bus 2008"), _T("BSC/Alfa Data"),
-               alf_init, NULL, alf_add_ide_unit, ROMTYPE_ALFA, 0, 0, 2, false,
+               alf_init, NULL, alf_add_ide_unit, ROMTYPE_ALFA, 0, 0, BOARD_AUTOCONFIG_Z2, false,
                NULL, 0,
                false, EXPANSIONTYPE_IDE,
                2092, 8, 0
        },
        {
                _T("alfapowerplus"), _T("AlfaPower Plus"), _T("BSC/Alfa Data"),
-               alf_init, NULL, alf_add_ide_unit, ROMTYPE_ALFAPLUS, 0, 0, 2, false,
+               alf_init, NULL, alf_add_ide_unit, ROMTYPE_ALFAPLUS, 0, 0, BOARD_AUTOCONFIG_Z2, false,
                NULL, 0,
                false, EXPANSIONTYPE_IDE,
                2092, 8, 0
        },
        {
-               _T("apollo"), _T("Apollo"), _T("ACT"),
-               apollo_init_hd, NULL, apollo_add_scsi_unit, ROMTYPE_APOLLO, 0, 0, 2, false,
+               _T("cltda1000scsi"), _T("A1000/A2000 SCSI"), _T("C-Ltd"),
+               cltda1000scsi_init, NULL, cltda1000scsi_add_scsi_unit, ROMTYPE_CLTDSCSI | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, false,
                NULL, 0,
-               false, EXPANSIONTYPE_SCSI | EXPANSIONTYPE_IDE,
-               8738, 0, 0
+               false, EXPANSIONTYPE_SCSI,
+               0, 0, 0, false, NULL,
+               false, NULL,
+               { 0xc1, 0x0c, 0x00, 0x00, 0x03, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
        },
        {
-               _T("masoboshi"), _T("MasterCard"), _T("Masoboshi"),
-               masoboshi_init, NULL, masoboshi_add_idescsi_unit, ROMTYPE_MASOBOSHI | ROMTYPE_NONE, 0, 0, 2, false,
-               masoboshi_sub, 0,
-               true, EXPANSIONTYPE_SCSI | EXPANSIONTYPE_IDE
+               _T("a2090a"), _T("A2090a"), _T("Commodore"),
+               a2090_init, NULL, a2090_add_scsi_unit, ROMTYPE_A2090 | ROMTYPE_NONE, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+               NULL, 0,
+               true, EXPANSIONTYPE_SCSI
        },
        {
-               _T("supradrive"), _T("SupraDrive"), _T("Supra"),
-               supra_init, NULL, supra_add_scsi_unit, ROMTYPE_SUPRA | ROMTYPE_NONE, 0, 0, 2, false,
-               supra_sub, 0,
+               _T("a2091"), _T("A590/A2091"), _T("Commodore"),
+               a2091_init, NULL, a2091_add_scsi_unit, ROMTYPE_A2091 | ROMTYPE_NONE, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+               a2091_sub, 1,
+               true, EXPANSIONTYPE_SCSI,
+               0, 0, 0, true, NULL
+       },
+       {
+               _T("a4091"), _T("A4091"), _T("Commodore"),
+               ncr710_a4091_autoconfig_init, NULL, a4091_add_scsi_unit, ROMTYPE_A4091, 0, 0, BOARD_AUTOCONFIG_Z3, false,
+               NULL, 0,
+               false, EXPANSIONTYPE_SCSI,
+               0, 0, 0, false, NULL,
+               true
+       },
+       {
+               _T("dataflyerscsiplus"), _T("DataFlyer SCSI+"), _T("Expansion Systems"),
+               dataflyer_init, NULL, dataflyer_add_scsi_unit, ROMTYPE_DATAFLYER | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG, true,
+               NULL, 0,
+               false, EXPANSIONTYPE_SCSI
+       },
+       {
+               _T("gvp1"), _T("Series I"), _T("GVP"),
+               gvp_init_s1, NULL, gvp_s1_add_scsi_unit, ROMTYPE_GVPS1 | ROMTYPE_NONE, ROMTYPE_GVPS12, 0, BOARD_AUTOCONFIG_Z2, false,
+               gvp1_sub, 1,
                true, EXPANSIONTYPE_SCSI
        },
        {
-               _T("golem"), _T("Golem"), _T("Kupke"),
-               golem_init, NULL, golem_add_scsi_unit, ROMTYPE_GOLEM, 0, 0, 2, false,
+               _T("gvp"), _T("Series II"), _T("GVP"),
+               gvp_init_s2, NULL, gvp_s2_add_scsi_unit, ROMTYPE_GVPS2 | ROMTYPE_NONE, ROMTYPE_GVPS12, 0, BOARD_AUTOCONFIG_Z2, false,
                NULL, 0,
                true, EXPANSIONTYPE_SCSI,
-               2079, 3, 0
+               2017, 10, 0
+       },
+       {
+               _T("vector"), _T("Vector Falcon 8000"), _T("HK-Computer"),
+               vector_init, NULL, vector_add_scsi_unit, ROMTYPE_VECTOR, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+               NULL, 0,
+               false, EXPANSIONTYPE_SCSI
        },
        {
                _T("adide"), _T("AdIDE"), _T("ICD"),
-               adide_init, NULL, adide_add_ide_unit, ROMTYPE_ADIDE | ROMTYPE_NONE, 0, 0, 2, false,
+               adide_init, NULL, adide_add_ide_unit, ROMTYPE_ADIDE | ROMTYPE_NONE, 0, 0, BOARD_AUTOCONFIG_Z2, false,
                NULL, 0,
                true, EXPANSIONTYPE_IDE
        },
        {
                _T("adscsi2000"), _T("AdSCSI Advantage 2000"), _T("ICD"),
-               adscsi_init, NULL, adscsi_add_scsi_unit, ROMTYPE_ADSCSI, 0, 0, 2, false,
+               adscsi_init, NULL, adscsi_add_scsi_unit, ROMTYPE_ADSCSI, 0, 0, BOARD_AUTOCONFIG_Z2, false,
                NULL, 0,
                false, EXPANSIONTYPE_SCSI,
                0, 0, 0, false, NULL,
@@ -2536,21 +2574,33 @@ const struct expansionromtype expansionroms[] = {
                adscsi2000_settings
        },
        {
-               _T("mtecat"), _T("AT 500"), _T("M-Tec"),
-               mtec_init, NULL, mtec_add_ide_unit, ROMTYPE_MTEC, 0, 0, 2, false,
+               _T("kommos"), _T("A500/A2000 SCSI"), _T("Jürgen Kommos"),
+               kommos_init, NULL, kommos_add_scsi_unit, ROMTYPE_KOMMOS, 0, 0, BOARD_NONAUTOCONFIG, true,
                NULL, 0,
-               true, EXPANSIONTYPE_IDE
+               false, EXPANSIONTYPE_SCSI
        },
        {
-               _T("protar"), _T("A500 HD"), _T("Protar"),
-               protar_init, NULL, protar_add_ide_unit, ROMTYPE_PROTAR, 0, 0, 2, false,
+               _T("golem"), _T("Golem"), _T("Kupke"),
+               golem_init, NULL, golem_add_scsi_unit, ROMTYPE_GOLEM, 0, 0, BOARD_AUTOCONFIG_Z2, false,
                NULL, 0,
                true, EXPANSIONTYPE_SCSI,
-               4149, 51, 0
+               2079, 3, 0
+       },
+       {
+               _T("mtecat"), _T("AT 500"), _T("M-Tec"),
+               mtec_init, NULL, mtec_add_ide_unit, ROMTYPE_MTEC, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+               NULL, 0,
+               true, EXPANSIONTYPE_IDE
+       },
+       {
+               _T("masoboshi"), _T("MasterCard"), _T("Masoboshi"),
+               masoboshi_init, NULL, masoboshi_add_idescsi_unit, ROMTYPE_MASOBOSHI | ROMTYPE_NONE, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+               masoboshi_sub, 0,
+               true, EXPANSIONTYPE_SCSI | EXPANSIONTYPE_IDE
        },
        {
                _T("stardrive"), _T("StarDrive"), _T("Microbotics"),
-               stardrive_init, NULL, stardrive_add_scsi_unit, ROMTYPE_STARDRIVE | ROMTYPE_NOT, 0, 0, 2, true,
+               stardrive_init, NULL, stardrive_add_scsi_unit, ROMTYPE_STARDRIVE | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, true,
                NULL, 0,
                false, EXPANSIONTYPE_SCSI,
                1010, 0, 0, false, NULL,
@@ -2559,54 +2609,60 @@ const struct expansionromtype expansionroms[] = {
 
        },
        {
-               _T("kommos"), _T("A500/A2000 SCSI"), _T("Jürgen Kommos"),
-               kommos_init, NULL, kommos_add_scsi_unit, ROMTYPE_KOMMOS, 0, 0, 1, true,
+               _T("fastlane"), _T("Fastlane"), _T("Phase 5"),
+               ncr_fastlane_autoconfig_init, NULL, fastlane_add_scsi_unit, ROMTYPE_FASTLANE, 0, 0, BOARD_AUTOCONFIG_Z3, false,
                NULL, 0,
-               false, EXPANSIONTYPE_SCSI
+               false, EXPANSIONTYPE_SCSI,
+               8512, 10, 0, false, fastlane_memory_callback
        },
        {
-               _T("vector"), _T("Vector Falcon 8000"), _T("HK-Computer"),
-               vector_init, NULL, vector_add_scsi_unit, ROMTYPE_VECTOR, 0, 0, 2, false,
+               _T("ptnexus"), _T("Nexus"), _T("Preferred Technologies"),
+               ptnexus_init, NULL, ptnexus_add_scsi_unit, ROMTYPE_PTNEXUS | ROMTYPE_NONE, 0, 0, BOARD_AUTOCONFIG_Z2, false,
                NULL, 0,
-               false, EXPANSIONTYPE_SCSI
+               false, EXPANSIONTYPE_SCSI,
+               2102, 4, 0, false, nexus_memory_callback,
+               false, nexus_settings,
+               { 0xd1, 0x01, 0x00, 0x00, 0x08, 0x36, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 },
        },
        {
-               _T("add500"), _T("ADD-500"), _T("Archos"),
-               add500_init, NULL, add500_add_scsi_unit, ROMTYPE_ADD500, 0, 0, 2, false,
+               _T("protar"), _T("A500 HD"), _T("Protar"),
+               protar_init, NULL, protar_add_ide_unit, ROMTYPE_PROTAR, 0, 0, BOARD_AUTOCONFIG_Z2, false,
                NULL, 0,
-               false, EXPANSIONTYPE_SCSI,
-               8498, 27, 0, true, NULL
+               true, EXPANSIONTYPE_SCSI,
+               4149, 51, 0
        },
        {
                _T("rochard"), _T("RocHard RH800C"), _T("Roctec"),
-               rochard_init, NULL, rochard_add_idescsi_unit, ROMTYPE_ROCHARD | ROMTYPE_NONE, 0, 0, 2, false,
+               rochard_init, NULL, rochard_add_idescsi_unit, ROMTYPE_ROCHARD | ROMTYPE_NONE, 0, 0, BOARD_AUTOCONFIG_Z2, false,
                rochard_sub, 0,
                true, EXPANSIONTYPE_IDE | EXPANSIONTYPE_SCSI | EXPANSIONTYPE_IDE_PORT_DOUBLED,
                2144, 2, 0
        },
        {
-               _T("cltda1000scsi"), _T("A1000/A2000 SCSI"), _T("C-Ltd"),
-               cltda1000scsi_init, NULL, cltda1000scsi_add_scsi_unit, ROMTYPE_CLTDSCSI | ROMTYPE_NOT, 0, 0, 2, false,
+               _T("supradrive"), _T("SupraDrive"), _T("Supra Corporation"),
+               supra_init, NULL, supra_add_scsi_unit, ROMTYPE_SUPRA | ROMTYPE_NONE, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+               supra_sub, 0,
+               true, EXPANSIONTYPE_SCSI
+       },
+#if 0 /* driver is MIA, 3rd party ScottDevice driver is not enough for full implementation. */
+       {
+               _T("microforge"), _T("Hard Disk"), _T("Micro Forge"),
+               microforge_init, NULL, microforge_add_scsi_unit, ROMTYPE_MICROFORGE | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG, true,
                NULL, 0,
-               false, EXPANSIONTYPE_SCSI,
-               0, 0, 0, false, NULL,
-               false, NULL,
-               { 0xc1, 0x0c, 0x00, 0x00, 0x03, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+               false, EXPANSIONTYPE_SASI | EXPANSIONTYPE_SCSI
        },
+#endif
        {
-               _T("ptnexus"), _T("Nexus"), _T("Preferred Technologies"),
-               ptnexus_init, NULL, ptnexus_add_scsi_unit, ROMTYPE_PTNEXUS | ROMTYPE_NONE, 0, 0, 2, false,
+               _T("tecmar"), _T("T-Card/T-Disk"), _T("Tecmar"),
+               tecmar_init, NULL, tecmar_add_scsi_unit, ROMTYPE_TECMAR | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG, true,
                NULL, 0,
-               false, EXPANSIONTYPE_SCSI,
-               2102, 4, 0, false, nexus_memory_callback,
-               false, nexus_settings,
-               { 0xd1, 0x01, 0x00, 0x00, 0x08, 0x36, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 },
+               false, EXPANSIONTYPE_SASI | EXPANSIONTYPE_SCSI
        },
        {
-               _T("dataflyerscsiplus"), _T("DataFlyer SCSI+"), _T("Expansion Systems"),
-               dataflyer_init, NULL, dataflyer_add_scsi_unit, ROMTYPE_DATAFLYER | ROMTYPE_NOT, 0, 0, 1, true,
+               _T("xebec"), _T("9720H"), _T("Xebec"),
+               xebec_init, NULL, xebec_add_scsi_unit, ROMTYPE_XEBEC | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG, true,
                NULL, 0,
-               false, EXPANSIONTYPE_SCSI,
+               false, EXPANSIONTYPE_SASI | EXPANSIONTYPE_SCSI
        },
 #if 0
        {
@@ -2646,7 +2702,7 @@ static const struct cpuboardsubtype gvpboard_sub[] = {
                BOARD_MEMORY_Z2,
                8 * 1024 * 1024,
                0,
-               gvp_ide_rom_autoconfig_init, NULL, 2, 0
+               gvp_ide_rom_autoconfig_init, NULL, BOARD_AUTOCONFIG_Z2, 0
        },
        {
                _T("A3001 Series II"),
@@ -2656,7 +2712,7 @@ static const struct cpuboardsubtype gvpboard_sub[] = {
                BOARD_MEMORY_Z2,
                8 * 1024 * 1024,
                0,
-               gvp_ide_rom_autoconfig_init, gvp_ide_controller_autoconfig_init, 2, 0
+               gvp_ide_rom_autoconfig_init, gvp_ide_controller_autoconfig_init, BOARD_AUTOCONFIG_Z2, 0
        },
        {
                _T("A530"),
@@ -2666,7 +2722,7 @@ static const struct cpuboardsubtype gvpboard_sub[] = {
                BOARD_MEMORY_Z2,
                8 * 1024 * 1024,
                0,
-               gvp_init_accelerator, NULL, 2, 1,
+               gvp_init_accelerator, NULL, BOARD_AUTOCONFIG_Z2, 1,
                NULL, NULL,
                2017, 9, 0, false
        },
@@ -2678,7 +2734,7 @@ static const struct cpuboardsubtype gvpboard_sub[] = {
                BOARD_MEMORY_25BITMEM,
                128 * 1024 * 1024,
                0,
-               gvp_init_accelerator, NULL, 2, 1
+               gvp_init_accelerator, NULL, BOARD_AUTOCONFIG_Z2, 1
        },
        {
                _T("Tek Magic 2040/2060"),
@@ -2697,7 +2753,7 @@ static const struct cpuboardsubtype blizzardboard_sub[] = {
                _T("Blizzard 1230 IV"),
                _T("Blizzard1230IV"),
                ROMTYPE_CB_BLIZ1230, 0,
-               cpuboard_ncr9x_add_scsi_unit, EXPANSIONTYPE_SCSI,
+               NULL, 0,
                BOARD_MEMORY_BLIZZARD_12xx,
                256 * 1024 * 1024,
                0,
@@ -2708,7 +2764,7 @@ static const struct cpuboardsubtype blizzardboard_sub[] = {
                _T("Blizzard 1260"),
                _T("Blizzard1260"),
                ROMTYPE_CB_BLIZ1260, 0,
-               cpuboard_ncr9x_add_scsi_unit, EXPANSIONTYPE_SCSI,
+               NULL, 0,
                BOARD_MEMORY_BLIZZARD_12xx,
                256 * 1024 * 1024,
                0,
@@ -2784,7 +2840,7 @@ static const struct cpuboardsubtype warpengine_sub[] = {
                BOARD_MEMORY_HIGHMEM,
                128 * 1024 * 1024,
                0x01000000,
-               ncr710_warpengine_autoconfig_init, NULL, 3, 1
+               ncr710_warpengine_autoconfig_init, NULL, BOARD_AUTOCONFIG_Z3, 1
        },
        {
                NULL
@@ -2825,7 +2881,7 @@ static const struct cpuboardsubtype dbk_sub[] = {
                0,
                128 * 1024 * 1024,
                0,
-               ncr_dkb_autoconfig_init, NULL, 2, 0
+               ncr_dkb_autoconfig_init, NULL, BOARD_AUTOCONFIG_Z2, 0
        },
        {
                _T("Wildfire"),
@@ -2835,7 +2891,7 @@ static const struct cpuboardsubtype dbk_sub[] = {
                BOARD_MEMORY_HIGHMEM,
                128 * 1024 * 1024,
                0,
-               dkb_wildfire_pci_init, NULL, 1, 0 // fake board
+               dkb_wildfire_pci_init, NULL, BOARD_NONAUTOCONFIG, 0
        },
        {
                NULL
@@ -2905,19 +2961,9 @@ const struct cpuboardtype cpuboards[] = {
                dummy_sub, 0
        },
        {
-               BOARD_BLIZZARD,
-               _T("Phase 5 - Blizzard"),
-               blizzardboard_sub, 0
-       },
-       {
-               BOARD_CYBERSTORM,
-               _T("Phase 5 - CyberStorm"),
-               cyberstormboard_sub, 0
-       },
-       {
-               BOARD_MACROSYSTEM,
-               _T("MacroSystem"),
-               warpengine_sub, 0
+               BOARD_ACT,
+               _T("ACT"),
+               apollo_sub, 0
        },
        {
                BOARD_COMMODORE,
@@ -2929,16 +2975,6 @@ const struct cpuboardtype cpuboards[] = {
                _T("DKB"),
                dbk_sub, 0
        },
-       {
-               BOARD_RCS,
-               _T("RCS Management"),
-               fusionforty_sub, 0
-       },
-       {
-               BOARD_ACT,
-               _T("ACT"),
-               apollo_sub, 0
-       },
        {
                BOARD_GVP,
                _T("GVP"),
@@ -2949,6 +2985,26 @@ const struct cpuboardtype cpuboards[] = {
                _T("Kupke"),
                kupkeboard_sub, 0
        },
+       {
+               BOARD_MACROSYSTEM,
+               _T("MacroSystem"),
+               warpengine_sub, 0
+       },
+       {
+               BOARD_BLIZZARD,
+               _T("Phase 5 - Blizzard"),
+               blizzardboard_sub, 0
+       },
+       {
+               BOARD_CYBERSTORM,
+               _T("Phase 5 - CyberStorm"),
+               cyberstormboard_sub, 0
+       },
+       {
+               BOARD_RCS,
+               _T("RCS Management"),
+               fusionforty_sub, 0
+       },
 #if 0
        {
                BOARD_IC,
index cc3613130698cf1645aca22a48413609ecbe4ce8..afc8d7390a79369124fb170db0b586f5373fdbda 100644 (file)
@@ -28,6 +28,7 @@
 #include "execio.h"
 #include "zfile.h"
 #include "ide.h"
+#include "debug.h"
 
 #ifdef WITH_CHD
 #include "archivers/chd/chdtypes.h"
@@ -1138,6 +1139,18 @@ static void setdrivestring(const TCHAR *s, uae_u8 *d, int start, int length)
        xfree (ss);
 }
 
+static const uae_u8 sasi_commands[] =
+{
+       0x00, 0x01, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x12,
+       0xe0, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+       0xff
+};
+static const uae_u8 sasi_commands2[] =
+{
+       0x12,
+       0xff
+};
+
 int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, uae_u8 *cmdbuf, int scsi_cmd_len,
        uae_u8 *scsi_data, int *data_len, uae_u8 *r, int *reply_len, uae_u8 *s, int *sense_len)
 {
@@ -1147,6 +1160,8 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua
        int status = 0;
        int lun;
        uae_u8 cmd = cmdbuf[0];
+       bool sasi = hfd->ci.unit_feature_level >= HD_LEVEL_SASI;
+       bool sasie = hfd->ci.unit_feature_level == HD_LEVEL_SASI_ENHANCED;
 
        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,
@@ -1168,6 +1183,8 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua
 
        *reply_len = *sense_len = 0;
        lun = cmdbuf[1] >> 5;
+       if (sasi)
+               lun = 0;
        if (cmd != 0x03 && cmd != 0x12 && lun) {
                status = 2; /* CHECK CONDITION */
                s[0] = 0x70;
@@ -1178,6 +1195,55 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua
                goto scsi_done;
        }
 
+       if (sasi) {
+               int i;
+               for (i = 0; sasi_commands[i] != 0xff; i++) {
+                       if (sasi_commands[i] == cmdbuf[0])
+                               break;
+               }
+               if (sasi_commands[i] == 0xff) {
+                       if (sasie) {
+                               for (i = 0; sasi_commands2[i] != 0xff; i++) {
+                                       if (sasi_commands2[i] == cmdbuf[0])
+                                               break;
+                               }
+                               if (sasi_commands2[i] == 0xff)
+                                       goto errreq;
+                       } else {
+                               goto errreq;
+                       }
+               }
+               switch (cmdbuf[0])
+               {
+                       case 0x0c: /* INITIALIZE DRIVE CHARACTERICS */
+                       scsi_len = 8;
+                       goto scsi_done;
+                       case 0x12: /* INQUIRY */
+                       {
+                               int cyl, cylsec, head, tracksec;
+                               int alen = cmdbuf[4];
+                               if (nodisk(hfd))
+                                       goto nodisk;
+                               if (hdhfd) {
+                                       cyl = hdhfd->cyls;
+                                       head = hdhfd->heads;
+                                       tracksec = hdhfd->secspertrack;
+                                       cylsec = 0;
+                               } else {
+                                       getchsx(hfd, &cyl, &cylsec, &head, &tracksec);
+                               }
+                               r[0] = 0;
+                               r[1] = 11;
+                               r[9] = cyl >> 8;
+                               r[10] = cyl;
+                               r[11] = head;
+                               scsi_len = lr = alen > 12 ? 12 : alen;
+                               goto scsi_done;
+                       }
+                       break;
+               }
+       }
+
        switch (cmdbuf[0])
        {
        case 0x12: /* INQUIRY */
@@ -1245,6 +1311,15 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua
                        goto readprot;
                scsi_len = 0;
                break;
+       case 0x09: /* READ VERIFY */
+               if (nodisk(hfd))
+                       goto nodisk;
+               offset = ((cmdbuf[1] & 31) << 16) | (cmdbuf[2] << 8) | cmdbuf[3];
+               offset *= hfd->ci.blocksize;
+               if (!checkbounds(hfd, offset, hfd->ci.blocksize))
+                       goto outofbounds;
+               scsi_len = 0;
+               break;
        case 0x0b: /* SEEK (6) */
                if (nodisk (hfd))
                        goto nodisk;
@@ -1267,6 +1342,9 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua
                        goto outofbounds;
                scsi_len = (uae_u32)cmd_readx (hfd, scsi_data, offset, len);
                break;
+       case 0x0f: /* WRITE SECTOR BUFFER */
+               scsi_len = hfd->ci.blocksize;
+               break;
        case 0x0a: /* WRITE (6) */
                if (nodisk (hfd))
                        goto nodisk;
@@ -1493,6 +1571,11 @@ int scsi_hd_emulate (struct hardfiledata *hfd, struct hd_hardfiledata *hdhfd, ua
                ls = 0x12;
 #endif
                break;
+               case 0xe0: /* RAM DIAGNOSTICS */
+               case 0xe3: /* DRIVE DIAGNOSTIC */
+               case 0xe4: /* CONTROLLER INTERNAL DIAGNOSTICS */
+               scsi_len = 0;
+               break;
 readprot:
                status = 2; /* CHECK CONDITION */
                s[0] = 0x70;
index 65e1ab4f611f600a6087c11448594c4ab26d2b65..98c048dadec2490edc4874053facae0634718ade 100644 (file)
@@ -111,6 +111,8 @@ typedef void(*DEVICE_MEMORY_CALLBACK)(struct romconfig*, uae_u8*, int);
 #define EXPANSIONTYPE_IDE 2
 #define EXPANSIONTYPE_24BIT 4
 #define EXPANSIONTYPE_IDE_PORT_DOUBLED 8
+#define EXPANSIONTYPE_SASI 16
+#define EXPANSIONTYPE_PCI_BRIDGE 32
 struct expansionboardsettings
 {
        const TCHAR *name;
index 358c900e3e8791aa81223e2aef4ec76db9019e0a..1c648db39d931647070db85dfc8bfcd22c3b06d7 100644 (file)
@@ -200,3 +200,12 @@ void ptnexus_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconf
 
 addrbank *dataflyer_init(struct romconfig *rc);
 void dataflyer_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
+
+addrbank *tecmar_init(struct romconfig *rc);
+void tecmar_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
+
+addrbank *xebec_init(struct romconfig *rc);
+void xebec_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
+
+addrbank *microforge_init(struct romconfig *rc);
+void microforge_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
index 9e19df30411e1b0ee87976aebff85b908549de06..03b1af91285f16d7ca182e4e7c71b62f1e58ac00 100644 (file)
--- a/scsi.cpp
+++ b/scsi.cpp
 #define NCR5380_CLTD 12
 #define NCR5380_PTNEXUS 13
 #define NCR5380_DATAFLYER 14
-#define NCR_LAST 15
+#define NONCR_TECMAR 15
+#define NCR5380_XEBEC 16
+#define NONCR_MICROFORGE 17
+#define NCR_LAST 18
 
 extern int log_scsiemu;
 
-static const int outcmd[] = { 0x04, 0x0a, 0x2a, 0xaa, 0x15, 0x55, -1 };
+static const int outcmd[] = { 0x04, 0x0a, 0x0c, 0x2a, 0xaa, 0x15, 0x55, 0x0f, -1 };
 static const int incmd[] = { 0x01, 0x03, 0x05, 0x08, 0x12, 0x1a, 0x5a, 0x25, 0x28, 0x34, 0x37, 0x42, 0x43, 0xa8, 0x51, 0x52, 0xbd, -1 };
-static const int nonecmd[] = { 0x00, 0x0b, 0x11, 0x16, 0x17, 0x19, 0x1b, 0x1e, 0x2b, 0x35, -1 };
+static const int nonecmd[] = { 0x00, 0x09, 0x0b, 0x11, 0x16, 0x17, 0x19, 0x1b, 0x1e, 0x2b, 0x35, 0xe0, 0xe3, 0xe4, -1 };
 static const int scsicmdsizes[] = { 6, 10, 10, 12, 16, 12, 10, 10 };
 
 static void scsi_illegal_command(struct scsi_data *sd)
@@ -127,6 +130,9 @@ bool scsi_emulate_analyze (struct scsi_data *sd)
                        return true;
                }
        break;
+       case 0x0c: // INITIALIZE DRIVE CHARACTERICS (SASI)
+               data_len = 8;
+       break;
        case 0x08: // READ(6)
                data_len2 = sd->cmd[4] * sd->blocksize;
                scsi_grow_buffer(sd, data_len2);
@@ -139,6 +145,10 @@ bool scsi_emulate_analyze (struct scsi_data *sd)
                data_len2 = ((sd->cmd[6] << 24) | (sd->cmd[7] << 16) | (sd->cmd[8] << 8) | (sd->cmd[9] << 0)) * (uae_s64)sd->blocksize;
                scsi_grow_buffer(sd, data_len2);
        break;
+       case 0x0f: // WRITE SECTOR BUFFER
+               data_len = sd->blocksize;
+               scsi_grow_buffer(sd, data_len);
+       break;
        case 0x0a: // WRITE(6)
                if (sd->device_type == UAEDEV_CD)
                        goto nocmd;
@@ -614,6 +624,7 @@ struct soft_scsi
        struct raw_scsi rscsi;
        bool irq;
        bool intena;
+       bool level6;
        bool enabled;
        bool delayed_irq;
        bool configured;
@@ -648,6 +659,10 @@ struct soft_scsi
        int databuffer_size;
        int db_read_index;
        int db_write_index;
+
+       // sasi
+       bool active_select;
+       bool wait_select;
 };
 
 
@@ -729,6 +744,8 @@ static struct soft_scsi *getscsiboard(uaecptr addr)
                        return s;
                if (s->baseaddress2 && (addr & ~s->board_mask) == s->baseaddress2)
                        return s;
+               if (s->baseaddress == 0xe80000 && addr < 65536)
+                       return s;
        }
        return NULL;
 }
@@ -1198,10 +1215,24 @@ static void supra_do_dma(struct soft_scsi *ncr)
        }
 }
 
+static void xebec_do_dma(struct soft_scsi *ncr)
+{
+       struct raw_scsi *rs = &ncr->rscsi;
+       while (rs->bus_phase == SCSI_SIGNAL_PHASE_DATA_OUT || rs->bus_phase == SCSI_SIGNAL_PHASE_DATA_IN) {
+               if (rs->bus_phase == SCSI_SIGNAL_PHASE_DATA_IN) {
+                       x_put_byte(ncr->dmac_address, ncr5380_bget(ncr, 8));
+               } else if (rs->bus_phase == SCSI_SIGNAL_PHASE_DATA_OUT) {
+                       ncr5380_bput(ncr, 8, x_get_byte(ncr->dmac_address));
+               }
+       }
+}
+
+
 static void dma_check(struct soft_scsi *ncr)
 {
        if (ncr->dmac_active && ncr->dma_direction) {
-               if (ncr->type ==NCR5380_SUPRA && ncr->subtype == 4) {
+
+               if (ncr->type == NCR5380_SUPRA && ncr->subtype == 4) {
                        if (ncr->dmac_direction != ncr->dma_direction)  {
                                write_log(_T("SUPRADMA: mismatched direction\n"));
                                ncr->dmac_active = 0;
@@ -1209,6 +1240,12 @@ static void dma_check(struct soft_scsi *ncr)
                        }
                        supra_do_dma(ncr);
                }
+
+               if (ncr->type == NCR5380_XEBEC) {
+               
+                       xebec_do_dma(ncr);
+
+               }
                ncr->dmac_active = 0;
        }
 }
@@ -1219,7 +1256,10 @@ void ncr80_rethink(void)
 {
        for (int i = 0; soft_scsi_devices[i]; i++) {
                if (soft_scsi_devices[i]->irq && soft_scsi_devices[i]->intena) {
-                       INTREQ_0(0x8000 | 0x0008);
+                       if (soft_scsi_devices[i]->level6)
+                               INTREQ_0(0x8000 | 0x2000);
+                       else
+                               INTREQ_0(0x8000 | 0x0008);
                        return;
                }
        }
@@ -1319,6 +1359,15 @@ uae_u8 ncr5380_bget(struct soft_scsi *scsi, int reg)
                        if (scsi->dma_active && !scsi->dma_controller) {
                                v |= 1 << 6;
                        }
+                       if (scsi->regs[2] & 4) {
+                               // monitor busy
+                               if (r->bus_phase == SCSI_SIGNAL_PHASE_FREE) {
+                                       // any loss of busy = Busy error
+                                       // not just "unexpected" loss of busy
+                                       v |= 1 << 2;
+                                       scsi->dmac_active = false;
+                               }
+                       }
                }
                break;
                case 0:
@@ -1344,6 +1393,7 @@ void ncr5380_bput(struct soft_scsi *scsi, int reg, uae_u8 v)
 {
        if (reg > 8)
                return;
+       bool dataoutput = (scsi->regs[1] & 1) != 0;
        struct raw_scsi *r = &scsi->rscsi;
        uae_u8 old = scsi->regs[reg];
        scsi->regs[reg] = v;
@@ -1363,20 +1413,25 @@ void ncr5380_bput(struct soft_scsi *scsi, int reg, uae_u8 v)
                }
                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;
-                       ncr5380_databusoutput(scsi);
-                       raw_scsi_set_signal_phase(r,
-                               (v & (1 << 3)) != 0,
-                               (v & (1 << 2)) != 0,
-                               (v & (1 << 1)) != 0);
-                       if (!(scsi->regs[2] & 2))
-                               raw_scsi_set_ack(r, (v & (1 << 4)) != 0);
-               }
-               if (v & 0x80) { // RST
-                       ncr5380_reset(scsi);
+               {
+                       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;
+                               ncr5380_databusoutput(scsi);
+                               if (init && !dataoutput && (v & 1) && (scsi->regs[2] & 1)) {
+                                       r->bus_phase = SCSI_SIGNAL_PHASE_SELECT_1;
+                               }
+                               raw_scsi_set_signal_phase(r,
+                                       (v & (1 << 3)) != 0,
+                                       (v & (1 << 2)) != 0,
+                                       (v & (1 << 1)) != 0);
+                               if (!(scsi->regs[2] & 2))
+                                       raw_scsi_set_ack(r, (v & (1 << 4)) != 0);
+                       }
+                       if (v & 0x80) { // RST
+                               ncr5380_reset(scsi);
+                       }
                }
                break;
                case 2:
@@ -1403,7 +1458,7 @@ void ncr5380_bput(struct soft_scsi *scsi, int reg, uae_u8 v)
                        dma_check(scsi);
                }
 #if NCR5380_DEBUG
-               write_log(_T("DMA send\n"));
+               write_log(_T("DMA send PC=%08x\n"), M68K_GETPC);
 #endif
                break;
                case 6:
@@ -1412,7 +1467,7 @@ void ncr5380_bput(struct soft_scsi *scsi, int reg, uae_u8 v)
                        scsi->dma_active = true;
                }
 #if NCR5380_DEBUG
-               write_log(_T("DMA target recv\n"));
+               write_log(_T("DMA target recv PC=%08x\n"), M68K_GETPC);
 #endif
                break;
                case 7:
@@ -1422,7 +1477,7 @@ void ncr5380_bput(struct soft_scsi *scsi, int reg, uae_u8 v)
                        dma_check(scsi);
                }
 #if NCR5380_DEBUG
-               write_log(_T("DMA initiator recv\n"));
+               write_log(_T("DMA initiator recv PC=%08x\n"), M68K_GETPC);
 #endif
                break;
                case 8: // fake dma port
@@ -1523,6 +1578,143 @@ static void ncr53400_bput(struct soft_scsi *scsi, int reg, uae_u8 v)
        ncr5380_check_phase(scsi);
 }
 
+/* SASI */
+
+static uae_u8 sasi_tecmar_bget(struct soft_scsi *scsi, int reg)
+{
+       struct raw_scsi *rs = &scsi->rscsi;
+       uae_u8 v = 0;
+
+       if (reg == 1) {
+
+               uae_u8 t = raw_scsi_get_signal_phase(rs);
+               v = 0;
+               switch (rs->bus_phase)
+               {
+                       case SCSI_SIGNAL_PHASE_DATA_OUT:
+                       v = 0;
+                       break;
+                       case SCSI_SIGNAL_PHASE_DATA_IN:
+                       v = 1 << 2;
+                       break;
+                       case SCSI_SIGNAL_PHASE_COMMAND:
+                       v = 1 << 3;
+                       break;
+                       case SCSI_SIGNAL_PHASE_STATUS:
+                       v = (1 << 2) | (1 << 3);
+                       break;
+                       case SCSI_SIGNAL_PHASE_MESSAGE_IN:
+                       v = (1 << 2) | (1 << 3) | (1 << 4);
+                       break;
+               }
+               if (t & SCSI_IO_BUSY)
+                       v |= 1 << 1;
+               if (t & SCSI_IO_REQ)
+                       v |= 1 << 0;
+               v = v ^ 0xff;
+
+       } else {
+
+               v = raw_scsi_get_data_2(rs, true, false);
+
+       }
+
+       //write_log(_T("SASI READ port %d: %02x\n"), reg, v);
+
+       return v;
+}
+
+static void sasi_tecmar_bput(struct soft_scsi *scsi, int reg, uae_u8 v)
+{
+       struct raw_scsi *rs = &scsi->rscsi;
+
+       //write_log(_T("SASI WRITE port %d: %02x\n"), reg, v);
+
+       if (reg == 1) {
+               if ((v & 1)) {
+                       raw_scsi_busfree(rs);
+               }
+               if ((v & 2) && !scsi->active_select) {
+                       // select?
+                       scsi->active_select = true;
+                       if (!rs->data_write)
+                               scsi->wait_select = true;
+                       else
+                               raw_scsi_set_signal_phase(rs, false, true, false);
+               } else if (!(v & 2) && scsi->active_select) {
+                       scsi->active_select = false;
+                       raw_scsi_set_signal_phase(rs, false, false, false);
+               }
+       } else {
+               raw_scsi_put_data(rs, v, true);
+               if (scsi->wait_select && scsi->active_select)
+                       raw_scsi_set_signal_phase(rs, false, true, false);
+               scsi->wait_select = false;
+       }
+}
+
+static uae_u8 sasi_microforge_bget(struct soft_scsi *scsi, int reg)
+{
+       struct raw_scsi *rs = &scsi->rscsi;
+       uae_u8 v = 0;
+
+       if (reg == 1) {
+
+               uae_u8 t = raw_scsi_get_signal_phase(rs);
+               v = 0;
+               if (rs->bus_phase >= 0) {
+                       if (rs->bus_phase & SCSI_IO_MESSAGE)
+                               v |= 1 << 1;
+                       if (rs->bus_phase & SCSI_IO_COMMAND)
+                               v |= 1 << 2;
+                       if (rs->bus_phase & SCSI_IO_DIRECTION)
+                               v |= 1 << 3;
+               }
+               if (t & SCSI_IO_BUSY)
+                       v |= 1 << 0;
+               if (t & SCSI_IO_REQ)
+                       v |= 1 << 4;
+               v = v ^ 0xff;
+
+       }
+       else {
+
+               v = raw_scsi_get_data_2(rs, true, false);
+
+       }
+
+       //write_log(_T("SASI READ port %d: %02x\n"), reg, v);
+
+       return v;
+}
+
+static void sasi_microforge_bput(struct soft_scsi *scsi, int reg, uae_u8 v)
+{
+       struct raw_scsi *rs = &scsi->rscsi;
+
+       //write_log(_T("SASI WRITE port %d: %02x\n"), reg, v);
+
+       if (reg == 1) {
+               if ((v & 4) && !scsi->active_select) {
+                       // select?
+                       scsi->active_select = true;
+                       if (!rs->data_write)
+                               scsi->wait_select = true;
+                       else
+                               raw_scsi_set_signal_phase(rs, false, true, false);
+               } else if (!(v & 4) && scsi->active_select) {
+                       scsi->active_select = false;
+                       raw_scsi_set_signal_phase(rs, false, false, false);
+               }
+       }
+       else {
+               raw_scsi_put_data(rs, v, true);
+               if (scsi->wait_select && scsi->active_select)
+                       raw_scsi_set_signal_phase(rs, false, true, false);
+               scsi->wait_select = false;
+       }
+}
+
 static int suprareg(struct soft_scsi *ncr, uaecptr addr, bool write)
 {
        int reg = (addr & 0x0f) >> 1;
@@ -1601,6 +1793,52 @@ static int ptnexusreg(struct soft_scsi *ncr, uaecptr addr)
        return reg;
 }
 
+static int xebec_reg(struct soft_scsi *ncr, uaecptr addr)
+{
+       if (addr < 0x10000) {
+               if (addr & 1)
+                       return (addr & 0xff) >> 1;
+               return -1;
+       }
+       if ((addr & 0x180000) == 0x100000) {
+               
+               ncr->dmac_active = 1;
+
+       } else if ((addr & 0x180000) == 0x180000) {
+
+               ncr->dmac_active = 0;
+               ncr->dmac_address = ncr->baseaddress | 0x80000;
+
+       } else if ((addr & 0x180000) == 0x080000) {
+               ncr->dmac_address = addr | ncr->baseaddress | 1;
+               ncr->dmac_address += 2;
+               if (addr & 1)
+                       return 0x80000 + (addr & 32767);
+               return -1;
+       }
+
+//     if (addr >= 0x10000)
+//             write_log(_T("XEBEC %08x PC=%08x\n"), addr, M68K_GETPC);
+       return -1;
+}
+
+
+static int microforge_reg(struct soft_scsi *ncr, uaecptr addr, bool write)
+{
+       int reg = -1;
+       if ((addr & 0x7000) != 0x7000)
+               return -1;
+       addr &= 0xfff;
+       if (addr == 38 && !write)
+               return 0;
+       if (addr == 40 && write)
+               return 0;
+       if (addr == 42 && !write)
+               return 1;
+       if (addr == 44 && write)
+               return 1;
+       return reg;
+}
 
 static uae_u8 read_supra_dma(struct soft_scsi *ncr, uaecptr addr)
 {
@@ -1667,13 +1905,81 @@ static void vector_scsi_status(struct raw_scsi *rs)
        }
 }
 
+static int tecmar_clock_reg_select;
+static uae_u8 tecmar_clock_regs[64];
+static uae_u8 tecmar_clock_bcd(uae_u8 v)
+{
+       uae_u8 out = v;
+       if (!(tecmar_clock_regs[11] & 4)) {
+               out = ((v / 10) << 4) + (v % 10);
+       }
+       return out;
+}
+static void tecmar_clock_bput(int addr, uae_u8 v)
+{
+       if (addr == 0) {
+               tecmar_clock_reg_select = v & 63;
+       }
+       else if (addr == 1) {
+               tecmar_clock_regs[tecmar_clock_reg_select] = v;
+               tecmar_clock_regs[12] = 0x00;
+               tecmar_clock_regs[13] = 0x80;
+       }
+}
+static uae_u8 tecmar_clock_bget(int addr)
+{
+       uae_u8 v = 0;
+       if (addr == 0) {
+               v = tecmar_clock_reg_select;
+       }
+       else if (addr == 1) {
+               time_t t = time(0);
+               t += currprefs.cs_rtc_adjust;
+               struct tm *ct = localtime(&t);
+               switch (tecmar_clock_reg_select)
+               {
+                       case 0:
+                       v = tecmar_clock_bcd(ct->tm_sec);
+                       break;
+                       case 2:
+                       v = tecmar_clock_bcd(ct->tm_min);
+                       break;
+                       case 4:
+                       v = tecmar_clock_bcd(ct->tm_hour);
+                       if (!(tecmar_clock_regs[11] & 2)) {
+                               if (v >= 12) {
+                                       v -= 12;
+                                       v |= 0x80;
+                               }
+                               v++;
+                       }
+                       break;
+                       case 6:
+                       v = tecmar_clock_bcd(ct->tm_wday + 1);
+                       break;
+                       case 7:
+                       v = tecmar_clock_bcd(ct->tm_mday);
+                       break;
+                       case 8:
+                       v = tecmar_clock_bcd(ct->tm_mon + 1);
+                       break;
+                       case 9:
+                       v = tecmar_clock_bcd(ct->tm_year % 100);
+                       break;
+                       default:
+                       v = tecmar_clock_regs[tecmar_clock_reg_select];
+                       break;
+               }
+       }
+       return v;
+}
 
 static uae_u32 ncr80_bget2(struct soft_scsi *ncr, uaecptr addr, int size)
 {
        int reg = -1;
        uae_u32 v = 0;
        int addresstype = -1;
-       uaecptr origddr = addr;
+       uaecptr origaddr = addr;
 
        addr &= ncr->board_mask;
 
@@ -1801,7 +2107,7 @@ static uae_u32 ncr80_bget2(struct soft_scsi *ncr, uaecptr addr, int size)
                struct raw_scsi *rs = &ncr->rscsi;
                if (addr & 0x8000) {
                        v = ncr->rom[addr & 0x7fff];
-               } else if ((origddr & 0xf00000) != 0xf00000) {
+               } else if ((origaddr & 0xf00000) != 0xf00000) {
                        if (!(addr & 8)) {
                                v = raw_scsi_get_data(rs, true);
                        } else {
@@ -1961,11 +2267,41 @@ static uae_u32 ncr80_bget2(struct soft_scsi *ncr, uaecptr addr, int size)
                reg = addr & 0xff;
                v = ncr5380_bget(ncr, reg);
 
+       } else if (ncr->type == NONCR_TECMAR) {
+
+               v = ncr->rom[addr];
+               if (addr >= 0x2000 && addr < 0x3000) {
+                       if (addr == 0x2040)
+                               v = tecmar_clock_bget(0);
+                       else if (addr == 0x2042)
+                               v = tecmar_clock_bget(1);
+               } else if (addr >= 0x4000 && addr < 0x5000) {
+                       if (addr == 0x4040)
+                               v = sasi_tecmar_bget(ncr, 1);
+                       else if (addr == 0x4042)
+                               v = sasi_tecmar_bget(ncr, 0);
+               }
+
+       } else if (ncr->type == NCR5380_XEBEC) {
+
+               reg = xebec_reg(ncr, addr);
+               if (reg >= 0 && reg < 8) {
+                       v = ncr5380_bget(ncr, reg);
+               } else if (reg >= 0x80000) {
+                       v = ncr->databufferptr[reg & (ncr->databuffer_size - 1)];
+               }
+
+       } else if (ncr->type == NONCR_MICROFORGE) {
+
+               reg = microforge_reg(ncr, addr, false);
+               if (reg >= 0)
+                       v = sasi_microforge_bget(ncr, reg);
+
        }
 
 #if NCR5380_DEBUG > 1
        //if (addr >= 0x8000)
-               write_log(_T("GET %08x %02x %d %08x %d\n"), addr, v, reg, M68K_GETPC, regs.intmask);
+               write_log(_T("GET %08x %02x %d %08x %d\n"), origaddr, v, reg, M68K_GETPC, regs.intmask);
 #endif
 
        return v;
@@ -2131,10 +2467,54 @@ static void ncr80_bput2(struct soft_scsi *ncr, uaecptr addr, uae_u32 val, int si
                reg = addr & 0xff;
                ncr5380_bput(ncr, reg, val);
 
+       } else if (ncr->type == NONCR_TECMAR) {
+
+               if (addr == 0x22) {
+                       // box
+                       ncr->baseaddress = 0xe80000 + ((val & 0x7f) * 4096);
+                       map_banks_z2(ncr->bank, ncr->baseaddress >> 16, 1);
+                       expamem_next(ncr->bank, NULL);
+               } else if (addr == 0x1020) {
+                       // memory board control/status
+                       ncr->rom[addr] = val & (0x80 | 0x40 | 0x02);
+               } else if (addr == 0x1024) {
+                       // memory board memory address reg
+                       if (currprefs.fastmem2_size)
+                               map_banks_z2(&fastmem2_bank, val, currprefs.fastmem2_size >> 16);
+               }
+               else if (addr >= 0x2000 && addr < 0x3000) {
+                       // clock
+                       if (addr == 0x2040)
+                               tecmar_clock_bput(0, val);
+                       else if (addr == 0x2042)
+                               tecmar_clock_bput(1, val);
+               } else if (addr >= 0x4000 && addr < 0x5000) {
+                       // sasi
+                       if (addr == 0x4040)
+                               sasi_tecmar_bput(ncr, 1, val);
+                       else if (addr == 0x4042)
+                               sasi_tecmar_bput(ncr, 0, val);
+               }
+
+       } else if (ncr->type == NCR5380_XEBEC) {
+
+               reg = xebec_reg(ncr, addr);
+               if (reg >= 0 && reg < 8) {
+                       ncr5380_bput(ncr, reg, val);
+               } else if (reg >= 0x80000) {
+                       ncr->databufferptr[reg & (ncr->databuffer_size - 1)] = val;
+               }
+
+       } else if (ncr->type == NONCR_MICROFORGE) {
+
+               reg = microforge_reg(ncr, addr, true);
+               if (reg >= 0)
+                       sasi_microforge_bput(ncr, reg, val);
+
        }
 
 #if NCR5380_DEBUG > 1
-       write_log(_T("PUT %08x %02x %d %08x %d\n"), addr, val, reg, M68K_GETPC, regs.intmask);
+       write_log(_T("PUT %08x %02x %d %08x %d\n"), origddr, val, reg, M68K_GETPC, regs.intmask);
 #endif
 }
 
@@ -2639,6 +3019,133 @@ void dataflyer_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romco
        generic_soft_scsi_add(ch, ci, rc, NCR5380_DATAFLYER, 4096, 0, ROMTYPE_DATAFLYER);
 }
 
+static void expansion_add_protoautoconfig_data(uae_u8 *p, uae_u16 manufacturer_id, uae_u8 product_id)
+{
+       memset(p, 0, 4096);
+       p[0x02] = product_id;
+       p[0x08] = manufacturer_id >> 8;
+       p[0x0a] = manufacturer_id;
+}
+
+static void expansion_add_protoautoconfig_box(uae_u8 *p, int box_size, uae_u16 manufacturer_id, uae_u8 product_id)
+{
+       expansion_add_protoautoconfig_data(p, manufacturer_id, product_id);
+       // "box without init/diagnostics code"
+       p[0] = 0x40 | (box_size << 3);
+}
+static void expansion_add_protoautoconfig_board(uae_u8 *p, int board, uae_u16 manufacturer_id, uae_u8 product_id, int memorysize)
+{
+       p += (board + 1) * 4096;
+       expansion_add_protoautoconfig_data(p, manufacturer_id, product_id);
+       // "board without init/diagnostic code"
+       p[0] = 0x08;
+       if (memorysize) {
+               int v = 0;
+               switch (memorysize)
+               {
+                       case 64 * 1024:
+                       v = 1;
+                       break;
+                       case 128 * 1024:
+                       v = 2;
+                       break;
+                       case 256 * 1024:
+                       v = 3;
+                       break;
+                       case 512 * 1024:
+                       v = 4;
+                       break;
+                       case 1024 * 1024:
+                       v = 5;
+                       break;
+                       case 2048 * 1024:
+                       v = 6;
+                       break;
+                       case 4096 * 1024:
+                       default:
+                       v = 7;
+                       break;
+               }
+               p[0] |= v;
+       }
+}
+
+addrbank *tecmar_init(struct romconfig *rc)
+{
+       struct soft_scsi *scsi = getscsi(rc);
+       int index = 0;
+
+       if (!scsi)
+               return &expamem_null;
+
+       const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_PTNEXUS);
+       scsi->rom = xcalloc(uae_u8, 65536);
+       expansion_add_protoautoconfig_box(scsi->rom, 3, 1001, 0);
+       // memory
+       expansion_add_protoautoconfig_board(scsi->rom, index++, 1001, 1, currprefs.fastmem2_size);
+       // clock
+       expansion_add_protoautoconfig_board(scsi->rom, index++, 1001, 2, 0);
+       // serial
+       expansion_add_protoautoconfig_board(scsi->rom, index++, 1001, 3, 0);
+       // parallel
+       expansion_add_protoautoconfig_board(scsi->rom, index++, 1001, 4, 0);
+       // sasi
+       expansion_add_protoautoconfig_board(scsi->rom, index++, 1001, 4, 0);
+       memset(tecmar_clock_regs, 0, sizeof tecmar_clock_regs);
+       tecmar_clock_regs[11] = 0x04 | 0x02 | 0x01;
+       scsi->configured = true;
+       scsi->baseaddress = 0xe80000;
+       return scsi->bank;
+}
+
+void tecmar_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+       generic_soft_scsi_add(ch, ci, rc, NONCR_TECMAR, 65536, 65536, ROMTYPE_TECMAR);
+}
+
+addrbank *microforge_init(struct romconfig *rc)
+{
+       struct soft_scsi *scsi = getscsi(rc);
+
+       if (!scsi)
+               return NULL;
+
+       scsi->configured = 1;
+
+       map_banks(scsi->bank, 0xef0000 >> 16, 0x10000 >> 16, 0);
+       scsi->baseaddress = 0xef0000;
+       return NULL;
+}
+
+void microforge_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+       generic_soft_scsi_add(ch, ci, rc, NONCR_MICROFORGE, 65536, 0, ROMTYPE_MICROFORGE);
+}
+
+addrbank *xebec_init(struct romconfig *rc)
+{
+       struct soft_scsi *scsi = getscsi(rc);
+
+       if (!scsi)
+               return NULL;
+
+       scsi->configured = 1;
+
+       map_banks(scsi->bank, 0x600000 >> 16, (0x800000 - 0x600000) >> 16, 0);
+       scsi->board_mask = 0x1fffff;
+       scsi->baseaddress = 0x600000;
+       scsi->level6 = true;
+       scsi->intena = true;
+       scsi->dma_controller = true;
+       scsi->databuffer_size = 32768;
+       scsi->databufferptr = xcalloc(uae_u8, scsi->databuffer_size);
+       return NULL;
+}
+
+void xebec_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
+{
+       generic_soft_scsi_add(ch, ci, rc, NCR5380_XEBEC, 65536, 0, ROMTYPE_XEBEC);
+}
 
 void soft_scsi_free(void)
 {