From 9da23ce493fb7dcd435f7d3928ff88b017fe87b0 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Fri, 21 Oct 2016 18:58:15 +0300 Subject: [PATCH] Ethernet emulation updates. --- a2065.cpp | 25 ++- devices.cpp | 3 + ethernet.cpp | 29 +++- expansion.cpp | 189 ++++++++++++++++++--- gayle.cpp | 13 +- include/ethernet.h | 13 +- include/rommgr.h | 4 + od-win32/win32_uaenet.cpp | 183 ++++++++++++++++----- qemuvga/ne2000.cpp | 338 ++++++++++++++++++++++++++++++-------- qemuvga/ne2000.h | 1 + 10 files changed, 642 insertions(+), 156 deletions(-) diff --git a/a2065.cpp b/a2065.cpp index 7efcb911..3a977a6c 100644 --- 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; diff --git a/devices.cpp b/devices.cpp index b146faa1..7d452ca6 100644 --- a/devices.cpp +++ b/devices.cpp @@ -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); } diff --git a/ethernet.cpp b/ethernet.cpp index e05ee12b..29332214 100644 --- a/ethernet.cpp +++ b/ethernet.cpp @@ -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; +} diff --git a/expansion.cpp b/expansion.cpp index 7b228050..5390d1a8 100644 --- a/expansion.cpp +++ b/expansion.cpp @@ -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, diff --git a/gayle.cpp b/gayle.cpp index 87bf6875..8b4bd649 100644 --- 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)); } } diff --git a/include/ethernet.h b/include/ethernet.h index 904617bb..6a8138af 100644 --- a/include/ethernet.h +++ b/include/ethernet.h @@ -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 */ diff --git a/include/rommgr.h b/include/rommgr.h index 64dff7ac..f2d43e54 100644 --- a/include/rommgr.h +++ b/include/rommgr.h @@ -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 diff --git a/od-win32/win32_uaenet.cpp b/od-win32/win32_uaenet.cpp index 244db1de..c7211fc2 100644 --- a/od-win32/win32_uaenet.cpp +++ b/od-win32/win32_uaenet.cpp @@ -34,6 +34,33 @@ 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; +} diff --git a/qemuvga/ne2000.cpp b/qemuvga/ne2000.cpp index 9a0de441..b4d0057e 100644 --- a/qemuvga/ne2000.cpp +++ b/qemuvga/ne2000.cpp @@ -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("NE2000rsr |= 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); diff --git a/qemuvga/ne2000.h b/qemuvga/ne2000.h index d4bf94da..d547e71a 100644 --- a/qemuvga/ne2000.h +++ b/qemuvga/ne2000.h @@ -38,6 +38,7 @@ typedef struct NE2000State { void *eeprom; bool byteswapsupported; uae_u8 idbytes[2]; + bool dp8390; } NE2000State; #if 0 -- 2.47.3