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

@@ -1214,6 +1214,11 @@ load_network(void)
} else { } else {
strcpy(net_cards_conf[c].host_dev_name, "none"); strcpy(net_cards_conf[c].host_dev_name, "none");
} }
sprintf(temp, "net_%02i_link", c +1);
net_cards_conf[c].link_state = config_get_int(cat, temp,
(NET_LINK_10_HD|NET_LINK_10_FD|NET_LINK_100_HD|NET_LINK_100_FD|NET_LINK_1000_HD|NET_LINK_1000_FD));
} }
} }
@@ -2767,6 +2772,13 @@ save_network(void)
/* config_set_string(cat, temp, "none"); */ /* config_set_string(cat, temp, "none"); */
config_delete_var(cat, temp); config_delete_var(cat, temp);
} }
sprintf(temp, "net_%02i_link", c + 1);
if (net_cards_conf[c].link_state == (NET_LINK_10_HD|NET_LINK_10_FD|NET_LINK_100_HD|NET_LINK_100_FD|NET_LINK_1000_HD|NET_LINK_1000_FD)) {
config_delete_var(cat, temp);
} else {
config_set_int(cat, temp, net_cards_conf[c].link_state);
}
} }
delete_section_if_empty(cat); delete_section_if_empty(cat);

View File

@@ -21,7 +21,7 @@ typedef struct {
dev_status_empty_active_t mo[MO_NUM]; dev_status_empty_active_t mo[MO_NUM];
dev_status_empty_active_t cassette; dev_status_empty_active_t cassette;
dev_status_active_t hdd[HDD_BUS_USB]; dev_status_active_t hdd[HDD_BUS_USB];
dev_status_active_t net; dev_status_active_t net[NET_CARD_MAX];
dev_status_empty_t cartridge[2]; dev_status_empty_t cartridge[2];
} machine_status_t; } machine_status_t;

View File

@@ -65,6 +65,17 @@
#define NET_PERIOD_10M 0.8 #define NET_PERIOD_10M 0.8
#define NET_PERIOD_100M 0.08 #define NET_PERIOD_100M 0.08
enum {
NET_LINK_DOWN = (1 << 1),
NET_LINK_TEMP_DOWN = (1 << 2),
NET_LINK_10_HD = (1 << 3),
NET_LINK_10_FD = (1 << 4),
NET_LINK_100_HD = (1 << 5),
NET_LINK_100_FD = (1 << 6),
NET_LINK_1000_HD = (1 << 7),
NET_LINK_1000_FD = (1 << 8),
};
/* Supported network cards. */ /* Supported network cards. */
enum { enum {
NONE = 0, NONE = 0,
@@ -84,14 +95,14 @@ typedef struct {
int device_num; int device_num;
int net_type; int net_type;
char host_dev_name[128]; char host_dev_name[128];
uint32_t link_state;
} netcard_conf_t; } netcard_conf_t;
extern netcard_conf_t net_cards_conf[NET_CARD_MAX]; extern netcard_conf_t net_cards_conf[NET_CARD_MAX];
extern int net_card_current; 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 (*NETSETLINKSTATE)(void *, uint32_t link_state);
typedef int (*NETSETLINKSTATE)(void *);
typedef struct netpkt { typedef struct netpkt {
@@ -121,9 +132,7 @@ struct _netcard_t {
const device_t *device; const device_t *device;
void *card_drv; void *card_drv;
struct netdrv_t host_drv; struct netdrv_t host_drv;
int (*poll)(void *);
NETRXCB rx; NETRXCB rx;
NETWAITCB wait;
NETSETLINKSTATE set_link_state; NETSETLINKSTATE set_link_state;
netqueue_t queues[3]; netqueue_t queues[3];
netpkt_t queued_pkt; netpkt_t queued_pkt;
@@ -132,6 +141,9 @@ struct _netcard_t {
pc_timer_t timer; pc_timer_t timer;
int card_num; int card_num;
double byte_period; double byte_period;
uint32_t led_timer;
uint32_t led_state;
uint32_t link_state;
}; };
typedef struct { typedef struct {
@@ -152,7 +164,7 @@ extern netdev_t network_devs[NET_HOST_INTF_MAX];
/* Function prototypes. */ /* Function prototypes. */
extern void network_init(void); extern void network_init(void);
extern netcard_t *network_attach(void *card_drv, uint8_t *mac, NETRXCB rx, NETWAITCB wait, NETSETLINKSTATE set_link_state); extern netcard_t *network_attach(void *card_drv, uint8_t *mac, NETRXCB rx, NETSETLINKSTATE set_link_state);
extern void netcard_close(netcard_t *card); 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);
@@ -161,6 +173,9 @@ extern void network_tx(netcard_t *card, uint8_t *, int);
extern int net_pcap_prepare(netdev_t *); extern int net_pcap_prepare(netdev_t *);
extern void network_connect(int id, int connect);
extern int network_is_connected(int id);
extern int network_dev_available(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);
extern int network_card_has_config(int); extern int network_card_has_config(int);

View File

@@ -19,6 +19,8 @@
#include <86box/zip.h> #include <86box/zip.h>
#include <86box/mo.h> #include <86box/mo.h>
#include <86box/hdd.h> #include <86box/hdd.h>
#include <86box/thread.h>
#include <86box/network.h>
#include <86box/machine_status.h> #include <86box/machine_status.h>
machine_status_t machine_status; machine_status_t machine_status;
@@ -48,5 +50,7 @@ machine_status_init() {
machine_status.hdd[i].active = false; machine_status.hdd[i].active = false;
} }
machine_status.net.active = false; for (size_t i = 0; i < NET_CARD_MAX; i++) {
machine_status.net[i].active = false;
}
} }

View File

@@ -619,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. */
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); return(dev);
} }

View File

@@ -228,7 +228,9 @@ 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->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 */ /* some more debug */
#ifdef ENABLE_DP8390_LOG #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)) if ((dev->CR.stop != 0) || (dev->page_start == 0))
return 0; return 0;
if (dev->card->link_state & NET_LINK_DOWN)
return 0;
/* /*
* Add the pkt header + CRC to the length, and work * Add the pkt header + CRC to the length, and work
* out how many 256-byte pages the frame would occupy. * 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); nic_reset(dev);
/* Attach ourselves to the network module. */ /* 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, 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);

View File

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

View File

@@ -788,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. */
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)) { 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,

View File

@@ -346,6 +346,13 @@ network_rx_queue(void *priv)
{ {
netcard_t *card = (netcard_t *)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; uint32_t rx_bytes = 0;
for (int i = 0; i < NET_QUEUE_LEN; i++) { for (int i = 0; i < NET_QUEUE_LEN; i++) {
if (card->queued_pkt.len == 0) { if (card->queued_pkt.len == 0) {
@@ -386,7 +393,13 @@ network_rx_queue(void *priv)
timer_on_auto(&card->timer, timer_period); timer_on_auto(&card->timer, timer_period);
bool activity = rx_bytes || tx_bytes; 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. * modules.
*/ */
netcard_t * 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)); netcard_t *card = calloc(1, sizeof(netcard_t));
card->queued_pkt.data = calloc(1, NET_MAX_FRAME); card->queued_pkt.data = calloc(1, NET_MAX_FRAME);
card->card_drv = card_drv; card->card_drv = card_drv;
card->rx = rx; card->rx = rx;
card->wait = wait;
card->set_link_state = set_link_state; card->set_link_state = set_link_state;
card->tx_mutex = thread_create_mutex(); card->tx_mutex = thread_create_mutex();
card->rx_mutex = thread_create_mutex(); card->rx_mutex = thread_create_mutex();
@@ -496,8 +508,7 @@ network_reset(void)
#endif #endif
for (i = 0; i < NET_CARD_MAX; i++) { for (i = 0; i < NET_CARD_MAX; i++) {
if (!net_cards_conf[i].device_num || net_cards_conf[i].net_type == NET_TYPE_NONE || if (!network_dev_available(i)) {
(net_cards_conf[i].net_type == NET_TYPE_PCAP && !strcmp(net_cards_conf[i].host_dev_name, "none"))) {
continue; continue;
} }
@@ -564,6 +575,28 @@ int network_rx_put_pkt(netcard_t *card, netpkt_t *pkt)
return ret; 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 int
network_dev_to_id(char *devname) network_dev_to_id(char *devname)
{ {
@@ -575,19 +608,29 @@ network_dev_to_id(char *devname)
} }
} }
/* If no match found, assume "none". */ return(-1);
return(0);
} }
/* UI */ /* 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 int
network_available(void) network_available(void)
{ {
int available = 0; int available = 0;
for (int i = 0; i < NET_CARD_MAX; i ++) { 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; return available;

View File

@@ -220,7 +220,9 @@ struct MachineStatus::States {
for (auto& h : hdds) { for (auto& h : hdds) {
h.pixmaps = &pixmaps.hd; h.pixmaps = &pixmaps.hd;
} }
net.pixmaps = &pixmaps.net; for (auto& n : net) {
n.pixmaps = &pixmaps.net;
}
} }
std::array<StateEmpty, 2> cartridge; std::array<StateEmpty, 2> cartridge;
@@ -230,7 +232,7 @@ struct MachineStatus::States {
std::array<StateEmptyActive, ZIP_NUM> zip; std::array<StateEmptyActive, ZIP_NUM> zip;
std::array<StateEmptyActive, MO_NUM> mo; std::array<StateEmptyActive, MO_NUM> mo;
std::array<StateActive, HDD_BUS_USB> hdds; std::array<StateActive, HDD_BUS_USB> hdds;
StateActive net; std::array<StateActive, NET_CARD_MAX> net;
std::unique_ptr<ClickableLabel> sound; std::unique_ptr<ClickableLabel> sound;
std::unique_ptr<QLabel> text; std::unique_ptr<QLabel> text;
}; };
@@ -320,6 +322,14 @@ void MachineStatus::iterateMO(const std::function<void (int)> &cb) {
} }
} }
void MachineStatus::iterateNIC(const std::function<void (int)> &cb) {
for (int i = 0; i < NET_CARD_MAX; i++) {
if (network_dev_available(i)) {
cb(i);
}
}
}
static int hdd_count(int bus) { static int hdd_count(int bus) {
int c = 0; int c = 0;
int i; int i;
@@ -357,7 +367,9 @@ void MachineStatus::refreshIcons() {
d->hdds[i].setActive(machine_status.hdd[i].active); d->hdds[i].setActive(machine_status.hdd[i].active);
} }
d->net.setActive(machine_status.net.active); for (size_t i = 0; i < NET_CARD_MAX; i++) {
d->net[i].setActive(machine_status.net[i].active);
}
for (int i = 0; i < 2; ++i) { for (int i = 0; i < 2; ++i) {
d->cartridge[i].setEmpty(machine_status.cartridge[i].empty); d->cartridge[i].setEmpty(machine_status.cartridge[i].empty);
@@ -375,7 +387,6 @@ void MachineStatus::refresh(QStatusBar* sbar) {
int c_xta = hdd_count(HDD_BUS_XTA); int c_xta = hdd_count(HDD_BUS_XTA);
int c_ide = hdd_count(HDD_BUS_IDE); int c_ide = hdd_count(HDD_BUS_IDE);
int c_scsi = hdd_count(HDD_BUS_SCSI); int c_scsi = hdd_count(HDD_BUS_SCSI);
int do_net = network_available();
sbar->removeWidget(d->cassette.label.get()); sbar->removeWidget(d->cassette.label.get());
for (int i = 0; i < 2; ++i) { for (int i = 0; i < 2; ++i) {
@@ -396,7 +407,9 @@ void MachineStatus::refresh(QStatusBar* sbar) {
for (size_t i = 0; i < HDD_BUS_USB; i++) { for (size_t i = 0; i < HDD_BUS_USB; i++) {
sbar->removeWidget(d->hdds[i].label.get()); sbar->removeWidget(d->hdds[i].label.get());
} }
sbar->removeWidget(d->net.label.get()); for (size_t i = 0; i < NET_CARD_MAX; i++) {
sbar->removeWidget(d->net[i].label.get());
}
sbar->removeWidget(d->sound.get()); sbar->removeWidget(d->sound.get());
if (cassette_enable) { if (cassette_enable) {
@@ -503,6 +516,17 @@ void MachineStatus::refresh(QStatusBar* sbar) {
sbar->addWidget(d->mo[i].label.get()); sbar->addWidget(d->mo[i].label.get());
}); });
iterateNIC([this, sbar](int i) {
d->net[i].label = std::make_unique<ClickableLabel>();
d->net[i].setActive(false);
d->net[i].refresh();
d->net[i].label->setToolTip(MediaMenu::ptr->netMenus[i]->title());
connect((ClickableLabel*)d->net[i].label.get(), &ClickableLabel::clicked, [i](QPoint pos) {
MediaMenu::ptr->netMenus[i]->popup(pos - QPoint(0, MediaMenu::ptr->netMenus[i]->sizeHint().height()));
});
sbar->addWidget(d->net[i].label.get());
});
auto hdc_name = QString(hdc_get_internal_name(hdc_current)); auto hdc_name = QString(hdc_get_internal_name(hdc_current));
if ((has_mfm || hdc_name.left(5) == QStringLiteral("st506")) && c_mfm > 0) { if ((has_mfm || hdc_name.left(5) == QStringLiteral("st506")) && c_mfm > 0) {
d->hdds[HDD_BUS_MFM].label = std::make_unique<QLabel>(); d->hdds[HDD_BUS_MFM].label = std::make_unique<QLabel>();
@@ -541,13 +565,6 @@ void MachineStatus::refresh(QStatusBar* sbar) {
sbar->addWidget(d->hdds[HDD_BUS_SCSI].label.get()); sbar->addWidget(d->hdds[HDD_BUS_SCSI].label.get());
} }
if (do_net) {
d->net.label = std::make_unique<QLabel>();
d->net.setActive(false);
d->net.refresh();
d->net.label->setToolTip(tr("Network"));
sbar->addWidget(d->net.label.get());
}
d->sound = std::make_unique<ClickableLabel>(); d->sound = std::make_unique<ClickableLabel>();
d->sound->setPixmap(d->pixmaps.sound); d->sound->setPixmap(d->pixmaps.sound);

View File

@@ -66,6 +66,7 @@ public:
static void iterateCDROM(const std::function<void(int i)>& cb); static void iterateCDROM(const std::function<void(int i)>& cb);
static void iterateZIP(const std::function<void(int i)>& cb); static void iterateZIP(const std::function<void(int i)>& cb);
static void iterateMO(const std::function<void(int i)>& cb); static void iterateMO(const std::function<void(int i)>& cb);
static void iterateNIC(const std::function<void(int i)>& cb);
QString getMessage(); QString getMessage();
public slots: public slots:

View File

@@ -44,10 +44,14 @@ extern "C" {
#include <86box/mo.h> #include <86box/mo.h>
#include <86box/sound.h> #include <86box/sound.h>
#include <86box/ui.h> #include <86box/ui.h>
#include <86box/thread.h>
#include <86box/network.h>
}; };
#include "qt_newfloppydialog.hpp" #include "qt_newfloppydialog.hpp"
#include "qt_util.hpp" #include "qt_util.hpp"
#include "qt_deviceconfig.hpp"
std::shared_ptr<MediaMenu> MediaMenu::ptr; std::shared_ptr<MediaMenu> MediaMenu::ptr;
@@ -156,6 +160,16 @@ void MediaMenu::refresh(QMenu *parentMenu) {
moMenus[i] = menu; moMenus[i] = menu;
moUpdateMenu(i); moUpdateMenu(i);
}); });
netMenus.clear();
MachineStatus::iterateNIC([this, parentMenu](int i) {
auto *menu = parentMenu->addMenu("");
netDisconnPos = menu->children().count();
auto *action = menu->addAction(tr("&Disconnected"), [i] { network_connect(i, !network_is_connected(i)); config_save(); });
action->setCheckable(true);
netMenus[i] = menu;
nicUpdateMenu(i);
});
} }
void MediaMenu::cassetteNewImage() { void MediaMenu::cassetteNewImage() {
@@ -662,6 +676,30 @@ void MediaMenu::moUpdateMenu(int i) {
menu->setTitle(QString::asprintf(tr("MO %i (%ls): %ls").toUtf8().constData(), i + 1, busName.toStdU16String().data(), name.isEmpty() ? tr("(empty)").toStdU16String().data() : name.toStdU16String().data())); menu->setTitle(QString::asprintf(tr("MO %i (%ls): %ls").toUtf8().constData(), i + 1, busName.toStdU16String().data(), name.isEmpty() ? tr("(empty)").toStdU16String().data() : name.toStdU16String().data()));
} }
void MediaMenu::nicUpdateMenu(int i) {
if (!netMenus.contains(i))
return;
QString netType = tr("None");
switch (net_cards_conf[i].net_type) {
case NET_TYPE_SLIRP:
netType = "SLiRP";
break;
case NET_TYPE_PCAP:
netType = "PCAP";
break;
}
QString devName = DeviceConfig::DeviceName(network_card_getdevice(net_cards_conf[i].device_num), network_card_get_internal_name(net_cards_conf[i].device_num), 1);
auto *menu = netMenus[i];
auto childs = menu->children();
auto *connectedAction = dynamic_cast<QAction*>(childs[netDisconnPos]);
connectedAction->setChecked(!network_is_connected(i));
menu->setTitle(QString::asprintf(tr("NIC %02i (%ls) %ls").toUtf8().constData(), i + 1, netType.toStdU16String().data(), devName.toStdU16String().data()));
}
QString MediaMenu::getMediaOpenDirectory() { QString MediaMenu::getMediaOpenDirectory() {
QString openDirectory; QString openDirectory;
if (open_dir_usr_path > 0) { if (open_dir_usr_path > 0) {

View File

@@ -56,6 +56,8 @@ public:
void moEject(int i); void moEject(int i);
void moReload(int i); void moReload(int i);
void moUpdateMenu(int i); void moUpdateMenu(int i);
void nicUpdateMenu(int i);
private: private:
QWidget* parentWidget = nullptr; QWidget* parentWidget = nullptr;
@@ -65,6 +67,7 @@ private:
QMap<int, QMenu*> cdromMenus; QMap<int, QMenu*> cdromMenus;
QMap<int, QMenu*> zipMenus; QMap<int, QMenu*> zipMenus;
QMap<int, QMenu*> moMenus; QMap<int, QMenu*> moMenus;
QMap<int, QMenu*> netMenus;
QString getMediaOpenDirectory(); QString getMediaOpenDirectory();
@@ -89,5 +92,7 @@ private:
int moEjectPos; int moEjectPos;
int moReloadPos; int moReloadPos;
int netDisconnPos;
friend class MachineStatus; friend class MachineStatus;
}; };

View File

@@ -50,6 +50,8 @@ extern "C" {
#include <86box/zip.h> #include <86box/zip.h>
#include <86box/mo.h> #include <86box/mo.h>
#include <86box/hdd.h> #include <86box/hdd.h>
#include <86box/thread.h>
#include <86box/network.h>
#include <86box/machine_status.h> #include <86box/machine_status.h>
void void
@@ -246,7 +248,7 @@ ui_sb_update_icon(int tag, int active) {
machine_status.hdd[item].active = active > 0 ? true : false; machine_status.hdd[item].active = active > 0 ? true : false;
break; break;
case SB_NETWORK: case SB_NETWORK:
machine_status.net.active = active > 0 ? true : false; machine_status.net[item].active = active > 0 ? true : false;
break; break;
case SB_SOUND: case SB_SOUND:
break; break;