Applied Ryuzaki's Media menu patch, fixed a bug in cpu.c reported by ms. person, fixed bugs (and added a workaround for the Windows 2000 PCnet problems) to mem.c, and added a network packet queue to cap network speed (and do the actual rx poll in the main thread instead) for more stability, also some ES1371 fixes (but not enough to make it work on Linux).
This commit is contained in:
@@ -201,7 +201,8 @@ poll_thread(void *arg)
|
||||
if ((mac_cmp32[0] != mac_cmp32[1]) ||
|
||||
(mac_cmp16[0] != mac_cmp16[1])) {
|
||||
|
||||
poll_card->rx(poll_card->priv, data, h.caplen);
|
||||
network_queue_put(poll_card->priv, data, h.caplen);
|
||||
// poll_card->rx(poll_card->priv, data, h.caplen);
|
||||
} else {
|
||||
/* Mark as invalid packet. */
|
||||
data = NULL;
|
||||
|
||||
@@ -441,11 +441,15 @@ pcnetTmdLoad(nic_t *dev, TMD *tmd, uint32_t addr, int fRetIfNotOwn)
|
||||
uint16_t xda[4];
|
||||
uint32_t xda32[4];
|
||||
|
||||
use_phys_exec = 1;
|
||||
|
||||
if (BCR_SWSTYLE(dev) == 0) {
|
||||
dma_bm_read(addr, (uint8_t *) bytes, 4, dev->transfer_size);
|
||||
ownbyte = bytes[3];
|
||||
if (!(ownbyte & 0x80) && fRetIfNotOwn)
|
||||
if (!(ownbyte & 0x80) && fRetIfNotOwn) {
|
||||
use_phys_exec = 0;
|
||||
return 0;
|
||||
}
|
||||
dma_bm_read(addr, (uint8_t*)&xda[0], sizeof(xda), dev->transfer_size);
|
||||
((uint32_t *)tmd)[0] = (uint32_t)xda[0] | ((uint32_t)(xda[1] & 0x00ff) << 16);
|
||||
((uint32_t *)tmd)[1] = (uint32_t)xda[2] | ((uint32_t)(xda[1] & 0xff00) << 16);
|
||||
@@ -454,14 +458,18 @@ pcnetTmdLoad(nic_t *dev, TMD *tmd, uint32_t addr, int fRetIfNotOwn)
|
||||
} else if (BCR_SWSTYLE(dev) != 3) {
|
||||
dma_bm_read(addr + 4, (uint8_t *) bytes, 4, dev->transfer_size);
|
||||
ownbyte = bytes[3];
|
||||
if (!(ownbyte & 0x80) && fRetIfNotOwn)
|
||||
if (!(ownbyte & 0x80) && fRetIfNotOwn) {
|
||||
use_phys_exec = 0;
|
||||
return 0;
|
||||
}
|
||||
dma_bm_read(addr, (uint8_t*)tmd, 16, dev->transfer_size);
|
||||
} else {
|
||||
dma_bm_read(addr + 4, (uint8_t *) bytes, 4, dev->transfer_size);
|
||||
ownbyte = bytes[3];
|
||||
if (!(ownbyte & 0x80) && fRetIfNotOwn)
|
||||
if (!(ownbyte & 0x80) && fRetIfNotOwn) {
|
||||
use_phys_exec = 0;
|
||||
return 0;
|
||||
}
|
||||
dma_bm_read(addr, (uint8_t*)&xda32[0], sizeof(xda32), dev->transfer_size);
|
||||
((uint32_t *)tmd)[0] = xda32[2];
|
||||
((uint32_t *)tmd)[1] = xda32[1];
|
||||
@@ -474,6 +482,8 @@ pcnetTmdLoad(nic_t *dev, TMD *tmd, uint32_t addr, int fRetIfNotOwn)
|
||||
if (!(ownbyte & 0x80))
|
||||
tmd->tmd1.own = 0;
|
||||
|
||||
use_phys_exec = 0;
|
||||
|
||||
return !!tmd->tmd1.own;
|
||||
}
|
||||
|
||||
@@ -485,12 +495,12 @@ pcnetTmdLoad(nic_t *dev, TMD *tmd, uint32_t addr, int fRetIfNotOwn)
|
||||
static __inline void
|
||||
pcnetTmdStorePassHost(nic_t *dev, TMD *tmd, uint32_t addr)
|
||||
{
|
||||
uint8_t bytes[4] = { 0, 0, 0, 0 };
|
||||
uint16_t xda[4];
|
||||
uint32_t xda32[3];
|
||||
|
||||
use_phys_exec = 1;
|
||||
|
||||
if (BCR_SWSTYLE(dev) == 0) {
|
||||
dma_bm_read(addr, (uint8_t *) bytes, sizeof(xda), dev->transfer_size);
|
||||
xda[0] = ((uint32_t *)tmd)[0] & 0xffff;
|
||||
xda[1] = ((((uint32_t *)tmd)[0] >> 16) & 0xff) | ((((uint32_t *)tmd)[1]>>16) & 0xff00);
|
||||
xda[2] = ((uint32_t *)tmd)[1] & 0xffff;
|
||||
@@ -519,6 +529,8 @@ pcnetTmdStorePassHost(nic_t *dev, TMD *tmd, uint32_t addr)
|
||||
xda32[1] &= ~0x80000000;
|
||||
dma_bm_write(addr, (uint8_t*)&xda32[0], sizeof(xda32), dev->transfer_size);
|
||||
}
|
||||
|
||||
use_phys_exec = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -538,11 +550,15 @@ pcnetRmdLoad(nic_t *dev, RMD *rmd, uint32_t addr, int fRetIfNotOwn)
|
||||
uint16_t rda[4];
|
||||
uint32_t rda32[4];
|
||||
|
||||
use_phys_exec = 1;
|
||||
|
||||
if (BCR_SWSTYLE(dev) == 0) {
|
||||
dma_bm_read(addr, (uint8_t *) bytes, 4, dev->transfer_size);
|
||||
ownbyte = bytes[3];
|
||||
if (!(ownbyte & 0x80) && fRetIfNotOwn)
|
||||
if (!(ownbyte & 0x80) && fRetIfNotOwn) {
|
||||
use_phys_exec = 0;
|
||||
return 0;
|
||||
}
|
||||
dma_bm_read(addr, (uint8_t*)&rda[0], sizeof(rda), dev->transfer_size);
|
||||
((uint32_t *)rmd)[0] = (uint32_t)rda[0] | ((rda[1] & 0x00ff) << 16);
|
||||
((uint32_t *)rmd)[1] = (uint32_t)rda[2] | ((rda[1] & 0xff00) << 16);
|
||||
@@ -551,14 +567,18 @@ pcnetRmdLoad(nic_t *dev, RMD *rmd, uint32_t addr, int fRetIfNotOwn)
|
||||
} else if (BCR_SWSTYLE(dev) != 3) {
|
||||
dma_bm_read(addr + 4, (uint8_t *) bytes, 4, dev->transfer_size);
|
||||
ownbyte = bytes[3];
|
||||
if (!(ownbyte & 0x80) && fRetIfNotOwn)
|
||||
if (!(ownbyte & 0x80) && fRetIfNotOwn) {
|
||||
use_phys_exec = 0;
|
||||
return 0;
|
||||
}
|
||||
dma_bm_read(addr, (uint8_t*)rmd, 16, dev->transfer_size);
|
||||
} else {
|
||||
dma_bm_read(addr + 4, (uint8_t *) bytes, 4, dev->transfer_size);
|
||||
ownbyte = bytes[3];
|
||||
if (!(ownbyte & 0x80) && fRetIfNotOwn)
|
||||
if (!(ownbyte & 0x80) && fRetIfNotOwn) {
|
||||
use_phys_exec = 0;
|
||||
return 0;
|
||||
}
|
||||
dma_bm_read(addr, (uint8_t*)&rda32[0], sizeof(rda32), dev->transfer_size);
|
||||
((uint32_t *)rmd)[0] = rda32[2];
|
||||
((uint32_t *)rmd)[1] = rda32[1];
|
||||
@@ -572,6 +592,8 @@ pcnetRmdLoad(nic_t *dev, RMD *rmd, uint32_t addr, int fRetIfNotOwn)
|
||||
if (!(ownbyte & 0x80))
|
||||
rmd->rmd1.own = 0;
|
||||
|
||||
use_phys_exec = 0;
|
||||
|
||||
return !!rmd->rmd1.own;
|
||||
}
|
||||
|
||||
@@ -586,6 +608,8 @@ pcnetRmdStorePassHost(nic_t *dev, RMD *rmd, uint32_t addr)
|
||||
uint16_t rda[4];
|
||||
uint32_t rda32[3];
|
||||
|
||||
use_phys_exec = 1;
|
||||
|
||||
if (BCR_SWSTYLE(dev) == 0) {
|
||||
rda[0] = ((uint32_t *)rmd)[0] & 0xffff;
|
||||
rda[1] = ((((uint32_t *)rmd)[0]>>16) & 0xff) | ((((uint32_t *)rmd)[1]>>16) & 0xff00);
|
||||
@@ -615,6 +639,8 @@ pcnetRmdStorePassHost(nic_t *dev, RMD *rmd, uint32_t addr)
|
||||
rda32[1] &= ~0x80000000;
|
||||
dma_bm_write(addr, (uint8_t*)&rda32[0], sizeof(rda32), dev->transfer_size);
|
||||
}
|
||||
|
||||
use_phys_exec = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -931,8 +957,10 @@ pcnetInit(nic_t *dev)
|
||||
/** @todo Documentation says that RCVRL and XMTRL are stored as two's complement!
|
||||
* Software is allowed to write these registers directly. */
|
||||
#define PCNET_INIT() do { \
|
||||
use_phys_exec = 1; \
|
||||
dma_bm_read(PHYSADDR(dev, CSR_IADR(dev)), \
|
||||
(uint8_t *)&initblk, sizeof(initblk), dev->transfer_size); \
|
||||
use_phys_exec = 0; \
|
||||
dev->aCSR[15] = le16_to_cpu(initblk.mode); \
|
||||
CSR_RCVRL(dev) = (initblk.rlen < 9) ? (1 << initblk.rlen) : 512; \
|
||||
CSR_XMTRL(dev) = (initblk.tlen < 9) ? (1 << initblk.tlen) : 512; \
|
||||
@@ -1338,7 +1366,9 @@ pcnetReceiveNoSync(void *priv, uint8_t *buf, int size)
|
||||
* - we don't cache any register state beyond this point
|
||||
*/
|
||||
|
||||
use_phys_exec = 1;
|
||||
dma_bm_write(rbadr, src, cbBuf, dev->transfer_size);
|
||||
use_phys_exec = 0;
|
||||
|
||||
/* RX disabled in the meantime? If so, abort RX. */
|
||||
if (CSR_DRX(dev) || CSR_STOP(dev) || CSR_SPND(dev)) {
|
||||
@@ -1381,7 +1411,9 @@ pcnetReceiveNoSync(void *priv, uint8_t *buf, int size)
|
||||
/* We have to leave the critical section here or we risk deadlocking
|
||||
* with EMT when the write is to an unallocated page or has an access
|
||||
* handler associated with it. See above for additional comments. */
|
||||
use_phys_exec = 1;
|
||||
dma_bm_write(rbadr2, src, cbBuf, dev->transfer_size);
|
||||
use_phys_exec = 0;
|
||||
|
||||
/* RX disabled in the meantime? If so, abort RX. */
|
||||
if (CSR_DRX(dev) || CSR_STOP(dev) || CSR_SPND(dev)) {
|
||||
@@ -1506,7 +1538,9 @@ pcnetAsyncTransmit(nic_t *dev)
|
||||
* zero length if it is not the last one in the chain. */
|
||||
if (cb <= MAX_FRAME) {
|
||||
dev->xmit_pos = cb;
|
||||
use_phys_exec = 1;
|
||||
dma_bm_read(PHYSADDR(dev, tmd.tmd0.tbadr), dev->abLoopBuf, cb, dev->transfer_size);
|
||||
use_phys_exec = 0;
|
||||
|
||||
if (fLoopback) {
|
||||
if (HOST_IS_OWNER(CSR_CRST(dev)))
|
||||
@@ -1572,7 +1606,9 @@ pcnetAsyncTransmit(nic_t *dev)
|
||||
*/
|
||||
unsigned cb = 4096 - tmd.tmd1.bcnt;
|
||||
dev->xmit_pos = pcnetCalcPacketLen(dev, cb);
|
||||
use_phys_exec = 1;
|
||||
dma_bm_read(PHYSADDR(dev, tmd.tmd0.tbadr), dev->abLoopBuf, cb, dev->transfer_size);
|
||||
use_phys_exec = 0;
|
||||
|
||||
for (;;) {
|
||||
/*
|
||||
@@ -1611,7 +1647,9 @@ pcnetAsyncTransmit(nic_t *dev)
|
||||
if (dev->xmit_pos + cb <= MAX_FRAME) { /** @todo this used to be ... + cb < MAX_FRAME. */
|
||||
int off = dev->xmit_pos;
|
||||
dev->xmit_pos = cb + off;
|
||||
use_phys_exec = 1;
|
||||
dma_bm_read(PHYSADDR(dev, tmd.tmd0.tbadr), dev->abLoopBuf + off, cb, dev->transfer_size);
|
||||
use_phys_exec = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -165,7 +165,8 @@ poll_thread(void *arg)
|
||||
if ((mac_cmp32[0] != mac_cmp32[1]) ||
|
||||
(mac_cmp16[0] != mac_cmp16[1])) {
|
||||
|
||||
poll_card->rx(poll_card->priv, (uint8_t *)qp->data, qp->len);
|
||||
network_queue_put(poll_card->priv, (uint8_t *)qp->data, qp->len);
|
||||
// poll_card->rx(poll_card->priv, (uint8_t *)qp->data, qp->len);
|
||||
data_valid = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/plat.h>
|
||||
#include <86box/ui.h>
|
||||
#include <86box/network.h>
|
||||
@@ -118,6 +119,8 @@ 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;
|
||||
|
||||
|
||||
static struct {
|
||||
@@ -215,6 +218,99 @@ network_init(void)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
network_queue_put(void *priv, uint8_t *data, int len)
|
||||
{
|
||||
netpkt_t *temp;
|
||||
|
||||
temp = (netpkt_t *) malloc(sizeof(netpkt_t));
|
||||
memset(temp, 0, sizeof(netpkt_t));
|
||||
temp->priv = priv;
|
||||
temp->data = (uint8_t *) malloc(len);
|
||||
memcpy(temp->data, data, len);
|
||||
temp->len = len;
|
||||
|
||||
if (last_pkt != NULL)
|
||||
last_pkt->next = temp;
|
||||
last_pkt = temp;
|
||||
|
||||
if (first_pkt == NULL)
|
||||
first_pkt = temp;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
network_queue_get(netpkt_t *pkt)
|
||||
{
|
||||
pkt->priv = NULL;
|
||||
pkt->data = NULL;
|
||||
pkt->len = 0;
|
||||
|
||||
if (first_pkt == NULL)
|
||||
return;
|
||||
|
||||
memcpy(pkt, first_pkt, sizeof(netpkt_t));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
network_queue_advance(void)
|
||||
{
|
||||
netpkt_t *temp;
|
||||
|
||||
temp = first_pkt;
|
||||
|
||||
if (temp == NULL)
|
||||
return;
|
||||
|
||||
first_pkt = temp->next;
|
||||
if (temp->data != NULL)
|
||||
free(temp->data);
|
||||
free(temp);
|
||||
|
||||
if (first_pkt == NULL)
|
||||
last_pkt = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
network_queue_clear(void)
|
||||
{
|
||||
netpkt_t *temp = first_pkt;
|
||||
|
||||
if (temp == NULL)
|
||||
return;
|
||||
|
||||
do {
|
||||
if (temp->data != NULL)
|
||||
free(temp->data);
|
||||
free(temp);
|
||||
temp = temp->next;
|
||||
} while (temp != NULL);
|
||||
|
||||
first_pkt = last_pkt = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
network_queue(void *priv)
|
||||
{
|
||||
netpkt_t pkt;
|
||||
|
||||
network_busy(1);
|
||||
|
||||
network_queue_get(&pkt);
|
||||
if (pkt.len > 0) {
|
||||
net_cards[network_card].rx(pkt.priv, pkt.data, pkt.len);
|
||||
timer_on_auto(&network_queue_timer, 0.762939453125 * 2.0 * ((double) pkt.len));
|
||||
} else
|
||||
timer_on_auto(&network_queue_timer, 0.762939453125 * 2.0);
|
||||
network_queue_advance();
|
||||
|
||||
network_busy(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Attach a network card to the system.
|
||||
*
|
||||
@@ -250,6 +346,11 @@ network_attach(void *dev, uint8_t *mac, NETRXCB rx, NETWAITCB wait, NETSETLINKST
|
||||
(void)net_slirp_reset(&net_cards[network_card], network_mac);
|
||||
break;
|
||||
}
|
||||
|
||||
first_pkt = last_pkt = NULL;
|
||||
timer_add(&network_queue_timer, network_queue, NULL, 0);
|
||||
/* 10 mbps. */
|
||||
timer_on_auto(&network_queue_timer, 0.762939453125 * 2.0);
|
||||
}
|
||||
|
||||
|
||||
@@ -257,6 +358,8 @@ network_attach(void *dev, uint8_t *mac, NETRXCB rx, NETWAITCB wait, NETSETLINKST
|
||||
void
|
||||
network_close(void)
|
||||
{
|
||||
timer_stop(&network_queue_timer);
|
||||
|
||||
/* If already closed, do nothing. */
|
||||
if (network_mutex == NULL) return;
|
||||
|
||||
@@ -282,6 +385,7 @@ network_close(void)
|
||||
network_mac = NULL;
|
||||
|
||||
/* Here is where we should clear the queue. */
|
||||
network_queue_clear();
|
||||
|
||||
network_log("NETWORK: closed.\n");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user