mirror of
https://github.com/LIV2/WinUAE.git
synced 2025-12-06 00:12:52 +00:00
Ethernet emulation updates.
This commit is contained in:
parent
4e668927b5
commit
9da23ce493
25
a2065.cpp
25
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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
29
ethernet.cpp
29
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;
|
||||
}
|
||||
|
||||
189
expansion.cpp
189
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,
|
||||
|
||||
13
gayle.cpp
13
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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"));
|
||||
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"));
|
||||
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;
|
||||
}
|
||||
|
||||
ss = au (pcap_lib_version ());
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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))
|
||||
if (s->cmd & E8390_STOP)
|
||||
return -1;
|
||||
|
||||
if (!ne2000_canreceive(nc, buf))
|
||||
return -1;
|
||||
|
||||
if (ne2000_buffer_full(s))
|
||||
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 (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;
|
||||
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);
|
||||
|
||||
|
||||
@ -38,6 +38,7 @@ typedef struct NE2000State {
|
||||
void *eeprom;
|
||||
bool byteswapsupported;
|
||||
uae_u8 idbytes[2];
|
||||
bool dp8390;
|
||||
} NE2000State;
|
||||
|
||||
#if 0
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user