Ethernet emulation updates.

This commit is contained in:
Toni Wilen 2016-10-21 18:58:15 +03:00
parent 4e668927b5
commit 9da23ce493
10 changed files with 644 additions and 158 deletions

View File

@ -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;

View 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);
}

View 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;
}

View 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,

View File

@ -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));
}
}

View 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 */

View 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

View File

@ -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;
}

View 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))
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);

View File

@ -38,6 +38,7 @@ typedef struct NE2000State {
void *eeprom;
bool byteswapsupported;
uae_u8 idbytes[2];
bool dp8390;
} NE2000State;
#if 0