network: allow to set a NIC's link from the status bar

This commit is contained in:
Adrien Moulin
2022-08-27 19:08:28 +02:00
parent c0b6c55926
commit ea21790fc9
16 changed files with 202 additions and 67 deletions

View File

@@ -619,7 +619,7 @@ threec503_nic_init(const device_t *info)
dev->regs.gacfr = 0x09; /* Start with RAM mapping enabled. */
/* Attach ourselves to the network module. */
dev->dp8390->card = network_attach(dev->dp8390, dev->dp8390->physaddr, dp8390_rx, NULL, NULL);
dev->dp8390->card = network_attach(dev->dp8390, dev->dp8390->physaddr, dp8390_rx, NULL);
return(dev);
}

View File

@@ -228,7 +228,9 @@ dp8390_write_cr(dp8390_t *dev, uint32_t val)
/* Send the packet to the system driver */
dev->CR.tx_packet = 1;
network_tx(dev->card, &dev->mem[(dev->tx_page_start * 256) - dev->mem_start], dev->tx_bytes);
/* TODO: report TX error to the driver ? */
if (!(dev->card->link_state & NET_LINK_DOWN))
network_tx(dev->card, &dev->mem[(dev->tx_page_start * 256) - dev->mem_start], dev->tx_bytes);
/* some more debug */
#ifdef ENABLE_DP8390_LOG
@@ -291,6 +293,8 @@ dp8390_rx_common(void *priv, uint8_t *buf, int io_len)
if ((dev->CR.stop != 0) || (dev->page_start == 0))
return 0;
if (dev->card->link_state & NET_LINK_DOWN)
return 0;
/*
* Add the pkt header + CRC to the length, and work
* out how many 256-byte pages the frame would occupy.

View File

@@ -1122,7 +1122,7 @@ nic_init(const device_t *info)
nic_reset(dev);
/* Attach ourselves to the network module. */
dev->dp8390->card = network_attach(dev->dp8390, dev->dp8390->physaddr, dp8390_rx, NULL, NULL);
dev->dp8390->card = network_attach(dev->dp8390, dev->dp8390->physaddr, dp8390_rx, NULL);
nelog(1, "%s: %s attached IO=0x%X IRQ=%d\n", dev->name,
dev->is_pci?"PCI":"ISA", dev->base_address, dev->base_irq);

View File

@@ -29,6 +29,7 @@
#include <stdarg.h>
#include <wchar.h>
#include <time.h>
#include <stdbool.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/io.h>
@@ -1253,6 +1254,10 @@ pcnetReceiveNoSync(void *priv, uint8_t *buf, int size)
if (!pcnetIsLinkUp(dev))
return 0;
dev->fMaybeOutOfSpace = !pcnetCanReceive(dev);
if (dev->fMaybeOutOfSpace)
return 0;
pcnetlog(1, "%s: pcnetReceiveNoSync: RX %x:%x:%x:%x:%x:%x > %x:%x:%x:%x:%x:%x len %d\n", dev->name,
buf[6], buf[7], buf[8], buf[9], buf[10], buf[11],
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],
@@ -2095,12 +2100,13 @@ pcnet_mii_readw(nic_t *dev, uint16_t miiaddr)
| 0x0008 /* Able to do auto-negotiation. */
| 0x0004 /* Link up. */
| 0x0001; /* Extended Capability, i.e. registers 4+ valid. */
if (!dev->fLinkUp || dev->fLinkTempDown || isolate) {
if (!pcnetIsLinkUp(dev) || isolate) {
val &= ~(0x0020 | 0x0004);
dev->cLinkDownReported++;
}
if (!autoneg) {
/* Auto-negotiation disabled. */
val &= ~(0x0020 | 0x0008);
if (duplex)
val &= ~0x2800; /* Full duplex forced. */
else
@@ -2131,7 +2137,7 @@ pcnet_mii_readw(nic_t *dev, uint16_t miiaddr)
case 5:
/* Link partner ability register. */
if (dev->fLinkUp && !dev->fLinkTempDown && !isolate) {
if (pcnetIsLinkUp(dev) && !isolate) {
val = 0x8000 /* Next page bit. */
| 0x4000 /* Link partner acked us. */
| 0x0400 /* Can do flow control. */
@@ -2145,7 +2151,7 @@ pcnet_mii_readw(nic_t *dev, uint16_t miiaddr)
case 6:
/* Auto negotiation expansion register. */
if (dev->fLinkUp && !dev->fLinkTempDown && !isolate) {
if (pcnetIsLinkUp(dev) && !isolate) {
val = 0x0008 /* Link partner supports npage. */
| 0x0004 /* Enable npage words. */
| 0x0001; /* Can do N-way auto-negotiation. */
@@ -2157,7 +2163,7 @@ pcnet_mii_readw(nic_t *dev, uint16_t miiaddr)
case 18:
/* Diagnostic Register (FreeBSD pcn/ac101 driver reads this). */
if (dev->fLinkUp && !dev->fLinkTempDown && !isolate) {
if (pcnetIsLinkUp(dev) && !isolate) {
val = 0x1000 /* Receive PLL locked. */
| 0x0200; /* Signal detected. */
@@ -2195,7 +2201,7 @@ pcnet_bcr_readw(nic_t *dev, uint16_t rap)
case BCR_LED2:
case BCR_LED3:
val = dev->aBCR[rap] & ~0x8000;
if (dev->fLinkTempDown || !dev->fLinkUp) {
if (!(pcnetIsLinkUp(dev))) {
if (rap == 4)
dev->cLinkDownReported++;
val &= ~0x40;
@@ -2846,40 +2852,28 @@ pcnetCanReceive(nic_t *dev)
return rc;
}
static int
pcnetWaitReceiveAvail(void *priv)
pcnetSetLinkState(void *priv, uint32_t link_state)
{
nic_t *dev = (nic_t *) priv;
dev->fMaybeOutOfSpace = !pcnetCanReceive(dev);
return dev->fMaybeOutOfSpace;
}
static int
pcnetSetLinkState(void *priv)
{
nic_t *dev = (nic_t *) priv;
int fLinkUp;
if (dev->fLinkTempDown) {
pcnetTempLinkDown(dev);
return 1;
if (link_state & NET_LINK_TEMP_DOWN) {
pcnetTempLinkDown(dev);
return 1;
}
fLinkUp = (dev->fLinkUp && !dev->fLinkTempDown);
if (dev->fLinkUp != fLinkUp) {
dev->fLinkUp = fLinkUp;
if (fLinkUp) {
dev->fLinkTempDown = 1;
dev->cLinkDownReported = 0;
dev->aCSR[0] |= 0x8000 | 0x2000; /* ERR | CERR (this is probably wrong) */
timer_set_delay_u64(&dev->timer_restore, (dev->cMsLinkUpDelay * 1000) * TIMER_USEC);
} else {
dev->cLinkDownReported = 0;
dev->aCSR[0] |= 0x8000 | 0x2000; /* ERR | CERR (this is probably wrong) */
}
bool link_up = !(link_state & NET_LINK_DOWN);
if (dev->fLinkUp != link_up) {
dev->fLinkUp = link_up;
if (link_up) {
dev->fLinkTempDown = 1;
dev->cLinkDownReported = 0;
dev->aCSR[0] |= 0x8000 | 0x2000;
timer_set_delay_u64(&dev->timer_restore, (dev->cMsLinkUpDelay * 1000) * TIMER_USEC);
} else {
dev->cLinkDownReported = 0;
dev->aCSR[0] |= 0x8000 | 0x2000;
}
}
return 0;
@@ -3058,7 +3052,7 @@ pcnet_init(const device_t *info)
pcnetHardReset(dev);
/* Attach ourselves to the network module. */
dev->netcard = network_attach(dev, dev->aPROM, pcnetReceiveNoSync, pcnetWaitReceiveAvail, pcnetSetLinkState);
dev->netcard = network_attach(dev, dev->aPROM, pcnetReceiveNoSync, pcnetSetLinkState);
dev->netcard->byte_period = (dev->board == DEV_AM79C973) ? NET_PERIOD_100M : NET_PERIOD_10M;
timer_add(&dev->timer, pcnetPollTimer, dev, 0);

View File

@@ -476,7 +476,7 @@ plip_net_init(const device_t *info)
}
plip_log(1, " (attached to LPT)\n");
instance->card = network_attach(instance, instance->mac, plip_rx, NULL, NULL);
instance->card = network_attach(instance, instance->mac, plip_rx, NULL);
return instance;
}

View File

@@ -788,7 +788,7 @@ wd_init(const device_t *info)
mem_mapping_disable(&dev->ram_mapping);
/* Attach ourselves to the network module. */
dev->dp8390->card = network_attach(dev->dp8390, dev->dp8390->physaddr, dp8390_rx, NULL, NULL);
dev->dp8390->card = network_attach(dev->dp8390, dev->dp8390->physaddr, dp8390_rx, NULL);
if (!(dev->board_chip & WE_ID_BUS_MCA)) {
wdlog("%s: attached IO=0x%X IRQ=%d, RAM addr=0x%06x\n", dev->name,

View File

@@ -346,6 +346,13 @@ network_rx_queue(void *priv)
{
netcard_t *card = (netcard_t *)priv;
uint32_t new_link_state = net_cards_conf[card->card_num].link_state;
if (new_link_state != card->link_state) {
if (card->set_link_state)
card->set_link_state(card->card_drv, new_link_state);
card->link_state = new_link_state;
}
uint32_t rx_bytes = 0;
for (int i = 0; i < NET_QUEUE_LEN; i++) {
if (card->queued_pkt.len == 0) {
@@ -386,7 +393,13 @@ network_rx_queue(void *priv)
timer_on_auto(&card->timer, timer_period);
bool activity = rx_bytes || tx_bytes;
ui_sb_update_icon(SB_NETWORK, activity);
bool led_on = card->led_timer & 0x80000000;
if ((activity && !led_on) || (card->led_timer & 0x7fffffff) >= 150000) {
ui_sb_update_icon(SB_NETWORK | card->card_num, activity);
card->led_timer = 0 | (activity << 31);
}
card->led_timer += timer_period;
}
@@ -398,13 +411,12 @@ network_rx_queue(void *priv)
* modules.
*/
netcard_t *
network_attach(void *card_drv, uint8_t *mac, NETRXCB rx, NETWAITCB wait, NETSETLINKSTATE set_link_state)
network_attach(void *card_drv, uint8_t *mac, NETRXCB rx, NETSETLINKSTATE set_link_state)
{
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();
@@ -496,8 +508,7 @@ network_reset(void)
#endif
for (i = 0; i < NET_CARD_MAX; i++) {
if (!net_cards_conf[i].device_num || net_cards_conf[i].net_type == NET_TYPE_NONE ||
(net_cards_conf[i].net_type == NET_TYPE_PCAP && !strcmp(net_cards_conf[i].host_dev_name, "none"))) {
if (!network_dev_available(i)) {
continue;
}
@@ -564,6 +575,28 @@ int network_rx_put_pkt(netcard_t *card, netpkt_t *pkt)
return ret;
}
void
network_connect(int id, int connect)
{
if (id >= NET_CARD_MAX)
return;
if (connect) {
net_cards_conf[id].link_state &= ~NET_LINK_DOWN;
} else {
net_cards_conf[id].link_state |= NET_LINK_DOWN;
}
}
int
network_is_connected(int id)
{
if (id >= NET_CARD_MAX)
return 0;
return !(net_cards_conf[id].link_state & NET_LINK_DOWN);
}
int
network_dev_to_id(char *devname)
{
@@ -575,19 +608,29 @@ network_dev_to_id(char *devname)
}
}
/* If no match found, assume "none". */
return(0);
return(-1);
}
/* UI */
int
network_dev_available(int id)
{
int available = (net_cards_conf[id].device_num > 0) && (net_cards_conf[id].net_type != NET_TYPE_NONE);
if ((net_cards_conf[id].net_type == NET_TYPE_PCAP && (network_dev_to_id(net_cards_conf[id].host_dev_name) <= 0)))
available = 0;
return available;
}
int
network_available(void)
{
int available = 0;
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);
available |= network_dev_available(i);
}
return available;