]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Ethernet emulation updates.
authorToni Wilen <twilen@winuae.net>
Fri, 21 Oct 2016 15:58:15 +0000 (18:58 +0300)
committerToni Wilen <twilen@winuae.net>
Fri, 21 Oct 2016 15:58:15 +0000 (18:58 +0300)
a2065.cpp
devices.cpp
ethernet.cpp
expansion.cpp
gayle.cpp
include/ethernet.h
include/rommgr.h
od-win32/win32_uaenet.cpp
qemuvga/ne2000.cpp
qemuvga/ne2000.h

index 7efcb911059c18a1d996f80403eb79eb5661b1eb..3a977a6c09df0742edd11fd19bb90e91081bc6d8 100644 (file)
--- a/a2065.cpp
+++ b/a2065.cpp
@@ -21,6 +21,7 @@
 #include "crc32.h"
 #include "savestate.h"
 #include "autoconf.h"
+#include "rommgr.h"
 
 #define DUMPPACKET 0
 
@@ -162,6 +163,9 @@ static volatile int transmitlen;
 
 static int dofakemac (uae_u8 *packet)
 {
+       if (!memcmp(fakemac, realmac, 6)) {
+               return 1;
+       }
        if (!memcmp (packet, fakemac, 6)) {
                memcpy (packet, realmac, 6);
                return 1;
@@ -185,6 +189,8 @@ static int mungepacket (uae_u8 *packet, int len)
 
        if (len < 20)
                return 0;
+       if (!memcmp(fakemac, realmac, 6))
+               return len;
 #if DUMPPACKET
        dumppacket (_T("pre:"), packet, len);
 #endif
@@ -551,6 +557,7 @@ void rethink_a2065 (void)
        if (csr[0] & (CSR0_BABL | CSR0_MISS | CSR0_MERR | CSR0_RINT | CSR0_TINT | CSR0_IDON))
                csr[0] |= CSR0_INTR;
        if ((csr[0] & (CSR0_INTR | CSR0_INEA)) == (CSR0_INTR | CSR0_INEA)) {
+               set_special_exter(SPCFLAG_UAEINT);
                atomic_or(&uae_int_requested, 4);
                if (!was && log_a2065 > 2)
                        write_log(_T("A2065 +IRQ\n"));
@@ -880,17 +887,19 @@ static bool a2065_config (struct autoconfig_info *aci)
        ew (0x10, 0x02);
        ew (0x14, 0x02);
 
+       // 0x00 0x80 0x10 = Commodore MAC range, A2065 drivers expect it.
+
        td = NULL;
-       if (ethernet_enumerate (&td, currprefs.a2065name)) {
-               memcpy (realmac, td->mac, sizeof realmac);
-               if (!td->mac[0] && !td->mac[1] && !td->mac[2]) {
-                       realmac[0] = 0x00;
-                       realmac[1] = 0x80;
-                       realmac[2] = 0x10;
+       if (ethernet_enumerate (&td, ROMTYPE_A2065)) {
+               if (!ethernet_getmac(realmac, aci->rc->configtext)) {
+                       memcpy (realmac, td->mac, sizeof realmac);
                }
+               realmac[0] = 0x00;
+               realmac[1] = 0x80;
+               realmac[2] = 0x10;
                if (aci->doinit)
                        write_log (_T("A2065: '%s' %02X:%02X:%02X:%02X:%02X:%02X\n"),
-                               td->name, td->mac[0], td->mac[1], td->mac[2], td->mac[3], td->mac[4], td->mac[5]);
+                               td->name, realmac[0], realmac[1], realmac[2], realmac[3], realmac[4], realmac[5]);
        } else {
                realmac[0] = 0x00;
                realmac[1] = 0x80;
@@ -930,7 +939,7 @@ uae_u8 *save_a2065 (int *len, uae_u8 *dstptr)
 {
        uae_u8 *dstbak,*dst;
 
-       if (currprefs.a2065name[0] == 0)
+       if (!is_board_enabled(&currprefs, ROMTYPE_A2065, 0))
                return NULL;
        if (dstptr)
                dstbak = dst = dstptr;
index b146faa1bf6c20461d5567400dd261638c114be8..7d452ca63247e7930cb4ecc6921ac782b5296d09 100644 (file)
@@ -116,6 +116,7 @@ void devices_reset(int hardreset)
 #ifdef DRIVESOUND
        driveclick_reset();
 #endif
+       ethernet_reset();
        uae_int_requested = 0;
 }
 
@@ -467,6 +468,7 @@ void devices_pause(void)
        rp_pause(pause_emulation);
 #endif
        pausevideograb(1);
+       ethernet_pause(1);
 }
 
 void devices_unpause(void)
@@ -479,4 +481,5 @@ void devices_unpause(void)
        uae_ppc_pause(0);
 #endif
        pausevideograb(0);
+       ethernet_pause(0);
 }
index e05ee12b69d65cc621ccb1a81f07f6eab40a5bda..293322147228d3929143c6070a9c28d9cc372489 100644 (file)
@@ -11,6 +11,7 @@
 #include "sana2.h"
 #include "uae/slirp.h"
 #include "gui.h"
+#include "rommgr.h"
 
 #ifndef HAVE_INET_ATON
 static int inet_aton(const char *cp, struct in_addr *ia)
@@ -193,10 +194,17 @@ void ethernet_enumerate_free (void)
 #endif
 }
 
-bool ethernet_enumerate (struct netdriverdata **nddp, const TCHAR *name)
+bool ethernet_enumerate (struct netdriverdata **nddp, int romtype)
 {
        int j;
        struct netdriverdata *nd;
+       const TCHAR *name = NULL;
+       
+       if (romtype) {
+               struct romconfig *rc = get_device_romconfig(&currprefs, romtype, 0);
+               name = ethernet_getselectionname(rc ? rc->device_settings : 0);
+       }
+
        gui_flicker_led(LED_NET, 0, 0);
        if (name) {
                netmode = 0;
@@ -260,3 +268,22 @@ int ethernet_getdatalenght (struct netdriverdata *ndd)
        }
        return 0;
 }
+
+bool ethernet_getmac(uae_u8 *m, const TCHAR *mac)
+{
+       if (!mac)
+               return false;
+       if (_tcslen(mac) != 3 * 5 + 2)
+               return false;
+       for (int i = 0; i < 6; i++) {
+               TCHAR *endptr;
+               if (mac[0] == 0 || mac[1] == 0)
+                       return false;
+               if (i < 5 && mac[2] != '.')
+                       return false;
+               uae_u8 v = (uae_u8)_tcstol(mac, &endptr, 16);
+               mac += 3;
+               m[i] = v;
+       }
+       return true;
+}
index 7b2280500092eb3961fb4b3ffbff8db594435a1d..5390d1a8e204f7095b1e6deabc970a928a29a060 100644 (file)
@@ -45,6 +45,7 @@
 #include "x86.h"
 #include "filesys.h"
 #include "ethernet.h"
+#include "sana2.h"
 
 
 #define CARD_FLAG_CAN_Z3 1
@@ -3997,23 +3998,6 @@ static const struct expansionboardsettings x86_bridge_sidecar_settings[] = {
        }
 };
 
-static const struct expansionboardsettings ne2k_isa_settings[] = {
-       {
-               _T("IO\0") _T("240\0") _T("260\0") _T("280\0") _T("2A0\0") _T("300\0") _T("320\0") _T("340\0") _T("360\0"),
-               _T("io\0") _T("240\0") _T("260\0") _T("280\0") _T("2A0\0") _T("300\0") _T("320\0") _T("340\0") _T("360\0"),
-               true, false, 0
-       },
-       {
-               _T("IRQ\0") _T("3\0") _T("4\0") _T("5\0") _T("7\0") _T("9\0") _T("10\0") _T("11\0") _T("12\0") _T("15\0"),
-               _T("irq\0") _T("3\0") _T("4\0") _T("5\0") _T("7\0") _T("9\0") _T("10\0") _T("11\0") _T("12\0") _T("15\0"),
-               true, false, 0
-       },
-       {
-               NULL
-       }
-};
-
-
 static const struct expansionboardsettings toccata_soundcard_settings[] = {
        {
                _T("Paula/CD audio mixer"),
@@ -4056,6 +4040,133 @@ static const struct expansionboardsettings harlequin_settings[] = {
        }
 };
 
+static struct expansionboardsettings ne2k_isa_settings[] = {
+       {
+               _T("IO\0") _T("240\0") _T("260\0") _T("280\0") _T("2A0\0") _T("300\0") _T("320\0") _T("340\0") _T("360\0"),
+               _T("io\0") _T("240\0") _T("260\0") _T("280\0") _T("2A0\0") _T("300\0") _T("320\0") _T("340\0") _T("360\0"),
+               true, false, 0
+       },
+       {
+               _T("IRQ\0") _T("3\0") _T("4\0") _T("5\0") _T("7\0") _T("9\0") _T("10\0") _T("11\0") _T("12\0") _T("15\0"),
+               _T("irq\0") _T("3\0") _T("4\0") _T("5\0") _T("7\0") _T("9\0") _T("10\0") _T("11\0") _T("12\0") _T("15\0"),
+               true, false, 0
+       },
+       {
+               NULL, NULL,
+               true, false, 4
+       },
+       {
+               NULL
+       }
+};
+
+static struct expansionboardsettings lanrover_settings[] ={
+       {
+               _T("Interrupt level\0") _T("2\0") _T("6\0"),
+               _T("irq\0") _T("2\0") _T("6\0"),
+               true, false, 0
+       },
+       {
+               _T("MAC\0"),
+               _T("mac\0"),
+               2, false, 0
+       },
+       {
+               NULL, NULL,
+               true, false, 15
+       },
+       {
+               NULL
+       }
+};
+static struct expansionboardsettings ethernet_settings[] = {
+       {
+               _T("MAC\0"),
+               _T("mac\0"),
+               2, false, 0
+       },
+       {
+               NULL, NULL,
+               true, false, 16
+       },
+       {
+               NULL
+       }
+};
+
+static struct expansionboardsettings *netsettings[] = {
+       ethernet_settings,
+       lanrover_settings,
+       ne2k_isa_settings,
+       NULL
+};
+
+struct netdriverdata **target_ethernet_enumerate(void);
+
+uae_u32 ethernet_getselection(const TCHAR *name)
+{
+       struct netdriverdata **ndd = target_ethernet_enumerate();
+       if (!ndd)
+               return 0;
+       for (int i = 0; ndd && i < MAX_TOTAL_NET_DEVICES; i++) {
+               if (ndd[i] && !_tcsicmp(ndd[i]->name, name))
+                       return i << 16;
+       }
+       return 0;
+}
+
+const TCHAR *ethernet_getselectionname(uae_u32 settings)
+{
+       struct netdriverdata **ndd = target_ethernet_enumerate();
+       if (!ndd)
+               return 0;
+       settings = (settings >> 16) & 255;
+       for (int i = 0; ndd && i < MAX_TOTAL_NET_DEVICES; i++) {
+               if (i == settings)
+                       return ndd[i]->name;
+       }
+       return _T("slirp");
+}
+
+void ethernet_updateselection(void)
+{
+       static int updated;
+       if (updated)
+               return;
+       updated = 1;
+       struct netdriverdata **ndd = target_ethernet_enumerate();
+       if (!ndd)
+               return;
+       static TCHAR tmp1[MAX_DPATH];
+       static TCHAR tmp2[MAX_DPATH];
+       _tcscpy(tmp1, _T("Network mode"));
+       _tcscpy(tmp2, _T("netmode"));
+       TCHAR *p1 = tmp1 + _tcslen(tmp1) + 1;
+       TCHAR *p2 = tmp2 + _tcslen(tmp2) + 1;
+       for (int i = 0; ndd && i < MAX_TOTAL_NET_DEVICES; i++) {
+               if (ndd[i]) {
+                       TCHAR mac[20];
+                       mac[0] = 0;
+                       if (ndd[i]->type == UAENET_SLIRP || ndd[i]->type == UAENET_SLIRP_INBOUND) {
+                               _stprintf(mac, _T(" xx:xx:xx:%02X:%02X:%02X"),
+                                       ndd[i]->mac[3], ndd[i]->mac[4], ndd[i]->mac[5]);
+                       }
+                       _stprintf(p1, _T("%s%s"), ndd[i]->desc, mac[0] ? mac : _T(""));
+                       p1 += _tcslen(p1) + 1;
+                       _tcscpy(p2, ndd[i]->name);
+                       p2 += _tcslen(p2) + 1;
+               }
+       }
+       *p1 = 0;
+       *p2 = 0;
+       for (int i = 0; netsettings[i]; i++) {
+               struct expansionboardsettings *ebs = netsettings[i];
+               int j;
+               for (j = 0; ebs[j].name; j++);
+               ebs[j].name = tmp1;
+               ebs[j].configname = tmp2;
+       }
+}
 
 static void fastlane_memory_callback(struct romconfig *rc, uae_u8 *ac, int size)
 {
@@ -4697,7 +4808,9 @@ const struct expansionromtype expansionroms[] = {
                _T("a2065"), _T("A2065"), _T("Commodore"),
                a2065_init, NULL, NULL, ROMTYPE_A2065 | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, true,
                NULL, 0,
-               false, EXPANSIONTYPE_NET
+               false, EXPANSIONTYPE_NET,
+               0, 0, 0, false, NULL,
+               false, 0, ethernet_settings,
        },
        {
                _T("ariadne2"), _T("Ariadne II"), _T("Village Tronic"),
@@ -4705,16 +4818,34 @@ const struct expansionromtype expansionroms[] = {
                NULL, 0,
                false, EXPANSIONTYPE_NET,
                0, 0, 0, false, NULL,
-               false, 0, NULL,
+               false, 0, ethernet_settings,
                { 0xc1, 0xca, 0x00, 0x00, 2167 >> 8, 2167 & 255, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
        },
+       {
+               _T("hydra"), _T("AmigaNet"), _T("Hydra Systems"),
+               hydra_init, NULL, NULL, ROMTYPE_HYDRA | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+               NULL, 0,
+               false, EXPANSIONTYPE_NET,
+               0, 0, 0, false, NULL,
+               false, 0, ethernet_settings,
+               { 0xc1, 0x01, 0x00, 0x00, 2121 >> 8, 2121 & 255, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+       },
+       {
+               _T("eb920"), _T("LAN Rover/EB920"), _T("ASDG"),
+               lanrover_init, NULL, NULL, ROMTYPE_LANROVER | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+               NULL, 0,
+               false, EXPANSIONTYPE_NET,
+               0, 0, 0, false, NULL,
+               false, 0, lanrover_settings,
+               { 0xc1, 0xfe, 0x00, 0x00, 1023 >> 8, 1023 & 255, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+       },
        {
                _T("xsurf"), _T("X-Surf"), _T("Individual Computers"),
                xsurf_init, NULL, NULL, ROMTYPE_XSURF | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, true,
                NULL, 0,
                false, EXPANSIONTYPE_NET,
                0, 0, 0, false, NULL,
-               false, 0, NULL,
+               false, 0, ethernet_settings,
                { 0xc1, 0x17, 0x00, 0x00, 4626 >> 8, 4626 & 255, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
        },
        {
@@ -4723,7 +4854,7 @@ const struct expansionromtype expansionroms[] = {
                NULL, 0,
                false, EXPANSIONTYPE_NET,
                0, 0, 0, false, NULL,
-               false, 0, NULL,
+               false, 0, ethernet_settings,
                { 0xc1, 0x64, 0x10, 0x00, 4626 >> 8, 4626 & 255, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00 }
        },
        {
@@ -4732,23 +4863,27 @@ const struct expansionromtype expansionroms[] = {
                NULL, 0,
                false, EXPANSIONTYPE_NET,
                0, 0, 0, false, NULL,
-               false, 0, NULL,
+               false, 0, ethernet_settings,
                { 0x82, 0x64, 0x32, 0x00, 4626 >> 8, 4626 & 255, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00 }
        },
        {
-               _T("ne2000_pcmcia"), _T("NE2000 PCMCIA"), NULL,
+               _T("ne2000_pcmcia"), _T("RTL8019 PCMCIA (NE2000 compatible)"), NULL,
                gayle_init_ne2000_pcmcia, NULL, NULL, ROMTYPE_NE2KPCMCIA | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
                NULL, 0,
-               false, EXPANSIONTYPE_NET
+               false, EXPANSIONTYPE_NET,
+               0, 0, 0, false, NULL,
+               false, 0, ethernet_settings,
        },
        {
-               _T("ne2000_pci"), _T("NE2000 PCI"), NULL,
+               _T("ne2000_pci"), _T("RTL8029 PCI (NE2000 compatible)"), NULL,
                pci_expansion_init, NULL, NULL, ROMTYPE_NE2KPCI | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
                NULL, 0,
-               false, EXPANSIONTYPE_NET
+               false, EXPANSIONTYPE_NET,
+               0, 0, 0, false, NULL,
+               false, 0, ethernet_settings,
        },
        {
-               _T("ne2000_isa"), _T("NE2000 ISA"), NULL,
+               _T("ne2000_isa"), _T("RTL8019 ISA (NE2000 compatible)"), NULL,
                isa_expansion_init, NULL, NULL, ROMTYPE_NE2KISA | ROMTYPE_NOT, 0, 0, BOARD_NONAUTOCONFIG_BEFORE, true,
                NULL, 0,
                false, EXPANSIONTYPE_NET,
index 87bf687511cfc76e14e734194846ca0812be3499..8b4bd649454b13d6fb620e7d7774c94e6ff502a0 100644 (file)
--- a/gayle.cpp
+++ b/gayle.cpp
@@ -33,6 +33,7 @@
 #include "pci_hw.h"
 #include "debug.h"
 #include "autoconf.h"
+#include "rommgr.h"
 
 #define PCMCIA_SRAM 1
 #define PCMCIA_IDE 2
@@ -1496,7 +1497,7 @@ static int initpcmcia (const TCHAR *path, int readonly, int type, int reset, str
                ne2000 = &ne2000_pci_board;
                ne2000_board_state = xcalloc(pci_board_state, 1);
                ne2000_board_state->irq_callback = ne2000_pcmcia_irq_callback;
-               if (!ne2000->init(ne2000_board_state)) {
+               if (!ne2000->init(ne2000_board_state, NULL)) {
                        write_log(_T("NE2000 init failed\n"));
                } else {
                        pcmcia_readonly = true;
@@ -1879,15 +1880,17 @@ void gayle_reset (int hardreset)
 #endif
        gayle_bank.name = bankname;
        gayle_dataflyer_enable(false);
-       if (currprefs.ne2000pcmcianame[0])
+       if (is_board_enabled(&currprefs, ROMTYPE_NE2KPCMCIA, 0))
                gayle_ne2000_unit(1);
 }
 
 void check_prefs_changed_gayle(void)
 {
-       if (_tcscmp(currprefs.ne2000pcmcianame, changed_prefs.ne2000pcmcianame)) {
-               _tcscpy(currprefs.ne2000pcmcianame, changed_prefs.ne2000pcmcianame);
-               gayle_ne2000_unit(currprefs.ne2000pcmcianame[0]);
+       if (!currprefs.cs_pcmcia)
+               return;
+       if (is_board_enabled(&currprefs, ROMTYPE_NE2KPCMCIA, 0) != is_board_enabled(&changed_prefs, ROMTYPE_NE2KPCMCIA, 0)) {
+               board_prefs_changed(ROMTYPE_NE2KPCMCIA, 0);
+               gayle_ne2000_unit(is_board_enabled(&currprefs, ROMTYPE_NE2KPCMCIA, 0));
        }
 }
 
index 904617bb186fe3c4d9cae92dfc7fdd048e4349cd..6a8138afc7bf2076380c00f6e1afe5ca40e311fc 100644 (file)
@@ -15,6 +15,7 @@ struct netdriverdata
        const TCHAR *desc;
        int mtu;
        uae_u8 mac[6];
+       uae_u8 originalmac[6];
        int active;
 };
 
@@ -22,7 +23,7 @@ struct netdriverdata
 typedef void (ethernet_gotfunc)(void *dev, const uae_u8 *data, int len);
 typedef int (ethernet_getfunc)(void *dev, uae_u8 *d, int *len);
 
-extern bool ethernet_enumerate (struct netdriverdata **, const TCHAR *name);
+extern bool ethernet_enumerate (struct netdriverdata **, int romtype);
 extern void ethernet_enumerate_free (void);
 extern void ethernet_close_driver (struct netdriverdata *ndd);
 
@@ -32,6 +33,8 @@ extern void ethernet_close (struct netdriverdata *ndd, void*);
 extern void ethernet_trigger (struct netdriverdata *ndd, void*);
 
 extern bool ariadne2_init(struct autoconfig_info *aci);
+extern bool hydra_init(struct autoconfig_info *aci);
+extern bool lanrover_init(struct autoconfig_info *aci);
 extern bool xsurf_init(struct autoconfig_info *aci);
 extern bool xsurf100_init(struct autoconfig_info *aci);
 
@@ -39,4 +42,12 @@ void rethink_ne2000(void);
 void ne2000_reset(void);
 void ne2000_hsync(void);
 
+void ethernet_updateselection(void);
+uae_u32 ethernet_getselection(const TCHAR*);
+const TCHAR *ethernet_getselectionname(uae_u32 settings);
+bool ethernet_getmac(uae_u8 *m, const TCHAR *mac);
+
+void ethernet_pause(int);
+void ethernet_reset(void);
+
 #endif /* UAE_ETHERNET_H */
index 64dff7acdcb14dc48df8235093346a6470cab66c..f2d43e54a26855342205e3ac27c9b6f5cb2f16a9 100644 (file)
@@ -141,6 +141,8 @@ extern int decode_cloanto_rom_do (uae_u8 *mem, int size, int real_size);
 #define ROMTYPE_XSURF          0x00100058
 #define ROMTYPE_XSURF100Z2     0x00100059
 #define ROMTYPE_XSURF100Z3     0x0010005a
+#define ROMTYPE_HYDRA          0x0010005b
+#define ROMTYPE_LANROVER       0x0010005c
 
 #define ROMTYPE_NOT                    0x00800000
 #define ROMTYPE_QUAD           0x01000000
@@ -236,6 +238,8 @@ const struct expansionromtype *get_unit_expansion_rom(int hdunit);
 struct boardromconfig *get_device_rom_new(struct uae_prefs *p, int romtype, int devnum, int *index);
 void clear_device_rom(struct uae_prefs *p, int romtype, int devnum, bool deleteDevice);
 struct boardromconfig *get_boardromconfig(struct uae_prefs *p, int romtype, int *index);
+bool is_board_enabled(struct uae_prefs *p, int romtype, int devnum);
+void board_prefs_changed(int romtype, int devnum);
 
 #define LOADROM_FILL 1
 #define LOADROM_EVENONLY 2
index 244db1de3cb5d825c450b8408d7af19d9f601d42..c7211fc2183b829554c73056f874302fa46cb5a6 100644 (file)
 
 static struct netdriverdata tds[MAX_TOTAL_NET_DEVICES];
 static int enumerated;
+static int ethernet_paused;
+
+typedef int(_cdecl *PCAP_FINDALLDEVS_EX)(char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf);
+static PCAP_FINDALLDEVS_EX ppcap_findalldevs_ex;
+typedef void(_cdecl *PCAP_FREEALLDEVS)(pcap_if_t *);
+static PCAP_FREEALLDEVS ppcap_freealldevs;
+typedef pcap_t *(_cdecl *PCAP_OPEN)(const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf);
+static PCAP_OPEN ppcap_open;
+typedef void (_cdecl *PCAP_CLOSE)(pcap_t *);
+static PCAP_CLOSE ppcap_close;
+typedef int (_cdecl *PCAP_DATALINK)(pcap_t *);
+static PCAP_DATALINK ppcap_datalink;
+typedef int (_cdecl *PCAP_SENDPACKET)(pcap_t *, const u_char *, int);
+static PCAP_SENDPACKET ppcap_sendpacket;
+typedef int(_cdecl *PCAP_NEXT_EX)(pcap_t *, struct pcap_pkthdr **, const u_char **);
+static PCAP_NEXT_EX ppcap_next_ex;
+typedef const char *(_cdecl *PCAP_LIB_VERSION)(void);
+static PCAP_LIB_VERSION ppcap_lib_version;
+
+typedef LPADAPTER(_cdecl *PACKETOPENADAPTER)(PCHAR AdapterName);
+static PACKETOPENADAPTER pPacketOpenAdapter;
+typedef VOID(_cdecl *PACKETCLOSEADAPTER)(LPADAPTER lpAdapter);
+static PACKETCLOSEADAPTER pPacketCloseAdapter;
+typedef BOOLEAN (_cdecl *PACKETREQUEST)(LPADAPTER  AdapterObject, BOOLEAN Set, PPACKET_OID_DATA  OidData);
+static PACKETREQUEST pPacketRequest;
+
+static HMODULE wpcap, packet;
 
 struct uaenetdatawin32
 {
@@ -159,8 +186,8 @@ static void *uaenet_trap_threadr (void *arg)
        uae_sem_post (&sd->sync_semr);
        while (sd->threadactiver == 1) {
                int r;
-               r = pcap_next_ex (sd->fp, &header, &pkt_data);
-               if (r == 1) {
+               r = ppcap_next_ex(sd->fp, &header, &pkt_data);
+               if (r == 1 && !ethernet_paused) {
                        uae_sem_wait (&sd->change_sem);
                        sd->gotfunc ((struct s2devstruct*)sd->user, pkt_data, header->len);
                        uae_sem_post (&sd->change_sem);
@@ -187,7 +214,7 @@ static void *uaenet_trap_threadw (void *arg)
                int towrite = sd->mtu;
                uae_sem_wait (&sd->change_sem);
                if (sd->getfunc ((struct s2devstruct*)sd->user, sd->writebuffer, &towrite)) {
-                       pcap_sendpacket (sd->fp, sd->writebuffer, towrite);
+                       ppcap_sendpacket(sd->fp, sd->writebuffer, towrite);
                        donotwait = 1;
                }
                uae_sem_post (&sd->change_sem);
@@ -207,13 +234,19 @@ void uaenet_trigger (void *vsd)
        SetEvent (sd->evttw);
 }
 
+// locally administered unicast MAC: U<<1, A<<1, E<<1
+static const uae_u8 uaemac[] = { 0xaa, 0x82, 0x8a, 0x00, 0x00, 0x00 };
+
 int uaenet_open (void *vsd, struct netdriverdata *tc, void *user, uaenet_gotfunc *gotfunc, uaenet_getfunc *getfunc, int promiscuous)
 {
        struct uaenetdatawin32 *sd = (struct uaenetdatawin32*)vsd;
        char *s;
 
        s = ua (tc->name);
-       sd->fp = pcap_open (s, 65536, (promiscuous ? PCAP_OPENFLAG_PROMISCUOUS : 0) | PCAP_OPENFLAG_MAX_RESPONSIVENESS, 100, NULL, sd->errbuf);
+       if (memcmp(tc->mac, tc->originalmac, 6)) {
+               promiscuous = 1;
+       }
+       sd->fp = ppcap_open(s, 65536, (promiscuous ? PCAP_OPENFLAG_PROMISCUOUS : 0) | PCAP_OPENFLAG_MAX_RESPONSIVENESS, 100, NULL, sd->errbuf);
        xfree (s);
        if (sd->fp == NULL) {
                TCHAR *ss = au (sd->errbuf);
@@ -276,7 +309,7 @@ void uaenet_close (void *vsd)
        xfree (sd->readbuffer);
        xfree (sd->writebuffer);
        if (sd->fp)
-               pcap_close (sd->fp);
+               ppcap_close (sd->fp);
        uaeser_initdata (sd, sd->user);
        write_log (_T("uaenet_win32 closed\n"));
 }
@@ -314,47 +347,87 @@ struct netdriverdata *uaenet_enumerate (const TCHAR *name)
        char errbuf[PCAP_ERRBUF_SIZE];
        pcap_if_t *alldevs, *d;
        int cnt;
-       HMODULE hm;
        LPADAPTER lpAdapter = 0;
        PPACKET_OID_DATA OidData;
        struct netdriverdata *tc, *tcp;
        pcap_t *fp;
        int val;
        TCHAR *ss;
+       bool npcap = true;
 
        if (enumerated) {
                return enumit (name);
        }
        tcp = tds;
-       hm = LoadLibrary (_T("wpcap.dll"));
-       if (hm == NULL) {
-               write_log (_T("uaenet: winpcap not installed (wpcap.dll)\n"));
-               return NULL;
+       wpcap = LoadLibrary(_T("npcap\\wpcap.dll"));
+       if (wpcap == NULL) {
+               int err = GetLastError();
+               wpcap = LoadLibrary (_T("wpcap.dll"));
+               if (wpcap == NULL) {
+                       write_log (_T("uaenet: npcap/winpcap not installed (wpcap.dll)\n"));
+                       return NULL;
+               }
+               npcap = false;
        }
-       FreeLibrary (hm);
-       hm = LoadLibrary (_T("packet.dll"));
-       if (hm == NULL) {
-               write_log (_T("uaenet: winpcap not installed (packet.dll)\n"));
+       packet = LoadLibrary (npcap ? _T("npcap\\packet.dll") : _T("packet.dll"));
+       if (packet == NULL) {
+               write_log (_T("uaenet: npcap/winpcap not installed (packet.dll)\n"));
+               FreeLibrary(wpcap);
+               wpcap = NULL;
                return NULL;
        }
-       FreeLibrary (hm);
-       if (!isdllversion (_T("wpcap.dll"), 4, 0, 0, 0)) {
-               write_log (_T("uaenet: too old winpcap, v4 or newer required\n"));
+
+       if (!isdllversion (npcap ? _T("npcap\\wpcap.dll") : _T("wpcap.dll"), 4, 0, 0, 0)) {
+               write_log (_T("uaenet: too old npcap/winpcap, v4 or newer required\n"));
                return NULL;
        }
 
-       ss = au (pcap_lib_version ());
+       ppcap_lib_version = (PCAP_LIB_VERSION)GetProcAddress(wpcap, "pcap_lib_version");
+       ppcap_findalldevs_ex = (PCAP_FINDALLDEVS_EX)GetProcAddress(wpcap, "pcap_findalldevs_ex");
+       ppcap_freealldevs = (PCAP_FREEALLDEVS)GetProcAddress(wpcap, "pcap_freealldevs");
+       ppcap_open = (PCAP_OPEN)GetProcAddress(wpcap, "pcap_open");
+       ppcap_close = (PCAP_CLOSE)GetProcAddress(wpcap, "pcap_close");
+       ppcap_datalink = (PCAP_DATALINK)GetProcAddress(wpcap, "pcap_datalink");
+
+       ppcap_sendpacket = (PCAP_SENDPACKET)GetProcAddress(wpcap, "pcap_sendpacket");
+       ppcap_next_ex = (PCAP_NEXT_EX)GetProcAddress(wpcap, "pcap_next_ex");
+
+       pPacketOpenAdapter = (PACKETOPENADAPTER)GetProcAddress(packet, "PacketOpenAdapter");
+       pPacketCloseAdapter = (PACKETCLOSEADAPTER)GetProcAddress(packet, "PacketCloseAdapter");
+       pPacketRequest = (PACKETREQUEST)GetProcAddress(packet, "PacketRequest");
+
+       ss = au (ppcap_lib_version());
        if (!done)
                write_log (_T("uaenet: %s\n"), ss);
        xfree (ss);
 
-       if (pcap_findalldevs_ex (PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1) {
+       if (ppcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1) {
                ss = au (errbuf);
                write_log (_T("uaenet: failed to get interfaces: %s\n"), ss);
                xfree (ss);
                return NULL;
        }
 
+
+       PIP_ADAPTER_ADDRESSES aa = NULL;
+       DWORD aasize = 0;
+       DWORD err = GetAdaptersAddresses(AF_UNSPEC,
+               GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER,
+               NULL, NULL, &aasize);
+       if (err == ERROR_BUFFER_OVERFLOW) {
+               aa = (IP_ADAPTER_ADDRESSES*)xcalloc(uae_u8, aasize);
+               if (GetAdaptersAddresses(AF_UNSPEC,
+                       GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER,
+                       NULL, aa, &aasize) != ERROR_SUCCESS)  {
+                       xfree(aa);
+                       aa = NULL;
+               }
+       }
+
+       OidData = (PPACKET_OID_DATA)xcalloc(uae_u8, 6 + sizeof(PACKET_OID_DATA));
+       OidData->Length = 6;
+       OidData->Oid = OID_802_3_CURRENT_ADDRESS;
+
        if (!done)
                write_log (_T("uaenet: detecting interfaces\n"));
        for(cnt = 0, d = alldevs; d != NULL; d = d->next) {
@@ -375,54 +448,66 @@ struct netdriverdata *uaenet_enumerate (const TCHAR *name)
                        write_log (_T("- corrupt name\n"));
                        continue;
                }
-               fp = pcap_open (d->name, 65536, 0, 0, NULL, errbuf);
+               fp = ppcap_open(d->name, 65536, 0, 0, NULL, errbuf);
                if (!fp) {
                        ss = au (errbuf);
                        write_log (_T("- pcap_open() failed: %s\n"), ss);
                        xfree (ss);
                        continue;
                }
-               val = pcap_datalink (fp);
-               pcap_close (fp);
+               val = ppcap_datalink(fp);
+               ppcap_close (fp);
                if (val != DLT_EN10MB) {
                        if (!done)
                                write_log (_T("- not an ethernet adapter (%d)\n"), val);
                        continue;
                }
 
-               lpAdapter = PacketOpenAdapter (n2 + strlen (PCAP_SRC_IF_STRING));
+               lpAdapter = pPacketOpenAdapter(n2 + strlen (PCAP_SRC_IF_STRING));
                if (lpAdapter == NULL) {
                        if (!done)
                                write_log (_T("- PacketOpenAdapter() failed\n"));
                        continue;
                }
-               OidData = (PPACKET_OID_DATA)xcalloc (uae_u8, 6 + sizeof(PACKET_OID_DATA));
-               if (OidData) {
-                       OidData->Length = 6;
-                       OidData->Oid = OID_802_3_CURRENT_ADDRESS;
-                       if (PacketRequest (lpAdapter, FALSE, OidData)) {
-                               memcpy (tc->mac, OidData->Data, 6);
-                               if (!done)
-                                       write_log (_T("- MAC %02X:%02X:%02X:%02X:%02X:%02X (%d)\n"),
-                                       tc->mac[0], tc->mac[1], tc->mac[2],
-                                       tc->mac[3], tc->mac[4], tc->mac[5], cnt);
-                               tc->type = UAENET_PCAP;
-                               tc->active = 1;
-                               tc->mtu = 1522;
-                               tc->name = au (d->name);
-                               tc->desc = au (d->description);
-                               cnt++;
-                       } else {
-                               write_log (_T(" - failed to get MAC\n"));
+               memset(tc->originalmac, 0, sizeof tc->originalmac);
+               memcpy(tc->mac, uaemac, 6);
+               if (pPacketRequest (lpAdapter, FALSE, OidData)) {
+                       memcpy(tc->mac, OidData->Data, 6);
+                       memcpy(tc->originalmac, tc->mac, 6);
+               } else {
+                       PIP_ADAPTER_ADDRESSES aap = aa;
+                       while (aap) {
+                               char *name1 = aap->AdapterName;
+                               char *name2 = d->name;
+                               while (*name2 && *name2 != '{')
+                                       name2++;
+                               if (*name2 && !stricmp(name1, name2)) {
+                                       memcpy(tc->mac, aap->PhysicalAddress, 6);
+                                       memcpy(tc->originalmac, tc->mac, 6);
+                                       break;
+                               }
+                               aap = aap->Next;
                        }
-                       xfree (OidData);
                }
-               PacketCloseAdapter (lpAdapter);
+               if (!done)
+                       write_log(_T("- MAC %02X:%02X:%02X:%02X:%02X:%02X -> %02X:%02X:%02X:%02X:%02X:%02X\n"),
+                               tc->mac[0], tc->mac[1], tc->mac[2], tc->mac[3], tc->mac[4], tc->mac[5],
+                               uaemac[0], uaemac[1], uaemac[2], tc->mac[3], tc->mac[4], tc->mac[5]);
+               memcpy(tc->mac, uaemac, 3);
+               tc->type = UAENET_PCAP;
+               tc->active = 1;
+               tc->mtu = 1522;
+               tc->name = au(d->name);
+               tc->desc = au(d->description);
+               cnt++;
+               pPacketCloseAdapter(lpAdapter);
        }
        if (!done)
                write_log (_T("uaenet: end of detection, %d devices found.\n"), cnt);
        done = 1;
-       pcap_freealldevs (alldevs);
+       ppcap_freealldevs(alldevs);
+       xfree(OidData);
+       xfree(aa);
        enumerated = 1;
        return enumit (name);
 }
@@ -437,3 +522,13 @@ void uaenet_close_driver (struct netdriverdata *tc)
                tc[i].active = 0;
        }
 }
+
+void ethernet_pause(int pause)
+{
+       ethernet_paused = pause;
+}
+
+void ethernet_reset(void)
+{
+       ethernet_paused = 0;
+}
index 9a0de4412207eceaffbb9bb1245273218e1793e2..b4d0057e43b2843c6776e7f2e922356d9d617f1f 100644 (file)
@@ -34,6 +34,7 @@
 #include "newcpu.h"
 #include "custom.h"
 #include "debug.h"
+#include "sana2.h"
 
 #include "qemuuaeglue.h"
 #include "queue.h"
@@ -41,6 +42,8 @@
 
 //#define DEBUG_NE2000
 
+extern int log_a2065;
+
 struct NetClientState
 {
        struct NE2000State *ne2000state;
@@ -227,7 +230,7 @@ static void ne2000_reset2(NE2000State *s)
     s->mem[15] = 0x57;
 
     /* duplicate prom data */
-    for(i = 15;i >= 0; i--) {
+    for(i = 15; i >= 0; i--) {
         s->mem[2 * i] = s->mem[i];
         s->mem[2 * i + 1] = s->mem[i];
     }
@@ -279,50 +282,79 @@ static int ne2000_can_receive(NetClientState *nc)
 
 #define MIN_BUF_SIZE 60
 
+static bool ne2000_canreceive(NetClientState *nc, const uint8_t *buf)
+{
+       NE2000State *s = qemu_get_nic_opaque(nc);
+       unsigned int mcast_idx;
+       static const uint8_t broadcast_macaddr[6] =
+       { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+       /* XXX: check this */
+       if (s->rxcr & 0x10) {
+               /* promiscuous: receive all */
+       } else {
+               if (!memcmp(buf, broadcast_macaddr, 6)) {
+                       /* broadcast address */
+                       if (!(s->rxcr & 0x04))
+                               return false;
+               } else if (buf[0] & 0x01) {
+                       /* multicast */
+                       if (!(s->rxcr & 0x08))
+                               return false;
+                       mcast_idx = compute_mcast_idx(buf);
+                       if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))))
+                               return false;
+               } else if (s->dp8390 &&
+                       s->c.macaddr.a[0] == buf[0] &&
+                       s->c.macaddr.a[1] == buf[1] &&
+                       s->c.macaddr.a[2] == buf[2] &&
+                       s->c.macaddr.a[3] == buf[3] &&
+                       s->c.macaddr.a[4] == buf[4] &&
+                       s->c.macaddr.a[5] == buf[5]) {
+                       /* match */
+               } else if (!s->dp8390 &&
+                       s->mem[0] == buf[0] &&
+                       s->mem[2] == buf[1] &&
+                       s->mem[4] == buf[2] &&
+                       s->mem[6] == buf[3] &&
+                       s->mem[8] == buf[4] &&
+                       s->mem[10] == buf[5]) {
+                       /* match */
+               } else {
+                       return false;
+               }
+       }
+       return true;
+}
+
 static ssize_t ne2000_receive(NetClientState *nc, const uint8_t *buf, size_t size_)
 {
     NE2000State *s = qemu_get_nic_opaque(nc);
     int size = size_;
     uint8_t *p;
-    unsigned int total_len, next, avail, len, index, mcast_idx;
+    unsigned int total_len, next, avail, len, index;
     uint8_t buf1[60];
-    static const uint8_t broadcast_macaddr[6] =
-        { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 
 #if defined(DEBUG_NE2000)
     write_log("NE2000: received len=%d\n", size);
 #endif
 
-    if (s->cmd & E8390_STOP || ne2000_buffer_full(s))
-        return -1;
+    if (s->cmd & E8390_STOP)
+               return -1;
 
-    /* XXX: check this */
-    if (s->rxcr & 0x10) {
-        /* promiscuous: receive all */
-    } else {
-        if (!memcmp(buf,  broadcast_macaddr, 6)) {
-            /* broadcast address */
-            if (!(s->rxcr & 0x04))
-                return size;
-        } else if (buf[0] & 0x01) {
-            /* multicast */
-            if (!(s->rxcr & 0x08))
-                return size;
-            mcast_idx = compute_mcast_idx(buf);
-            if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))))
-                return size;
-        } else if (s->mem[0] == buf[0] &&
-                   s->mem[2] == buf[1] &&
-                   s->mem[4] == buf[2] &&
-                   s->mem[6] == buf[3] &&
-                   s->mem[8] == buf[4] &&
-                   s->mem[10] == buf[5]) {
-            /* match */
-        } else {
-            return size;
-        }
-    }
+       if (!ne2000_canreceive(nc, buf))
+               return -1;
 
+       if (ne2000_buffer_full(s))
+        return -1;
+
+       if (log_a2065 > 1) {
+               const uae_u8 *dstmac = buf;
+               const uae_u8 *srcmac = buf + 6;
+               write_log(_T("NE2000<!DST:%02X.%02X.%02X.%02X.%02X.%02X SRC:%02X.%02X.%02X.%02X.%02X.%02X E=%04X S=%d\n"),
+                       dstmac[0], dstmac[1], dstmac[2], dstmac[3], dstmac[4], dstmac[5],
+                       srcmac[6], srcmac[7], srcmac[8], srcmac[9], srcmac[10], srcmac[11],
+                       (buf[12] << 8) | buf[13], size);
+       }
 
     /* if too small buffer, then expand it */
     if (size < MIN_BUF_SIZE) {
@@ -345,10 +377,18 @@ static ssize_t ne2000_receive(NetClientState *nc, const uint8_t *buf, size_t siz
     /* XXX: check this */
     if (buf[0] & 0x01)
         s->rsr |= ENRSR_PHY;
-    p[0] = s->rsr;
-    p[1] = next >> 8;
-    p[2] = total_len;
-    p[3] = total_len >> 8;
+
+       if ((s->dcfg & 2) && s->dp8390) {
+               p[1] = s->rsr;
+               p[0] = next >> 8;
+               p[2] = total_len;
+               p[3] = total_len >> 8;
+       } else {
+           p[0] = s->rsr;
+           p[1] = next >> 8;
+           p[2] = total_len;
+           p[3] = total_len >> 8;
+       }
     index += 4;
 
     /* write packet data */
@@ -392,6 +432,9 @@ static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val)
     if (addr == E8390_CMD) {
         /* control register */
         s->cmd = val;
+               if ((val & E8390_STOP) && s->dp8390) {
+                       s->isr |= ENISR_RESET;
+               }
         if (!(val & E8390_STOP)) { /* START bit makes no sense on RTL8029... */
             s->isr &= ~ENISR_RESET;
             /* test specific case: zero length transfer */
@@ -467,6 +510,17 @@ static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val)
                                                s->fifo_offset = 0;
                                                xfree(loop);
                                        } else {
+
+                                               if (log_a2065 > 1) {
+                                                       const uae_u8 *dstmac = transmitbuffer;
+                                                       const uae_u8 *srcmac = transmitbuffer + 6;
+                                                       write_log(_T("NE2000>!DST:%02X.%02X.%02X.%02X.%02X.%02X SRC:%02X.%02X.%02X.%02X.%02X.%02X E=%04X S=%d\n"),
+                                                               dstmac[0], dstmac[1], dstmac[2], dstmac[3], dstmac[4], dstmac[5],
+                                                               srcmac[6], srcmac[7], srcmac[8], srcmac[9], srcmac[10], srcmac[11],
+                                                               (transmitbuffer[12] << 8) | transmitbuffer[13], transmitlen);
+                                               }
+
+
                                                ethernet_trigger(td, sysdata);
                                        }
 #if 0
@@ -696,30 +750,27 @@ static uint32_t ne2000_ioport_read(void *opaque, uint32_t addr)
     return ret;
 }
 
-static inline void ne2000_mem_writeb(NE2000State *s, uint32_t addr,
-                                     uint32_t val)
+static inline void ne2000_mem_writeb(NE2000State *s, uint32_t addr, uint32_t val)
 {
-    if (addr < 32 ||
+    if (s->dp8390 || addr < 32 ||
         (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
         s->mem[addr] = val;
     }
 }
 
-static inline void ne2000_mem_writew(NE2000State *s, uint32_t addr,
-                                     uint32_t val)
+static inline void ne2000_mem_writew(NE2000State *s, uint32_t addr, uint32_t val)
 {
     addr &= ~1; /* XXX: check exact behaviour if not even */
-    if (addr < 32 ||
+    if (s->dp8390 || addr < 32 ||
         (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
         *(uint16_t *)(s->mem + addr) = cpu_to_le16(val);
     }
 }
 
-static inline void ne2000_mem_writel(NE2000State *s, uint32_t addr,
-                                     uint32_t val)
+static inline void ne2000_mem_writel(NE2000State *s, uint32_t addr, uint32_t val)
 {
     addr &= ~1; /* XXX: check exact behaviour if not even */
-    if (addr < 32 ||
+    if (s->dp8390 || addr < 32 ||
         (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
         stl_le_p(s->mem + addr, val);
     }
@@ -727,7 +778,7 @@ static inline void ne2000_mem_writel(NE2000State *s, uint32_t addr,
 
 static inline uint32_t ne2000_mem_readb(NE2000State *s, uint32_t addr)
 {
-    if (addr < 32 ||
+    if (s->dp8390 || addr < 32 ||
         (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
         return s->mem[addr];
     } else {
@@ -738,7 +789,7 @@ static inline uint32_t ne2000_mem_readb(NE2000State *s, uint32_t addr)
 static inline uint32_t ne2000_mem_readw(NE2000State *s, uint32_t addr)
 {
     addr &= ~1; /* XXX: check exact behaviour if not even */
-    if (addr < 32 ||
+    if (s->dp8390 || addr < 32 ||
         (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
         return le16_to_cpu(*(uint16_t *)(s->mem + addr));
     } else {
@@ -749,7 +800,7 @@ static inline uint32_t ne2000_mem_readw(NE2000State *s, uint32_t addr)
 static inline uint32_t ne2000_mem_readl(NE2000State *s, uint32_t addr)
 {
     addr &= ~1; /* XXX: check exact behaviour if not even */
-    if (addr < 32 ||
+    if (s->dp8390 || addr < 32 ||
         (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
         return ldl_le_p(s->mem + addr);
     } else {
@@ -1117,6 +1168,9 @@ static void gotfunc(void *devv, const uae_u8 *databuf, int len)
 #ifdef DEBUG_NE2000
        write_log("NE2000: %d byte received (%d %d)\n", len, receive_buffer_read, receive_buffer_write);
 #endif
+       // immediately check if we don't need this packet. for better performance.
+       if (!ne2000_canreceive(&ncs, databuf))
+               return;
        ne2000_receive_check();
        if (len > MAX_PACKET_SIZE) 
                return;
@@ -1181,8 +1235,10 @@ static void ne2000_free(struct pci_board_state *pcibs)
        sysdata = NULL;
        xfree(receive_buffer);
        receive_buffer = NULL;
-       if (ncs.ne2000state)
+       if (ncs.ne2000state) {
                eeprom93xx_free(ncs.ne2000state->eeprom);
+               ncs.ne2000state->eeprom = NULL;
+       }
        uae_sem_destroy(&ne2000_sem);
 }
 
@@ -1198,12 +1254,18 @@ static void ne2000_byteswapsupported(void *opaque)
        NE2000State *s = (NE2000State*)opaque;
        s->byteswapsupported = true;
 }
+static void ne2000_setisdp8390(void *opaque)
+{
+       NE2000State *s = (NE2000State*)opaque;
+       s->dp8390 = true;
+}
+
 
-static uae_u8 e9346[128] = {
+static uae_u8 e9346[64 * 2] = {
        0x80, 0x00, 0x10, 0x00 // CONFIG1-4
 };
 
-static bool ne2000_init(struct pci_board_state *pcibs)
+static bool ne2000_init_2(struct pci_board_state *pcibs, int romtype, const TCHAR *mac)
 {
        ne2000_free(pcibs);
        ncs.device = &ne2000_pci_board;
@@ -1219,21 +1281,19 @@ static bool ne2000_init(struct pci_board_state *pcibs)
 
        td = NULL;
        uae_u8 *m = ncs.ne2000state->c.macaddr.a;
-       const TCHAR *name = currprefs.ne2000pciname[0] ? currprefs.ne2000pciname : currprefs.ne2000pcmcianame; // hack!
-       memset(m, 0, 6);
-
-       if (name[0] == 0)
-               name = _T("slirp");
 
-       if (ethernet_enumerate(&td, name)) {
-               memcpy(m, td->mac, 6);
-               if (!m[0] && !m[1] && !m[2]) {
-                       m[0] = 0x52;
-                       m[1] = 0x54;
-                       m[2] = 0x05;
+       memset(m, 0, 6);
+       if (ethernet_enumerate(&td, romtype)) {
+               if (!ethernet_getmac(m, mac)) {
+                       memcpy(m, td->mac, 6);
+                       if (!m[0] && !m[1] && !m[2]) {
+                               m[0] = 0x52;
+                               m[1] = 0x54;
+                               m[2] = 0x05;
+                       }
                }
                write_log(_T("NE2000: '%s' %02X:%02X:%02X:%02X:%02X:%02X\n"),
-                                 td->name, td->mac[0], td->mac[1], td->mac[2], td->mac[3], td->mac[4], td->mac[5]);
+                                 td->name, m[0], m[1], m[2], m[3], m[4], m[5]);
        } else {
                m[0] = 0x52;
                m[1] = 0x54;
@@ -1270,6 +1330,10 @@ static bool ne2000_init(struct pci_board_state *pcibs)
        return true;
 }
 
+static bool ne2000_init(struct pci_board_state *pcibs, struct autoconfig_info *aci)
+{
+       return ne2000_init_2(pcibs, ROMTYPE_NE2KPCI, aci->rc->configtext);
+}
 
 static const struct pci_config ne2000_pci_config =
 {
@@ -1302,7 +1366,7 @@ static const uae_u8 pnp_init_key[] =
        0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1, 0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x39
 };
 
-static const uae_u8 rtl8029as_pnpdata[] =
+static const uae_u8 rtl8019as_pnpdata[] =
 {
        0x4a, 0x8c, 0x80, 0x19,
        0x0d, 0x00, 0x19, 0x00,
@@ -1348,6 +1412,7 @@ struct ne2000_s
        int ne2000_romtype;
        uae_u32 flags;
        struct isapnp pnp;
+       bool level6;
 };
 static struct ne2000_s ne2000_data;
 
@@ -1513,6 +1578,76 @@ static int toariadne2(struct ne2000_s *ne, uaecptr addr, uae_u32 *vp, int size,
                addr >>= 1;
                addr &= 0x1f;
                return addr;
+       } else if (ne->ne2000_romtype == ROMTYPE_LANROVER) {
+               if ((addr & 0xc000) == 0x8000) {
+                       int maddr = addr & 16383;
+                       // memory
+                       if (size == -4) {
+                               uae_u16 vv = v >> 16;
+                               vv = (vv >> 8) | (vv << 8);
+                               ne2000_mem_writew(ncs.ne2000state, maddr + 0, vv);
+                               vv = v;
+                               vv = (vv >> 8) | (vv << 8);
+                               ne2000_mem_writew(ncs.ne2000state, maddr + 2, vv);
+                       } else if (size == -2) {
+                               v = (v >> 8) | (v << 8);
+                               ne2000_mem_writew(ncs.ne2000state, maddr, v);
+                       } else if (size == -1) {
+                               ne2000_mem_writeb(ncs.ne2000state, maddr, v);
+                       } else if (size == 4) {
+                               *bs = true;
+                               *vp = ne2000_mem_readw(ncs.ne2000state, maddr) << 16;
+                               *vp |= ne2000_mem_readw(ncs.ne2000state, maddr + 2) << 0;
+                       } else if (size == 2) {
+                               *bs = true;
+                               *vp = ne2000_mem_readw(ncs.ne2000state, maddr);
+                       } else if (size == 1) {
+                               *vp = ne2000_mem_readb(ncs.ne2000state, maddr);
+                       }
+               } else if ((addr & 0x8101) == 0x0100) {
+                       // mac rom
+                       *vp = ncs.ne2000state->c.macaddr.a[(addr >> 1) & 7];
+               } else if ((addr & 0x8101) == 0x0001) {
+                       // io
+                       addr &= (15 << 1);
+                       addr >>= 1;
+                       return addr;
+               }
+       } else if (ne->ne2000_romtype == ROMTYPE_HYDRA) {
+               if (!(addr & 0xc000)) {
+                       int maddr = addr;
+                       // memory
+                       if (size == -4) {
+                               uae_u16 vv = v >> 16;
+                               vv = (vv >> 8) | (vv << 8);
+                               ne2000_mem_writew(ncs.ne2000state, maddr + 0, vv);
+                               vv = v;
+                               vv = (vv >> 8) | (vv << 8);
+                               ne2000_mem_writew(ncs.ne2000state, maddr + 2, vv);
+                       } else if (size == -2) {
+                               v = (v >> 8) | (v << 8);
+                               ne2000_mem_writew(ncs.ne2000state, maddr, v);
+                       } else if (size == -1) {
+                               ne2000_mem_writeb(ncs.ne2000state, maddr, v);
+                       } else if (size == 4) {
+                               *bs = true;
+                               *vp = ne2000_mem_readw(ncs.ne2000state, maddr) << 16;
+                               *vp |= ne2000_mem_readw(ncs.ne2000state, maddr + 2) << 0;
+                       } else if (size == 2) {
+                               *bs = true;
+                               *vp = ne2000_mem_readw(ncs.ne2000state, maddr);
+                       } else if (size == 1) {
+                               *vp = ne2000_mem_readb(ncs.ne2000state, maddr);
+                       }
+               } else if ((addr & 0xffe1) == 0xffc0) {
+                       // mac rom
+                       *vp = ncs.ne2000state->c.macaddr.a[(addr >> 1) & 7];
+               } else if ((addr & 0xffe1) == 0xffe1) {
+                       // io
+                       addr &= (15 << 1);
+                       addr >>= 1;
+                       return addr;
+               }
        } else if (ne->ne2000_romtype == ROMTYPE_XSURF) {
                if (addr == 0x7e && size == -1) {
                        ne->flags &= ~1;
@@ -1618,6 +1753,16 @@ static uae_u32 REGPARAM2 ariadne2_lget(uaecptr addr)
                        w = (w >> 8) | (w << 8);
                }
                v |= w;
+       } else {
+               if (bs) {
+                       uae_u32 l = v;
+                       uae_u16 w = l >> 16;
+                       w = (w >> 8) | (w << 8);
+                       v = w << 16;
+                       w = l;
+                       w = (w >> 8) | (w << 8);
+                       v |= w;
+               }
        }
 #if ARIADNE2_LOG
        write_log(_T("NE2000 LGET %08x %08X %d %08X\n"), addr, v, reg, M68K_GETPC);
@@ -1709,8 +1854,12 @@ void rethink_ne2000(void)
        struct ne2000_s *ne = getne2k(0);
        if (!ne->ariadne2_board_state)
                return;
-       if (ne->ariadne2_irq)
-               INTREQ_0(0x8000 | 0x0008);
+       if (ne->ariadne2_irq) {
+               if (ne->level6)
+                       INTREQ_0(0x8000 | 0x2000);
+               else
+                       INTREQ_0(0x8000 | 0x0008);
+       }
 }
 
 void ne2000_hsync(void)
@@ -1766,13 +1915,62 @@ bool ariadne2_init(struct autoconfig_info *aci)
 
        ne->ariadne2_board_state = xcalloc(pci_board_state, 1);
        ne->ariadne2_board_state->irq_callback = ariadne2_irq_callback;
-       if (!ne2000_pci_board.init(ne->ariadne2_board_state))
+       if (!ne2000_init_2(ne->ariadne2_board_state, ne->ne2000_romtype, aci->rc->configtext))
                return false;
        ne2000_byteswapsupported(&ne2000state);
 
        return true;
 }
 
+bool hydra_init(struct autoconfig_info *aci)
+{
+       struct ne2000_s *ne = getne2k(0);
+       ne->ariadne2_irq = false;
+       if (aci->postinit) {
+               return true;
+       }
+       ne->ne2000_romtype = ROMTYPE_HYDRA;
+       const struct expansionromtype *ert = get_device_expansion_rom(ne->ne2000_romtype);
+       aci->autoconfigp = ert->autoconfig;
+       aci->addrbank = &ariadne2_bank;
+       aci->autoconfig_automatic = true;
+       if (!aci->doinit)
+               return true;
+
+       ne->ariadne2_board_state = xcalloc(pci_board_state, 1);
+       ne->ariadne2_board_state->irq_callback = ariadne2_irq_callback;
+       if (!ne2000_init_2(ne->ariadne2_board_state, ne->ne2000_romtype, aci->rc->configtext))
+               return false;
+       ne2000_setisdp8390(&ne2000state);
+
+       return true;
+}
+
+bool lanrover_init(struct autoconfig_info *aci)
+{
+       struct ne2000_s *ne = getne2k(0);
+       ne->ariadne2_irq = false;
+       if (aci->postinit) {
+               return true;
+       }
+       ne->ne2000_romtype = ROMTYPE_LANROVER;
+       const struct expansionromtype *ert = get_device_expansion_rom(ne->ne2000_romtype);
+       aci->autoconfigp = ert->autoconfig;
+       aci->addrbank = &ariadne2_bank;
+       aci->autoconfig_automatic = true;
+       if (!aci->doinit)
+               return true;
+
+       ne->ariadne2_board_state = xcalloc(pci_board_state, 1);
+       ne->ariadne2_board_state->irq_callback = ariadne2_irq_callback;
+       if (!ne2000_init_2(ne->ariadne2_board_state, ne->ne2000_romtype, aci->rc->configtext))
+               return false;
+       ne2000_setisdp8390(&ne2000state);
+       ne->level6 = (aci->rc->device_settings & 1) != 0;
+
+       return true;
+}
+
 bool xsurf_init(struct autoconfig_info *aci)
 {
        struct ne2000_s *ne = getne2k(0);
@@ -1790,9 +1988,9 @@ bool xsurf_init(struct autoconfig_info *aci)
 
        ne->ariadne2_board_state = xcalloc(pci_board_state, 1);
        ne->ariadne2_board_state->irq_callback = ariadne2_irq_callback;
-       if (!ne2000_pci_board.init(ne->ariadne2_board_state))
+       if (!ne2000_init_2(ne->ariadne2_board_state, ne->ne2000_romtype, aci->rc->configtext))
                return false;
-       isapnp_init(&ne->pnp, rtl8029as_pnpdata, sizeof rtl8029as_pnpdata, rt_pnp_init_key, 32);
+       isapnp_init(&ne->pnp, rtl8019as_pnpdata, sizeof rtl8019as_pnpdata, rt_pnp_init_key, 32);
        ne2000_byteswapsupported(&ne2000state);
        ne2000_setident(&ne2000state, 0x50, 0x70);
 
@@ -1816,7 +2014,7 @@ bool xsurf100_init(struct autoconfig_info *aci)
 
        ne->ariadne2_board_state = xcalloc(pci_board_state, 1);
        ne->ariadne2_board_state->irq_callback = ariadne2_irq_callback;
-       if (!ne2000_pci_board.init(ne->ariadne2_board_state))
+       if (!ne2000_init_2(ne->ariadne2_board_state, ne->ne2000_romtype, aci->rc->configtext))
                return false;
        ne2000_setident(&ne2000state, 0x50, 0x70);
 
index d4bf94da4b0f050518e1fcab2838ffbce0f6e24c..d547e71a36ec6be7c014922539c52d59f39a3318 100644 (file)
@@ -38,6 +38,7 @@ typedef struct NE2000State {
        void *eeprom;
        bool byteswapsupported;
        uae_u8 idbytes[2];
+       bool dp8390;
 } NE2000State;
 
 #if 0