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

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