2017-05-09 22:09:55 -04:00
|
|
|
/*
|
2018-03-19 01:02:04 +01:00
|
|
|
* VARCem Virtual ARchaeological Computer EMulator.
|
|
|
|
|
* An emulator of (mostly) x86-based PC systems and devices,
|
|
|
|
|
* using the ISA,EISA,VLB,MCA and PCI system buses, roughly
|
|
|
|
|
* spanning the era between 1981 and 1995.
|
2017-05-09 22:09:55 -04:00
|
|
|
*
|
2018-03-19 01:02:04 +01:00
|
|
|
* This file is part of the VARCem Project.
|
2017-05-09 22:09:55 -04:00
|
|
|
*
|
|
|
|
|
* Implementation of the network module.
|
|
|
|
|
*
|
2017-05-12 05:05:20 -04:00
|
|
|
* NOTE The definition of the netcard_t is currently not optimal;
|
|
|
|
|
* it should be malloc'ed and then linked to the NETCARD def.
|
|
|
|
|
* Will be done later.
|
|
|
|
|
*
|
2020-03-25 00:46:02 +02:00
|
|
|
*
|
2017-05-09 22:09:55 -04:00
|
|
|
*
|
2017-06-04 02:11:19 -04:00
|
|
|
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
|
2017-10-10 03:07:29 -04:00
|
|
|
*
|
2019-11-14 20:59:51 +01:00
|
|
|
* Copyright 2017-2019 Fred N. van Kempen.
|
2018-03-19 01:02:04 +01:00
|
|
|
*
|
|
|
|
|
* Redistribution and use in source and binary forms, with
|
|
|
|
|
* or without modification, are permitted provided that the
|
|
|
|
|
* following conditions are met:
|
|
|
|
|
*
|
|
|
|
|
* 1. Redistributions of source code must retain the entire
|
|
|
|
|
* above notice, this list of conditions and the following
|
|
|
|
|
* disclaimer.
|
|
|
|
|
*
|
|
|
|
|
* 2. Redistributions in binary form must reproduce the above
|
|
|
|
|
* copyright notice, this list of conditions and the
|
|
|
|
|
* following disclaimer in the documentation and/or other
|
|
|
|
|
* materials provided with the distribution.
|
|
|
|
|
*
|
|
|
|
|
* 3. Neither the name of the copyright holder nor the names
|
|
|
|
|
* of its contributors may be used to endorse or promote
|
|
|
|
|
* products derived from this software without specific
|
|
|
|
|
* prior written permission.
|
|
|
|
|
*
|
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
|
|
|
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
2017-05-09 22:09:55 -04:00
|
|
|
*/
|
2018-05-21 19:04:05 +02:00
|
|
|
#include <stdarg.h>
|
2021-12-17 18:48:13 +01:00
|
|
|
#include <stdatomic.h>
|
2017-09-25 04:31:20 -04:00
|
|
|
#include <stdint.h>
|
2018-05-21 19:04:05 +02:00
|
|
|
#include <stdio.h>
|
2017-05-06 17:48:33 +02:00
|
|
|
#include <string.h>
|
2017-09-25 04:31:20 -04:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <wchar.h>
|
2020-12-16 20:35:07 +01:00
|
|
|
#include <time.h>
|
2018-05-21 19:04:05 +02:00
|
|
|
#define HAVE_STDARG_H
|
2020-03-29 14:24:42 +02:00
|
|
|
#include <86box/86box.h>
|
|
|
|
|
#include <86box/device.h>
|
2020-04-29 23:39:54 +02:00
|
|
|
#include <86box/timer.h>
|
2020-03-29 14:24:42 +02:00
|
|
|
#include <86box/plat.h>
|
2022-04-19 23:06:39 +02:00
|
|
|
#include <86box/thread.h>
|
2020-03-29 14:24:42 +02:00
|
|
|
#include <86box/ui.h>
|
|
|
|
|
#include <86box/network.h>
|
|
|
|
|
#include <86box/net_3c503.h>
|
|
|
|
|
#include <86box/net_ne2000.h>
|
|
|
|
|
#include <86box/net_pcnet.h>
|
2020-10-17 01:21:46 -03:00
|
|
|
#include <86box/net_plip.h>
|
2020-03-29 14:24:42 +02:00
|
|
|
#include <86box/net_wd8003.h>
|
2017-05-06 17:48:33 +02:00
|
|
|
|
|
|
|
|
|
2022-02-02 17:48:04 -05:00
|
|
|
static const device_t net_none_device = {
|
2022-03-13 09:50:25 -04:00
|
|
|
.name = "None",
|
|
|
|
|
.internal_name = "none",
|
|
|
|
|
.flags = 0,
|
|
|
|
|
.local = NET_TYPE_NONE,
|
|
|
|
|
.init = NULL,
|
|
|
|
|
.close = NULL,
|
|
|
|
|
.reset = NULL,
|
|
|
|
|
{ .available = NULL },
|
|
|
|
|
.speed_changed = NULL,
|
|
|
|
|
.force_redraw = NULL,
|
|
|
|
|
.config = NULL
|
2022-02-02 17:48:04 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2017-05-12 05:05:20 -04:00
|
|
|
static netcard_t net_cards[] = {
|
2022-02-26 23:31:28 -05:00
|
|
|
// clang-format off
|
|
|
|
|
{ &net_none_device, NULL },
|
|
|
|
|
{ &threec503_device, NULL },
|
|
|
|
|
{ &pcnet_am79c960_device, NULL },
|
|
|
|
|
{ &pcnet_am79c961_device, NULL },
|
|
|
|
|
{ &ne1000_device, NULL },
|
|
|
|
|
{ &ne2000_device, NULL },
|
|
|
|
|
{ &pcnet_am79c960_eb_device, NULL },
|
|
|
|
|
{ &rtl8019as_device, NULL },
|
|
|
|
|
{ &wd8003e_device, NULL },
|
|
|
|
|
{ &wd8003eb_device, NULL },
|
|
|
|
|
{ &wd8013ebt_device, NULL },
|
|
|
|
|
{ &plip_device, NULL },
|
|
|
|
|
{ ðernext_mc_device, NULL },
|
|
|
|
|
{ &wd8003eta_device, NULL },
|
|
|
|
|
{ &wd8003ea_device, NULL },
|
2022-07-23 23:54:42 +02:00
|
|
|
{ &wd8013epa_device, NULL },
|
2022-02-26 23:31:28 -05:00
|
|
|
{ &pcnet_am79c973_device, NULL },
|
|
|
|
|
{ &pcnet_am79c970a_device, NULL },
|
|
|
|
|
{ &rtl8029as_device, NULL },
|
|
|
|
|
{ &pcnet_am79c960_vlb_device, NULL },
|
|
|
|
|
{ NULL, NULL }
|
|
|
|
|
// clang-format off
|
2017-05-12 05:05:20 -04:00
|
|
|
};
|
2017-05-06 17:48:33 +02:00
|
|
|
|
|
|
|
|
|
2017-05-18 01:57:16 -04:00
|
|
|
/* Global variables. */
|
|
|
|
|
int network_type;
|
|
|
|
|
int network_ndev;
|
2017-10-07 00:46:54 -04:00
|
|
|
int network_card;
|
2019-02-06 03:34:39 +01:00
|
|
|
char network_host[522];
|
2018-03-18 20:48:10 +01:00
|
|
|
netdev_t network_devs[32];
|
2020-11-16 00:01:21 +01:00
|
|
|
int network_rx_pause = 0,
|
|
|
|
|
network_tx_pause = 0;
|
2020-04-30 02:12:59 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Local variables. */
|
2021-12-17 18:48:13 +01:00
|
|
|
static volatile atomic_int net_wait = 0;
|
2020-04-30 02:12:59 +02:00
|
|
|
static mutex_t *network_mutex;
|
|
|
|
|
static uint8_t *network_mac;
|
2020-07-12 20:20:06 +02:00
|
|
|
static uint8_t network_timer_active = 0;
|
2020-04-30 02:12:59 +02:00
|
|
|
static pc_timer_t network_rx_queue_timer;
|
2022-02-20 13:58:38 +01:00
|
|
|
static netpkt_t *first_pkt[3] = { NULL, NULL, NULL },
|
|
|
|
|
*last_pkt[3] = { NULL, NULL, NULL };
|
2022-02-20 21:04:30 +01:00
|
|
|
static netpkt_t queued_pkt;
|
2017-10-16 21:19:51 +02:00
|
|
|
|
|
|
|
|
|
2018-05-21 19:04:05 +02:00
|
|
|
#ifdef ENABLE_NETWORK_LOG
|
|
|
|
|
int network_do_log = ENABLE_NETWORK_LOG;
|
2020-10-17 20:28:30 -03:00
|
|
|
static FILE *network_dump = NULL;
|
|
|
|
|
static mutex_t *network_dump_mutex;
|
2018-03-19 01:02:04 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2018-10-19 00:37:25 +02:00
|
|
|
network_log(const char *fmt, ...)
|
2018-03-19 01:02:04 +01:00
|
|
|
{
|
2018-05-21 19:04:05 +02:00
|
|
|
va_list ap;
|
2018-03-19 01:02:04 +01:00
|
|
|
|
2018-05-21 19:04:05 +02:00
|
|
|
if (network_do_log) {
|
2018-10-19 00:37:25 +02:00
|
|
|
va_start(ap, fmt);
|
|
|
|
|
pclog_ex(fmt, ap);
|
2018-05-21 19:04:05 +02:00
|
|
|
va_end(ap);
|
2018-03-19 01:02:04 +01:00
|
|
|
}
|
2018-05-21 19:04:05 +02:00
|
|
|
}
|
2020-10-17 01:21:46 -03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
network_dump_packet(netpkt_t *pkt)
|
|
|
|
|
{
|
|
|
|
|
if (!network_dump)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
struct timeval tv;
|
|
|
|
|
gettimeofday(&tv, NULL);
|
|
|
|
|
struct {
|
|
|
|
|
uint32_t ts_sec, ts_usec, incl_len, orig_len;
|
|
|
|
|
} pcap_packet_hdr = {
|
|
|
|
|
tv.tv_sec, tv.tv_usec, pkt->len, pkt->len
|
|
|
|
|
};
|
|
|
|
|
|
2020-10-17 20:28:30 -03:00
|
|
|
if (network_dump_mutex)
|
|
|
|
|
thread_wait_mutex(network_dump_mutex);
|
|
|
|
|
|
|
|
|
|
size_t written;
|
|
|
|
|
if ((written = fwrite(&pcap_packet_hdr, 1, sizeof(pcap_packet_hdr), network_dump)) < sizeof(pcap_packet_hdr)) {
|
|
|
|
|
network_log("NETWORK: failed to write dump packet header\n");
|
|
|
|
|
fseek(network_dump, -written, SEEK_CUR);
|
|
|
|
|
} else {
|
|
|
|
|
if ((written = fwrite(pkt->data, 1, pkt->len, network_dump)) < pkt->len) {
|
|
|
|
|
network_log("NETWORK: failed to write dump packet data\n");
|
|
|
|
|
fseek(network_dump, -written - sizeof(pcap_packet_hdr), SEEK_CUR);
|
|
|
|
|
}
|
|
|
|
|
fflush(network_dump);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (network_dump_mutex)
|
|
|
|
|
thread_release_mutex(network_dump_mutex);
|
2020-10-17 01:21:46 -03:00
|
|
|
}
|
2018-10-19 00:37:25 +02:00
|
|
|
#else
|
|
|
|
|
#define network_log(fmt, ...)
|
2020-10-17 01:21:46 -03:00
|
|
|
#define network_dump_packet(pkt)
|
2018-10-19 00:37:25 +02:00
|
|
|
#endif
|
2018-03-19 01:02:04 +01:00
|
|
|
|
|
|
|
|
|
2017-10-16 21:19:51 +02:00
|
|
|
void
|
2017-10-29 04:20:20 -05:00
|
|
|
network_wait(uint8_t wait)
|
2017-10-16 21:19:51 +02:00
|
|
|
{
|
2017-10-17 05:15:53 +02:00
|
|
|
if (wait)
|
2017-10-29 04:20:20 -05:00
|
|
|
thread_wait_mutex(network_mutex);
|
|
|
|
|
else
|
|
|
|
|
thread_release_mutex(network_mutex);
|
2017-10-16 21:19:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-05-12 05:05:20 -04:00
|
|
|
/*
|
|
|
|
|
* Initialize the configured network cards.
|
|
|
|
|
*
|
|
|
|
|
* This function gets called only once, from the System
|
|
|
|
|
* Platform initialization code (currently in pc.c) to
|
|
|
|
|
* set our local stuff to a known state.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
network_init(void)
|
|
|
|
|
{
|
2017-05-22 00:21:22 -04:00
|
|
|
int i;
|
|
|
|
|
|
2017-10-07 00:46:54 -04:00
|
|
|
/* Initialize to a known state. */
|
2017-05-18 01:57:16 -04:00
|
|
|
network_type = NET_TYPE_NONE;
|
2017-05-12 05:05:20 -04:00
|
|
|
network_card = 0;
|
2017-05-18 01:57:16 -04:00
|
|
|
|
2017-05-22 00:21:22 -04:00
|
|
|
/* Create a first device entry that's always there, as needed by UI. */
|
|
|
|
|
strcpy(network_devs[0].device, "none");
|
|
|
|
|
strcpy(network_devs[0].description, "None");
|
|
|
|
|
network_ndev = 1;
|
|
|
|
|
|
|
|
|
|
/* Initialize the Pcap system module, if present. */
|
2017-10-29 04:20:20 -05:00
|
|
|
i = net_pcap_prepare(&network_devs[network_ndev]);
|
2017-05-22 00:21:22 -04:00
|
|
|
if (i > 0)
|
|
|
|
|
network_ndev += i;
|
2020-10-17 01:21:46 -03:00
|
|
|
|
|
|
|
|
#ifdef ENABLE_NETWORK_LOG
|
|
|
|
|
/* Start packet dump. */
|
|
|
|
|
network_dump = fopen("network.pcap", "wb");
|
|
|
|
|
|
|
|
|
|
struct {
|
|
|
|
|
uint32_t magic_number;
|
|
|
|
|
uint16_t version_major, version_minor;
|
|
|
|
|
int32_t thiszone;
|
|
|
|
|
uint32_t sigfigs, snaplen, network;
|
|
|
|
|
} pcap_hdr = {
|
|
|
|
|
0xa1b2c3d4,
|
|
|
|
|
2, 4,
|
|
|
|
|
0,
|
|
|
|
|
0, 65535, 1
|
|
|
|
|
};
|
|
|
|
|
fwrite(&pcap_hdr, sizeof(pcap_hdr), 1, network_dump);
|
|
|
|
|
fflush(network_dump);
|
|
|
|
|
#endif
|
2017-05-12 05:05:20 -04:00
|
|
|
}
|
2017-05-06 17:48:33 +02:00
|
|
|
|
|
|
|
|
|
2020-04-29 23:39:54 +02:00
|
|
|
void
|
2020-04-30 02:12:59 +02:00
|
|
|
network_queue_put(int tx, void *priv, uint8_t *data, int len)
|
2020-04-29 23:39:54 +02:00
|
|
|
{
|
|
|
|
|
netpkt_t *temp;
|
|
|
|
|
|
2022-02-20 21:04:30 +01:00
|
|
|
temp = (netpkt_t *) calloc(sizeof(netpkt_t), 1);
|
2020-04-29 23:39:54 +02:00
|
|
|
temp->priv = priv;
|
|
|
|
|
memcpy(temp->data, data, len);
|
|
|
|
|
temp->len = len;
|
2020-04-30 02:12:59 +02:00
|
|
|
temp->prev = last_pkt[tx];
|
|
|
|
|
temp->next = NULL;
|
2020-04-29 23:39:54 +02:00
|
|
|
|
2020-04-30 02:12:59 +02:00
|
|
|
if (last_pkt[tx] != NULL)
|
|
|
|
|
last_pkt[tx]->next = temp;
|
|
|
|
|
last_pkt[tx] = temp;
|
2020-04-29 23:39:54 +02:00
|
|
|
|
2020-04-30 02:12:59 +02:00
|
|
|
if (first_pkt[tx] == NULL)
|
|
|
|
|
first_pkt[tx] = temp;
|
2020-04-29 23:39:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2022-02-20 21:04:30 +01:00
|
|
|
network_queue_get(int tx, netpkt_t *pkt)
|
2020-04-29 23:39:54 +02:00
|
|
|
{
|
2022-02-20 21:04:30 +01:00
|
|
|
netpkt_t *temp;
|
|
|
|
|
|
|
|
|
|
temp = first_pkt[tx];
|
|
|
|
|
|
|
|
|
|
if (temp == NULL) {
|
|
|
|
|
memset(pkt, 0x00, sizeof(netpkt_t));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memcpy(pkt, temp, sizeof(netpkt_t));
|
|
|
|
|
|
|
|
|
|
first_pkt[tx] = temp->next;
|
|
|
|
|
free(temp);
|
|
|
|
|
|
2020-04-30 02:12:59 +02:00
|
|
|
if (first_pkt[tx] == NULL)
|
2022-02-20 21:04:30 +01:00
|
|
|
last_pkt[tx] = NULL;
|
2020-04-29 23:39:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2022-02-20 21:04:30 +01:00
|
|
|
network_queue_transmit(int tx)
|
2020-04-29 23:39:54 +02:00
|
|
|
{
|
|
|
|
|
netpkt_t *temp;
|
|
|
|
|
|
2020-04-30 02:12:59 +02:00
|
|
|
temp = first_pkt[tx];
|
2020-04-29 23:39:54 +02:00
|
|
|
|
|
|
|
|
if (temp == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
2022-02-20 21:04:30 +01:00
|
|
|
if (temp->len > 0) {
|
|
|
|
|
network_dump_packet(temp);
|
|
|
|
|
/* 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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-30 02:12:59 +02:00
|
|
|
first_pkt[tx] = temp->next;
|
2020-04-29 23:39:54 +02:00
|
|
|
free(temp);
|
|
|
|
|
|
2020-04-30 02:12:59 +02:00
|
|
|
if (first_pkt[tx] == NULL)
|
|
|
|
|
last_pkt[tx] = NULL;
|
2020-04-29 23:39:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-02-20 21:04:30 +01:00
|
|
|
static void
|
|
|
|
|
network_queue_copy(int dest, int src)
|
|
|
|
|
{
|
|
|
|
|
netpkt_t *temp, *temp2;
|
|
|
|
|
|
|
|
|
|
temp = first_pkt[src];
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-04-29 23:39:54 +02:00
|
|
|
static void
|
2020-04-30 02:12:59 +02:00
|
|
|
network_queue_clear(int tx)
|
2020-04-29 23:39:54 +02:00
|
|
|
{
|
2020-05-06 00:26:07 +02:00
|
|
|
netpkt_t *temp = first_pkt[tx], *temp2;
|
2020-04-29 23:39:54 +02:00
|
|
|
|
|
|
|
|
if (temp == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
do {
|
2020-05-06 00:26:07 +02:00
|
|
|
temp2 = temp->next;
|
2020-04-29 23:39:54 +02:00
|
|
|
free(temp);
|
2020-05-06 00:26:07 +02:00
|
|
|
temp = temp2;
|
2020-04-29 23:39:54 +02:00
|
|
|
} while (temp != NULL);
|
|
|
|
|
|
2020-04-30 02:12:59 +02:00
|
|
|
first_pkt[tx] = last_pkt[tx] = NULL;
|
2020-04-29 23:39:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2020-04-30 02:12:59 +02:00
|
|
|
network_rx_queue(void *priv)
|
2020-04-29 23:39:54 +02:00
|
|
|
{
|
2020-11-16 00:01:21 +01:00
|
|
|
int ret = 1;
|
|
|
|
|
|
2022-02-20 01:22:28 +01:00
|
|
|
if (network_rx_pause || !thread_test_mutex(network_mutex)) {
|
2020-10-17 01:21:46 -03:00
|
|
|
timer_on_auto(&network_rx_queue_timer, 0.762939453125 * 2.0 * 128.0);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-20 21:04:30 +01:00
|
|
|
if (queued_pkt.len == 0)
|
2022-02-20 19:41:34 +01:00
|
|
|
network_queue_get(0, &queued_pkt);
|
2022-02-20 21:04:30 +01:00
|
|
|
if (queued_pkt.len > 0) {
|
|
|
|
|
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));
|
2020-11-16 00:01:21 +01:00
|
|
|
if (ret)
|
2022-02-20 21:04:30 +01:00
|
|
|
queued_pkt.len = 0;
|
2020-04-29 23:39:54 +02:00
|
|
|
|
2022-02-20 13:58:38 +01:00
|
|
|
/* Transmission. */
|
2022-02-20 21:04:30 +01:00
|
|
|
network_queue_copy(1, 2);
|
2022-02-20 01:30:37 +01:00
|
|
|
|
|
|
|
|
network_wait(0);
|
2020-04-29 23:39:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-05-12 05:05:20 -04:00
|
|
|
/*
|
|
|
|
|
* Attach a network card to the system.
|
|
|
|
|
*
|
|
|
|
|
* This function is called by a hardware driver ("card") after it has
|
|
|
|
|
* finished initializing itself, to link itself to the platform support
|
|
|
|
|
* modules.
|
|
|
|
|
*/
|
2017-10-29 04:20:20 -05:00
|
|
|
void
|
2020-04-20 19:02:13 +02:00
|
|
|
network_attach(void *dev, uint8_t *mac, NETRXCB rx, NETWAITCB wait, NETSETLINKSTATE set_link_state)
|
2017-05-06 17:48:33 +02:00
|
|
|
{
|
2017-10-29 04:20:20 -05:00
|
|
|
if (network_card == 0) return;
|
2017-05-06 17:48:33 +02:00
|
|
|
|
2017-10-29 04:20:20 -05:00
|
|
|
/* Save the card's info. */
|
2017-10-16 04:54:41 -04:00
|
|
|
net_cards[network_card].priv = dev;
|
2017-05-12 05:05:20 -04:00
|
|
|
net_cards[network_card].rx = rx;
|
2020-02-29 19:12:23 +01:00
|
|
|
net_cards[network_card].wait = wait;
|
2020-04-20 19:02:13 +02:00
|
|
|
net_cards[network_card].set_link_state = set_link_state;
|
2018-03-18 20:48:10 +01:00
|
|
|
network_mac = mac;
|
2017-05-12 05:05:20 -04:00
|
|
|
|
2019-11-14 21:22:54 +01:00
|
|
|
network_set_wait(0);
|
2019-11-14 21:00:52 +01:00
|
|
|
|
2017-10-29 04:20:20 -05:00
|
|
|
/* Activate the platform module. */
|
2017-05-12 05:05:20 -04:00
|
|
|
switch(network_type) {
|
2017-05-18 01:57:16 -04:00
|
|
|
case NET_TYPE_PCAP:
|
2018-03-18 20:48:10 +01:00
|
|
|
(void)net_pcap_reset(&net_cards[network_card], network_mac);
|
2017-05-12 05:05:20 -04:00
|
|
|
break;
|
|
|
|
|
|
2017-05-18 01:57:16 -04:00
|
|
|
case NET_TYPE_SLIRP:
|
2018-03-18 20:48:10 +01:00
|
|
|
(void)net_slirp_reset(&net_cards[network_card], network_mac);
|
2017-05-12 05:05:20 -04:00
|
|
|
break;
|
2017-05-06 17:48:33 +02:00
|
|
|
}
|
2020-04-29 23:39:54 +02:00
|
|
|
|
2022-02-20 13:58:38 +01:00
|
|
|
first_pkt[0] = first_pkt[1] = first_pkt[2] = NULL;
|
|
|
|
|
last_pkt[0] = last_pkt[1] = last_pkt[2] = NULL;
|
2022-02-20 21:04:30 +01:00
|
|
|
memset(&queued_pkt, 0x00, sizeof(netpkt_t));
|
2020-05-20 20:35:55 +02:00
|
|
|
memset(&network_rx_queue_timer, 0x00, sizeof(pc_timer_t));
|
2020-04-30 02:12:59 +02:00
|
|
|
timer_add(&network_rx_queue_timer, network_rx_queue, NULL, 0);
|
2020-04-29 23:39:54 +02:00
|
|
|
/* 10 mbps. */
|
2020-04-30 02:12:59 +02:00
|
|
|
timer_on_auto(&network_rx_queue_timer, 0.762939453125 * 2.0);
|
2020-07-12 20:20:06 +02:00
|
|
|
network_timer_active = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Stop the network timer. */
|
|
|
|
|
void
|
|
|
|
|
network_timer_stop(void)
|
|
|
|
|
{
|
|
|
|
|
if (network_timer_active) {
|
|
|
|
|
timer_stop(&network_rx_queue_timer);
|
2020-07-12 20:21:43 +02:00
|
|
|
memset(&network_rx_queue_timer, 0x00, sizeof(pc_timer_t));
|
2020-07-12 20:20:06 +02:00
|
|
|
network_timer_active = 0;
|
|
|
|
|
}
|
2017-05-06 17:48:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-05-12 05:05:20 -04:00
|
|
|
/* Stop any network activity. */
|
2017-05-06 17:48:33 +02:00
|
|
|
void
|
2017-05-12 05:05:20 -04:00
|
|
|
network_close(void)
|
2017-05-06 17:48:33 +02:00
|
|
|
{
|
2020-07-12 20:20:06 +02:00
|
|
|
network_timer_stop();
|
2020-04-29 23:39:54 +02:00
|
|
|
|
2017-10-29 04:20:20 -05:00
|
|
|
/* 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();
|
2022-02-20 02:26:27 -05:00
|
|
|
|
2017-10-29 04:20:20 -05:00
|
|
|
/* Close the network thread mutex. */
|
|
|
|
|
thread_close_mutex(network_mutex);
|
|
|
|
|
network_mutex = NULL;
|
2018-03-18 20:48:10 +01:00
|
|
|
network_mac = NULL;
|
2020-10-17 20:28:30 -03:00
|
|
|
#ifdef ENABLE_NETWORK_LOG
|
|
|
|
|
thread_close_mutex(network_dump_mutex);
|
|
|
|
|
network_dump_mutex = NULL;
|
|
|
|
|
#endif
|
2017-10-29 04:20:20 -05:00
|
|
|
|
2020-04-30 02:12:59 +02:00
|
|
|
/* Here is where we clear the queues. */
|
|
|
|
|
network_queue_clear(0);
|
|
|
|
|
network_queue_clear(1);
|
2020-04-28 01:01:39 +02:00
|
|
|
|
2018-05-21 19:04:05 +02:00
|
|
|
network_log("NETWORK: closed.\n");
|
2017-05-09 22:09:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-05-12 05:05:20 -04:00
|
|
|
/*
|
|
|
|
|
* Reset the network card(s).
|
|
|
|
|
*
|
|
|
|
|
* This function is called each time the system is reset,
|
|
|
|
|
* either a hard reset (including power-up) or a soft reset
|
|
|
|
|
* including C-A-D reset.) It is responsible for connecting
|
|
|
|
|
* everything together.
|
|
|
|
|
*/
|
2017-05-09 22:09:55 -04:00
|
|
|
void
|
|
|
|
|
network_reset(void)
|
|
|
|
|
{
|
2017-10-29 04:20:20 -05:00
|
|
|
int i = -1;
|
|
|
|
|
|
2018-05-21 19:04:05 +02:00
|
|
|
network_log("NETWORK: reset (type=%d, card=%d)\n",
|
2018-03-19 01:02:04 +01:00
|
|
|
network_type, network_card);
|
2022-02-07 18:05:58 +05:00
|
|
|
|
2017-10-29 04:20:20 -05:00
|
|
|
ui_sb_update_icon(SB_NETWORK, 0);
|
2017-05-12 05:05:20 -04:00
|
|
|
|
|
|
|
|
/* Just in case.. */
|
|
|
|
|
network_close();
|
2017-05-06 17:48:33 +02:00
|
|
|
|
2017-05-12 05:05:20 -04:00
|
|
|
/* If no active card, we're done. */
|
2017-05-18 01:57:16 -04:00
|
|
|
if ((network_type==NET_TYPE_NONE) || (network_card==0)) return;
|
2017-05-06 17:48:33 +02:00
|
|
|
|
2020-04-27 13:24:43 +02:00
|
|
|
network_mutex = thread_create_mutex();
|
2020-10-17 20:28:30 -03:00
|
|
|
#ifdef ENABLE_NETWORK_LOG
|
|
|
|
|
network_dump_mutex = thread_create_mutex();
|
|
|
|
|
#endif
|
2017-10-29 04:20:20 -05:00
|
|
|
|
|
|
|
|
/* Initialize the platform module. */
|
|
|
|
|
switch(network_type) {
|
|
|
|
|
case NET_TYPE_PCAP:
|
|
|
|
|
i = net_pcap_init();
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case NET_TYPE_SLIRP:
|
|
|
|
|
i = net_slirp_init();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (i < 0) {
|
|
|
|
|
/* Tell user we can't do this (at the moment.) */
|
2020-06-18 21:20:10 -03:00
|
|
|
ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2093, (wchar_t *) IDS_2129);
|
2017-10-29 04:20:20 -05:00
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
}
|
2017-05-27 03:53:32 +02:00
|
|
|
|
2018-05-21 19:04:05 +02:00
|
|
|
network_log("NETWORK: set up for %s, card='%s'\n",
|
2017-10-29 04:20:20 -05:00
|
|
|
(network_type==NET_TYPE_SLIRP)?"SLiRP":"Pcap",
|
2022-04-02 15:46:19 +00:19
|
|
|
net_cards[network_card].device->name);
|
2017-05-12 17:33:28 -04:00
|
|
|
|
2017-05-12 05:05:20 -04:00
|
|
|
/* Add the (new?) card to the I/O system. */
|
|
|
|
|
if (net_cards[network_card].device) {
|
2018-05-21 19:04:05 +02:00
|
|
|
network_log("NETWORK: adding device '%s'\n",
|
2022-04-02 15:46:19 +00:19
|
|
|
net_cards[network_card].device->name);
|
2017-05-12 05:05:20 -04:00
|
|
|
device_add(net_cards[network_card].device);
|
2017-05-06 17:48:33 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-04-30 02:12:59 +02:00
|
|
|
/* Queue a packet for transmission to one of the network providers. */
|
2017-05-06 17:48:33 +02:00
|
|
|
void
|
2017-05-12 05:05:20 -04:00
|
|
|
network_tx(uint8_t *bufp, int len)
|
2017-05-06 17:48:33 +02:00
|
|
|
{
|
2017-10-29 04:20:20 -05:00
|
|
|
ui_sb_update_icon(SB_NETWORK, 1);
|
|
|
|
|
|
2022-02-20 13:58:38 +01:00
|
|
|
network_queue_put(2, NULL, bufp, len);
|
2017-05-12 05:05:20 -04:00
|
|
|
|
2020-04-30 02:12:59 +02:00
|
|
|
ui_sb_update_icon(SB_NETWORK, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Actually transmit the packet. */
|
|
|
|
|
int
|
|
|
|
|
network_tx_queue_check(void)
|
|
|
|
|
{
|
|
|
|
|
if ((first_pkt[1] == NULL) && (last_pkt[1] == NULL))
|
|
|
|
|
return 0;
|
|
|
|
|
|
2020-11-16 00:01:21 +01:00
|
|
|
if (network_tx_pause)
|
2022-02-20 13:58:38 +01:00
|
|
|
return 1;
|
2020-11-16 00:01:21 +01:00
|
|
|
|
2022-02-20 21:04:30 +01:00
|
|
|
network_queue_transmit(1);
|
2020-04-30 02:12:59 +02:00
|
|
|
return 1;
|
2017-10-29 04:20:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
network_dev_to_id(char *devname)
|
|
|
|
|
{
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
|
|
for (i=0; i<network_ndev; i++) {
|
2018-03-19 01:02:04 +01:00
|
|
|
if (! strcmp((char *)network_devs[i].device, devname)) {
|
2017-10-29 04:20:20 -05:00
|
|
|
return(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If no match found, assume "none". */
|
|
|
|
|
return(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* UI */
|
|
|
|
|
int
|
|
|
|
|
network_available(void)
|
|
|
|
|
{
|
|
|
|
|
if ((network_type == NET_TYPE_NONE) || (network_card == 0)) return(0);
|
|
|
|
|
|
|
|
|
|
return(1);
|
2017-05-06 17:48:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-05-12 05:05:20 -04:00
|
|
|
/* UI */
|
2017-05-06 17:48:33 +02:00
|
|
|
int
|
|
|
|
|
network_card_available(int card)
|
|
|
|
|
{
|
|
|
|
|
if (net_cards[card].device)
|
|
|
|
|
return(device_available(net_cards[card].device));
|
|
|
|
|
|
|
|
|
|
return(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-05-12 05:05:20 -04:00
|
|
|
/* UI */
|
2018-03-19 01:02:04 +01:00
|
|
|
const device_t *
|
2017-05-06 17:48:33 +02:00
|
|
|
network_card_getdevice(int card)
|
|
|
|
|
{
|
|
|
|
|
return(net_cards[card].device);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-05-12 05:05:20 -04:00
|
|
|
/* UI */
|
2017-05-06 17:48:33 +02:00
|
|
|
int
|
|
|
|
|
network_card_has_config(int card)
|
|
|
|
|
{
|
|
|
|
|
if (! net_cards[card].device) return(0);
|
|
|
|
|
|
2022-04-04 18:16:53 +02:00
|
|
|
return(device_has_config(net_cards[card].device) ? 1 : 0);
|
2017-05-06 17:48:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-05-12 05:05:20 -04:00
|
|
|
/* UI */
|
2017-05-06 17:48:33 +02:00
|
|
|
char *
|
|
|
|
|
network_card_get_internal_name(int card)
|
|
|
|
|
{
|
2022-02-03 03:10:06 +01:00
|
|
|
return device_get_internal_name(net_cards[card].device);
|
2017-05-06 17:48:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-05-12 05:05:20 -04:00
|
|
|
/* UI */
|
2017-05-06 17:48:33 +02:00
|
|
|
int
|
|
|
|
|
network_card_get_from_internal_name(char *s)
|
|
|
|
|
{
|
|
|
|
|
int c = 0;
|
2022-02-20 02:26:27 -05:00
|
|
|
|
2022-02-03 03:10:06 +01:00
|
|
|
while (net_cards[c].device != NULL) {
|
2022-01-31 16:14:36 -05:00
|
|
|
if (! strcmp((char *)net_cards[c].device->internal_name, s))
|
2022-02-03 03:10:06 +01:00
|
|
|
return(c);
|
2017-05-06 17:48:33 +02:00
|
|
|
c++;
|
|
|
|
|
}
|
2022-02-20 02:26:27 -05:00
|
|
|
|
2022-02-03 03:10:06 +01:00
|
|
|
return 0;
|
2017-05-06 17:48:33 +02:00
|
|
|
}
|
2019-11-14 20:59:51 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
network_set_wait(int wait)
|
|
|
|
|
{
|
2019-11-14 21:22:54 +01:00
|
|
|
net_wait = wait;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
network_get_wait(void)
|
|
|
|
|
{
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
ret = net_wait;
|
|
|
|
|
return ret;
|
2019-11-14 20:59:51 +01:00
|
|
|
}
|