diff --git a/src/include/86box/network.h b/src/include/86box/network.h index ac4a08d02..85b2d8276 100644 --- a/src/include/86box/network.h +++ b/src/include/86box/network.h @@ -116,6 +116,8 @@ extern void network_close(void); extern void network_reset(void); extern int network_available(void); extern void network_tx(uint8_t *, int); +extern void network_do_tx(void); +extern int network_tx_queue_check(void); extern int net_pcap_prepare(netdev_t *); extern int net_pcap_init(void); @@ -139,7 +141,7 @@ extern const device_t *network_card_getdevice(int); extern void network_set_wait(int wait); extern int network_get_wait(void); -extern void network_queue_put(void *priv, uint8_t *data, int len); +extern void network_queue_put(int tx, void *priv, uint8_t *data, int len); #ifdef __cplusplus } diff --git a/src/network/net_pcap.c b/src/network/net_pcap.c index 0d91fa55a..7068443cd 100644 --- a/src/network/net_pcap.c +++ b/src/network/net_pcap.c @@ -166,6 +166,7 @@ poll_thread(void *arg) uint32_t mac_cmp32[2]; uint16_t mac_cmp16[2]; event_t *evt; + int tx; pcap_log("PCAP: polling started.\n"); thread_set_event(poll_state); @@ -181,16 +182,16 @@ poll_thread(void *arg) /* Wait for a poll request. */ network_poll(); - if (pcap == NULL) break; + if (pcap == NULL) + break; /* Wait for the next packet to arrive. */ + tx = network_tx_queue_check(); 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))) data = NULL; else data = (uint8_t *)f_pcap_next((void *)pcap, &h); if (data != NULL) { - // ui_sb_update_icon(SB_NETWORK, 1); - /* Received MAC. */ mac_cmp32[0] = *(uint32_t *)(data+6); mac_cmp16[0] = *(uint16_t *)(data+10); @@ -201,19 +202,19 @@ poll_thread(void *arg) if ((mac_cmp32[0] != mac_cmp32[1]) || (mac_cmp16[0] != mac_cmp16[1])) { - network_queue_put(poll_card->priv, data, h.caplen); - // poll_card->rx(poll_card->priv, data, h.caplen); + network_queue_put(0, poll_card->priv, data, h.caplen); } else { /* Mark as invalid packet. */ data = NULL; } } + if (tx) + network_do_tx(); + /* If we did not get anything, wait a while. */ - if (data == NULL) { - // ui_sb_update_icon(SB_NETWORK, 0); + if ((data == NULL) && !tx) thread_wait_event(evt, 10); - } /* Release ownership of the device. */ network_wait(0); @@ -295,17 +296,8 @@ net_pcap_init(void) char *str; /* Did we already load the library? */ - if (pcap_handle == NULL) return(-1); -#if 0 - // no, we don't.. - /* Load the DLL if needed. We already know it exists. */ -#ifdef _WIN32 - pcap_handle = dynld_module("wpcap.dll", pcap_imports); -#else - pcap_handle = dynld_module("libpcap.so", pcap_imports); -#endif - if (pcap_handle == NULL) return(-1); -#endif + if (pcap_handle == NULL) + return(-1); /* Get the PCAP library name and version. */ strcpy(errbuf, f_pcap_lib_version()); @@ -333,8 +325,6 @@ net_pcap_close(void) { void *pc; - // ui_sb_update_icon(SB_NETWORK, 0); - if (pcap == NULL) return; pcap_log("PCAP: closing.\n"); @@ -360,15 +350,6 @@ net_pcap_close(void) /* OK, now shut down Pcap itself. */ f_pcap_close(pc); pcap = NULL; - -#if 0 - // no, we don't.. - /* Unload the DLL if possible. */ - if (pcap_handle != NULL) { - dynld_close((void *)pcap_handle); - pcap_handle = NULL; - } -#endif } @@ -390,8 +371,6 @@ net_pcap_reset(const netcard_t *card, uint8_t *mac) char filter_exp[255]; struct bpf_program fp; - // ui_sb_update_icon(SB_NETWORK, 0); - /* Open a PCAP live channel. */ if ((pcap = f_pcap_open_live(network_host, /* interface name */ 1518, /* max packet size */ @@ -438,15 +417,8 @@ net_pcap_reset(const netcard_t *card, uint8_t *mac) void net_pcap_in(uint8_t *bufp, int len) { - if (pcap == NULL) return; - - // ui_sb_update_icon(SB_NETWORK, 1); - - network_busy(1); + if (pcap == NULL) + return; f_pcap_sendpacket((void *)pcap, bufp, len); - - network_busy(0); - - // ui_sb_update_icon(SB_NETWORK, 0); } diff --git a/src/network/net_slirp.c b/src/network/net_slirp.c index 455dcd29e..aef813f6d 100644 --- a/src/network/net_slirp.c +++ b/src/network/net_slirp.c @@ -124,6 +124,7 @@ poll_thread(void *arg) uint16_t mac_cmp16[2]; event_t *evt; int data_valid = 0; + int tx; slirp_log("SLiRP: polling started.\n"); thread_set_event(poll_state); @@ -145,12 +146,11 @@ poll_thread(void *arg) if (slirpq == NULL) break; /* Wait for the next packet to arrive. */ + tx = network_tx_queue_check(); data_valid = 0; 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))) && (QueuePeek(slirpq) != 0)) { /* Grab a packet from the queue. */ - // ui_sb_update_icon(SB_NETWORK, 1); - qp = QueueDelete(slirpq); slirp_log("SLiRP: inQ:%d got a %dbyte packet @%08lx\n", QueuePeek(slirpq), qp->len, qp); @@ -165,8 +165,7 @@ poll_thread(void *arg) if ((mac_cmp32[0] != mac_cmp32[1]) || (mac_cmp16[0] != mac_cmp16[1])) { - network_queue_put(poll_card->priv, (uint8_t *)qp->data, qp->len); - // poll_card->rx(poll_card->priv, (uint8_t *)qp->data, qp->len); + network_queue_put(0, poll_card->priv, (uint8_t *)qp->data, qp->len); data_valid = 1; } @@ -174,11 +173,12 @@ poll_thread(void *arg) free(qp); } + if (tx) + network_do_tx(); + /* If we did not get anything, wait a while. */ - if (!data_valid) { - // ui_sb_update_icon(SB_NETWORK, 0); + if (!data_valid && !tx) thread_wait_event(evt, 10); - } /* Release ownership of the queue. */ network_wait(0); @@ -218,8 +218,6 @@ net_slirp_init(void) int net_slirp_reset(const netcard_t *card, uint8_t *mac) { - // ui_sb_update_icon(SB_NETWORK, 0); - /* Save the callback info. */ poll_card = card; @@ -237,9 +235,8 @@ net_slirp_close(void) { queueADT sl; - // ui_sb_update_icon(SB_NETWORK, 0); - - if (slirpq == NULL) return; + if (slirpq == NULL) + return; slirp_log("SLiRP: closing.\n"); @@ -271,17 +268,10 @@ net_slirp_close(void) void net_slirp_in(uint8_t *pkt, int pkt_len) { - if (slirpq == NULL) return; - - // ui_sb_update_icon(SB_NETWORK, 1); - - network_busy(1); + if (slirpq == NULL) + return; slirp_input((const uint8_t *)pkt, pkt_len); - - network_busy(0); - - // ui_sb_update_icon(SB_NETWORK, 0); } diff --git a/src/network/network.c b/src/network/network.c index b3eb95201..de9c2ed1c 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -111,16 +111,20 @@ static netcard_t net_cards[] = { int network_type; int network_ndev; int network_card; -static volatile int net_wait = 0; char network_host[522]; netdev_t network_devs[32]; #ifdef ENABLE_NIC_LOG int nic_do_log = ENABLE_NIC_LOG; #endif -static mutex_t *network_mutex; -static uint8_t *network_mac; -pc_timer_t network_queue_timer; -netpkt_t *first_pkt = NULL, *last_pkt = NULL; + + +/* Local variables. */ +static volatile int net_wait = 0; +static mutex_t *network_mutex; +static uint8_t *network_mac; +static pc_timer_t network_rx_queue_timer; +static netpkt_t *first_pkt[2] = { NULL, NULL }, + *last_pkt[2] = { NULL, NULL }; static struct { @@ -219,7 +223,7 @@ network_init(void) void -network_queue_put(void *priv, uint8_t *data, int len) +network_queue_put(int tx, void *priv, uint8_t *data, int len) { netpkt_t *temp; @@ -229,50 +233,52 @@ network_queue_put(void *priv, uint8_t *data, int len) temp->data = (uint8_t *) malloc(len); memcpy(temp->data, data, len); temp->len = len; + temp->prev = last_pkt[tx]; + temp->next = NULL; - if (last_pkt != NULL) - last_pkt->next = temp; - last_pkt = temp; + if (last_pkt[tx] != NULL) + last_pkt[tx]->next = temp; + last_pkt[tx] = temp; - if (first_pkt == NULL) - first_pkt = temp; + if (first_pkt[tx] == NULL) + first_pkt[tx] = temp; } static void -network_queue_get(netpkt_t **pkt) +network_queue_get(int tx, netpkt_t **pkt) { - if (first_pkt == NULL) + if (first_pkt[tx] == NULL) *pkt = NULL; else - *pkt = first_pkt; + *pkt = first_pkt[tx]; } static void -network_queue_advance(void) +network_queue_advance(int tx) { netpkt_t *temp; - temp = first_pkt; + temp = first_pkt[tx]; if (temp == NULL) return; - first_pkt = temp->next; + first_pkt[tx] = temp->next; if (temp->data != NULL) free(temp->data); free(temp); - if (first_pkt == NULL) - last_pkt = NULL; + if (first_pkt[tx] == NULL) + last_pkt[tx] = NULL; } static void -network_queue_clear(void) +network_queue_clear(int tx) { - netpkt_t *temp = first_pkt; + netpkt_t *temp = first_pkt[tx]; if (temp == NULL) return; @@ -284,27 +290,27 @@ network_queue_clear(void) temp = temp->next; } while (temp != NULL); - first_pkt = last_pkt = NULL; + first_pkt[tx] = last_pkt[tx] = NULL; } static void -network_queue(void *priv) +network_rx_queue(void *priv) { netpkt_t *pkt = NULL; network_busy(1); - network_queue_get(&pkt); + network_queue_get(0, &pkt); if ((pkt != NULL) && (pkt->len > 0)) { net_cards[network_card].rx(pkt->priv, pkt->data, pkt->len); if (pkt->len >= 128) - timer_on_auto(&network_queue_timer, 0.762939453125 * 2.0 * ((double) pkt->len)); + timer_on_auto(&network_rx_queue_timer, 0.762939453125 * 2.0 * ((double) pkt->len)); else - timer_on_auto(&network_queue_timer, 0.762939453125 * 2.0 * 128.0); + timer_on_auto(&network_rx_queue_timer, 0.762939453125 * 2.0 * 128.0); } else - timer_on_auto(&network_queue_timer, 0.762939453125 * 2.0 * 128.0); - network_queue_advance(); + timer_on_auto(&network_rx_queue_timer, 0.762939453125 * 2.0 * 128.0); + network_queue_advance(0); network_busy(0); } @@ -346,10 +352,11 @@ network_attach(void *dev, uint8_t *mac, NETRXCB rx, NETWAITCB wait, NETSETLINKST break; } - first_pkt = last_pkt = NULL; - timer_add(&network_queue_timer, network_queue, NULL, 0); + first_pkt[0] = first_pkt[1] = NULL; + last_pkt[0] = last_pkt[1] = NULL; + timer_add(&network_rx_queue_timer, network_rx_queue, NULL, 0); /* 10 mbps. */ - timer_on_auto(&network_queue_timer, 0.762939453125 * 2.0); + timer_on_auto(&network_rx_queue_timer, 0.762939453125 * 2.0); } @@ -357,7 +364,7 @@ network_attach(void *dev, uint8_t *mac, NETRXCB rx, NETWAITCB wait, NETSETLINKST void network_close(void) { - timer_stop(&network_queue_timer); + timer_stop(&network_rx_queue_timer); /* If already closed, do nothing. */ if (network_mutex == NULL) return; @@ -383,8 +390,9 @@ network_close(void) network_mutex = NULL; network_mac = NULL; - /* Here is where we should clear the queue. */ - network_queue_clear(); + /* Here is where we clear the queues. */ + network_queue_clear(0); + network_queue_clear(1); network_log("NETWORK: closed.\n"); } @@ -458,23 +466,51 @@ network_reset(void) } -/* Transmit a packet to one of the network providers. */ +/* Queue a packet for transmission to one of the network providers. */ void network_tx(uint8_t *bufp, int len) { + network_busy(1); + ui_sb_update_icon(SB_NETWORK, 1); - switch(network_type) { - case NET_TYPE_PCAP: - net_pcap_in(bufp, len); - break; - - case NET_TYPE_SLIRP: - net_slirp_in(bufp, len); - break; - } + network_queue_put(1, NULL, bufp, len); ui_sb_update_icon(SB_NETWORK, 0); + + network_busy(0); +} + + +/* Actually transmit the packet. */ +void +network_do_tx(void) +{ + netpkt_t *pkt = NULL; + + network_queue_get(1, &pkt); + if ((pkt != NULL) && (pkt->len > 0)) { + switch(network_type) { + case NET_TYPE_PCAP: + net_pcap_in(pkt->data, pkt->len); + break; + + case NET_TYPE_SLIRP: + net_slirp_in(pkt->data, pkt->len); + break; + } + } + network_queue_advance(1); +} + + +int +network_tx_queue_check(void) +{ + if ((first_pkt[1] == NULL) && (last_pkt[1] == NULL)) + return 0; + + return 1; }