Network overhaul : support for multiple NICs, performance improvement
- Add support for multiple NICs - Switch from polling to an event loop for the host networking to avoid latency and locking issues
This commit is contained in:
@@ -60,7 +60,6 @@
|
|||||||
#include <86box/device.h>
|
#include <86box/device.h>
|
||||||
#include <86box/pit.h>
|
#include <86box/pit.h>
|
||||||
#include <86box/random.h>
|
#include <86box/random.h>
|
||||||
#include <86box/timer.h>
|
|
||||||
#include <86box/nvr.h>
|
#include <86box/nvr.h>
|
||||||
#include <86box/machine.h>
|
#include <86box/machine.h>
|
||||||
#include <86box/bugger.h>
|
#include <86box/bugger.h>
|
||||||
@@ -85,6 +84,7 @@
|
|||||||
#include <86box/mo.h>
|
#include <86box/mo.h>
|
||||||
#include <86box/scsi_disk.h>
|
#include <86box/scsi_disk.h>
|
||||||
#include <86box/cdrom_image.h>
|
#include <86box/cdrom_image.h>
|
||||||
|
#include <86box/thread.h>
|
||||||
#include <86box/network.h>
|
#include <86box/network.h>
|
||||||
#include <86box/sound.h>
|
#include <86box/sound.h>
|
||||||
#include <86box/midi.h>
|
#include <86box/midi.h>
|
||||||
@@ -93,7 +93,6 @@
|
|||||||
#include <86box/ui.h>
|
#include <86box/ui.h>
|
||||||
#include <86box/path.h>
|
#include <86box/path.h>
|
||||||
#include <86box/plat.h>
|
#include <86box/plat.h>
|
||||||
#include <86box/thread.h>
|
|
||||||
#include <86box/version.h>
|
#include <86box/version.h>
|
||||||
#include <86box/gdbstub.h>
|
#include <86box/gdbstub.h>
|
||||||
#include <86box/machine_status.h>
|
#include <86box/machine_status.h>
|
||||||
@@ -951,8 +950,6 @@ pc_reset_hard_close(void)
|
|||||||
/* Close all the memory mappings. */
|
/* Close all the memory mappings. */
|
||||||
mem_close();
|
mem_close();
|
||||||
|
|
||||||
network_timer_stop();
|
|
||||||
|
|
||||||
/* Turn off timer processing to avoid potential segmentation faults. */
|
/* Turn off timer processing to avoid potential segmentation faults. */
|
||||||
timer_close();
|
timer_close();
|
||||||
|
|
||||||
@@ -1173,8 +1170,6 @@ pc_close(thread_t *ptr)
|
|||||||
/* Close all the memory mappings. */
|
/* Close all the memory mappings. */
|
||||||
mem_close();
|
mem_close();
|
||||||
|
|
||||||
network_timer_stop();
|
|
||||||
|
|
||||||
/* Turn off timer processing to avoid potential segmentation faults. */
|
/* Turn off timer processing to avoid potential segmentation faults. */
|
||||||
timer_close();
|
timer_close();
|
||||||
|
|
||||||
|
|||||||
133
src/config.c
133
src/config.c
@@ -55,6 +55,7 @@
|
|||||||
#include <86box/gameport.h>
|
#include <86box/gameport.h>
|
||||||
#include <86box/machine.h>
|
#include <86box/machine.h>
|
||||||
#include <86box/mouse.h>
|
#include <86box/mouse.h>
|
||||||
|
#include <86box/thread.h>
|
||||||
#include <86box/network.h>
|
#include <86box/network.h>
|
||||||
#include <86box/scsi.h>
|
#include <86box/scsi.h>
|
||||||
#include <86box/scsi_device.h>
|
#include <86box/scsi_device.h>
|
||||||
@@ -1131,45 +1132,89 @@ load_network(void)
|
|||||||
{
|
{
|
||||||
char *cat = "Network";
|
char *cat = "Network";
|
||||||
char *p;
|
char *p;
|
||||||
|
char temp[512];
|
||||||
|
int c = 0, min = 0;
|
||||||
|
|
||||||
|
/* Handle legacy configuration which supported only one NIC */
|
||||||
|
p = config_get_string(cat, "net_card", NULL);
|
||||||
|
if (p != NULL) {
|
||||||
|
net_cards_conf[c].device_num = network_card_get_from_internal_name(p);
|
||||||
|
|
||||||
p = config_get_string(cat, "net_type", NULL);
|
p = config_get_string(cat, "net_type", NULL);
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
if (!strcmp(p, "pcap") || !strcmp(p, "1"))
|
if (!strcmp(p, "pcap") || !strcmp(p, "1"))
|
||||||
network_type = NET_TYPE_PCAP;
|
net_cards_conf[c].net_type = NET_TYPE_PCAP;
|
||||||
else if (!strcmp(p, "slirp") || !strcmp(p, "2"))
|
else if (!strcmp(p, "slirp") || !strcmp(p, "2"))
|
||||||
network_type = NET_TYPE_SLIRP;
|
net_cards_conf[c].net_type = NET_TYPE_SLIRP;
|
||||||
else
|
else
|
||||||
network_type = NET_TYPE_NONE;
|
net_cards_conf[c].net_type = NET_TYPE_NONE;
|
||||||
} else
|
} else {
|
||||||
network_type = NET_TYPE_NONE;
|
net_cards_conf[c].net_type = NET_TYPE_NONE;
|
||||||
|
|
||||||
memset(network_host, '\0', sizeof(network_host));
|
|
||||||
p = config_get_string(cat, "net_host_device", NULL);
|
|
||||||
if (p == NULL) {
|
|
||||||
p = config_get_string(cat, "net_host_device", NULL);
|
|
||||||
if (p != NULL)
|
|
||||||
config_delete_var(cat, "net_host_device");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p = config_get_string(cat, "net_host_device", NULL);
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
if ((network_dev_to_id(p) == -1) || (network_ndev == 1)) {
|
if ((network_dev_to_id(p) == -1) || (network_ndev == 1)) {
|
||||||
if ((network_ndev == 1) && strcmp(network_host, "none")) {
|
if (network_ndev == 1) {
|
||||||
ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2094, (wchar_t *) IDS_2129);
|
ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2094, (wchar_t *) IDS_2129);
|
||||||
} else if (network_dev_to_id(p) == -1) {
|
} else if (network_dev_to_id(p) == -1) {
|
||||||
ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2095, (wchar_t *) IDS_2129);
|
ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2095, (wchar_t *) IDS_2129);
|
||||||
}
|
}
|
||||||
|
strcpy(net_cards_conf[c].host_dev_name, "none");
|
||||||
strcpy(network_host, "none");
|
|
||||||
} else {
|
} else {
|
||||||
strncpy(network_host, p, sizeof(network_host) - 1);
|
strncpy(net_cards_conf[c].host_dev_name, p, sizeof(net_cards_conf[c].host_dev_name) - 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
strcpy(net_cards_conf[c].host_dev_name, "none");
|
||||||
}
|
}
|
||||||
} else
|
|
||||||
strcpy(network_host, "none");
|
|
||||||
|
|
||||||
p = config_get_string(cat, "net_card", NULL);
|
min++;
|
||||||
if (p != NULL)
|
}
|
||||||
network_card = network_card_get_from_internal_name(p);
|
|
||||||
else
|
config_delete_var(cat, "net_card");
|
||||||
network_card = 0;
|
config_delete_var(cat, "net_type");
|
||||||
|
config_delete_var(cat, "net_host_device");
|
||||||
|
|
||||||
|
for (c = min; c < NET_CARD_MAX; c++) {
|
||||||
|
sprintf(temp, "net_%02i_card", c + 1);
|
||||||
|
p = config_get_string(cat, temp, NULL);
|
||||||
|
if (p != NULL) {
|
||||||
|
net_cards_conf[c].device_num = network_card_get_from_internal_name(p);
|
||||||
|
} else {
|
||||||
|
net_cards_conf[c].device_num = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(temp, "net_%02i_net_type", c + 1);
|
||||||
|
p = config_get_string(cat, temp, NULL);
|
||||||
|
if (p != NULL) {
|
||||||
|
if (!strcmp(p, "pcap") || !strcmp(p, "1")) {
|
||||||
|
net_cards_conf[c].net_type = NET_TYPE_PCAP;
|
||||||
|
} else if (!strcmp(p, "slirp") || !strcmp(p, "2")) {
|
||||||
|
net_cards_conf[c].net_type = NET_TYPE_SLIRP;
|
||||||
|
} else {
|
||||||
|
net_cards_conf[c].net_type = NET_TYPE_NONE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
net_cards_conf[c].net_type = NET_TYPE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(temp, "net_%02i_host_device", c + 1);
|
||||||
|
p = config_get_string(cat, temp, NULL);
|
||||||
|
if (p != NULL) {
|
||||||
|
if ((network_dev_to_id(p) == -1) || (network_ndev == 1)) {
|
||||||
|
if (network_ndev == 1) {
|
||||||
|
ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2094, (wchar_t *) IDS_2129);
|
||||||
|
} else if (network_dev_to_id(p) == -1) {
|
||||||
|
ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2095, (wchar_t *) IDS_2129);
|
||||||
|
}
|
||||||
|
strcpy(net_cards_conf[c].host_dev_name, "none");
|
||||||
|
} else {
|
||||||
|
strncpy(net_cards_conf[c].host_dev_name, p, sizeof(net_cards_conf[c].host_dev_name) - 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
strcpy(net_cards_conf[c].host_dev_name, "none");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load "Ports" section. */
|
/* Load "Ports" section. */
|
||||||
@@ -2688,29 +2733,41 @@ save_sound(void)
|
|||||||
static void
|
static void
|
||||||
save_network(void)
|
save_network(void)
|
||||||
{
|
{
|
||||||
|
int c = 0;
|
||||||
|
char temp[512];
|
||||||
char *cat = "Network";
|
char *cat = "Network";
|
||||||
|
|
||||||
if (network_type == NET_TYPE_NONE)
|
|
||||||
config_delete_var(cat, "net_type");
|
config_delete_var(cat, "net_type");
|
||||||
else
|
config_delete_var(cat, "net_host_device");
|
||||||
config_set_string(cat, "net_type",
|
config_delete_var(cat, "net_card");
|
||||||
(network_type == NET_TYPE_SLIRP) ? "slirp" : "pcap");
|
|
||||||
|
|
||||||
if (network_host[0] != '\0') {
|
for (c = 0; c < NET_CARD_MAX; c++) {
|
||||||
if (!strcmp(network_host, "none"))
|
sprintf(temp, "net_%02i_card", c + 1);
|
||||||
config_delete_var(cat, "net_host_device");
|
if (net_cards_conf[c].device_num == 0) {
|
||||||
else
|
config_delete_var(cat, temp);
|
||||||
config_set_string(cat, "net_host_device", network_host);
|
|
||||||
} else {
|
} else {
|
||||||
/* config_set_string(cat, "net_host_device", "none"); */
|
config_set_string(cat, temp, network_card_get_internal_name(net_cards_conf[c].device_num));
|
||||||
config_delete_var(cat, "net_host_device");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (network_card == 0)
|
sprintf(temp, "net_%02i_net_type", c + 1);
|
||||||
config_delete_var(cat, "net_card");
|
if (net_cards_conf[c].net_type == NET_TYPE_NONE) {
|
||||||
|
config_delete_var(cat, temp);
|
||||||
|
} else {
|
||||||
|
config_set_string(cat, temp,
|
||||||
|
(net_cards_conf[c].net_type == NET_TYPE_SLIRP) ? "slirp" : "pcap");
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(temp, "net_%02i_host_device", c + 1);
|
||||||
|
if (net_cards_conf[c].host_dev_name[0] != '\0') {
|
||||||
|
if (!strcmp(net_cards_conf[c].host_dev_name, "none"))
|
||||||
|
config_delete_var(cat, temp);
|
||||||
else
|
else
|
||||||
config_set_string(cat, "net_card",
|
config_set_string(cat, temp, net_cards_conf[c].host_dev_name);
|
||||||
network_card_get_internal_name(network_card));
|
} else {
|
||||||
|
/* config_set_string(cat, temp, "none"); */
|
||||||
|
config_delete_var(cat, temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
delete_section_if_empty(cat);
|
delete_section_if_empty(cat);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -184,11 +184,13 @@ typedef struct {
|
|||||||
int tx_timer_active;
|
int tx_timer_active;
|
||||||
|
|
||||||
void *priv;
|
void *priv;
|
||||||
|
netcard_t *card;
|
||||||
|
|
||||||
void (*interrupt)(void *priv, int set);
|
void (*interrupt)(void *priv, int set);
|
||||||
} dp8390_t;
|
} dp8390_t;
|
||||||
|
|
||||||
extern const device_t dp8390_device;
|
extern const device_t dp8390_device;
|
||||||
|
extern int dp3890_inst;
|
||||||
|
|
||||||
|
|
||||||
extern uint32_t dp8390_chipmem_read(dp8390_t *dev, uint32_t addr, unsigned int len);
|
extern uint32_t dp8390_chipmem_read(dp8390_t *dev, uint32_t addr, unsigned int len);
|
||||||
|
|||||||
22
src/include/86box/net_event.h
Normal file
22
src/include/86box/net_event.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#ifndef EMU_NET_EVENT_H
|
||||||
|
#define EMU_NET_EVENT_H
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
#ifdef _WIN32
|
||||||
|
HANDLE handle;
|
||||||
|
#else
|
||||||
|
int fds[2];
|
||||||
|
#endif
|
||||||
|
} net_evt_t;
|
||||||
|
|
||||||
|
extern void net_event_init(net_evt_t *event);
|
||||||
|
extern void net_event_set(net_evt_t *event);
|
||||||
|
extern void net_event_clear(net_evt_t *event);
|
||||||
|
extern void net_event_close(net_evt_t *event);
|
||||||
|
#ifdef _WIN32
|
||||||
|
extern HANDLE net_event_get_handle(net_evt_t *event);
|
||||||
|
#else
|
||||||
|
extern int net_event_get_fd(net_evt_t *event);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -52,8 +52,12 @@
|
|||||||
|
|
||||||
/* Network provider types. */
|
/* Network provider types. */
|
||||||
#define NET_TYPE_NONE 0 /* networking disabled */
|
#define NET_TYPE_NONE 0 /* networking disabled */
|
||||||
#define NET_TYPE_PCAP 1 /* use the (Win)Pcap API */
|
#define NET_TYPE_SLIRP 1 /* use the SLiRP port forwarder */
|
||||||
#define NET_TYPE_SLIRP 2 /* use the SLiRP port forwarder */
|
#define NET_TYPE_PCAP 2 /* use the (Win)Pcap API */
|
||||||
|
|
||||||
|
#define NET_MAX_FRAME 1518
|
||||||
|
#define NET_QUEUE_LEN 8
|
||||||
|
#define NET_CARD_MAX 4
|
||||||
|
|
||||||
/* Supported network cards. */
|
/* Supported network cards. */
|
||||||
enum {
|
enum {
|
||||||
@@ -64,6 +68,20 @@ enum {
|
|||||||
RTL8029AS
|
RTL8029AS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
NET_QUEUE_RX,
|
||||||
|
NET_QUEUE_TX_VM,
|
||||||
|
NET_QUEUE_TX_HOST
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int device_num;
|
||||||
|
int net_type;
|
||||||
|
char host_dev_name[128];
|
||||||
|
} netcard_conf_t;
|
||||||
|
|
||||||
|
extern netcard_conf_t net_cards_conf[NET_CARD_MAX];
|
||||||
|
extern int net_card_current;
|
||||||
|
|
||||||
typedef int (*NETRXCB)(void *, uint8_t *, int);
|
typedef int (*NETRXCB)(void *, uint8_t *, int);
|
||||||
typedef int (*NETWAITCB)(void *);
|
typedef int (*NETWAITCB)(void *);
|
||||||
@@ -71,21 +89,44 @@ typedef int (*NETSETLINKSTATE)(void *);
|
|||||||
|
|
||||||
|
|
||||||
typedef struct netpkt {
|
typedef struct netpkt {
|
||||||
void *priv;
|
uint8_t *data;
|
||||||
uint8_t data[65536]; /* Maximum length + 1 to round up to the nearest power of 2. */
|
|
||||||
int len;
|
int len;
|
||||||
|
uint64_t tsc;
|
||||||
struct netpkt *prev, *next;
|
|
||||||
} netpkt_t;
|
} netpkt_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const device_t *device;
|
netpkt_t packets[NET_QUEUE_LEN];
|
||||||
|
int size;
|
||||||
|
int head;
|
||||||
|
int tail;
|
||||||
|
} netqueue_t;
|
||||||
|
|
||||||
|
typedef struct _netcard_t netcard_t;
|
||||||
|
|
||||||
|
typedef struct netdrv_t {
|
||||||
|
void (*notify_in)(void *priv);
|
||||||
|
void *(*init)(const netcard_t *card, const uint8_t *mac_addr, void *priv);
|
||||||
|
void (*close)(void *priv);
|
||||||
void *priv;
|
void *priv;
|
||||||
|
} netdrv_t;
|
||||||
|
|
||||||
|
extern const netdrv_t net_pcap_drv;
|
||||||
|
extern const netdrv_t net_slirp_drv;
|
||||||
|
|
||||||
|
struct _netcard_t {
|
||||||
|
const device_t *device;
|
||||||
|
void *card_drv;
|
||||||
|
struct netdrv_t host_drv;
|
||||||
int (*poll)(void *);
|
int (*poll)(void *);
|
||||||
NETRXCB rx;
|
NETRXCB rx;
|
||||||
NETWAITCB wait;
|
NETWAITCB wait;
|
||||||
NETSETLINKSTATE set_link_state;
|
NETSETLINKSTATE set_link_state;
|
||||||
} netcard_t;
|
netqueue_t queues[3];
|
||||||
|
netpkt_t queued_pkt;
|
||||||
|
mutex_t *tx_mutex;
|
||||||
|
mutex_t *rx_mutex;
|
||||||
|
pc_timer_t timer;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char device[128];
|
char device[128];
|
||||||
@@ -100,31 +141,19 @@ extern "C" {
|
|||||||
/* Global variables. */
|
/* Global variables. */
|
||||||
extern int nic_do_log; /* config */
|
extern int nic_do_log; /* config */
|
||||||
extern int network_ndev;
|
extern int network_ndev;
|
||||||
extern int network_rx_pause;
|
|
||||||
extern netdev_t network_devs[32];
|
extern netdev_t network_devs[32];
|
||||||
|
|
||||||
|
|
||||||
/* Function prototypes. */
|
/* Function prototypes. */
|
||||||
extern void network_wait(uint8_t wait);
|
|
||||||
|
|
||||||
extern void network_init(void);
|
extern void network_init(void);
|
||||||
extern void network_attach(void *, uint8_t *, NETRXCB, NETWAITCB, NETSETLINKSTATE);
|
extern netcard_t *network_attach(void *card_drv, uint8_t *mac, NETRXCB rx, NETWAITCB wait, NETSETLINKSTATE set_link_state);
|
||||||
|
extern void netcard_close(netcard_t *card);
|
||||||
extern void network_close(void);
|
extern void network_close(void);
|
||||||
extern void network_reset(void);
|
extern void network_reset(void);
|
||||||
extern int network_available(void);
|
extern int network_available(void);
|
||||||
extern void network_tx(uint8_t *, int);
|
extern void network_tx(netcard_t *card, uint8_t *, int);
|
||||||
extern int network_tx_queue_check(void);
|
|
||||||
|
|
||||||
extern int net_pcap_prepare(netdev_t *);
|
extern int net_pcap_prepare(netdev_t *);
|
||||||
extern int net_pcap_init(void);
|
|
||||||
extern int net_pcap_reset(const netcard_t *, uint8_t *);
|
|
||||||
extern void net_pcap_close(void);
|
|
||||||
extern void net_pcap_in(uint8_t *, int);
|
|
||||||
|
|
||||||
extern int net_slirp_init(void);
|
|
||||||
extern int net_slirp_reset(const netcard_t *, uint8_t *);
|
|
||||||
extern void net_slirp_close(void);
|
|
||||||
extern void net_slirp_in(uint8_t *, int);
|
|
||||||
|
|
||||||
extern int network_dev_to_id(char *);
|
extern int network_dev_to_id(char *);
|
||||||
extern int network_card_available(int);
|
extern int network_card_available(int);
|
||||||
@@ -133,13 +162,8 @@ extern char *network_card_get_internal_name(int);
|
|||||||
extern int network_card_get_from_internal_name(char *);
|
extern int network_card_get_from_internal_name(char *);
|
||||||
extern const device_t *network_card_getdevice(int);
|
extern const device_t *network_card_getdevice(int);
|
||||||
|
|
||||||
extern void network_set_wait(int wait);
|
extern int network_tx_pop(netcard_t *card, netpkt_t *out_pkt);
|
||||||
extern int network_get_wait(void);
|
extern int network_rx_put(netcard_t *card, uint8_t *bufp, int len);
|
||||||
|
|
||||||
extern void network_timer_stop(void);
|
|
||||||
|
|
||||||
extern void network_queue_put(int tx, void *priv, uint8_t *data, int len);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
add_library(net OBJECT network.c net_pcap.c net_slirp.c net_dp8390.c net_3c503.c
|
add_library(net OBJECT network.c net_pcap.c net_slirp.c net_dp8390.c net_3c503.c
|
||||||
net_ne2000.c net_pcnet.c net_wd8003.c net_plip.c)
|
net_ne2000.c net_pcnet.c net_wd8003.c net_plip.c net_event.c)
|
||||||
|
|
||||||
option(SLIRP_EXTERNAL "Link against the system-provided libslirp library" OFF)
|
option(SLIRP_EXTERNAL "Link against the system-provided libslirp library" OFF)
|
||||||
mark_as_advanced(SLIRP_EXTERNAL)
|
mark_as_advanced(SLIRP_EXTERNAL)
|
||||||
|
|||||||
@@ -55,6 +55,8 @@
|
|||||||
#include <86box/mem.h>
|
#include <86box/mem.h>
|
||||||
#include <86box/random.h>
|
#include <86box/random.h>
|
||||||
#include <86box/device.h>
|
#include <86box/device.h>
|
||||||
|
#include <86box/thread.h>
|
||||||
|
#include <86box/timer.h>
|
||||||
#include <86box/network.h>
|
#include <86box/network.h>
|
||||||
#include <86box/net_dp8390.h>
|
#include <86box/net_dp8390.h>
|
||||||
#include <86box/net_3c503.h>
|
#include <86box/net_3c503.h>
|
||||||
@@ -592,7 +594,7 @@ threec503_nic_init(const device_t *info)
|
|||||||
dev->maclocal[5] = (mac & 0xff);
|
dev->maclocal[5] = (mac & 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->dp8390 = device_add(&dp8390_device);
|
dev->dp8390 = device_add_inst(&dp8390_device, dp3890_inst++);
|
||||||
dev->dp8390->priv = dev;
|
dev->dp8390->priv = dev;
|
||||||
dev->dp8390->interrupt = threec503_interrupt;
|
dev->dp8390->interrupt = threec503_interrupt;
|
||||||
dp8390_set_defaults(dev->dp8390, DP8390_FLAG_CHECK_CR | DP8390_FLAG_CLEAR_IRQ);
|
dp8390_set_defaults(dev->dp8390, DP8390_FLAG_CHECK_CR | DP8390_FLAG_CLEAR_IRQ);
|
||||||
@@ -617,7 +619,7 @@ threec503_nic_init(const device_t *info)
|
|||||||
dev->regs.gacfr = 0x09; /* Start with RAM mapping enabled. */
|
dev->regs.gacfr = 0x09; /* Start with RAM mapping enabled. */
|
||||||
|
|
||||||
/* Attach ourselves to the network module. */
|
/* Attach ourselves to the network module. */
|
||||||
network_attach(dev->dp8390, dev->dp8390->physaddr, dp8390_rx, NULL, NULL);
|
dev->dp8390->card = network_attach(dev->dp8390, dev->dp8390->physaddr, dp8390_rx, NULL, NULL);
|
||||||
|
|
||||||
return(dev);
|
return(dev);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,8 @@
|
|||||||
#define HAVE_STDARG_H
|
#define HAVE_STDARG_H
|
||||||
#include <86box/86box.h>
|
#include <86box/86box.h>
|
||||||
#include <86box/device.h>
|
#include <86box/device.h>
|
||||||
|
#include <86box/thread.h>
|
||||||
|
#include <86box/timer.h>
|
||||||
#include <86box/network.h>
|
#include <86box/network.h>
|
||||||
#include <86box/net_dp8390.h>
|
#include <86box/net_dp8390.h>
|
||||||
|
|
||||||
@@ -33,6 +35,7 @@ static void dp8390_tx(dp8390_t *dev, uint32_t val);
|
|||||||
static int dp8390_rx_common(void *priv, uint8_t *buf, int io_len);
|
static int dp8390_rx_common(void *priv, uint8_t *buf, int io_len);
|
||||||
int dp8390_rx(void *priv, uint8_t *buf, int io_len);
|
int dp8390_rx(void *priv, uint8_t *buf, int io_len);
|
||||||
|
|
||||||
|
int dp3890_inst = 0;
|
||||||
|
|
||||||
#ifdef ENABLE_DP8390_LOG
|
#ifdef ENABLE_DP8390_LOG
|
||||||
int dp8390_do_log = ENABLE_DP8390_LOG;
|
int dp8390_do_log = ENABLE_DP8390_LOG;
|
||||||
@@ -225,7 +228,7 @@ dp8390_write_cr(dp8390_t *dev, uint32_t val)
|
|||||||
/* Send the packet to the system driver */
|
/* Send the packet to the system driver */
|
||||||
dev->CR.tx_packet = 1;
|
dev->CR.tx_packet = 1;
|
||||||
|
|
||||||
network_tx(&dev->mem[(dev->tx_page_start * 256) - dev->mem_start], dev->tx_bytes);
|
network_tx(dev->card, &dev->mem[(dev->tx_page_start * 256) - dev->mem_start], dev->tx_bytes);
|
||||||
|
|
||||||
/* some more debug */
|
/* some more debug */
|
||||||
#ifdef ENABLE_DP8390_LOG
|
#ifdef ENABLE_DP8390_LOG
|
||||||
@@ -1099,13 +1102,14 @@ dp8390_close(void *priv)
|
|||||||
{
|
{
|
||||||
dp8390_t *dp8390 = (dp8390_t *) priv;
|
dp8390_t *dp8390 = (dp8390_t *) priv;
|
||||||
|
|
||||||
/* Make sure the platform layer is shut down. */
|
|
||||||
network_close();
|
|
||||||
|
|
||||||
if (dp8390) {
|
if (dp8390) {
|
||||||
if (dp8390->mem)
|
if (dp8390->mem)
|
||||||
free(dp8390->mem);
|
free(dp8390->mem);
|
||||||
|
|
||||||
|
if (dp8390->card) {
|
||||||
|
netcard_close(dp8390->card);
|
||||||
|
}
|
||||||
|
|
||||||
free(dp8390);
|
free(dp8390);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
76
src/network/net_event.c
Normal file
76
src/network/net_event.c
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
#ifdef _WIN32
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <86box/net_event.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
static void setup_fd(int fd)
|
||||||
|
{
|
||||||
|
fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||||
|
fcntl(fd, F_SETFL, O_NONBLOCK);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
net_event_init(net_evt_t *event)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
event->handle = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
|
#else
|
||||||
|
(void)pipe(event->fds);
|
||||||
|
setup_fd(event->fds[0]);
|
||||||
|
setup_fd(event->fds[1]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
net_event_set(net_evt_t *event)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
SetEvent(event->handle);
|
||||||
|
#else
|
||||||
|
(void)write(event->fds[1], "a", 1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
net_event_clear(net_evt_t *event)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
/* Do nothing on WIN32 since we use an auto-reset event */
|
||||||
|
#else
|
||||||
|
char dummy[1];
|
||||||
|
(void)read(event->fds[0], &dummy, sizeof(dummy));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
net_event_close(net_evt_t *event)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
CloseHandle(event->handle);
|
||||||
|
#else
|
||||||
|
close(event->fds[0]);
|
||||||
|
close(event->fds[1]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
HANDLE
|
||||||
|
net_event_get_handle(net_evt_t *event)
|
||||||
|
{
|
||||||
|
return event->handle;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int
|
||||||
|
net_event_get_fd(net_evt_t *event)
|
||||||
|
{
|
||||||
|
return event->fds[0];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -61,6 +61,8 @@
|
|||||||
#include <86box/pic.h>
|
#include <86box/pic.h>
|
||||||
#include <86box/random.h>
|
#include <86box/random.h>
|
||||||
#include <86box/device.h>
|
#include <86box/device.h>
|
||||||
|
#include <86box/thread.h>
|
||||||
|
#include <86box/timer.h>
|
||||||
#include <86box/network.h>
|
#include <86box/network.h>
|
||||||
#include <86box/net_dp8390.h>
|
#include <86box/net_dp8390.h>
|
||||||
#include <86box/net_ne2000.h>
|
#include <86box/net_ne2000.h>
|
||||||
@@ -973,7 +975,7 @@ nic_init(const device_t *info)
|
|||||||
dev->maclocal[5] = (mac & 0xff);
|
dev->maclocal[5] = (mac & 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->dp8390 = device_add(&dp8390_device);
|
dev->dp8390 = device_add_inst(&dp8390_device, dp3890_inst++);
|
||||||
dev->dp8390->priv = dev;
|
dev->dp8390->priv = dev;
|
||||||
dev->dp8390->interrupt = nic_interrupt;
|
dev->dp8390->interrupt = nic_interrupt;
|
||||||
|
|
||||||
@@ -1120,7 +1122,7 @@ nic_init(const device_t *info)
|
|||||||
nic_reset(dev);
|
nic_reset(dev);
|
||||||
|
|
||||||
/* Attach ourselves to the network module. */
|
/* Attach ourselves to the network module. */
|
||||||
network_attach(dev->dp8390, dev->dp8390->physaddr, dp8390_rx, NULL, NULL);
|
dev->dp8390->card = network_attach(dev->dp8390, dev->dp8390->physaddr, dp8390_rx, NULL, NULL);
|
||||||
|
|
||||||
nelog(1, "%s: %s attached IO=0x%X IRQ=%d\n", dev->name,
|
nelog(1, "%s: %s attached IO=0x%X IRQ=%d\n", dev->name,
|
||||||
dev->is_pci?"PCI":"ISA", dev->base_address, dev->base_irq);
|
dev->is_pci?"PCI":"ISA", dev->base_address, dev->base_irq);
|
||||||
|
|||||||
@@ -50,15 +50,38 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#include <winsock2.h>
|
||||||
|
#else
|
||||||
|
#include <poll.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define HAVE_STDARG_H
|
#define HAVE_STDARG_H
|
||||||
#include <86box/86box.h>
|
#include <86box/86box.h>
|
||||||
#include <86box/device.h>
|
#include <86box/device.h>
|
||||||
#include <86box/plat.h>
|
#include <86box/plat.h>
|
||||||
#include <86box/plat_dynld.h>
|
#include <86box/plat_dynld.h>
|
||||||
#include <86box/thread.h>
|
#include <86box/thread.h>
|
||||||
|
#include <86box/timer.h>
|
||||||
#include <86box/network.h>
|
#include <86box/network.h>
|
||||||
|
#include <86box/net_event.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
NET_EVENT_STOP = 0,
|
||||||
|
NET_EVENT_TX,
|
||||||
|
NET_EVENT_RX,
|
||||||
|
NET_EVENT_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <pcap/pcap.h>
|
||||||
|
#else
|
||||||
typedef int bpf_int32;
|
typedef int bpf_int32;
|
||||||
typedef unsigned int bpf_u_int32;
|
typedef unsigned int bpf_u_int32;
|
||||||
|
|
||||||
@@ -82,15 +105,10 @@ struct bpf_program {
|
|||||||
|
|
||||||
typedef struct pcap_if pcap_if_t;
|
typedef struct pcap_if pcap_if_t;
|
||||||
|
|
||||||
typedef struct net_timeval {
|
|
||||||
long tv_sec;
|
|
||||||
long tv_usec;
|
|
||||||
} net_timeval;
|
|
||||||
|
|
||||||
#define PCAP_ERRBUF_SIZE 256
|
#define PCAP_ERRBUF_SIZE 256
|
||||||
|
|
||||||
struct pcap_pkthdr {
|
struct pcap_pkthdr {
|
||||||
struct net_timeval ts;
|
struct timeval ts;
|
||||||
bpf_u_int32 caplen;
|
bpf_u_int32 caplen;
|
||||||
bpf_u_int32 len;
|
bpf_u_int32 len;
|
||||||
};
|
};
|
||||||
@@ -100,30 +118,51 @@ struct pcap_if {
|
|||||||
char *name;
|
char *name;
|
||||||
char *description;
|
char *description;
|
||||||
void *addresses;
|
void *addresses;
|
||||||
unsigned int flags;
|
bpf_u_int32 flags;
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void *pcap; /* handle to pcap lib instance */
|
||||||
|
netcard_t *card; /* netcard linked to us */
|
||||||
|
thread_t *poll_tid;
|
||||||
|
net_evt_t tx_event;
|
||||||
|
net_evt_t stop_event;
|
||||||
|
netpkt_t pkt;
|
||||||
|
uint8_t mac_addr[6];
|
||||||
|
} net_pcap_t;
|
||||||
|
|
||||||
static volatile void *pcap_handle; /* handle to WinPcap DLL */
|
typedef struct {
|
||||||
static volatile void *pcap; /* handle to WinPcap library */
|
char *intf_name;
|
||||||
static volatile thread_t *poll_tid;
|
uint8_t *mac_addr;
|
||||||
static const netcard_t *poll_card; /* netcard linked to us */
|
} net_pcap_params_t;
|
||||||
static event_t *poll_state;
|
|
||||||
|
|
||||||
|
static volatile void *libpcap_handle; /* handle to WinPcap DLL */
|
||||||
|
|
||||||
/* Pointers to the real functions. */
|
/* Pointers to the real functions. */
|
||||||
static const char *(*f_pcap_lib_version)(void);
|
static const char *(*f_pcap_lib_version)(void);
|
||||||
static int (*f_pcap_findalldevs)(pcap_if_t **,char *);
|
static int (*f_pcap_findalldevs)(pcap_if_t **,char *);
|
||||||
static void (*f_pcap_freealldevs)(void *);
|
static void (*f_pcap_freealldevs)(void *);
|
||||||
static void *(*f_pcap_open_live)(const char *,int,int,int,char *);
|
static void *(*f_pcap_open_live)(const char *,int,int,int,char *);
|
||||||
static int (*f_pcap_compile)(void *,void *,
|
static int (*f_pcap_compile)(void *,void *, const char *,int,bpf_u_int32);
|
||||||
const char *,int,bpf_u_int32);
|
|
||||||
static int (*f_pcap_setfilter)(void *,void *);
|
static int (*f_pcap_setfilter)(void *,void *);
|
||||||
static const unsigned char
|
static const unsigned char
|
||||||
*(*f_pcap_next)(void *,void *);
|
*(*f_pcap_next)(void *,void *);
|
||||||
static int (*f_pcap_sendpacket)(void *,const unsigned char *,int);
|
static int (*f_pcap_sendpacket)(void *,const unsigned char *,int);
|
||||||
static void (*f_pcap_close)(void *);
|
static void (*f_pcap_close)(void *);
|
||||||
static int (*f_pcap_setnonblock)(void*, int, char*);
|
static int (*f_pcap_setnonblock)(void*, int, char*);
|
||||||
|
static int (*f_pcap_set_immediate_mode)(void *, int);
|
||||||
|
static int (*f_pcap_set_promisc)(void *, int);
|
||||||
|
static int (*f_pcap_set_snaplen)(void *, int);
|
||||||
|
static void *(*f_pcap_create)(const char *, char*);
|
||||||
|
static int (*f_pcap_activate)(void *);
|
||||||
|
static void *(*f_pcap_geterr)(void *);
|
||||||
|
#ifdef _WIN32
|
||||||
|
static HANDLE (*f_pcap_getevent)(void *);
|
||||||
|
#else
|
||||||
|
static int (*f_pcap_get_selectable_fd)(void *);
|
||||||
|
#endif
|
||||||
|
|
||||||
static dllimp_t pcap_imports[] = {
|
static dllimp_t pcap_imports[] = {
|
||||||
{ "pcap_lib_version", &f_pcap_lib_version },
|
{ "pcap_lib_version", &f_pcap_lib_version },
|
||||||
{ "pcap_findalldevs", &f_pcap_findalldevs },
|
{ "pcap_findalldevs", &f_pcap_findalldevs },
|
||||||
@@ -135,14 +174,23 @@ static dllimp_t pcap_imports[] = {
|
|||||||
{ "pcap_sendpacket", &f_pcap_sendpacket },
|
{ "pcap_sendpacket", &f_pcap_sendpacket },
|
||||||
{ "pcap_close", &f_pcap_close },
|
{ "pcap_close", &f_pcap_close },
|
||||||
{ "pcap_setnonblock", &f_pcap_setnonblock },
|
{ "pcap_setnonblock", &f_pcap_setnonblock },
|
||||||
|
{ "pcap_set_immediate_mode", &f_pcap_set_immediate_mode},
|
||||||
|
{ "pcap_set_promisc", &f_pcap_set_promisc },
|
||||||
|
{ "pcap_set_snaplen", &f_pcap_set_snaplen },
|
||||||
|
{ "pcap_create", &f_pcap_create },
|
||||||
|
{ "pcap_activate", &f_pcap_activate },
|
||||||
|
{ "pcap_geterr", &f_pcap_geterr },
|
||||||
|
#ifdef _WIN32
|
||||||
|
{ "pcap_getevent", &f_pcap_getevent },
|
||||||
|
#else
|
||||||
|
{ "pcap_get_selectable_fd", &f_pcap_get_selectable_fd },
|
||||||
|
#endif
|
||||||
{ NULL, NULL },
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENABLE_PCAP_LOG
|
#ifdef ENABLE_PCAP_LOG
|
||||||
int pcap_do_log = ENABLE_PCAP_LOG;
|
int pcap_do_log = ENABLE_PCAP_LOG;
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pcap_log(const char *fmt, ...)
|
pcap_log(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
@@ -159,76 +207,118 @@ pcap_log(const char *fmt, ...)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Handle the receiving of frames from the channel. */
|
|
||||||
static void
|
static void
|
||||||
poll_thread(void *arg)
|
net_pcap_read_packet(net_pcap_t *pcap)
|
||||||
{
|
{
|
||||||
uint8_t *mac = (uint8_t *)arg;
|
|
||||||
uint8_t *data = NULL;
|
|
||||||
struct pcap_pkthdr h;
|
struct pcap_pkthdr h;
|
||||||
uint32_t mac_cmp32[2];
|
|
||||||
uint16_t mac_cmp16[2];
|
uint8_t *data = (uint8_t *) f_pcap_next((void *) pcap->pcap, &h);
|
||||||
event_t *evt;
|
if (!data)
|
||||||
int tx;
|
return;
|
||||||
|
|
||||||
|
network_rx_put(pcap->card, data, h.caplen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send a packet to the Pcap interface. */
|
||||||
|
void
|
||||||
|
net_pcap_in(void *pcap, uint8_t *bufp, int len)
|
||||||
|
{
|
||||||
|
if (pcap == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
f_pcap_sendpacket((void *)pcap, bufp, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
net_pcap_in_available(void *priv)
|
||||||
|
{
|
||||||
|
net_pcap_t *pcap = (net_pcap_t *)priv;
|
||||||
|
net_event_set(&pcap->tx_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
static void
|
||||||
|
net_pcap_thread(void *priv)
|
||||||
|
{
|
||||||
|
net_pcap_t *pcap = (net_pcap_t*)priv;
|
||||||
|
|
||||||
pcap_log("PCAP: polling started.\n");
|
pcap_log("PCAP: polling started.\n");
|
||||||
thread_set_event(poll_state);
|
|
||||||
|
|
||||||
/* Create a waitable event. */
|
HANDLE events[NET_EVENT_MAX];
|
||||||
pcap_log("PCAP: Creating event...\n");
|
events[NET_EVENT_STOP] = net_event_get_handle(&pcap->stop_event);
|
||||||
evt = thread_create_event();
|
events[NET_EVENT_TX] = net_event_get_handle(&pcap->tx_event);
|
||||||
|
events[NET_EVENT_RX] = f_pcap_getevent((void *)pcap->pcap);
|
||||||
|
|
||||||
|
bool run = true;
|
||||||
|
|
||||||
|
while (run) {
|
||||||
|
int ret = WaitForMultipleObjects(NET_EVENT_MAX, events, FALSE, INFINITE);
|
||||||
|
|
||||||
|
switch (ret - WAIT_OBJECT_0) {
|
||||||
|
case NET_EVENT_STOP:
|
||||||
|
net_event_clear(&pcap->stop_event);
|
||||||
|
run = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NET_EVENT_TX:
|
||||||
|
net_event_clear(&pcap->tx_event);
|
||||||
|
while (network_tx_pop(pcap->card, &pcap->pkt)) {
|
||||||
|
net_pcap_in(pcap->pcap, pcap->pkt.data, pcap->pkt.len);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NET_EVENT_RX:
|
||||||
|
net_pcap_read_packet(pcap);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pcap_log("PCAP: polling stopped.\n");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static void
|
||||||
|
net_pcap_thread(void *priv)
|
||||||
|
{
|
||||||
|
net_pcap_t *pcap = (net_pcap_t*)priv;
|
||||||
|
|
||||||
|
pcap_log("PCAP: polling started.\n");
|
||||||
|
|
||||||
|
struct pollfd pfd[NET_EVENT_MAX];
|
||||||
|
pfd[NET_EVENT_STOP].fd = net_event_get_fd(&pcap->stop_event);
|
||||||
|
pfd[NET_EVENT_STOP].events = POLLIN | POLLPRI;
|
||||||
|
|
||||||
|
pfd[NET_EVENT_TX].fd = net_event_get_fd(&pcap->tx_event);
|
||||||
|
pfd[NET_EVENT_TX].events = POLLIN | POLLPRI;
|
||||||
|
|
||||||
|
pfd[NET_EVENT_RX].fd = f_pcap_get_selectable_fd((void *) pcap->pcap);
|
||||||
|
pfd[NET_EVENT_RX].events = POLLIN | POLLPRI;
|
||||||
|
|
||||||
/* As long as the channel is open.. */
|
/* As long as the channel is open.. */
|
||||||
while (pcap != NULL) {
|
while (1) {
|
||||||
/* Request ownership of the device. */
|
poll(pfd, NET_EVENT_MAX, -1);
|
||||||
network_wait(1);
|
|
||||||
|
|
||||||
if (pcap == NULL) {
|
if (pfd[NET_EVENT_STOP].revents & POLLIN) {
|
||||||
network_wait(0);
|
net_event_clear(&pcap->stop_event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (network_get_wait() || (poll_card->set_link_state && poll_card->set_link_state(poll_card->priv)) || (poll_card->wait && poll_card->wait(poll_card->priv)))
|
if (pfd[NET_EVENT_TX].revents & POLLIN) {
|
||||||
data = NULL;
|
net_event_clear(&pcap->tx_event);
|
||||||
else
|
|
||||||
data = (uint8_t *)f_pcap_next((void *)pcap, &h);
|
|
||||||
if (data != NULL) {
|
|
||||||
/* Received MAC. */
|
|
||||||
mac_cmp32[0] = *(uint32_t *)(data+6);
|
|
||||||
mac_cmp16[0] = *(uint16_t *)(data+10);
|
|
||||||
|
|
||||||
/* Local MAC. */
|
if (network_tx_pop(pcap->card, &pcap->pkt)) {
|
||||||
mac_cmp32[1] = *(uint32_t *)mac;
|
net_pcap_in(pcap->pcap, pcap->pkt.data, pcap->pkt.len);
|
||||||
mac_cmp16[1] = *(uint16_t *)(mac+4);
|
|
||||||
if ((mac_cmp32[0] != mac_cmp32[1]) ||
|
|
||||||
(mac_cmp16[0] != mac_cmp16[1]))
|
|
||||||
network_queue_put(0, poll_card->priv, data, h.caplen);
|
|
||||||
else {
|
|
||||||
/* Mark as invalid packet. */
|
|
||||||
data = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for the next packet to arrive - network_do_tx() is called from there. */
|
if (pfd[NET_EVENT_RX].revents & POLLIN) {
|
||||||
tx = network_tx_queue_check();
|
net_pcap_read_packet(pcap);
|
||||||
|
|
||||||
/* Release ownership of the device. */
|
|
||||||
network_wait(0);
|
|
||||||
|
|
||||||
/* If we did not get anything, wait a while. */
|
|
||||||
if (!tx)
|
|
||||||
thread_wait_event(evt, 10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No longer needed. */
|
}
|
||||||
if (evt != NULL)
|
|
||||||
thread_destroy_event(evt);
|
|
||||||
|
|
||||||
pcap_log("PCAP: polling stopped.\n");
|
pcap_log("PCAP: polling stopped.\n");
|
||||||
if (poll_state != NULL)
|
|
||||||
thread_set_event(poll_state);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prepare the (Win)Pcap module for use.
|
* Prepare the (Win)Pcap module for use.
|
||||||
@@ -244,18 +334,18 @@ net_pcap_prepare(netdev_t *list)
|
|||||||
pcap_if_t *devlist, *dev;
|
pcap_if_t *devlist, *dev;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
/* Local variables. */
|
|
||||||
pcap = NULL;
|
|
||||||
|
|
||||||
/* Try loading the DLL. */
|
/* Try loading the DLL. */
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
pcap_handle = dynld_module("wpcap.dll", pcap_imports);
|
libpcap_handle = dynld_module("wpcap.dll", pcap_imports);
|
||||||
#elif defined __APPLE__
|
#elif defined __APPLE__
|
||||||
pcap_handle = dynld_module("libpcap.dylib", pcap_imports);
|
libpcap_handle = dynld_module("libpcap.dylib", pcap_imports);
|
||||||
#else
|
#else
|
||||||
pcap_handle = dynld_module("libpcap.so", pcap_imports);
|
libpcap_handle = dynld_module("libpcap.so", pcap_imports);
|
||||||
#endif
|
#endif
|
||||||
if (pcap_handle == NULL) return(-1);
|
if (libpcap_handle == NULL) {
|
||||||
|
pcap_log("PCAP: error loading pcap module\n");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Retrieve the device list from the local machine */
|
/* Retrieve the device list from the local machine */
|
||||||
if (f_pcap_findalldevs(&devlist, errbuf) == -1) {
|
if (f_pcap_findalldevs(&devlist, errbuf) == -1) {
|
||||||
@@ -292,141 +382,132 @@ net_pcap_prepare(netdev_t *list)
|
|||||||
/*
|
/*
|
||||||
* Initialize (Win)Pcap for use.
|
* Initialize (Win)Pcap for use.
|
||||||
*
|
*
|
||||||
* This is called on every 'cycle' of the emulator,
|
|
||||||
* if and as long the NetworkType is set to PCAP,
|
|
||||||
* and also as long as we have a NetCard defined.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
net_pcap_init(void)
|
|
||||||
{
|
|
||||||
char errbuf[PCAP_ERRBUF_SIZE];
|
|
||||||
char *str;
|
|
||||||
|
|
||||||
/* Did we already load the library? */
|
|
||||||
if (pcap_handle == NULL)
|
|
||||||
return(-1);
|
|
||||||
|
|
||||||
/* Get the PCAP library name and version. */
|
|
||||||
strcpy(errbuf, f_pcap_lib_version());
|
|
||||||
str = strchr(errbuf, '(');
|
|
||||||
if (str != NULL) *(str-1) = '\0';
|
|
||||||
pcap_log("PCAP: initializing, %s\n", errbuf);
|
|
||||||
|
|
||||||
/* Get the value of our capture interface. */
|
|
||||||
if ((network_host[0] == '\0') || !strcmp(network_host, "none")) {
|
|
||||||
pcap_log("PCAP: no interface configured!\n");
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
poll_tid = NULL;
|
|
||||||
poll_state = NULL;
|
|
||||||
poll_card = NULL;
|
|
||||||
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Close up shop. */
|
|
||||||
void
|
|
||||||
net_pcap_close(void)
|
|
||||||
{
|
|
||||||
void *pc;
|
|
||||||
|
|
||||||
if (pcap == NULL) return;
|
|
||||||
|
|
||||||
pcap_log("PCAP: closing.\n");
|
|
||||||
|
|
||||||
/* Tell the polling thread to shut down. */
|
|
||||||
pc = (void *)pcap; pcap = NULL;
|
|
||||||
|
|
||||||
/* Tell the thread to terminate. */
|
|
||||||
if (poll_tid != NULL) {
|
|
||||||
/* Wait for the thread to finish. */
|
|
||||||
pcap_log("PCAP: waiting for thread to end...\n");
|
|
||||||
thread_wait_event(poll_state, -1);
|
|
||||||
pcap_log("PCAP: thread ended\n");
|
|
||||||
thread_destroy_event(poll_state);
|
|
||||||
|
|
||||||
poll_tid = NULL;
|
|
||||||
poll_state = NULL;
|
|
||||||
poll_card = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* OK, now shut down Pcap itself. */
|
|
||||||
f_pcap_close(pc);
|
|
||||||
pcap = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reset (Win)Pcap and activate it.
|
|
||||||
*
|
|
||||||
* This is called on every 'cycle' of the emulator,
|
|
||||||
* if and as long the NetworkType is set to PCAP,
|
|
||||||
* and also as long as we have a NetCard defined.
|
|
||||||
*
|
|
||||||
* We already know we have PCAP available, as this
|
* We already know we have PCAP available, as this
|
||||||
* is called when the network activates itself and
|
* is called when the network activates itself and
|
||||||
* tries to attach to the network module.
|
* tries to attach to the network module.
|
||||||
*/
|
*/
|
||||||
int
|
void *
|
||||||
net_pcap_reset(const netcard_t *card, uint8_t *mac)
|
net_pcap_init(const netcard_t *card, const uint8_t *mac_addr, void *priv)
|
||||||
{
|
{
|
||||||
char errbuf[PCAP_ERRBUF_SIZE];
|
char errbuf[PCAP_ERRBUF_SIZE];
|
||||||
|
char *str;
|
||||||
char filter_exp[255];
|
char filter_exp[255];
|
||||||
struct bpf_program fp;
|
struct bpf_program fp;
|
||||||
|
|
||||||
/* Open a PCAP live channel. */
|
char *intf_name = (char*)priv;
|
||||||
if ((pcap = f_pcap_open_live(network_host, /* interface name */
|
|
||||||
1518, /* max packet size */
|
/* Did we already load the library? */
|
||||||
1, /* promiscuous mode? */
|
if (libpcap_handle == NULL) {
|
||||||
10, /* timeout in msec */
|
pcap_log("PCAP: net_pcap_init without handle.\n");
|
||||||
errbuf)) == NULL) { /* error buffer */
|
return NULL;
|
||||||
pcap_log(" Unable to open device: %s!\n", network_host);
|
|
||||||
return(-1);
|
|
||||||
}
|
}
|
||||||
if (f_pcap_setnonblock((void*)pcap, 1, errbuf) != 0)
|
|
||||||
|
/* Get the PCAP library name and version. */
|
||||||
|
strcpy(errbuf, f_pcap_lib_version());
|
||||||
|
str = strchr(errbuf, '(');
|
||||||
|
if (str != NULL)
|
||||||
|
*(str - 1) = '\0';
|
||||||
|
pcap_log("PCAP: initializing, %s\n", errbuf);
|
||||||
|
|
||||||
|
/* Get the value of our capture interface. */
|
||||||
|
if ((intf_name[0] == '\0') || !strcmp(intf_name, "none")) {
|
||||||
|
pcap_log("PCAP: no interface configured!\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pcap_log("PCAP: interface: %s\n", intf_name);
|
||||||
|
|
||||||
|
net_pcap_t *pcap = calloc(1, sizeof(net_pcap_t));
|
||||||
|
pcap->card = (netcard_t *)card;
|
||||||
|
memcpy(pcap->mac_addr, mac_addr, sizeof(pcap->mac_addr));
|
||||||
|
|
||||||
|
if ((pcap->pcap = f_pcap_create(intf_name, errbuf)) == NULL) {
|
||||||
|
pcap_log(" Unable to open device: %s!\n", intf_name);
|
||||||
|
free(pcap);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f_pcap_setnonblock((void *) pcap->pcap, 1, errbuf) != 0)
|
||||||
pcap_log("PCAP: failed nonblock %s\n", errbuf);
|
pcap_log("PCAP: failed nonblock %s\n", errbuf);
|
||||||
|
|
||||||
pcap_log("PCAP: interface: %s\n", network_host);
|
if (f_pcap_set_immediate_mode((void *) pcap->pcap, 1) != 0)
|
||||||
|
pcap_log("PCAP: error setting immediate mode\n");
|
||||||
|
|
||||||
|
if (f_pcap_set_promisc((void *) pcap->pcap, 1) != 0)
|
||||||
|
pcap_log("PCAP: error enabling promiscuous mode\n");
|
||||||
|
|
||||||
|
if (f_pcap_set_snaplen((void *) pcap->pcap, NET_MAX_FRAME) != 0)
|
||||||
|
pcap_log("PCAP: error setting snaplen\n");
|
||||||
|
|
||||||
|
if (f_pcap_activate((void *) pcap->pcap) != 0) {
|
||||||
|
pcap_log("PCAP: failed pcap_activate");
|
||||||
|
f_pcap_close((void *) pcap->pcap);
|
||||||
|
free(pcap);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Create a MAC address based packet filter. */
|
/* Create a MAC address based packet filter. */
|
||||||
pcap_log("PCAP: installing filter for MAC=%02x:%02x:%02x:%02x:%02x:%02x\n",
|
pcap_log("PCAP: installing filter for MAC=%02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
|
||||||
sprintf(filter_exp,
|
sprintf(filter_exp,
|
||||||
"( ((ether dst ff:ff:ff:ff:ff:ff) or (ether dst %02x:%02x:%02x:%02x:%02x:%02x)) and not (ether src %02x:%02x:%02x:%02x:%02x:%02x) )",
|
"( ((ether dst ff:ff:ff:ff:ff:ff) or (ether dst %02x:%02x:%02x:%02x:%02x:%02x)) and not (ether src %02x:%02x:%02x:%02x:%02x:%02x) )",
|
||||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
|
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5],
|
||||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
|
||||||
if (f_pcap_compile((void *)pcap, &fp, filter_exp, 0, 0xffffffff) != -1) {
|
if (f_pcap_compile((void *) pcap->pcap, &fp, filter_exp, 0, 0xffffffff) != -1) {
|
||||||
if (f_pcap_setfilter((void *)pcap, &fp) != 0) {
|
if (f_pcap_setfilter((void *) pcap->pcap, &fp) != 0) {
|
||||||
pcap_log("PCAP: error installing filter (%s) !\n", filter_exp);
|
pcap_log("PCAP: error installing filter (%s) !\n", filter_exp);
|
||||||
f_pcap_close((void *)pcap);
|
f_pcap_close((void *) pcap->pcap);
|
||||||
return(-1);
|
free(pcap);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pcap_log("PCAP: could not compile filter (%s) !\n", filter_exp);
|
pcap_log("PCAP: could not compile filter (%s) : %s!\n", filter_exp, f_pcap_geterr((void*)pcap->pcap));
|
||||||
f_pcap_close((void *)pcap);
|
f_pcap_close((void *) pcap->pcap);
|
||||||
return(-1);
|
free(pcap);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save the callback info. */
|
pcap->pkt.data = calloc(1, NET_MAX_FRAME);
|
||||||
poll_card = card;
|
net_event_init(&pcap->tx_event);
|
||||||
|
net_event_init(&pcap->stop_event);
|
||||||
|
pcap->poll_tid = thread_create(net_pcap_thread, pcap);
|
||||||
|
|
||||||
pcap_log("PCAP: starting thread..\n");
|
return pcap;
|
||||||
poll_state = thread_create_event();
|
|
||||||
poll_tid = thread_create(poll_thread, mac);
|
|
||||||
thread_wait_event(poll_state, -1);
|
|
||||||
|
|
||||||
return(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Close up shop. */
|
||||||
/* Send a packet to the Pcap interface. */
|
|
||||||
void
|
void
|
||||||
net_pcap_in(uint8_t *bufp, int len)
|
net_pcap_close(void *priv)
|
||||||
{
|
{
|
||||||
if (pcap == NULL)
|
if (!priv)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
f_pcap_sendpacket((void *)pcap, bufp, len);
|
net_pcap_t *pcap = (net_pcap_t *)priv;
|
||||||
|
|
||||||
|
pcap_log("PCAP: closing.\n");
|
||||||
|
|
||||||
|
/* Tell the thread to terminate. */
|
||||||
|
net_event_set(&pcap->stop_event);
|
||||||
|
|
||||||
|
/* Wait for the thread to finish. */
|
||||||
|
pcap_log("PCAP: waiting for thread to end...\n");
|
||||||
|
thread_wait(pcap->poll_tid);
|
||||||
|
pcap_log("PCAP: thread ended\n");
|
||||||
|
|
||||||
|
free(pcap->pkt.data);
|
||||||
|
|
||||||
|
/* OK, now shut down Pcap itself. */
|
||||||
|
f_pcap_close((void*)pcap->pcap);
|
||||||
|
|
||||||
|
net_event_close(&pcap->tx_event);
|
||||||
|
net_event_close(&pcap->stop_event);
|
||||||
|
|
||||||
|
free(pcap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const netdrv_t net_pcap_drv = {
|
||||||
|
&net_pcap_in_available,
|
||||||
|
&net_pcap_init,
|
||||||
|
&net_pcap_close,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|||||||
@@ -41,6 +41,8 @@
|
|||||||
#include <86box/random.h>
|
#include <86box/random.h>
|
||||||
#include <86box/device.h>
|
#include <86box/device.h>
|
||||||
#include <86box/isapnp.h>
|
#include <86box/isapnp.h>
|
||||||
|
#include <86box/timer.h>
|
||||||
|
#include <86box/thread.h>
|
||||||
#include <86box/network.h>
|
#include <86box/network.h>
|
||||||
#include <86box/net_pcnet.h>
|
#include <86box/net_pcnet.h>
|
||||||
#include <86box/bswap.h>
|
#include <86box/bswap.h>
|
||||||
@@ -259,6 +261,7 @@ typedef struct {
|
|||||||
int transfer_size;
|
int transfer_size;
|
||||||
uint8_t maclocal[6]; /* configured MAC (local) address */
|
uint8_t maclocal[6]; /* configured MAC (local) address */
|
||||||
pc_timer_t timer, timer_soft_int, timer_restore;
|
pc_timer_t timer, timer_soft_int, timer_restore;
|
||||||
|
netcard_t *netcard;
|
||||||
} nic_t;
|
} nic_t;
|
||||||
|
|
||||||
/** @todo All structs: big endian? */
|
/** @todo All structs: big endian? */
|
||||||
@@ -1528,7 +1531,7 @@ pcnetAsyncTransmit(nic_t *dev)
|
|||||||
pcnetReceiveNoSync(dev, dev->abLoopBuf, dev->xmit_pos);
|
pcnetReceiveNoSync(dev, dev->abLoopBuf, dev->xmit_pos);
|
||||||
} else {
|
} else {
|
||||||
pcnetlog(3, "%s: pcnetAsyncTransmit: transmit loopbuf stp and enp, xmit pos = %d\n", dev->name, dev->xmit_pos);
|
pcnetlog(3, "%s: pcnetAsyncTransmit: transmit loopbuf stp and enp, xmit pos = %d\n", dev->name, dev->xmit_pos);
|
||||||
network_tx(dev->abLoopBuf, dev->xmit_pos);
|
network_tx(dev->netcard, dev->abLoopBuf, dev->xmit_pos);
|
||||||
}
|
}
|
||||||
} else if (cb == 4096) {
|
} else if (cb == 4096) {
|
||||||
/* The Windows NT4 pcnet driver sometimes marks the first
|
/* The Windows NT4 pcnet driver sometimes marks the first
|
||||||
@@ -1639,7 +1642,7 @@ pcnetAsyncTransmit(nic_t *dev)
|
|||||||
pcnetReceiveNoSync(dev, dev->abLoopBuf, dev->xmit_pos);
|
pcnetReceiveNoSync(dev, dev->abLoopBuf, dev->xmit_pos);
|
||||||
} else {
|
} else {
|
||||||
pcnetlog(3, "%s: pcnetAsyncTransmit: transmit loopbuf enp\n", dev->name);
|
pcnetlog(3, "%s: pcnetAsyncTransmit: transmit loopbuf enp\n", dev->name);
|
||||||
network_tx(dev->abLoopBuf, dev->xmit_pos);
|
network_tx(dev->netcard, dev->abLoopBuf, dev->xmit_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write back the TMD, pass it to the host */
|
/* Write back the TMD, pass it to the host */
|
||||||
@@ -3051,7 +3054,7 @@ pcnet_init(const device_t *info)
|
|||||||
pcnetHardReset(dev);
|
pcnetHardReset(dev);
|
||||||
|
|
||||||
/* Attach ourselves to the network module. */
|
/* Attach ourselves to the network module. */
|
||||||
network_attach(dev, dev->aPROM, pcnetReceiveNoSync, pcnetWaitReceiveAvail, pcnetSetLinkState);
|
dev->netcard = network_attach(dev, dev->aPROM, pcnetReceiveNoSync, pcnetWaitReceiveAvail, pcnetSetLinkState);
|
||||||
|
|
||||||
timer_add(&dev->timer, pcnetPollTimer, dev, 0);
|
timer_add(&dev->timer, pcnetPollTimer, dev, 0);
|
||||||
|
|
||||||
@@ -3071,8 +3074,7 @@ pcnet_close(void *priv)
|
|||||||
|
|
||||||
pcnetlog(1, "%s: closed\n", dev->name);
|
pcnetlog(1, "%s: closed\n", dev->name);
|
||||||
|
|
||||||
/* Make sure the platform layer is shut down. */
|
netcard_close(dev->netcard);
|
||||||
network_close();
|
|
||||||
|
|
||||||
if (dev) {
|
if (dev) {
|
||||||
free(dev);
|
free(dev);
|
||||||
|
|||||||
@@ -31,6 +31,8 @@
|
|||||||
#include <86box/timer.h>
|
#include <86box/timer.h>
|
||||||
#include <86box/pit.h>
|
#include <86box/pit.h>
|
||||||
#include <86box/device.h>
|
#include <86box/device.h>
|
||||||
|
#include <86box/thread.h>
|
||||||
|
#include <86box/timer.h>
|
||||||
#include <86box/network.h>
|
#include <86box/network.h>
|
||||||
#include <86box/net_plip.h>
|
#include <86box/net_plip.h>
|
||||||
|
|
||||||
@@ -70,6 +72,7 @@ typedef struct
|
|||||||
|
|
||||||
uint8_t *rx_pkt, rx_checksum, rx_return_state;
|
uint8_t *rx_pkt, rx_checksum, rx_return_state;
|
||||||
uint16_t rx_len, rx_ptr;
|
uint16_t rx_len, rx_ptr;
|
||||||
|
netcard_t *card;
|
||||||
} plip_t;
|
} plip_t;
|
||||||
|
|
||||||
|
|
||||||
@@ -117,8 +120,6 @@ timeout_timer(void *priv)
|
|||||||
dev->rx_pkt = NULL;
|
dev->rx_pkt = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
network_rx_pause = 0;
|
|
||||||
|
|
||||||
timer_disable(&dev->timeout_timer);
|
timer_disable(&dev->timeout_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,7 +230,7 @@ plip_write_data(uint8_t val, void *priv)
|
|||||||
|
|
||||||
/* Transmit packet. */
|
/* Transmit packet. */
|
||||||
plip_log(2, "PLIP: transmitting %d-byte packet\n", dev->tx_len);
|
plip_log(2, "PLIP: transmitting %d-byte packet\n", dev->tx_len);
|
||||||
network_tx(dev->tx_pkt, dev->tx_len);
|
network_tx(dev->card, dev->tx_pkt, dev->tx_len);
|
||||||
} else {
|
} else {
|
||||||
plip_log(1, "PLIP: checksum error: expected %02X, got %02X\n", dev->tx_checksum_calc, dev->tx_checksum);
|
plip_log(1, "PLIP: checksum error: expected %02X, got %02X\n", dev->tx_checksum_calc, dev->tx_checksum);
|
||||||
}
|
}
|
||||||
@@ -381,7 +382,6 @@ plip_receive_packet(plip_t *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!dev->rx_pkt || !dev->rx_len) { /* unpause RX queue if there's no packet to receive */
|
if (!dev->rx_pkt || !dev->rx_len) { /* unpause RX queue if there's no packet to receive */
|
||||||
network_rx_pause = 0;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -432,8 +432,6 @@ plip_rx(void *priv, uint8_t *buf, int io_len)
|
|||||||
if (!(dev->rx_pkt = malloc(io_len))) /* unlikely */
|
if (!(dev->rx_pkt = malloc(io_len))) /* unlikely */
|
||||||
fatal("PLIP: unable to allocate rx_pkt\n");
|
fatal("PLIP: unable to allocate rx_pkt\n");
|
||||||
|
|
||||||
network_rx_pause = 1; /* make sure we don't get any more packets while processing this one */
|
|
||||||
|
|
||||||
/* Copy this packet to our buffer. */
|
/* Copy this packet to our buffer. */
|
||||||
dev->rx_len = io_len;
|
dev->rx_len = io_len;
|
||||||
memcpy(dev->rx_pkt, buf, dev->rx_len);
|
memcpy(dev->rx_pkt, buf, dev->rx_len);
|
||||||
@@ -478,7 +476,7 @@ plip_net_init(const device_t *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
plip_log(1, " (attached to LPT)\n");
|
plip_log(1, " (attached to LPT)\n");
|
||||||
network_attach(instance, instance->mac, plip_rx, NULL, NULL);
|
instance->card = network_attach(instance, instance->mac, plip_rx, NULL, NULL);
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
@@ -487,6 +485,9 @@ plip_net_init(const device_t *info)
|
|||||||
static void
|
static void
|
||||||
plip_close(void *priv)
|
plip_close(void *priv)
|
||||||
{
|
{
|
||||||
|
if (instance->card) {
|
||||||
|
netcard_close(instance->card);
|
||||||
|
}
|
||||||
free(priv);
|
free(priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,52 +24,51 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <inttypes.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <slirp/libslirp.h>
|
#include <slirp/libslirp.h>
|
||||||
#define HAVE_STDARG_H
|
#define HAVE_STDARG_H
|
||||||
#include <86box/86box.h>
|
#include <86box/86box.h>
|
||||||
#include <86box/device.h>
|
#include <86box/device.h>
|
||||||
#include <86box/plat.h>
|
#include <86box/plat.h>
|
||||||
#include <86box/thread.h>
|
#include <86box/thread.h>
|
||||||
|
#include <86box/timer.h>
|
||||||
#include <86box/network.h>
|
#include <86box/network.h>
|
||||||
#include <86box/machine.h>
|
#include <86box/machine.h>
|
||||||
#include <86box/timer.h>
|
|
||||||
#include <86box/config.h>
|
#include <86box/config.h>
|
||||||
|
#include <86box/video.h>
|
||||||
|
#ifdef _WIN32
|
||||||
/* SLiRP can use poll() or select() for socket polling.
|
#define WIN32_LEAN_AND_MEAN
|
||||||
poll() is best on *nix but slow and limited on Windows. */
|
#include <windows.h>
|
||||||
#ifndef _WIN32
|
#else
|
||||||
# define SLIRP_USE_POLL 1
|
#include <poll.h>
|
||||||
#endif
|
|
||||||
#ifdef SLIRP_USE_POLL
|
|
||||||
# ifdef _WIN32
|
|
||||||
# include <winsock2.h>
|
|
||||||
# define poll WSAPoll
|
|
||||||
# else
|
|
||||||
# include <poll.h>
|
|
||||||
# endif
|
|
||||||
#endif
|
#endif
|
||||||
|
#include <86box/net_event.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
NET_EVENT_STOP = 0,
|
||||||
|
NET_EVENT_TX,
|
||||||
|
NET_EVENT_RX,
|
||||||
|
NET_EVENT_MAX
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Slirp *slirp;
|
Slirp *slirp;
|
||||||
void *mac;
|
uint8_t mac_addr[6];
|
||||||
const netcard_t *card; /* netcard attached to us */
|
netcard_t *card; /* netcard attached to us */
|
||||||
volatile thread_t *poll_tid;
|
thread_t *poll_tid;
|
||||||
event_t *poll_state;
|
net_evt_t tx_event;
|
||||||
uint8_t stop;
|
net_evt_t stop_event;
|
||||||
#ifdef SLIRP_USE_POLL
|
netpkt_t pkt;
|
||||||
|
#ifdef _WIN32
|
||||||
|
HANDLE sock_event;
|
||||||
|
#else
|
||||||
uint32_t pfd_len, pfd_size;
|
uint32_t pfd_len, pfd_size;
|
||||||
struct pollfd *pfd;
|
struct pollfd *pfd;
|
||||||
#else
|
|
||||||
uint32_t nfds;
|
|
||||||
fd_set rfds, wfds, xfds;
|
|
||||||
#endif
|
#endif
|
||||||
} slirp_t;
|
} net_slirp_t;
|
||||||
|
|
||||||
static slirp_t *slirp;
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENABLE_SLIRP_LOG
|
#ifdef ENABLE_SLIRP_LOG
|
||||||
int slirp_do_log = ENABLE_SLIRP_LOG;
|
int slirp_do_log = ENABLE_SLIRP_LOG;
|
||||||
@@ -101,7 +100,7 @@ net_slirp_guest_error(const char *msg, void *opaque)
|
|||||||
static int64_t
|
static int64_t
|
||||||
net_slirp_clock_get_ns(void *opaque)
|
net_slirp_clock_get_ns(void *opaque)
|
||||||
{
|
{
|
||||||
return (TIMER_USEC ? (tsc / (TIMER_USEC / 1000)) : 0);
|
return (int64_t)((double)tsc / cpuclock * 1000000000.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -118,13 +117,14 @@ static void
|
|||||||
net_slirp_timer_free(void *timer, void *opaque)
|
net_slirp_timer_free(void *timer, void *opaque)
|
||||||
{
|
{
|
||||||
timer_stop(timer);
|
timer_stop(timer);
|
||||||
|
free(timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
net_slirp_timer_mod(void *timer, int64_t expire_timer, void *opaque)
|
net_slirp_timer_mod(void *timer, int64_t expire_timer, void *opaque)
|
||||||
{
|
{
|
||||||
timer_set_delay_u64(timer, expire_timer);
|
timer_on_auto(timer, expire_timer * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -154,12 +154,11 @@ net_slirp_notify(void *opaque)
|
|||||||
ssize_t
|
ssize_t
|
||||||
net_slirp_send_packet(const void *qp, size_t pkt_len, void *opaque)
|
net_slirp_send_packet(const void *qp, size_t pkt_len, void *opaque)
|
||||||
{
|
{
|
||||||
slirp_t *slirp = (slirp_t *) opaque;
|
net_slirp_t *slirp = (net_slirp_t *) opaque;
|
||||||
uint8_t *mac = slirp->mac;
|
uint8_t *mac = slirp->mac_addr;
|
||||||
uint32_t mac_cmp32[2];
|
uint32_t mac_cmp32[2];
|
||||||
uint16_t mac_cmp16[2];
|
uint16_t mac_cmp16[2];
|
||||||
|
|
||||||
if (!(slirp->card->set_link_state && slirp->card->set_link_state(slirp->card->priv)) && !(slirp->card->wait && slirp->card->wait(slirp->card->priv))) {
|
|
||||||
slirp_log("SLiRP: received %d-byte packet\n", pkt_len);
|
slirp_log("SLiRP: received %d-byte packet\n", pkt_len);
|
||||||
|
|
||||||
/* Received MAC. */
|
/* Received MAC. */
|
||||||
@@ -169,25 +168,38 @@ net_slirp_send_packet(const void *qp, size_t pkt_len, void *opaque)
|
|||||||
/* Local MAC. */
|
/* Local MAC. */
|
||||||
mac_cmp32[1] = *(uint32_t *) mac;
|
mac_cmp32[1] = *(uint32_t *) mac;
|
||||||
mac_cmp16[1] = *(uint16_t *) (mac + 4);
|
mac_cmp16[1] = *(uint16_t *) (mac + 4);
|
||||||
if ((mac_cmp32[0] != mac_cmp32[1]) ||
|
if ((mac_cmp32[0] != mac_cmp32[1]) || (mac_cmp16[0] != mac_cmp16[1])) {
|
||||||
(mac_cmp16[0] != mac_cmp16[1])) {
|
network_rx_put(slirp->card, (uint8_t *) qp, pkt_len);
|
||||||
network_queue_put(0, slirp->card->priv, (uint8_t *) qp, pkt_len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return pkt_len;
|
return pkt_len;
|
||||||
} else {
|
|
||||||
slirp_log("SLiRP: ignored %d-byte packet\n", pkt_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
static int
|
static int
|
||||||
net_slirp_add_poll(int fd, int events, void *opaque)
|
net_slirp_add_poll(int fd, int events, void *opaque)
|
||||||
{
|
{
|
||||||
slirp_t *slirp = (slirp_t *) opaque;
|
net_slirp_t *slirp = (net_slirp_t *) opaque;
|
||||||
#ifdef SLIRP_USE_POLL
|
long bitmask = 0;
|
||||||
|
if (events & SLIRP_POLL_IN)
|
||||||
|
bitmask |= FD_READ | FD_ACCEPT;
|
||||||
|
if (events & SLIRP_POLL_OUT)
|
||||||
|
bitmask |= FD_WRITE | FD_CONNECT;
|
||||||
|
if (events & SLIRP_POLL_HUP)
|
||||||
|
bitmask |= FD_CLOSE;
|
||||||
|
if (events & SLIRP_POLL_PRI)
|
||||||
|
bitmask |= FD_OOB;
|
||||||
|
|
||||||
|
WSAEventSelect(fd, slirp->sock_event, bitmask);
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static int
|
||||||
|
net_slirp_add_poll(int fd, int events, void *opaque)
|
||||||
|
{
|
||||||
|
net_slirp_t *slirp = (net_slirp_t *) opaque;
|
||||||
|
|
||||||
if (slirp->pfd_len >= slirp->pfd_size) {
|
if (slirp->pfd_len >= slirp->pfd_size) {
|
||||||
int newsize = slirp->pfd_size + 16;
|
int newsize = slirp->pfd_size + 16;
|
||||||
struct pollfd *new = realloc(slirp->pfd, newsize * sizeof(struct pollfd));
|
struct pollfd *new = realloc(slirp->pfd, newsize * sizeof(struct pollfd));
|
||||||
@@ -200,92 +212,73 @@ net_slirp_add_poll(int fd, int events, void *opaque)
|
|||||||
int idx = slirp->pfd_len++;
|
int idx = slirp->pfd_len++;
|
||||||
slirp->pfd[idx].fd = fd;
|
slirp->pfd[idx].fd = fd;
|
||||||
int pevents = 0;
|
int pevents = 0;
|
||||||
if (events & SLIRP_POLL_IN) pevents |= POLLIN;
|
if (events & SLIRP_POLL_IN)
|
||||||
if (events & SLIRP_POLL_OUT) pevents |= POLLOUT;
|
pevents |= POLLIN;
|
||||||
# ifndef _WIN32
|
if (events & SLIRP_POLL_OUT)
|
||||||
/* Windows does not support some events. */
|
pevents |= POLLOUT;
|
||||||
if (events & SLIRP_POLL_ERR) pevents |= POLLERR;
|
if (events & SLIRP_POLL_ERR)
|
||||||
if (events & SLIRP_POLL_PRI) pevents |= POLLPRI;
|
pevents |= POLLERR;
|
||||||
if (events & SLIRP_POLL_HUP) pevents |= POLLHUP;
|
if (events & SLIRP_POLL_PRI)
|
||||||
# endif
|
pevents |= POLLPRI;
|
||||||
|
if (events & SLIRP_POLL_HUP)
|
||||||
|
pevents |= POLLHUP;
|
||||||
slirp->pfd[idx].events = pevents;
|
slirp->pfd[idx].events = pevents;
|
||||||
return idx;
|
return idx;
|
||||||
} else
|
} else
|
||||||
return -1;
|
return -1;
|
||||||
#else
|
|
||||||
if (events & SLIRP_POLL_IN)
|
|
||||||
FD_SET(fd, &slirp->rfds);
|
|
||||||
if (events & SLIRP_POLL_OUT)
|
|
||||||
FD_SET(fd, &slirp->wfds);
|
|
||||||
if (events & SLIRP_POLL_PRI)
|
|
||||||
FD_SET(fd, &slirp->xfds);
|
|
||||||
if (fd > slirp->nfds)
|
|
||||||
slirp->nfds = fd;
|
|
||||||
return fd;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
static int
|
static int
|
||||||
net_slirp_get_revents(int idx, void *opaque)
|
net_slirp_get_revents(int idx, void *opaque)
|
||||||
{
|
{
|
||||||
slirp_t *slirp = (slirp_t *) opaque;
|
net_slirp_t *slirp = (net_slirp_t *) opaque;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
#ifdef SLIRP_USE_POLL
|
WSANETWORKEVENTS ev;
|
||||||
int events = slirp->pfd[idx].revents;
|
if (WSAEnumNetworkEvents(idx, slirp->sock_event, &ev) != 0) {
|
||||||
if (events & POLLIN) ret |= SLIRP_POLL_IN;
|
return ret;
|
||||||
if (events & POLLOUT) ret |= SLIRP_POLL_OUT;
|
}
|
||||||
if (events & POLLPRI) ret |= SLIRP_POLL_PRI;
|
|
||||||
if (events & POLLERR) ret |= SLIRP_POLL_ERR;
|
# define WSA_TO_POLL(_wsaev, _pollev) \
|
||||||
if (events & POLLHUP) ret |= SLIRP_POLL_HUP;
|
do { \
|
||||||
#else
|
if (ev.lNetworkEvents & (_wsaev)) { \
|
||||||
if (FD_ISSET(idx, &slirp->rfds))
|
ret |= (_pollev); \
|
||||||
ret |= SLIRP_POLL_IN;
|
if (ev.iErrorCode[_wsaev##_BIT] != 0) { \
|
||||||
if (FD_ISSET(idx, &slirp->wfds))
|
ret |= SLIRP_POLL_ERR; \
|
||||||
ret |= SLIRP_POLL_OUT;
|
} \
|
||||||
if (FD_ISSET(idx, &slirp->xfds))
|
} \
|
||||||
ret |= SLIRP_POLL_PRI;
|
} while (0)
|
||||||
#endif
|
|
||||||
|
WSA_TO_POLL(FD_READ, SLIRP_POLL_IN);
|
||||||
|
WSA_TO_POLL(FD_ACCEPT, SLIRP_POLL_IN);
|
||||||
|
WSA_TO_POLL(FD_WRITE, SLIRP_POLL_OUT);
|
||||||
|
WSA_TO_POLL(FD_CONNECT, SLIRP_POLL_OUT);
|
||||||
|
WSA_TO_POLL(FD_OOB, SLIRP_POLL_PRI);
|
||||||
|
WSA_TO_POLL(FD_CLOSE, SLIRP_POLL_HUP);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
static int
|
||||||
static void
|
net_slirp_get_revents(int idx, void *opaque)
|
||||||
slirp_tic(slirp_t *slirp)
|
|
||||||
{
|
{
|
||||||
int ret;
|
net_slirp_t *slirp = (net_slirp_t *) opaque;
|
||||||
uint32_t tmo;
|
int ret = 0;
|
||||||
|
int events = slirp->pfd[idx].revents;
|
||||||
/* Let SLiRP create a list of all open sockets. */
|
if (events & POLLIN)
|
||||||
#ifdef SLIRP_USE_POLL
|
ret |= SLIRP_POLL_IN;
|
||||||
tmo = -1;
|
if (events & POLLOUT)
|
||||||
slirp->pfd_len = 0;
|
ret |= SLIRP_POLL_OUT;
|
||||||
#else
|
if (events & POLLPRI)
|
||||||
slirp->nfds = -1;
|
ret |= SLIRP_POLL_PRI;
|
||||||
FD_ZERO(&slirp->rfds);
|
if (events & POLLERR)
|
||||||
FD_ZERO(&slirp->wfds);
|
ret |= SLIRP_POLL_ERR;
|
||||||
FD_ZERO(&slirp->xfds);
|
if (events & POLLHUP)
|
||||||
#endif
|
ret |= SLIRP_POLL_HUP;
|
||||||
slirp_pollfds_fill(slirp->slirp, &tmo, net_slirp_add_poll, slirp);
|
return ret;
|
||||||
|
|
||||||
/* Now wait for something to happen, or at most 'tmo' usec. */
|
|
||||||
#ifdef SLIRP_USE_POLL
|
|
||||||
ret = poll(slirp->pfd, slirp->pfd_len, tmo);
|
|
||||||
#else
|
|
||||||
if (tmo < 0)
|
|
||||||
tmo = 500;
|
|
||||||
|
|
||||||
struct timeval tv;
|
|
||||||
tv.tv_sec = 0;
|
|
||||||
tv.tv_usec = tmo;
|
|
||||||
|
|
||||||
ret = select(slirp->nfds + 1, &slirp->rfds, &slirp->wfds, &slirp->xfds, &tv);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* If something happened, let SLiRP handle it. */
|
|
||||||
slirp_pollfds_poll(slirp->slirp, (ret <= 0), net_slirp_get_revents, slirp);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static const SlirpCb slirp_cb = {
|
static const SlirpCb slirp_cb = {
|
||||||
.send_packet = net_slirp_send_packet,
|
.send_packet = net_slirp_send_packet,
|
||||||
@@ -299,31 +292,140 @@ static const SlirpCb slirp_cb = {
|
|||||||
.notify = net_slirp_notify
|
.notify = net_slirp_notify
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Send a packet to the SLiRP interface. */
|
||||||
|
static void
|
||||||
|
net_slirp_in(net_slirp_t *slirp, uint8_t *pkt, int pkt_len)
|
||||||
|
{
|
||||||
|
if (!slirp)
|
||||||
|
return;
|
||||||
|
|
||||||
|
slirp_log("SLiRP: sending %d-byte packet to host network\n", pkt_len);
|
||||||
|
|
||||||
|
slirp_input(slirp->slirp, (const uint8_t *) pkt, pkt_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
net_slirp_in_available(void *priv)
|
||||||
|
{
|
||||||
|
net_slirp_t *slirp = (net_slirp_t *)priv;
|
||||||
|
net_event_set(&slirp->tx_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
static void
|
||||||
|
net_slirp_thread(void *priv)
|
||||||
|
{
|
||||||
|
net_slirp_t *slirp = (net_slirp_t *) priv;
|
||||||
|
|
||||||
|
/* Start polling. */
|
||||||
|
slirp_log("SLiRP: polling started.\n");
|
||||||
|
|
||||||
|
HANDLE events[3];
|
||||||
|
events[NET_EVENT_STOP] = net_event_get_handle(&slirp->stop_event);
|
||||||
|
events[NET_EVENT_TX] = net_event_get_handle(&slirp->tx_event);
|
||||||
|
events[NET_EVENT_RX] = slirp->sock_event;
|
||||||
|
bool run = true;
|
||||||
|
while (run) {
|
||||||
|
uint32_t timeout = -1;
|
||||||
|
slirp_pollfds_fill(slirp->slirp, &timeout, net_slirp_add_poll, slirp);
|
||||||
|
if (timeout < 0)
|
||||||
|
timeout = INFINITE;
|
||||||
|
|
||||||
|
int ret = WaitForMultipleObjects(3, events, FALSE, (DWORD)timeout);
|
||||||
|
switch (ret - WAIT_OBJECT_0) {
|
||||||
|
case NET_EVENT_STOP:
|
||||||
|
run = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NET_EVENT_TX:
|
||||||
|
while (network_tx_pop(slirp->card, &slirp->pkt)) {
|
||||||
|
net_slirp_in(slirp, slirp->pkt.data, slirp->pkt.len);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
slirp_pollfds_poll(slirp->slirp, ret == WAIT_FAILED, net_slirp_get_revents, slirp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
slirp_log("SLiRP: polling stopped.\n");
|
||||||
|
}
|
||||||
|
#else
|
||||||
/* Handle the receiving of frames. */
|
/* Handle the receiving of frames. */
|
||||||
static void
|
static void
|
||||||
poll_thread(void *arg)
|
net_slirp_thread(void *priv)
|
||||||
{
|
{
|
||||||
slirp_t *slirp = (slirp_t *) arg;
|
net_slirp_t *slirp = (net_slirp_t *) priv;
|
||||||
event_t *evt;
|
|
||||||
int tx;
|
|
||||||
|
|
||||||
|
/* Start polling. */
|
||||||
|
slirp_log("SLiRP: polling started.\n");
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
uint32_t timeout = -1;
|
||||||
|
|
||||||
|
slirp->pfd_len = 0;
|
||||||
|
net_slirp_add_poll(net_event_get_fd(&slirp->stop_event), SLIRP_POLL_IN, slirp);
|
||||||
|
net_slirp_add_poll(net_event_get_fd(&slirp->tx_event), SLIRP_POLL_IN, slirp);
|
||||||
|
|
||||||
|
slirp_pollfds_fill(slirp->slirp, &timeout, net_slirp_add_poll, slirp);
|
||||||
|
|
||||||
|
int ret = poll(slirp->pfd, slirp->pfd_len, timeout);
|
||||||
|
|
||||||
|
slirp_pollfds_poll(slirp->slirp, (ret < 0), net_slirp_get_revents, slirp);
|
||||||
|
|
||||||
|
if (slirp->pfd[NET_EVENT_STOP].revents & POLLIN) {
|
||||||
|
net_event_clear(&slirp->stop_event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slirp->pfd[NET_EVENT_TX].revents & POLLIN) {
|
||||||
|
net_event_clear(&slirp->tx_event);
|
||||||
|
|
||||||
|
if (network_tx_pop(slirp->card, &slirp->pkt)) {
|
||||||
|
net_slirp_in(slirp, slirp->pkt.data, slirp->pkt.len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
slirp_log("SLiRP: polling stopped.\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int slirp_card_num = 2;
|
||||||
|
|
||||||
|
/* Initialize SLiRP for use. */
|
||||||
|
void *
|
||||||
|
net_slirp_init(const netcard_t *card, const uint8_t *mac_addr, void *priv)
|
||||||
|
{
|
||||||
slirp_log("SLiRP: initializing...\n");
|
slirp_log("SLiRP: initializing...\n");
|
||||||
|
net_slirp_t *slirp = calloc(1, sizeof(net_slirp_t));
|
||||||
|
memcpy(slirp->mac_addr, mac_addr, sizeof(slirp->mac_addr));
|
||||||
|
slirp->card = (netcard_t*)card;
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
slirp->pfd_size = 16 * sizeof(struct pollfd);
|
||||||
|
slirp->pfd = malloc(slirp->pfd_size);
|
||||||
|
memset(slirp->pfd, 0, slirp->pfd_size);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Set the IP addresses to use. */
|
/* Set the IP addresses to use. */
|
||||||
struct in_addr net = { .s_addr = htonl(0x0a000200) }; /* 10.0.2.0 */
|
struct in_addr net = { .s_addr = htonl(0x0a000000 | (slirp_card_num << 8)) }; /* 10.0.x.0 */
|
||||||
struct in_addr mask = { .s_addr = htonl(0xffffff00) }; /* 255.255.255.0 */
|
struct in_addr mask = { .s_addr = htonl(0xffffff00) }; /* 255.255.255.0 */
|
||||||
struct in_addr host = { .s_addr = htonl(0x0a000202) }; /* 10.0.2.2 */
|
struct in_addr host = { .s_addr = htonl(0x0a000002 | (slirp_card_num << 8)) }; /* 10.0.x.2 */
|
||||||
struct in_addr dhcp = { .s_addr = htonl(0x0a00020f) }; /* 10.0.2.15 */
|
struct in_addr dhcp = { .s_addr = htonl(0x0a00000f | (slirp_card_num << 8)) }; /* 10.0.x.15 */
|
||||||
struct in_addr dns = { .s_addr = htonl(0x0a000203) }; /* 10.0.2.3 */
|
struct in_addr dns = { .s_addr = htonl(0x0a000003 | (slirp_card_num << 8)) }; /* 10.0.x.3 */
|
||||||
struct in_addr bind = { .s_addr = htonl(0x00000000) }; /* 0.0.0.0 */
|
struct in_addr bind = { .s_addr = htonl(0x00000000 | (slirp_card_num << 8)) }; /* 0.0.0.0 */
|
||||||
struct in6_addr ipv6_dummy = { 0 }; /* contents don't matter; we're not using IPv6 */
|
struct in6_addr ipv6_dummy = { 0 }; /* contents don't matter; we're not using IPv6 */
|
||||||
|
|
||||||
/* Initialize SLiRP. */
|
/* Initialize SLiRP. */
|
||||||
slirp->slirp = slirp_init(0, 1, net, mask, host, 0, ipv6_dummy, 0, ipv6_dummy, NULL, NULL, NULL, NULL, dhcp, dns, ipv6_dummy, NULL, NULL, &slirp_cb, arg);
|
slirp->slirp = slirp_init(0, 1, net, mask, host, 0, ipv6_dummy, 0, ipv6_dummy, NULL, NULL, NULL, NULL, dhcp, dns, ipv6_dummy, NULL, NULL, &slirp_cb, slirp);
|
||||||
if (!slirp->slirp) {
|
if (!slirp->slirp) {
|
||||||
slirp_log("SLiRP: initialization failed\n");
|
slirp_log("SLiRP: initialization failed\n");
|
||||||
return;
|
free(slirp);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set up port forwarding. */
|
/* Set up port forwarding. */
|
||||||
@@ -352,123 +454,48 @@ poll_thread(void *arg)
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start polling. */
|
slirp->pkt.data = calloc(1, NET_MAX_FRAME);
|
||||||
slirp_log("SLiRP: polling started.\n");
|
net_event_init(&slirp->tx_event);
|
||||||
thread_set_event(slirp->poll_state);
|
net_event_init(&slirp->stop_event);
|
||||||
|
#ifdef _WIN32
|
||||||
/* Create a waitable event. */
|
slirp->sock_event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
evt = thread_create_event();
|
|
||||||
|
|
||||||
while (!slirp->stop) {
|
|
||||||
/* Request ownership of the queue. */
|
|
||||||
network_wait(1);
|
|
||||||
|
|
||||||
/* Stop processing if asked to. */
|
|
||||||
if (slirp->stop) {
|
|
||||||
network_wait(0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* See if there is any work. */
|
|
||||||
slirp_tic(slirp);
|
|
||||||
|
|
||||||
/* Wait for the next packet to arrive - network_do_tx() is called from there. */
|
|
||||||
tx = network_tx_queue_check();
|
|
||||||
|
|
||||||
/* Release ownership of the queue. */
|
|
||||||
network_wait(0);
|
|
||||||
|
|
||||||
/* If we did not get anything, wait a while. */
|
|
||||||
if (!tx)
|
|
||||||
thread_wait_event(evt, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No longer needed. */
|
|
||||||
if (evt)
|
|
||||||
thread_destroy_event(evt);
|
|
||||||
|
|
||||||
slirp_log("SLiRP: polling stopped.\n");
|
|
||||||
thread_set_event(slirp->poll_state);
|
|
||||||
|
|
||||||
/* Destroy event here to avoid a crash. */
|
|
||||||
slirp_log("SLiRP: thread ended\n");
|
|
||||||
thread_destroy_event(slirp->poll_state);
|
|
||||||
/* Free here instead of immediately freeing the global slirp on the main
|
|
||||||
thread to avoid a race condition. */
|
|
||||||
slirp_cleanup(slirp->slirp);
|
|
||||||
free(slirp);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Initialize SLiRP for use. */
|
|
||||||
int
|
|
||||||
net_slirp_init(void)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Initialize SLiRP for use. */
|
|
||||||
int
|
|
||||||
net_slirp_reset(const netcard_t *card, uint8_t *mac)
|
|
||||||
{
|
|
||||||
slirp_t *new_slirp = malloc(sizeof(slirp_t));
|
|
||||||
memset(new_slirp, 0, sizeof(slirp_t));
|
|
||||||
new_slirp->mac = mac;
|
|
||||||
new_slirp->card = card;
|
|
||||||
#ifdef SLIRP_USE_POLL
|
|
||||||
new_slirp->pfd_size = 16 * sizeof(struct pollfd);
|
|
||||||
new_slirp->pfd = malloc(new_slirp->pfd_size);
|
|
||||||
memset(new_slirp->pfd, 0, new_slirp->pfd_size);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Save the callback info. */
|
|
||||||
slirp = new_slirp;
|
|
||||||
|
|
||||||
slirp_log("SLiRP: creating thread...\n");
|
slirp_log("SLiRP: creating thread...\n");
|
||||||
slirp->poll_state = thread_create_event();
|
slirp->poll_tid = thread_create(net_slirp_thread, slirp);
|
||||||
slirp->poll_tid = thread_create(poll_thread, new_slirp);
|
|
||||||
thread_wait_event(slirp->poll_state, -1);
|
|
||||||
|
|
||||||
return 0;
|
slirp_card_num++;
|
||||||
|
return slirp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
net_slirp_close(void)
|
net_slirp_close(void *priv)
|
||||||
{
|
{
|
||||||
if (!slirp)
|
if (!priv)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
net_slirp_t *slirp = (net_slirp_t *) priv;
|
||||||
|
|
||||||
slirp_log("SLiRP: closing\n");
|
slirp_log("SLiRP: closing\n");
|
||||||
|
|
||||||
/* Tell the polling thread to shut down. */
|
/* Tell the polling thread to shut down. */
|
||||||
slirp->stop = 1;
|
net_event_set(&slirp->stop_event);
|
||||||
|
|
||||||
/* Tell the thread to terminate. */
|
|
||||||
if (slirp->poll_tid) {
|
|
||||||
/* Wait for the thread to finish. */
|
/* Wait for the thread to finish. */
|
||||||
slirp_log("SLiRP: waiting for thread to end...\n");
|
slirp_log("SLiRP: waiting for thread to end...\n");
|
||||||
thread_wait_event(slirp->poll_state, -1);
|
thread_wait(slirp->poll_tid);
|
||||||
}
|
|
||||||
|
|
||||||
/* Shutdown work is done by the thread on its local copy of slirp. */
|
net_event_close(&slirp->tx_event);
|
||||||
slirp = NULL;
|
net_event_close(&slirp->stop_event);
|
||||||
}
|
slirp_cleanup(slirp->slirp);
|
||||||
|
free(slirp->pkt.data);
|
||||||
|
free(slirp);
|
||||||
/* Send a packet to the SLiRP interface. */
|
slirp_card_num--;
|
||||||
void
|
|
||||||
net_slirp_in(uint8_t *pkt, int pkt_len)
|
|
||||||
{
|
|
||||||
if (!slirp || !slirp->slirp)
|
|
||||||
return;
|
|
||||||
|
|
||||||
slirp_log("SLiRP: sending %d-byte packet\n", pkt_len);
|
|
||||||
|
|
||||||
slirp_input(slirp->slirp, (const uint8_t *) pkt, pkt_len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const netdrv_t net_slirp_drv = {
|
||||||
|
&net_slirp_in_available,
|
||||||
|
&net_slirp_init,
|
||||||
|
&net_slirp_close
|
||||||
|
};
|
||||||
|
|
||||||
/* Stubs to stand in for the parts of libslirp we skip compiling. */
|
/* Stubs to stand in for the parts of libslirp we skip compiling. */
|
||||||
void ncsi_input(void *slirp, const uint8_t *pkt, int pkt_len) {}
|
void ncsi_input(void *slirp, const uint8_t *pkt, int pkt_len) {}
|
||||||
|
|||||||
@@ -58,6 +58,8 @@
|
|||||||
#include <86box/pic.h>
|
#include <86box/pic.h>
|
||||||
#include <86box/random.h>
|
#include <86box/random.h>
|
||||||
#include <86box/device.h>
|
#include <86box/device.h>
|
||||||
|
#include <86box/timer.h>
|
||||||
|
#include <86box/thread.h>
|
||||||
#include <86box/network.h>
|
#include <86box/network.h>
|
||||||
#include <86box/net_dp8390.h>
|
#include <86box/net_dp8390.h>
|
||||||
#include <86box/net_wd8003.h>
|
#include <86box/net_wd8003.h>
|
||||||
@@ -696,7 +698,7 @@ wd_init(const device_t *info)
|
|||||||
dev->ram_addr = device_get_config_hex20("ram_addr");
|
dev->ram_addr = device_get_config_hex20("ram_addr");
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->dp8390 = device_add(&dp8390_device);
|
dev->dp8390 = device_add_inst(&dp8390_device, dp3890_inst++);
|
||||||
dev->dp8390->priv = dev;
|
dev->dp8390->priv = dev;
|
||||||
dev->dp8390->interrupt = wd_interrupt;
|
dev->dp8390->interrupt = wd_interrupt;
|
||||||
dp8390_set_defaults(dev->dp8390, DP8390_FLAG_CHECK_CR | DP8390_FLAG_CLEAR_IRQ);
|
dp8390_set_defaults(dev->dp8390, DP8390_FLAG_CHECK_CR | DP8390_FLAG_CLEAR_IRQ);
|
||||||
@@ -786,7 +788,7 @@ wd_init(const device_t *info)
|
|||||||
mem_mapping_disable(&dev->ram_mapping);
|
mem_mapping_disable(&dev->ram_mapping);
|
||||||
|
|
||||||
/* Attach ourselves to the network module. */
|
/* Attach ourselves to the network module. */
|
||||||
network_attach(dev->dp8390, dev->dp8390->physaddr, dp8390_rx, NULL, NULL);
|
dev->dp8390->card = network_attach(dev->dp8390, dev->dp8390->physaddr, dp8390_rx, NULL, NULL);
|
||||||
|
|
||||||
if (!(dev->board_chip & WE_ID_BUS_MCA)) {
|
if (!(dev->board_chip & WE_ID_BUS_MCA)) {
|
||||||
wdlog("%s: attached IO=0x%X IRQ=%d, RAM addr=0x%06x\n", dev->name,
|
wdlog("%s: attached IO=0x%X IRQ=%d, RAM addr=0x%06x\n", dev->name,
|
||||||
|
|||||||
@@ -56,6 +56,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#define HAVE_STDARG_H
|
#define HAVE_STDARG_H
|
||||||
#include <86box/86box.h>
|
#include <86box/86box.h>
|
||||||
#include <86box/device.h>
|
#include <86box/device.h>
|
||||||
@@ -63,6 +64,7 @@
|
|||||||
#include <86box/plat.h>
|
#include <86box/plat.h>
|
||||||
#include <86box/thread.h>
|
#include <86box/thread.h>
|
||||||
#include <86box/ui.h>
|
#include <86box/ui.h>
|
||||||
|
#include <86box/timer.h>
|
||||||
#include <86box/network.h>
|
#include <86box/network.h>
|
||||||
#include <86box/net_3c503.h>
|
#include <86box/net_3c503.h>
|
||||||
#include <86box/net_ne2000.h>
|
#include <86box/net_ne2000.h>
|
||||||
@@ -70,6 +72,11 @@
|
|||||||
#include <86box/net_plip.h>
|
#include <86box/net_plip.h>
|
||||||
#include <86box/net_wd8003.h>
|
#include <86box/net_wd8003.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#include <winsock2.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
static const device_t net_none_device = {
|
static const device_t net_none_device = {
|
||||||
.name = "None",
|
.name = "None",
|
||||||
@@ -86,32 +93,32 @@ static const device_t net_none_device = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static netcard_t net_cards[] = {
|
static const device_t *net_cards[] = {
|
||||||
// clang-format off
|
&net_none_device,
|
||||||
{ &net_none_device, NULL },
|
&threec503_device,
|
||||||
{ &threec503_device, NULL },
|
&pcnet_am79c960_device,
|
||||||
{ &pcnet_am79c960_device, NULL },
|
&pcnet_am79c961_device,
|
||||||
{ &pcnet_am79c961_device, NULL },
|
&ne1000_device,
|
||||||
{ &ne1000_device, NULL },
|
&ne2000_device,
|
||||||
{ &ne2000_device, NULL },
|
&pcnet_am79c960_eb_device,
|
||||||
{ &pcnet_am79c960_eb_device, NULL },
|
&rtl8019as_device,
|
||||||
{ &rtl8019as_device, NULL },
|
&wd8003e_device,
|
||||||
{ &wd8003e_device, NULL },
|
&wd8003eb_device,
|
||||||
{ &wd8003eb_device, NULL },
|
&wd8013ebt_device,
|
||||||
{ &wd8013ebt_device, NULL },
|
&plip_device,
|
||||||
{ &plip_device, NULL },
|
ðernext_mc_device,
|
||||||
{ ðernext_mc_device, NULL },
|
&wd8003eta_device,
|
||||||
{ &wd8003eta_device, NULL },
|
&wd8003ea_device,
|
||||||
{ &wd8003ea_device, NULL },
|
&wd8013epa_device,
|
||||||
{ &wd8013epa_device, NULL },
|
&pcnet_am79c973_device,
|
||||||
{ &pcnet_am79c973_device, NULL },
|
&pcnet_am79c970a_device,
|
||||||
{ &pcnet_am79c970a_device, NULL },
|
&rtl8029as_device,
|
||||||
{ &rtl8029as_device, NULL },
|
&pcnet_am79c960_vlb_device,
|
||||||
{ &pcnet_am79c960_vlb_device, NULL },
|
NULL
|
||||||
{ NULL, NULL }
|
|
||||||
// clang-format off
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
netcard_conf_t net_cards_conf[NET_CARD_MAX];
|
||||||
|
int net_card_current = 0;
|
||||||
|
|
||||||
/* Global variables. */
|
/* Global variables. */
|
||||||
int network_type;
|
int network_type;
|
||||||
@@ -119,20 +126,9 @@ int network_ndev;
|
|||||||
int network_card;
|
int network_card;
|
||||||
char network_host[522];
|
char network_host[522];
|
||||||
netdev_t network_devs[32];
|
netdev_t network_devs[32];
|
||||||
int network_rx_pause = 0,
|
|
||||||
network_tx_pause = 0;
|
|
||||||
|
|
||||||
|
|
||||||
/* Local variables. */
|
/* Local variables. */
|
||||||
static volatile atomic_int net_wait = 0;
|
|
||||||
static mutex_t *network_mutex;
|
|
||||||
static uint8_t *network_mac;
|
|
||||||
static uint8_t network_timer_active = 0;
|
|
||||||
static pc_timer_t network_rx_queue_timer;
|
|
||||||
static netpkt_t *first_pkt[3] = { NULL, NULL, NULL },
|
|
||||||
*last_pkt[3] = { NULL, NULL, NULL };
|
|
||||||
static netpkt_t queued_pkt;
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENABLE_NETWORK_LOG
|
#ifdef ENABLE_NETWORK_LOG
|
||||||
int network_do_log = ENABLE_NETWORK_LOG;
|
int network_do_log = ENABLE_NETWORK_LOG;
|
||||||
@@ -191,15 +187,13 @@ network_dump_packet(netpkt_t *pkt)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void
|
#ifdef _WIN32
|
||||||
network_wait(uint8_t wait)
|
static void
|
||||||
|
network_winsock_clean(void)
|
||||||
{
|
{
|
||||||
if (wait)
|
WSACleanup();
|
||||||
thread_wait_mutex(network_mutex);
|
|
||||||
else
|
|
||||||
thread_release_mutex(network_mutex);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the configured network cards.
|
* Initialize the configured network cards.
|
||||||
@@ -213,9 +207,11 @@ network_init(void)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Initialize to a known state. */
|
#ifdef _WIN32
|
||||||
network_type = NET_TYPE_NONE;
|
WSADATA Data;
|
||||||
network_card = 0;
|
WSAStartup(MAKEWORD(2, 0), &Data);
|
||||||
|
atexit(network_winsock_clean);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Create a first device entry that's always there, as needed by UI. */
|
/* Create a first device entry that's always there, as needed by UI. */
|
||||||
strcpy(network_devs[0].device, "none");
|
strcpy(network_devs[0].device, "none");
|
||||||
@@ -247,156 +243,133 @@ network_init(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
network_queue_put(int tx, void *priv, uint8_t *data, int len)
|
|
||||||
{
|
|
||||||
netpkt_t *temp;
|
|
||||||
|
|
||||||
temp = (netpkt_t *) calloc(sizeof(netpkt_t), 1);
|
|
||||||
temp->priv = priv;
|
|
||||||
memcpy(temp->data, data, len);
|
|
||||||
temp->len = len;
|
|
||||||
temp->prev = last_pkt[tx];
|
|
||||||
temp->next = NULL;
|
|
||||||
|
|
||||||
if (last_pkt[tx] != NULL)
|
|
||||||
last_pkt[tx]->next = temp;
|
|
||||||
last_pkt[tx] = temp;
|
|
||||||
|
|
||||||
if (first_pkt[tx] == NULL)
|
|
||||||
first_pkt[tx] = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
network_queue_get(int tx, netpkt_t *pkt)
|
network_queue_init(netqueue_t *queue)
|
||||||
{
|
{
|
||||||
netpkt_t *temp;
|
queue->size = NET_QUEUE_LEN;
|
||||||
|
queue->head = queue->tail = 0;
|
||||||
temp = first_pkt[tx];
|
for (int i=0; i<queue->size; i++) {
|
||||||
|
queue->packets[i].data = calloc(1, NET_MAX_FRAME);
|
||||||
if (temp == NULL) {
|
queue->packets[i].len = 0;
|
||||||
memset(pkt, 0x00, sizeof(netpkt_t));
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(pkt, temp, sizeof(netpkt_t));
|
|
||||||
|
|
||||||
first_pkt[tx] = temp->next;
|
|
||||||
free(temp);
|
|
||||||
|
|
||||||
if (first_pkt[tx] == NULL)
|
|
||||||
last_pkt[tx] = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
static void
|
network_queue_full(netqueue_t *queue)
|
||||||
network_queue_transmit(int tx)
|
|
||||||
{
|
{
|
||||||
netpkt_t *temp;
|
return ((queue->head + 1) % queue->size) == queue->tail;
|
||||||
|
}
|
||||||
|
|
||||||
temp = first_pkt[tx];
|
static bool
|
||||||
|
network_queue_empty(netqueue_t *queue)
|
||||||
|
{
|
||||||
|
return (queue->head == queue->tail);
|
||||||
|
}
|
||||||
|
|
||||||
if (temp == NULL)
|
int
|
||||||
return;
|
network_queue_put(netqueue_t *queue, uint8_t *data, int len)
|
||||||
|
{
|
||||||
if (temp->len > 0) {
|
if (len > NET_MAX_FRAME || network_queue_full(queue)) {
|
||||||
network_dump_packet(temp);
|
return 0;
|
||||||
/* Why on earth is this not a function pointer?! */
|
|
||||||
switch(network_type) {
|
|
||||||
case NET_TYPE_PCAP:
|
|
||||||
net_pcap_in(temp->data, temp->len);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NET_TYPE_SLIRP:
|
|
||||||
net_slirp_in(temp->data, temp->len);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
first_pkt[tx] = temp->next;
|
netpkt_t *pkt = &queue->packets[queue->head];
|
||||||
free(temp);
|
memcpy(pkt->data, data, len);
|
||||||
|
pkt->len = len;
|
||||||
if (first_pkt[tx] == NULL)
|
queue->head = (queue->head + 1) % queue->size;
|
||||||
last_pkt[tx] = NULL;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
network_queue_get(netqueue_t *queue, netpkt_t *dst_pkt) {
|
||||||
|
if (network_queue_empty(queue))
|
||||||
|
return 0;
|
||||||
|
|
||||||
static void
|
netpkt_t *pkt = &queue->packets[queue->tail];
|
||||||
network_queue_copy(int dest, int src)
|
memcpy(dst_pkt->data, pkt->data, pkt->len);
|
||||||
{
|
dst_pkt->len = pkt->len;
|
||||||
netpkt_t *temp, *temp2;
|
queue->tail = (queue->tail + 1) % queue->size;
|
||||||
|
|
||||||
temp = first_pkt[src];
|
return 1;
|
||||||
|
|
||||||
if (temp == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
temp2 = (netpkt_t *) calloc(sizeof(netpkt_t), 1);
|
|
||||||
temp2->priv = temp->priv;
|
|
||||||
memcpy(temp2->data, temp->data, temp->len);
|
|
||||||
temp2->len = temp->len;
|
|
||||||
temp2->prev = last_pkt[dest];
|
|
||||||
temp2->next = NULL;
|
|
||||||
|
|
||||||
if (last_pkt[dest] != NULL)
|
|
||||||
last_pkt[dest]->next = temp2;
|
|
||||||
last_pkt[dest] = temp2;
|
|
||||||
|
|
||||||
if (first_pkt[dest] == NULL)
|
|
||||||
first_pkt[dest] = temp2;
|
|
||||||
|
|
||||||
first_pkt[src] = temp->next;
|
|
||||||
free(temp);
|
|
||||||
|
|
||||||
if (first_pkt[src] == NULL)
|
|
||||||
last_pkt[src] = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
network_queue_move(netqueue_t *dst_q, netqueue_t *src_q)
|
||||||
|
{
|
||||||
|
if (network_queue_empty(src_q))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (network_queue_full(dst_q)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
netpkt_t *src_pkt = &src_q->packets[src_q->tail];
|
||||||
|
netpkt_t *dst_pkt = &dst_q->packets[dst_q->head];
|
||||||
|
uint8_t *tmp_dat = dst_pkt->data;
|
||||||
|
|
||||||
|
dst_pkt->data = src_pkt->data;
|
||||||
|
dst_pkt->len = src_pkt->len;
|
||||||
|
dst_q->head = (dst_q->head + 1) % dst_q->size;
|
||||||
|
|
||||||
|
src_pkt->data = tmp_dat;
|
||||||
|
src_pkt->len = 0;
|
||||||
|
src_q->tail = (src_q->tail + 1) % src_q->size;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
network_queue_clear(int tx)
|
network_queue_clear(netqueue_t *queue)
|
||||||
{
|
{
|
||||||
netpkt_t *temp = first_pkt[tx], *temp2;
|
for (int i=0; i<queue->size; i++) {
|
||||||
|
free(queue->packets[i].data);
|
||||||
if (temp == NULL)
|
queue->packets[i].len = 0;
|
||||||
return;
|
}
|
||||||
|
queue->tail = queue->head = 0;
|
||||||
do {
|
|
||||||
temp2 = temp->next;
|
|
||||||
free(temp);
|
|
||||||
temp = temp2;
|
|
||||||
} while (temp != NULL);
|
|
||||||
|
|
||||||
first_pkt[tx] = last_pkt[tx] = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
network_rx_queue(void *priv)
|
network_rx_queue(void *priv)
|
||||||
{
|
{
|
||||||
int ret = 1;
|
netcard_t *card = (netcard_t *)priv;
|
||||||
|
double timer_period;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
if (network_rx_pause || !thread_test_mutex(network_mutex)) {
|
bool activity = false;
|
||||||
timer_on_auto(&network_rx_queue_timer, 0.762939453125 * 2.0 * 128.0);
|
|
||||||
return;
|
if (card->queued_pkt.len == 0) {
|
||||||
|
thread_wait_mutex(card->rx_mutex);
|
||||||
|
network_queue_get(&card->queues[NET_QUEUE_RX], &card->queued_pkt);
|
||||||
|
thread_release_mutex(card->rx_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (queued_pkt.len == 0)
|
if (card->queued_pkt.len > 0) {
|
||||||
network_queue_get(0, &queued_pkt);
|
network_dump_packet(&card->queued_pkt);
|
||||||
if (queued_pkt.len > 0) {
|
ret = card->rx(card->card_drv, card->queued_pkt.data, card->queued_pkt.len);
|
||||||
network_dump_packet(&queued_pkt);
|
|
||||||
ret = net_cards[network_card].rx(queued_pkt.priv, queued_pkt.data, queued_pkt.len);
|
|
||||||
}
|
}
|
||||||
timer_on_auto(&network_rx_queue_timer, 0.762939453125 * 2.0 * ((queued_pkt.len >= 128) ? ((double) queued_pkt.len) : 128.0));
|
|
||||||
if (ret)
|
if (ret) {
|
||||||
queued_pkt.len = 0;
|
activity = true;
|
||||||
|
timer_period = 0.762939453125 * ((card->queued_pkt.len >= 128) ? ((double) card->queued_pkt.len) : 128.0);
|
||||||
|
card->queued_pkt.len = 0;
|
||||||
|
} else {
|
||||||
|
timer_period = 0.762939453125 * 128.0;
|
||||||
|
}
|
||||||
|
timer_on_auto(&card->timer, timer_period);
|
||||||
|
|
||||||
/* Transmission. */
|
/* Transmission. */
|
||||||
network_queue_copy(1, 2);
|
thread_wait_mutex(card->tx_mutex);
|
||||||
|
ret = network_queue_move(&card->queues[NET_QUEUE_TX_HOST], &card->queues[NET_QUEUE_TX_VM]);
|
||||||
|
thread_release_mutex(card->tx_mutex);
|
||||||
|
if (ret) {
|
||||||
|
/* Notify host that a packet is available in the TX queue */
|
||||||
|
card->host_drv.notify_in(card->host_drv.priv);
|
||||||
|
activity = true;
|
||||||
|
}
|
||||||
|
|
||||||
network_wait(0);
|
ui_sb_update_icon(SB_NETWORK, activity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -407,51 +380,67 @@ network_rx_queue(void *priv)
|
|||||||
* finished initializing itself, to link itself to the platform support
|
* finished initializing itself, to link itself to the platform support
|
||||||
* modules.
|
* modules.
|
||||||
*/
|
*/
|
||||||
void
|
netcard_t *
|
||||||
network_attach(void *dev, uint8_t *mac, NETRXCB rx, NETWAITCB wait, NETSETLINKSTATE set_link_state)
|
network_attach(void *card_drv, uint8_t *mac, NETRXCB rx, NETWAITCB wait, NETSETLINKSTATE set_link_state)
|
||||||
{
|
{
|
||||||
if (network_card == 0) return;
|
netcard_t *card = calloc(1, sizeof(netcard_t));
|
||||||
|
card->queued_pkt.data = calloc(1, NET_MAX_FRAME);
|
||||||
|
card->card_drv = card_drv;
|
||||||
|
card->rx = rx;
|
||||||
|
card->wait = wait;
|
||||||
|
card->set_link_state = set_link_state;
|
||||||
|
card->tx_mutex = thread_create_mutex();
|
||||||
|
card->rx_mutex = thread_create_mutex();
|
||||||
|
|
||||||
/* Save the card's info. */
|
for (int i=0; i<3; i++) {
|
||||||
net_cards[network_card].priv = dev;
|
network_queue_init(&card->queues[i]);
|
||||||
net_cards[network_card].rx = rx;
|
}
|
||||||
net_cards[network_card].wait = wait;
|
|
||||||
net_cards[network_card].set_link_state = set_link_state;
|
|
||||||
network_mac = mac;
|
|
||||||
|
|
||||||
network_set_wait(0);
|
switch (net_cards_conf[net_card_current].net_type) {
|
||||||
|
case NET_TYPE_SLIRP:
|
||||||
/* Activate the platform module. */
|
default:
|
||||||
switch(network_type) {
|
card->host_drv = net_slirp_drv;
|
||||||
case NET_TYPE_PCAP:
|
card->host_drv.priv = card->host_drv.init(card, mac, NULL);
|
||||||
(void)net_pcap_reset(&net_cards[network_card], network_mac);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NET_TYPE_SLIRP:
|
case NET_TYPE_PCAP:
|
||||||
(void)net_slirp_reset(&net_cards[network_card], network_mac);
|
card->host_drv = net_pcap_drv;
|
||||||
|
card->host_drv.priv = card->host_drv.init(card, mac, net_cards_conf[net_card_current].host_dev_name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
first_pkt[0] = first_pkt[1] = first_pkt[2] = NULL;
|
if (!card->host_drv.priv) {
|
||||||
last_pkt[0] = last_pkt[1] = last_pkt[2] = NULL;
|
thread_close_mutex(card->tx_mutex);
|
||||||
memset(&queued_pkt, 0x00, sizeof(netpkt_t));
|
thread_close_mutex(card->rx_mutex);
|
||||||
memset(&network_rx_queue_timer, 0x00, sizeof(pc_timer_t));
|
for (int i=0; i<3; i++) {
|
||||||
timer_add(&network_rx_queue_timer, network_rx_queue, NULL, 0);
|
network_queue_clear(&card->queues[i]);
|
||||||
/* 10 mbps. */
|
}
|
||||||
timer_on_auto(&network_rx_queue_timer, 0.762939453125 * 2.0);
|
|
||||||
network_timer_active = 1;
|
free(card->queued_pkt.data);
|
||||||
|
free(card);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
timer_add(&card->timer, network_rx_queue, card, 0);
|
||||||
|
timer_on_auto(&card->timer, 0.762939453125 * 2.0);
|
||||||
|
|
||||||
|
return card;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Stop the network timer. */
|
|
||||||
void
|
void
|
||||||
network_timer_stop(void)
|
netcard_close(netcard_t *card)
|
||||||
{
|
{
|
||||||
if (network_timer_active) {
|
timer_stop(&card->timer);
|
||||||
timer_stop(&network_rx_queue_timer);
|
card->host_drv.close(card->host_drv.priv);
|
||||||
memset(&network_rx_queue_timer, 0x00, sizeof(pc_timer_t));
|
|
||||||
network_timer_active = 0;
|
thread_close_mutex(card->tx_mutex);
|
||||||
|
thread_close_mutex(card->rx_mutex);
|
||||||
|
for (int i=0; i<3; i++) {
|
||||||
|
network_queue_clear(&card->queues[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(card->queued_pkt.data);
|
||||||
|
free(card);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -459,30 +448,11 @@ network_timer_stop(void)
|
|||||||
void
|
void
|
||||||
network_close(void)
|
network_close(void)
|
||||||
{
|
{
|
||||||
network_timer_stop();
|
|
||||||
|
|
||||||
/* If already closed, do nothing. */
|
|
||||||
if (network_mutex == NULL) return;
|
|
||||||
|
|
||||||
/* Force-close the PCAP module. */
|
|
||||||
net_pcap_close();
|
|
||||||
|
|
||||||
/* Force-close the SLIRP module. */
|
|
||||||
net_slirp_close();
|
|
||||||
|
|
||||||
/* Close the network thread mutex. */
|
|
||||||
thread_close_mutex(network_mutex);
|
|
||||||
network_mutex = NULL;
|
|
||||||
network_mac = NULL;
|
|
||||||
#ifdef ENABLE_NETWORK_LOG
|
#ifdef ENABLE_NETWORK_LOG
|
||||||
thread_close_mutex(network_dump_mutex);
|
thread_close_mutex(network_dump_mutex);
|
||||||
network_dump_mutex = NULL;
|
network_dump_mutex = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Here is where we clear the queues. */
|
|
||||||
network_queue_clear(0);
|
|
||||||
network_queue_clear(1);
|
|
||||||
|
|
||||||
network_log("NETWORK: closed.\n");
|
network_log("NETWORK: closed.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -500,86 +470,52 @@ network_reset(void)
|
|||||||
{
|
{
|
||||||
int i = -1;
|
int i = -1;
|
||||||
|
|
||||||
network_log("NETWORK: reset (type=%d, card=%d)\n",
|
|
||||||
network_type, network_card);
|
|
||||||
|
|
||||||
ui_sb_update_icon(SB_NETWORK, 0);
|
ui_sb_update_icon(SB_NETWORK, 0);
|
||||||
|
|
||||||
/* Just in case.. */
|
|
||||||
network_close();
|
|
||||||
|
|
||||||
/* If no active card, we're done. */
|
|
||||||
if ((network_type==NET_TYPE_NONE) || (network_card==0)) return;
|
|
||||||
|
|
||||||
network_mutex = thread_create_mutex();
|
|
||||||
#ifdef ENABLE_NETWORK_LOG
|
#ifdef ENABLE_NETWORK_LOG
|
||||||
network_dump_mutex = thread_create_mutex();
|
network_dump_mutex = thread_create_mutex();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Initialize the platform module. */
|
for (i = 0; i < NET_CARD_MAX; i++) {
|
||||||
switch(network_type) {
|
if (!net_cards_conf[i].device_num || net_cards_conf[i].net_type == NET_TYPE_NONE ||
|
||||||
case NET_TYPE_PCAP:
|
(net_cards_conf[i].net_type == NET_TYPE_PCAP && !strcmp(net_cards_conf[i].host_dev_name, "none"))) {
|
||||||
i = net_pcap_init();
|
continue;
|
||||||
break;
|
|
||||||
|
|
||||||
case NET_TYPE_SLIRP:
|
|
||||||
i = net_slirp_init();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i < 0) {
|
net_card_current = i;
|
||||||
/* Tell user we can't do this (at the moment.) */
|
device_add_inst(net_cards[net_cards_conf[i].device_num], i + 1);
|
||||||
ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2093, (wchar_t *) IDS_2129);
|
|
||||||
|
|
||||||
// FIXME: we should ask in the dialog if they want to
|
|
||||||
// reconfigure or quit, and throw them into the
|
|
||||||
// Settings dialog if yes.
|
|
||||||
|
|
||||||
/* Disable network. */
|
|
||||||
network_type = NET_TYPE_NONE;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
network_log("NETWORK: set up for %s, card='%s'\n",
|
|
||||||
(network_type==NET_TYPE_SLIRP)?"SLiRP":"Pcap",
|
|
||||||
net_cards[network_card].device->name);
|
|
||||||
|
|
||||||
/* Add the (new?) card to the I/O system. */
|
|
||||||
if (net_cards[network_card].device) {
|
|
||||||
network_log("NETWORK: adding device '%s'\n",
|
|
||||||
net_cards[network_card].device->name);
|
|
||||||
device_add(net_cards[network_card].device);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Queue a packet for transmission to one of the network providers. */
|
/* Queue a packet for transmission to one of the network providers. */
|
||||||
void
|
void
|
||||||
network_tx(uint8_t *bufp, int len)
|
network_tx(netcard_t *card, uint8_t *bufp, int len)
|
||||||
{
|
{
|
||||||
ui_sb_update_icon(SB_NETWORK, 1);
|
network_queue_put(&card->queues[NET_QUEUE_TX_VM], bufp, len);
|
||||||
|
|
||||||
network_queue_put(2, NULL, bufp, len);
|
|
||||||
|
|
||||||
ui_sb_update_icon(SB_NETWORK, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int network_tx_pop(netcard_t *card, netpkt_t *out_pkt)
|
||||||
/* Actually transmit the packet. */
|
|
||||||
int
|
|
||||||
network_tx_queue_check(void)
|
|
||||||
{
|
{
|
||||||
if ((first_pkt[1] == NULL) && (last_pkt[1] == NULL))
|
int ret = 0;
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (network_tx_pause)
|
thread_wait_mutex(card->tx_mutex);
|
||||||
return 1;
|
ret = network_queue_get(&card->queues[NET_QUEUE_TX_HOST], out_pkt);
|
||||||
|
thread_release_mutex(card->tx_mutex);
|
||||||
|
|
||||||
network_queue_transmit(1);
|
return ret;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int network_rx_put(netcard_t *card, uint8_t *bufp, int len)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
thread_wait_mutex(card->rx_mutex);
|
||||||
|
ret = network_queue_put(&card->queues[NET_QUEUE_RX], bufp, len);
|
||||||
|
thread_release_mutex(card->rx_mutex);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
network_dev_to_id(char *devname)
|
network_dev_to_id(char *devname)
|
||||||
@@ -601,9 +537,13 @@ network_dev_to_id(char *devname)
|
|||||||
int
|
int
|
||||||
network_available(void)
|
network_available(void)
|
||||||
{
|
{
|
||||||
if ((network_type == NET_TYPE_NONE) || (network_card == 0)) return(0);
|
int available = 0;
|
||||||
|
|
||||||
return(1);
|
for (int i = 0; i < NET_CARD_MAX; i ++) {
|
||||||
|
available |= (net_cards_conf[i].device_num > 0) && (net_cards_conf[i].net_type != NET_TYPE_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return available;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -611,8 +551,8 @@ network_available(void)
|
|||||||
int
|
int
|
||||||
network_card_available(int card)
|
network_card_available(int card)
|
||||||
{
|
{
|
||||||
if (net_cards[card].device)
|
if (net_cards[card])
|
||||||
return(device_available(net_cards[card].device));
|
return(device_available(net_cards[card]));
|
||||||
|
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
@@ -622,7 +562,7 @@ network_card_available(int card)
|
|||||||
const device_t *
|
const device_t *
|
||||||
network_card_getdevice(int card)
|
network_card_getdevice(int card)
|
||||||
{
|
{
|
||||||
return(net_cards[card].device);
|
return(net_cards[card]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -630,9 +570,9 @@ network_card_getdevice(int card)
|
|||||||
int
|
int
|
||||||
network_card_has_config(int card)
|
network_card_has_config(int card)
|
||||||
{
|
{
|
||||||
if (! net_cards[card].device) return(0);
|
if (!net_cards[card]) return(0);
|
||||||
|
|
||||||
return(device_has_config(net_cards[card].device) ? 1 : 0);
|
return(device_has_config(net_cards[card]) ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -640,7 +580,7 @@ network_card_has_config(int card)
|
|||||||
char *
|
char *
|
||||||
network_card_get_internal_name(int card)
|
network_card_get_internal_name(int card)
|
||||||
{
|
{
|
||||||
return device_get_internal_name(net_cards[card].device);
|
return device_get_internal_name(net_cards[card]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -650,28 +590,11 @@ network_card_get_from_internal_name(char *s)
|
|||||||
{
|
{
|
||||||
int c = 0;
|
int c = 0;
|
||||||
|
|
||||||
while (net_cards[c].device != NULL) {
|
while (net_cards[c] != NULL) {
|
||||||
if (! strcmp((char *)net_cards[c].device->internal_name, s))
|
if (! strcmp((char *)net_cards[c]->internal_name, s))
|
||||||
return(c);
|
return(c);
|
||||||
c++;
|
c++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
network_set_wait(int wait)
|
|
||||||
{
|
|
||||||
net_wait = wait;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
network_get_wait(void)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = net_wait;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ extern uint64_t tsc;
|
|||||||
#include <86box/mo.h>
|
#include <86box/mo.h>
|
||||||
#include <86box/plat.h>
|
#include <86box/plat.h>
|
||||||
#include <86box/machine.h>
|
#include <86box/machine.h>
|
||||||
|
#include <86box/thread.h>
|
||||||
#include <86box/network.h>
|
#include <86box/network.h>
|
||||||
#include <86box/ui.h>
|
#include <86box/ui.h>
|
||||||
#include <86box/machine_status.h>
|
#include <86box/machine_status.h>
|
||||||
|
|||||||
@@ -21,20 +21,29 @@ extern "C" {
|
|||||||
#include <86box/86box.h>
|
#include <86box/86box.h>
|
||||||
#include <86box/device.h>
|
#include <86box/device.h>
|
||||||
#include <86box/machine.h>
|
#include <86box/machine.h>
|
||||||
|
#include <86box/timer.h>
|
||||||
|
#include <86box/thread.h>
|
||||||
#include <86box/network.h>
|
#include <86box/network.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "qt_models_common.hpp"
|
#include "qt_models_common.hpp"
|
||||||
#include "qt_deviceconfig.hpp"
|
#include "qt_deviceconfig.hpp"
|
||||||
|
|
||||||
static void enableElements(Ui::SettingsNetwork *ui) {
|
void SettingsNetwork::enableElements(Ui::SettingsNetwork *ui) {
|
||||||
int netType = ui->comboBoxNetwork->currentData().toInt();
|
for (int i = 0; i < NET_CARD_MAX; ++i) {
|
||||||
ui->comboBoxPcap->setEnabled(netType == NET_TYPE_PCAP);
|
auto* nic_cbox = findChild<QComboBox*>(QString("comboBoxNIC%1").arg(i+1));
|
||||||
|
auto* net_type_cbox = findChild<QComboBox*>(QString("comboBoxNet%1").arg(i+1));
|
||||||
|
auto* intf_cbox = findChild<QComboBox*>(QString("comboBoxIntf%1").arg(i+1));
|
||||||
|
auto* conf_btn = findChild<QPushButton*>(QString("pushButtonConf%1").arg(i+1));
|
||||||
|
|
||||||
|
int netType = net_type_cbox->currentData().toInt();
|
||||||
bool adaptersEnabled = netType == NET_TYPE_SLIRP ||
|
bool adaptersEnabled = netType == NET_TYPE_SLIRP ||
|
||||||
(netType == NET_TYPE_PCAP && ui->comboBoxPcap->currentData().toInt() > 0);
|
(netType == NET_TYPE_PCAP && intf_cbox->currentData().toInt() > 0);
|
||||||
ui->comboBoxAdapter->setEnabled(adaptersEnabled);
|
|
||||||
ui->pushButtonConfigure->setEnabled(adaptersEnabled && ui->comboBoxAdapter->currentIndex() > 0 && network_card_has_config(ui->comboBoxAdapter->currentData().toInt()));
|
intf_cbox->setEnabled(net_type_cbox->currentData().toInt() == NET_TYPE_PCAP);
|
||||||
|
nic_cbox->setEnabled(adaptersEnabled);
|
||||||
|
conf_btn->setEnabled(adaptersEnabled && network_card_has_config(nic_cbox->currentData().toInt()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsNetwork::SettingsNetwork(QWidget *parent) :
|
SettingsNetwork::SettingsNetwork(QWidget *parent) :
|
||||||
@@ -43,27 +52,16 @@ SettingsNetwork::SettingsNetwork(QWidget *parent) :
|
|||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
auto* model = ui->comboBoxNetwork->model();
|
|
||||||
Models::AddEntry(model, tr("None"), NET_TYPE_NONE);
|
|
||||||
Models::AddEntry(model, "PCap", NET_TYPE_PCAP);
|
|
||||||
Models::AddEntry(model, "SLiRP", NET_TYPE_SLIRP);
|
|
||||||
ui->comboBoxNetwork->setCurrentIndex(network_type);
|
|
||||||
|
|
||||||
int selectedRow = 0;
|
|
||||||
model = ui->comboBoxPcap->model();
|
|
||||||
QString currentPcapDevice = network_host;
|
|
||||||
for (int c = 0; c < network_ndev; c++) {
|
|
||||||
|
|
||||||
Models::AddEntry(model, tr(network_devs[c].description), c);
|
|
||||||
if (QString(network_devs[c].device) == currentPcapDevice) {
|
|
||||||
selectedRow = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ui->comboBoxPcap->setCurrentIndex(-1);
|
|
||||||
ui->comboBoxPcap->setCurrentIndex(selectedRow);
|
|
||||||
|
|
||||||
onCurrentMachineChanged(machine);
|
onCurrentMachineChanged(machine);
|
||||||
enableElements(ui);
|
enableElements(ui);
|
||||||
|
for (int i = 0; i < NET_CARD_MAX; i++) {
|
||||||
|
auto* nic_cbox = findChild<QComboBox*>(QString("comboBoxNIC%1").arg(i+1));
|
||||||
|
auto* net_type_cbox = findChild<QComboBox*>(QString("comboBoxNet%1").arg(i+1));
|
||||||
|
auto* intf_cbox = findChild<QComboBox*>(QString("comboBoxIntf%1").arg(i+1));
|
||||||
|
connect(nic_cbox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &SettingsNetwork::on_comboIndexChanged);
|
||||||
|
connect(net_type_cbox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &SettingsNetwork::on_comboIndexChanged);
|
||||||
|
connect(intf_cbox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &SettingsNetwork::on_comboIndexChanged);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsNetwork::~SettingsNetwork()
|
SettingsNetwork::~SettingsNetwork()
|
||||||
@@ -72,19 +70,30 @@ SettingsNetwork::~SettingsNetwork()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SettingsNetwork::save() {
|
void SettingsNetwork::save() {
|
||||||
network_type = ui->comboBoxNetwork->currentData().toInt();
|
for (int i = 0; i < NET_CARD_MAX; ++i) {
|
||||||
memset(network_host, '\0', sizeof(network_host));
|
auto* cbox = findChild<QComboBox*>(QString("comboBoxNIC%1").arg(i+1));
|
||||||
strcpy(network_host, network_devs[ui->comboBoxPcap->currentData().toInt()].device);
|
net_cards_conf[i].device_num = cbox->currentData().toInt();
|
||||||
network_card = ui->comboBoxAdapter->currentData().toInt();
|
cbox = findChild<QComboBox*>(QString("comboBoxNet%1").arg(i+1));
|
||||||
|
net_cards_conf[i].net_type = cbox->currentData().toInt();
|
||||||
|
cbox = findChild<QComboBox*>(QString("comboBoxIntf%1").arg(i+1));
|
||||||
|
memset(net_cards_conf[i].host_dev_name, '\0', sizeof(net_cards_conf[i].host_dev_name));
|
||||||
|
strncpy(net_cards_conf[i].host_dev_name, network_devs[cbox->currentData().toInt()].device, sizeof(net_cards_conf[i].host_dev_name) - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsNetwork::onCurrentMachineChanged(int machineId) {
|
void SettingsNetwork::onCurrentMachineChanged(int machineId) {
|
||||||
this->machineId = machineId;
|
this->machineId = machineId;
|
||||||
|
|
||||||
auto* model = ui->comboBoxAdapter->model();
|
|
||||||
auto removeRows = model->rowCount();
|
|
||||||
int c = 0;
|
int c = 0;
|
||||||
int selectedRow = 0;
|
int selectedRow = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < NET_CARD_MAX; ++i) {
|
||||||
|
auto* cbox = findChild<QComboBox*>(QString("comboBoxNIC%1").arg(i+1));
|
||||||
|
auto *model = cbox->model();
|
||||||
|
auto removeRows = model->rowCount();
|
||||||
|
c = 0;
|
||||||
|
selectedRow = 0;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
auto name = DeviceConfig::DeviceName(network_card_getdevice(c), network_card_get_internal_name(c), 1);
|
auto name = DeviceConfig::DeviceName(network_card_getdevice(c), network_card_get_internal_name(c), 1);
|
||||||
if (name.isEmpty()) {
|
if (name.isEmpty()) {
|
||||||
@@ -93,20 +102,43 @@ void SettingsNetwork::onCurrentMachineChanged(int machineId) {
|
|||||||
|
|
||||||
if (network_card_available(c) && device_is_valid(network_card_getdevice(c), machineId)) {
|
if (network_card_available(c) && device_is_valid(network_card_getdevice(c), machineId)) {
|
||||||
int row = Models::AddEntry(model, name, c);
|
int row = Models::AddEntry(model, name, c);
|
||||||
if (c == network_card) {
|
if (c == net_cards_conf[i].device_num) {
|
||||||
selectedRow = row - removeRows;
|
selectedRow = row - removeRows;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c++;
|
c++;
|
||||||
}
|
}
|
||||||
|
|
||||||
model->removeRows(0, removeRows);
|
model->removeRows(0, removeRows);
|
||||||
ui->comboBoxAdapter->setEnabled(model->rowCount() > 0);
|
cbox->setEnabled(model->rowCount() > 0);
|
||||||
ui->comboBoxAdapter->setCurrentIndex(-1);
|
cbox->setCurrentIndex(-1);
|
||||||
ui->comboBoxAdapter->setCurrentIndex(selectedRow);
|
cbox->setCurrentIndex(selectedRow);
|
||||||
|
|
||||||
|
cbox = findChild<QComboBox*>(QString("comboBoxNet%1").arg(i+1));
|
||||||
|
model = cbox->model();
|
||||||
|
Models::AddEntry(model, tr("None"), NET_TYPE_NONE);
|
||||||
|
Models::AddEntry(model, "SLiRP", NET_TYPE_SLIRP);
|
||||||
|
if (network_ndev > 1) {
|
||||||
|
Models::AddEntry(model, "PCap", NET_TYPE_PCAP);
|
||||||
|
}
|
||||||
|
cbox->setCurrentIndex(net_cards_conf[i].net_type);
|
||||||
|
|
||||||
|
selectedRow = 0;
|
||||||
|
|
||||||
|
QString currentPcapDevice = net_cards_conf[i].host_dev_name;
|
||||||
|
cbox = findChild<QComboBox*>(QString("comboBoxIntf%1").arg(i+1));
|
||||||
|
model = cbox->model();
|
||||||
|
for (int c = 0; c < network_ndev; c++) {
|
||||||
|
Models::AddEntry(model, tr(network_devs[c].description), c);
|
||||||
|
if (QString(network_devs[c].device) == currentPcapDevice) {
|
||||||
|
selectedRow = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cbox->setCurrentIndex(selectedRow);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsNetwork::on_comboBoxNetwork_currentIndexChanged(int index) {
|
void SettingsNetwork::on_comboIndexChanged(int index) {
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -114,24 +146,18 @@ void SettingsNetwork::on_comboBoxNetwork_currentIndexChanged(int index) {
|
|||||||
enableElements(ui);
|
enableElements(ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsNetwork::on_comboBoxAdapter_currentIndexChanged(int index) {
|
void SettingsNetwork::on_pushButtonConf1_clicked() {
|
||||||
if (index < 0) {
|
DeviceConfig::ConfigureDevice(network_card_getdevice(ui->comboBoxNIC1->currentData().toInt()), 0, qobject_cast<Settings*>(Settings::settings));
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
enableElements(ui);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsNetwork::on_pushButtonConfigure_clicked() {
|
void SettingsNetwork::on_pushButtonConf2_clicked() {
|
||||||
DeviceConfig::ConfigureDevice(network_card_getdevice(ui->comboBoxAdapter->currentData().toInt()), 0, qobject_cast<Settings*>(Settings::settings));
|
DeviceConfig::ConfigureDevice(network_card_getdevice(ui->comboBoxNIC2->currentData().toInt()), 0, qobject_cast<Settings*>(Settings::settings));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SettingsNetwork::on_pushButtonConf3_clicked() {
|
||||||
void SettingsNetwork::on_comboBoxPcap_currentIndexChanged(int index)
|
DeviceConfig::ConfigureDevice(network_card_getdevice(ui->comboBoxNIC3->currentData().toInt()), 0, qobject_cast<Settings*>(Settings::settings));
|
||||||
{
|
}
|
||||||
if (index < 0) {
|
|
||||||
return;
|
void SettingsNetwork::on_pushButtonConf4_clicked() {
|
||||||
}
|
DeviceConfig::ConfigureDevice(network_card_getdevice(ui->comboBoxNIC4->currentData().toInt()), 0, qobject_cast<Settings*>(Settings::settings));
|
||||||
|
|
||||||
enableElements(ui);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,11 +21,13 @@ public slots:
|
|||||||
void onCurrentMachineChanged(int machineId);
|
void onCurrentMachineChanged(int machineId);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_pushButtonConfigure_clicked();
|
void on_pushButtonConf1_clicked();
|
||||||
void on_comboBoxAdapter_currentIndexChanged(int index);
|
void on_pushButtonConf2_clicked();
|
||||||
void on_comboBoxNetwork_currentIndexChanged(int index);
|
void on_pushButtonConf3_clicked();
|
||||||
|
void on_pushButtonConf4_clicked();
|
||||||
|
void on_comboIndexChanged(int index);
|
||||||
|
|
||||||
void on_comboBoxPcap_currentIndexChanged(int index);
|
void enableElements(Ui::SettingsNetwork *ui);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::SettingsNetwork *ui;
|
Ui::SettingsNetwork *ui;
|
||||||
|
|||||||
@@ -6,14 +6,14 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>400</width>
|
<width>548</width>
|
||||||
<height>300</height>
|
<height>458</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Form</string>
|
<string>Form</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
@@ -26,7 +26,291 @@
|
|||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="6" column="0">
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Network Interface Contollers</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_3">
|
||||||
|
<item row="0" column="4">
|
||||||
|
<widget class="QLabel" name="label_7">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Adapter</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="3">
|
||||||
|
<widget class="QComboBox" name="comboBoxIntf4">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="3">
|
||||||
|
<widget class="QComboBox" name="comboBoxIntf3">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="5">
|
||||||
|
<widget class="QPushButton" name="pushButtonConf3">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Configure</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="2">
|
||||||
|
<widget class="QComboBox" name="comboBoxNet1">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Card 3:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="4">
|
||||||
|
<widget class="QComboBox" name="comboBoxNIC4">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="sizeAdjustPolicy">
|
||||||
|
<enum>QComboBox::AdjustToContents</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Card 1:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="3">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Interface</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="4">
|
||||||
|
<widget class="QComboBox" name="comboBoxNIC1">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="sizeAdjustPolicy">
|
||||||
|
<enum>QComboBox::AdjustToContents</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="5">
|
||||||
|
<widget class="QPushButton" name="pushButtonConf1">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Configure</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="4">
|
||||||
|
<widget class="QComboBox" name="comboBoxNIC3">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="sizeAdjustPolicy">
|
||||||
|
<enum>QComboBox::AdjustToContents</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="2">
|
||||||
|
<widget class="QComboBox" name="comboBoxNet4">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Card 4:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Mode</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Card 2:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="2">
|
||||||
|
<widget class="QComboBox" name="comboBoxNet3">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="2">
|
||||||
|
<widget class="QComboBox" name="comboBoxNet2">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="5">
|
||||||
|
<widget class="QPushButton" name="pushButtonConf2">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Configure</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="5">
|
||||||
|
<widget class="QPushButton" name="pushButtonConf4">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Configure</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="3">
|
||||||
|
<widget class="QComboBox" name="comboBoxIntf1">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="3">
|
||||||
|
<widget class="QComboBox" name="comboBoxIntf2">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="4">
|
||||||
|
<widget class="QComboBox" name="comboBoxNIC2">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="sizeAdjustPolicy">
|
||||||
|
<enum>QComboBox::AdjustToContents</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
<spacer name="verticalSpacer">
|
<spacer name="verticalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
@@ -39,57 +323,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_2">
|
|
||||||
<property name="text">
|
|
||||||
<string>PCap device:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Network type:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QComboBox" name="comboBoxAdapter">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label_3">
|
|
||||||
<property name="text">
|
|
||||||
<string>Network adapter:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="2">
|
|
||||||
<widget class="QPushButton" name="pushButtonConfigure">
|
|
||||||
<property name="text">
|
|
||||||
<string>Configure</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1" colspan="2">
|
|
||||||
<widget class="QComboBox" name="comboBoxNetwork">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1" colspan="2">
|
|
||||||
<widget class="QComboBox" name="comboBoxPcap"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
|||||||
@@ -664,7 +664,7 @@ NETOBJ := network.o \
|
|||||||
net_dp8390.o \
|
net_dp8390.o \
|
||||||
net_3c503.o net_ne2000.o \
|
net_3c503.o net_ne2000.o \
|
||||||
net_pcnet.o net_wd8003.o \
|
net_pcnet.o net_wd8003.o \
|
||||||
net_plip.o
|
net_plip.o net_event.o
|
||||||
|
|
||||||
PRINTOBJ := png.o prt_cpmap.o \
|
PRINTOBJ := png.o prt_cpmap.o \
|
||||||
prt_escp.o prt_text.o prt_ps.o
|
prt_escp.o prt_text.o prt_ps.o
|
||||||
|
|||||||
Reference in New Issue
Block a user