clang-format in src/network/
This commit is contained in:
@@ -63,131 +63,124 @@
|
|||||||
#include <86box/bswap.h>
|
#include <86box/bswap.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
dp8390_t *dp8390;
|
dp8390_t *dp8390;
|
||||||
mem_mapping_t ram_mapping;
|
mem_mapping_t ram_mapping;
|
||||||
uint32_t base_address;
|
uint32_t base_address;
|
||||||
int base_irq;
|
int base_irq;
|
||||||
uint32_t bios_addr;
|
uint32_t bios_addr;
|
||||||
uint8_t maclocal[6]; /* configured MAC (local) address */
|
uint8_t maclocal[6]; /* configured MAC (local) address */
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint8_t pstr;
|
uint8_t pstr;
|
||||||
uint8_t pspr;
|
uint8_t pspr;
|
||||||
uint8_t dqtr;
|
uint8_t dqtr;
|
||||||
uint8_t bcfr;
|
uint8_t bcfr;
|
||||||
uint8_t pcfr;
|
uint8_t pcfr;
|
||||||
uint8_t gacfr;
|
uint8_t gacfr;
|
||||||
uint8_t ctrl;
|
uint8_t ctrl;
|
||||||
uint8_t streg;
|
uint8_t streg;
|
||||||
uint8_t idcfr;
|
uint8_t idcfr;
|
||||||
uint16_t da;
|
uint16_t da;
|
||||||
uint32_t vptr;
|
uint32_t vptr;
|
||||||
uint8_t rfmsb;
|
uint8_t rfmsb;
|
||||||
uint8_t rflsb;
|
uint8_t rflsb;
|
||||||
} regs;
|
} regs;
|
||||||
|
|
||||||
int dma_channel;
|
int dma_channel;
|
||||||
} threec503_t;
|
} threec503_t;
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENABLE_3COM503_LOG
|
#ifdef ENABLE_3COM503_LOG
|
||||||
int threec503_do_log = ENABLE_3COM503_LOG;
|
int threec503_do_log = ENABLE_3COM503_LOG;
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
threec503_log(const char *fmt, ...)
|
threec503_log(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (threec503_do_log) {
|
if (threec503_do_log) {
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
pclog_ex(fmt, ap);
|
pclog_ex(fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define threec503_log(fmt, ...)
|
# define threec503_log(fmt, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
threec503_interrupt(void *priv, int set)
|
threec503_interrupt(void *priv, int set)
|
||||||
{
|
{
|
||||||
threec503_t *dev = (threec503_t *) priv;
|
threec503_t *dev = (threec503_t *) priv;
|
||||||
|
|
||||||
switch (dev->base_irq) {
|
switch (dev->base_irq) {
|
||||||
case 2:
|
case 2:
|
||||||
dev->regs.idcfr = 0x10;
|
dev->regs.idcfr = 0x10;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
dev->regs.idcfr = 0x20;
|
dev->regs.idcfr = 0x20;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
dev->regs.idcfr = 0x40;
|
dev->regs.idcfr = 0x40;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5:
|
case 5:
|
||||||
dev->regs.idcfr = 0x80;
|
dev->regs.idcfr = 0x80;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (set)
|
if (set)
|
||||||
picint(1 << dev->base_irq);
|
picint(1 << dev->base_irq);
|
||||||
else
|
else
|
||||||
picintc(1 << dev->base_irq);
|
picintc(1 << dev->base_irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
threec503_ram_write(uint32_t addr, uint8_t val, void *priv)
|
threec503_ram_write(uint32_t addr, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
threec503_t *dev = (threec503_t *)priv;
|
threec503_t *dev = (threec503_t *) priv;
|
||||||
|
|
||||||
if ((addr & 0x3fff) >= 0x2000)
|
if ((addr & 0x3fff) >= 0x2000)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dev->dp8390->mem[addr & 0x1fff] = val;
|
dev->dp8390->mem[addr & 0x1fff] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
threec503_ram_read(uint32_t addr, void *priv)
|
threec503_ram_read(uint32_t addr, void *priv)
|
||||||
{
|
{
|
||||||
threec503_t *dev = (threec503_t *)priv;
|
threec503_t *dev = (threec503_t *) priv;
|
||||||
|
|
||||||
if ((addr & 0x3fff) >= 0x2000)
|
if ((addr & 0x3fff) >= 0x2000)
|
||||||
return 0xff;
|
return 0xff;
|
||||||
|
|
||||||
return dev->dp8390->mem[addr & 0x1fff];
|
return dev->dp8390->mem[addr & 0x1fff];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
threec503_set_drq(threec503_t *dev)
|
threec503_set_drq(threec503_t *dev)
|
||||||
{
|
{
|
||||||
switch (dev->dma_channel) {
|
switch (dev->dma_channel) {
|
||||||
case 1:
|
case 1:
|
||||||
dev->regs.idcfr = 1;
|
dev->regs.idcfr = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
dev->regs.idcfr = 2;
|
dev->regs.idcfr = 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
dev->regs.idcfr = 4;
|
dev->regs.idcfr = 4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* reset - restore state to power-up, cancelling all i/o */
|
/* reset - restore state to power-up, cancelling all i/o */
|
||||||
static void
|
static void
|
||||||
threec503_reset(void *priv)
|
threec503_reset(void *priv)
|
||||||
{
|
{
|
||||||
threec503_t *dev = (threec503_t *)priv;
|
threec503_t *dev = (threec503_t *) priv;
|
||||||
|
|
||||||
#ifdef ENABLE_3COM503_LOG
|
#ifdef ENABLE_3COM503_LOG
|
||||||
threec503_log("3Com503: reset\n");
|
threec503_log("3Com503: reset\n");
|
||||||
@@ -200,374 +193,370 @@ threec503_reset(void *priv)
|
|||||||
dev->regs.ctrl = 0x0a;
|
dev->regs.ctrl = 0x0a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
threec503_nic_lo_read(uint16_t addr, void *priv)
|
threec503_nic_lo_read(uint16_t addr, void *priv)
|
||||||
{
|
{
|
||||||
threec503_t *dev = (threec503_t *)priv;
|
threec503_t *dev = (threec503_t *) priv;
|
||||||
uint8_t retval = 0;
|
uint8_t retval = 0;
|
||||||
int off = addr - dev->base_address;
|
int off = addr - dev->base_address;
|
||||||
|
|
||||||
switch ((dev->regs.ctrl >> 2) & 3) {
|
switch ((dev->regs.ctrl >> 2) & 3) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
threec503_log("Read offset=%04x\n", off);
|
threec503_log("Read offset=%04x\n", off);
|
||||||
if (off == 0x00)
|
if (off == 0x00)
|
||||||
retval = dp8390_read_cr(dev->dp8390);
|
retval = dp8390_read_cr(dev->dp8390);
|
||||||
else switch(dev->dp8390->CR.pgsel) {
|
else
|
||||||
case 0x00:
|
switch (dev->dp8390->CR.pgsel) {
|
||||||
retval = dp8390_page0_read(dev->dp8390, off, 1);
|
case 0x00:
|
||||||
break;
|
retval = dp8390_page0_read(dev->dp8390, off, 1);
|
||||||
|
break;
|
||||||
|
|
||||||
case 0x01:
|
case 0x01:
|
||||||
retval = dp8390_page1_read(dev->dp8390, off, 1);
|
retval = dp8390_page1_read(dev->dp8390, off, 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x02:
|
case 0x02:
|
||||||
retval = dp8390_page2_read(dev->dp8390, off, 1);
|
retval = dp8390_page2_read(dev->dp8390, off, 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03:
|
case 0x03:
|
||||||
retval = 0xff;
|
retval = 0xff;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x01:
|
case 0x01:
|
||||||
retval = dev->dp8390->macaddr[off];
|
retval = dev->dp8390->macaddr[off];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x02:
|
case 0x02:
|
||||||
retval = dev->dp8390->macaddr[off + 0x10];
|
retval = dev->dp8390->macaddr[off + 0x10];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03:
|
case 0x03:
|
||||||
retval = 0xff;
|
retval = 0xff;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return(retval);
|
return (retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
threec503_nic_lo_write(uint16_t addr, uint8_t val, void *priv)
|
threec503_nic_lo_write(uint16_t addr, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
threec503_t *dev = (threec503_t *)priv;
|
threec503_t *dev = (threec503_t *) priv;
|
||||||
int off = addr - dev->base_address;
|
int off = addr - dev->base_address;
|
||||||
|
|
||||||
switch ((dev->regs.ctrl >> 2) & 3) {
|
switch ((dev->regs.ctrl >> 2) & 3) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
/* The high 16 bytes of i/o space are for the ne2000 asic -
|
/* The high 16 bytes of i/o space are for the ne2000 asic -
|
||||||
the low 16 bytes are for the DS8390, with the current
|
the low 16 bytes are for the DS8390, with the current
|
||||||
page being selected by the PS0,PS1 registers in the
|
page being selected by the PS0,PS1 registers in the
|
||||||
command register */
|
command register */
|
||||||
if (off == 0x00)
|
if (off == 0x00)
|
||||||
dp8390_write_cr(dev->dp8390, val);
|
dp8390_write_cr(dev->dp8390, val);
|
||||||
else switch(dev->dp8390->CR.pgsel) {
|
else
|
||||||
case 0x00:
|
switch (dev->dp8390->CR.pgsel) {
|
||||||
dp8390_page0_write(dev->dp8390, off, val, 1);
|
case 0x00:
|
||||||
break;
|
dp8390_page0_write(dev->dp8390, off, val, 1);
|
||||||
|
break;
|
||||||
|
|
||||||
case 0x01:
|
case 0x01:
|
||||||
dp8390_page1_write(dev->dp8390, off, val, 1);
|
dp8390_page1_write(dev->dp8390, off, val, 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x02:
|
case 0x02:
|
||||||
dp8390_page2_write(dev->dp8390, off, val, 1);
|
dp8390_page2_write(dev->dp8390, off, val, 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03:
|
case 0x03:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x01:
|
case 0x01:
|
||||||
case 0x02:
|
case 0x02:
|
||||||
case 0x03:
|
case 0x03:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
threec503_log("3Com503: write addr %x, value %x\n", addr, val);
|
threec503_log("3Com503: write addr %x, value %x\n", addr, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
threec503_nic_hi_read(uint16_t addr, void *priv)
|
threec503_nic_hi_read(uint16_t addr, void *priv)
|
||||||
{
|
{
|
||||||
threec503_t *dev = (threec503_t *)priv;
|
threec503_t *dev = (threec503_t *) priv;
|
||||||
|
|
||||||
threec503_log("3Com503: Read GA address=%04x\n", addr);
|
threec503_log("3Com503: Read GA address=%04x\n", addr);
|
||||||
|
|
||||||
switch (addr & 0x0f) {
|
switch (addr & 0x0f) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
return dev->regs.pstr;
|
return dev->regs.pstr;
|
||||||
|
|
||||||
case 0x01:
|
case 0x01:
|
||||||
return dev->regs.pspr;
|
return dev->regs.pspr;
|
||||||
|
|
||||||
case 0x02:
|
case 0x02:
|
||||||
return dev->regs.dqtr;
|
return dev->regs.dqtr;
|
||||||
|
|
||||||
case 0x03:
|
case 0x03:
|
||||||
switch (dev->base_address) {
|
switch (dev->base_address) {
|
||||||
default:
|
default:
|
||||||
case 0x300:
|
case 0x300:
|
||||||
dev->regs.bcfr = 0x80;
|
dev->regs.bcfr = 0x80;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x310:
|
case 0x310:
|
||||||
dev->regs.bcfr = 0x40;
|
dev->regs.bcfr = 0x40;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x330:
|
case 0x330:
|
||||||
dev->regs.bcfr = 0x20;
|
dev->regs.bcfr = 0x20;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x350:
|
case 0x350:
|
||||||
dev->regs.bcfr = 0x10;
|
dev->regs.bcfr = 0x10;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x250:
|
case 0x250:
|
||||||
dev->regs.bcfr = 0x08;
|
dev->regs.bcfr = 0x08;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x280:
|
case 0x280:
|
||||||
dev->regs.bcfr = 0x04;
|
dev->regs.bcfr = 0x04;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x2a0:
|
case 0x2a0:
|
||||||
dev->regs.bcfr = 0x02;
|
dev->regs.bcfr = 0x02;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x2e0:
|
case 0x2e0:
|
||||||
dev->regs.bcfr = 0x01;
|
dev->regs.bcfr = 0x01;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dev->regs.bcfr;
|
return dev->regs.bcfr;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x04:
|
case 0x04:
|
||||||
switch (dev->bios_addr) {
|
switch (dev->bios_addr) {
|
||||||
case 0xdc000:
|
case 0xdc000:
|
||||||
dev->regs.pcfr = 0x80;
|
dev->regs.pcfr = 0x80;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xd8000:
|
case 0xd8000:
|
||||||
dev->regs.pcfr = 0x40;
|
dev->regs.pcfr = 0x40;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xcc000:
|
case 0xcc000:
|
||||||
dev->regs.pcfr = 0x20;
|
dev->regs.pcfr = 0x20;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xc8000:
|
case 0xc8000:
|
||||||
dev->regs.pcfr = 0x10;
|
dev->regs.pcfr = 0x10;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dev->regs.pcfr;
|
return dev->regs.pcfr;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x05:
|
case 0x05:
|
||||||
return dev->regs.gacfr;
|
return dev->regs.gacfr;
|
||||||
|
|
||||||
case 0x06:
|
case 0x06:
|
||||||
return dev->regs.ctrl;
|
return dev->regs.ctrl;
|
||||||
|
|
||||||
case 0x07:
|
case 0x07:
|
||||||
return dev->regs.streg;
|
return dev->regs.streg;
|
||||||
|
|
||||||
case 0x08:
|
case 0x08:
|
||||||
return dev->regs.idcfr;
|
return dev->regs.idcfr;
|
||||||
|
|
||||||
case 0x09:
|
case 0x09:
|
||||||
return (dev->regs.da >> 8);
|
return (dev->regs.da >> 8);
|
||||||
|
|
||||||
case 0x0a:
|
case 0x0a:
|
||||||
return (dev->regs.da & 0xff);
|
return (dev->regs.da & 0xff);
|
||||||
|
|
||||||
case 0x0b:
|
case 0x0b:
|
||||||
return (dev->regs.vptr >> 12) & 0xff;
|
return (dev->regs.vptr >> 12) & 0xff;
|
||||||
|
|
||||||
case 0x0c:
|
case 0x0c:
|
||||||
return (dev->regs.vptr >> 4) & 0xff;
|
return (dev->regs.vptr >> 4) & 0xff;
|
||||||
|
|
||||||
case 0x0d:
|
case 0x0d:
|
||||||
return (dev->regs.vptr & 0x0f) << 4;
|
return (dev->regs.vptr & 0x0f) << 4;
|
||||||
|
|
||||||
case 0x0e:
|
case 0x0e:
|
||||||
case 0x0f:
|
case 0x0f:
|
||||||
if (!(dev->regs.ctrl & 0x80))
|
if (!(dev->regs.ctrl & 0x80))
|
||||||
return 0xff;
|
return 0xff;
|
||||||
|
|
||||||
threec503_set_drq(dev);
|
threec503_set_drq(dev);
|
||||||
|
|
||||||
return dp8390_chipmem_read(dev->dp8390, dev->regs.da++, 1);
|
return dp8390_chipmem_read(dev->dp8390, dev->regs.da++, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
threec503_nic_hi_write(uint16_t addr, uint8_t val, void *priv)
|
threec503_nic_hi_write(uint16_t addr, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
threec503_t *dev = (threec503_t *)priv;
|
threec503_t *dev = (threec503_t *) priv;
|
||||||
|
|
||||||
threec503_log("3Com503: Write GA address=%04x, val=%04x\n", addr, val);
|
threec503_log("3Com503: Write GA address=%04x, val=%04x\n", addr, val);
|
||||||
|
|
||||||
switch (addr & 0x0f) {
|
switch (addr & 0x0f) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
dev->regs.pstr = val;
|
dev->regs.pstr = val;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x01:
|
case 0x01:
|
||||||
dev->regs.pspr = val;
|
dev->regs.pspr = val;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x02:
|
case 0x02:
|
||||||
dev->regs.dqtr = val;
|
dev->regs.dqtr = val;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x05:
|
case 0x05:
|
||||||
if ((dev->regs.gacfr & 0x0f) != (val & 0x0f)) {
|
if ((dev->regs.gacfr & 0x0f) != (val & 0x0f)) {
|
||||||
switch (val & 0x0f) {
|
switch (val & 0x0f) {
|
||||||
case 0: /*ROM mapping*/
|
case 0: /*ROM mapping*/
|
||||||
/* FIXME: Implement this when a BIOS is found/generated. */
|
/* FIXME: Implement this when a BIOS is found/generated. */
|
||||||
mem_mapping_disable(&dev->ram_mapping);
|
mem_mapping_disable(&dev->ram_mapping);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 9: /*RAM mapping*/
|
case 9: /*RAM mapping*/
|
||||||
mem_mapping_enable(&dev->ram_mapping);
|
mem_mapping_enable(&dev->ram_mapping);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: /*No ROM mapping*/
|
default: /*No ROM mapping*/
|
||||||
mem_mapping_disable(&dev->ram_mapping);
|
mem_mapping_disable(&dev->ram_mapping);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(val & 0x80))
|
if (!(val & 0x80))
|
||||||
threec503_interrupt(dev, 1);
|
threec503_interrupt(dev, 1);
|
||||||
else
|
else
|
||||||
threec503_interrupt(dev, 0);
|
threec503_interrupt(dev, 0);
|
||||||
|
|
||||||
dev->regs.gacfr = val;
|
dev->regs.gacfr = val;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x06:
|
case 0x06:
|
||||||
if (val & 1) {
|
if (val & 1) {
|
||||||
threec503_reset(dev);
|
threec503_reset(dev);
|
||||||
dev->dp8390->ISR.reset = 1;
|
dev->dp8390->ISR.reset = 1;
|
||||||
dev->regs.ctrl = 0x0b;
|
dev->regs.ctrl = 0x0b;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((val & 0x80) != (dev->regs.ctrl & 0x80)) {
|
if ((val & 0x80) != (dev->regs.ctrl & 0x80)) {
|
||||||
if (val & 0x80)
|
if (val & 0x80)
|
||||||
dev->regs.streg |= 0x88;
|
dev->regs.streg |= 0x88;
|
||||||
else
|
else
|
||||||
dev->regs.streg &= ~0x88;
|
dev->regs.streg &= ~0x88;
|
||||||
dev->regs.streg &= ~0x10;
|
dev->regs.streg &= ~0x10;
|
||||||
}
|
}
|
||||||
dev->regs.ctrl = val;
|
dev->regs.ctrl = val;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x08:
|
case 0x08:
|
||||||
switch (val & 0xf0) {
|
switch (val & 0xf0) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
case 0x10:
|
case 0x10:
|
||||||
case 0x20:
|
case 0x20:
|
||||||
case 0x40:
|
case 0x40:
|
||||||
case 0x80:
|
case 0x80:
|
||||||
dev->regs.idcfr = (dev->regs.idcfr & 0x0f) | (val & 0xf0);
|
dev->regs.idcfr = (dev->regs.idcfr & 0x0f) | (val & 0xf0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
threec503_log("Trying to set multiple IRQs: %02x\n", val);
|
threec503_log("Trying to set multiple IRQs: %02x\n", val);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (val & 0x0f) {
|
switch (val & 0x0f) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
case 0x01:
|
case 0x01:
|
||||||
case 0x02:
|
case 0x02:
|
||||||
case 0x04:
|
case 0x04:
|
||||||
dev->regs.idcfr = (dev->regs.idcfr & 0xf0) | (val & 0x0f);
|
dev->regs.idcfr = (dev->regs.idcfr & 0xf0) | (val & 0x0f);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x08:
|
case 0x08:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
threec503_log("Trying to set multiple DMA channels: %02x\n", val);
|
threec503_log("Trying to set multiple DMA channels: %02x\n", val);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x09:
|
case 0x09:
|
||||||
dev->regs.da = (val << 8) | (dev->regs.da & 0xff);
|
dev->regs.da = (val << 8) | (dev->regs.da & 0xff);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0a:
|
case 0x0a:
|
||||||
dev->regs.da = (dev->regs.da & 0xff00) | val;
|
dev->regs.da = (dev->regs.da & 0xff00) | val;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0b:
|
case 0x0b:
|
||||||
dev->regs.vptr = (val << 12) | (dev->regs.vptr & 0xfff);
|
dev->regs.vptr = (val << 12) | (dev->regs.vptr & 0xfff);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0c:
|
case 0x0c:
|
||||||
dev->regs.vptr = (val << 4) | (dev->regs.vptr & 0xff00f);
|
dev->regs.vptr = (val << 4) | (dev->regs.vptr & 0xff00f);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0d:
|
case 0x0d:
|
||||||
dev->regs.vptr = (val << 4) | (dev->regs.vptr & 0xffff0);
|
dev->regs.vptr = (val << 4) | (dev->regs.vptr & 0xffff0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0e:
|
case 0x0e:
|
||||||
case 0x0f:
|
case 0x0f:
|
||||||
if (!(dev->regs.ctrl & 0x80))
|
if (!(dev->regs.ctrl & 0x80))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
threec503_set_drq(dev);
|
threec503_set_drq(dev);
|
||||||
|
|
||||||
dp8390_chipmem_write(dev->dp8390, dev->regs.da++, val, 1);
|
dp8390_chipmem_write(dev->dp8390, dev->regs.da++, val, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
threec503_nic_ioset(threec503_t *dev, uint16_t addr)
|
threec503_nic_ioset(threec503_t *dev, uint16_t addr)
|
||||||
{
|
{
|
||||||
io_sethandler(addr, 0x10,
|
io_sethandler(addr, 0x10,
|
||||||
threec503_nic_lo_read, NULL, NULL,
|
threec503_nic_lo_read, NULL, NULL,
|
||||||
threec503_nic_lo_write, NULL, NULL, dev);
|
threec503_nic_lo_write, NULL, NULL, dev);
|
||||||
|
|
||||||
io_sethandler(addr+0x400, 0x10,
|
io_sethandler(addr + 0x400, 0x10,
|
||||||
threec503_nic_hi_read, NULL, NULL,
|
threec503_nic_hi_read, NULL, NULL,
|
||||||
threec503_nic_hi_write, NULL, NULL, dev);
|
threec503_nic_hi_write, NULL, NULL, dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
threec503_nic_init(const device_t *info)
|
threec503_nic_init(const device_t *info)
|
||||||
{
|
{
|
||||||
uint32_t mac;
|
uint32_t mac;
|
||||||
threec503_t *dev;
|
threec503_t *dev;
|
||||||
|
|
||||||
dev = malloc(sizeof(threec503_t));
|
dev = malloc(sizeof(threec503_t));
|
||||||
memset(dev, 0x00, sizeof(threec503_t));
|
memset(dev, 0x00, sizeof(threec503_t));
|
||||||
dev->maclocal[0] = 0x02; /* 02:60:8C (3Com OID) */
|
dev->maclocal[0] = 0x02; /* 02:60:8C (3Com OID) */
|
||||||
dev->maclocal[1] = 0x60;
|
dev->maclocal[1] = 0x60;
|
||||||
dev->maclocal[2] = 0x8C;
|
dev->maclocal[2] = 0x8C;
|
||||||
|
|
||||||
dev->base_address = device_get_config_hex16("base");
|
dev->base_address = device_get_config_hex16("base");
|
||||||
dev->base_irq = device_get_config_int("irq");
|
dev->base_irq = device_get_config_int("irq");
|
||||||
dev->dma_channel = device_get_config_int("dma");
|
dev->dma_channel = device_get_config_int("dma");
|
||||||
dev->bios_addr = device_get_config_hex20("bios_addr");
|
dev->bios_addr = device_get_config_hex20("bios_addr");
|
||||||
|
|
||||||
/* See if we have a local MAC address configured. */
|
/* See if we have a local MAC address configured. */
|
||||||
mac = device_get_config_mac("mac", -1);
|
mac = device_get_config_mac("mac", -1);
|
||||||
@@ -580,22 +569,22 @@ threec503_nic_init(const device_t *info)
|
|||||||
|
|
||||||
/* Set up our BIA. */
|
/* Set up our BIA. */
|
||||||
if (mac & 0xff000000) {
|
if (mac & 0xff000000) {
|
||||||
/* Generate new local MAC. */
|
/* Generate new local MAC. */
|
||||||
dev->maclocal[3] = random_generate();
|
dev->maclocal[3] = random_generate();
|
||||||
dev->maclocal[4] = random_generate();
|
dev->maclocal[4] = random_generate();
|
||||||
dev->maclocal[5] = random_generate();
|
dev->maclocal[5] = random_generate();
|
||||||
mac = (((int) dev->maclocal[3]) << 16);
|
mac = (((int) dev->maclocal[3]) << 16);
|
||||||
mac |= (((int) dev->maclocal[4]) << 8);
|
mac |= (((int) dev->maclocal[4]) << 8);
|
||||||
mac |= ((int) dev->maclocal[5]);
|
mac |= ((int) dev->maclocal[5]);
|
||||||
device_set_config_mac("mac", mac);
|
device_set_config_mac("mac", mac);
|
||||||
} else {
|
} else {
|
||||||
dev->maclocal[3] = (mac>>16) & 0xff;
|
dev->maclocal[3] = (mac >> 16) & 0xff;
|
||||||
dev->maclocal[4] = (mac>>8) & 0xff;
|
dev->maclocal[4] = (mac >> 8) & 0xff;
|
||||||
dev->maclocal[5] = (mac & 0xff);
|
dev->maclocal[5] = (mac & 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->dp8390 = device_add_inst(&dp8390_device, dp3890_inst++);
|
dev->dp8390 = device_add_inst(&dp8390_device, dp3890_inst++);
|
||||||
dev->dp8390->priv = dev;
|
dev->dp8390->priv = dev;
|
||||||
dev->dp8390->interrupt = threec503_interrupt;
|
dev->dp8390->interrupt = threec503_interrupt;
|
||||||
dp8390_set_defaults(dev->dp8390, DP8390_FLAG_CHECK_CR | DP8390_FLAG_CLEAR_IRQ);
|
dp8390_set_defaults(dev->dp8390, DP8390_FLAG_CHECK_CR | DP8390_FLAG_CLEAR_IRQ);
|
||||||
dp8390_mem_alloc(dev->dp8390, 0x2000, 0x2000);
|
dp8390_mem_alloc(dev->dp8390, 0x2000, 0x2000);
|
||||||
@@ -603,32 +592,31 @@ threec503_nic_init(const device_t *info)
|
|||||||
memcpy(dev->dp8390->physaddr, dev->maclocal, sizeof(dev->maclocal));
|
memcpy(dev->dp8390->physaddr, dev->maclocal, sizeof(dev->maclocal));
|
||||||
|
|
||||||
threec503_log("I/O=%04x, IRQ=%d, MAC=%02x:%02x:%02x:%02x:%02x:%02x\n",
|
threec503_log("I/O=%04x, IRQ=%d, MAC=%02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||||
dev->base_address, dev->base_irq,
|
dev->base_address, dev->base_irq,
|
||||||
dev->dp8390->physaddr[0], dev->dp8390->physaddr[1], dev->dp8390->physaddr[2],
|
dev->dp8390->physaddr[0], dev->dp8390->physaddr[1], dev->dp8390->physaddr[2],
|
||||||
dev->dp8390->physaddr[3], dev->dp8390->physaddr[4], dev->dp8390->physaddr[5]);
|
dev->dp8390->physaddr[3], dev->dp8390->physaddr[4], dev->dp8390->physaddr[5]);
|
||||||
|
|
||||||
/* Reset the board. */
|
/* Reset the board. */
|
||||||
threec503_reset(dev);
|
threec503_reset(dev);
|
||||||
|
|
||||||
/* Map this system into the memory map. */
|
/* Map this system into the memory map. */
|
||||||
mem_mapping_add(&dev->ram_mapping, dev->bios_addr, 0x4000,
|
mem_mapping_add(&dev->ram_mapping, dev->bios_addr, 0x4000,
|
||||||
threec503_ram_read, NULL, NULL,
|
threec503_ram_read, NULL, NULL,
|
||||||
threec503_ram_write, NULL, NULL,
|
threec503_ram_write, NULL, NULL,
|
||||||
NULL, MEM_MAPPING_EXTERNAL, dev);
|
NULL, MEM_MAPPING_EXTERNAL, dev);
|
||||||
// mem_mapping_disable(&dev->ram_mapping);
|
// mem_mapping_disable(&dev->ram_mapping);
|
||||||
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);
|
dev->dp8390->card = network_attach(dev->dp8390, dev->dp8390->physaddr, dp8390_rx, NULL);
|
||||||
|
|
||||||
return(dev);
|
return (dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
threec503_nic_close(void *priv)
|
threec503_nic_close(void *priv)
|
||||||
{
|
{
|
||||||
threec503_t *dev = (threec503_t *)priv;
|
threec503_t *dev = (threec503_t *) priv;
|
||||||
|
|
||||||
#ifdef ENABLE_3COM503_LOG
|
#ifdef ENABLE_3COM503_LOG
|
||||||
threec503_log("3Com503: closed\n");
|
threec503_log("3Com503: closed\n");
|
||||||
@@ -638,7 +626,7 @@ threec503_nic_close(void *priv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const device_config_t threec503_config[] = {
|
static const device_config_t threec503_config[] = {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
{
|
{
|
||||||
.name = "base",
|
.name = "base",
|
||||||
.description = "Address",
|
.description = "Address",
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,19 +1,19 @@
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define WIN32_LEAN_AND_MEAN
|
# define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
# include <windows.h>
|
||||||
#else
|
#else
|
||||||
#include <unistd.h>
|
# include <unistd.h>
|
||||||
#include <fcntl.h>
|
# include <fcntl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <86box/net_event.h>
|
#include <86box/net_event.h>
|
||||||
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
static void setup_fd(int fd)
|
static void
|
||||||
|
setup_fd(int fd)
|
||||||
{
|
{
|
||||||
fcntl(fd, F_SETFD, FD_CLOEXEC);
|
fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||||
fcntl(fd, F_SETFL, O_NONBLOCK);
|
fcntl(fd, F_SETFL, O_NONBLOCK);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -52,14 +52,14 @@
|
|||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define WIN32_LEAN_AND_MEAN
|
# define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
# include <windows.h>
|
||||||
#include <winsock2.h>
|
# include <winsock2.h>
|
||||||
#else
|
#else
|
||||||
#include <poll.h>
|
# include <poll.h>
|
||||||
#include <unistd.h>
|
# include <unistd.h>
|
||||||
#include <fcntl.h>
|
# include <fcntl.h>
|
||||||
#include <sys/select.h>
|
# include <sys/select.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define HAVE_STDARG_H
|
#define HAVE_STDARG_H
|
||||||
@@ -82,45 +82,45 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <pcap/pcap.h>
|
# include <pcap/pcap.h>
|
||||||
#else
|
#else
|
||||||
typedef int bpf_int32;
|
typedef int bpf_int32;
|
||||||
typedef unsigned int bpf_u_int32;
|
typedef unsigned int bpf_u_int32;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The instruction data structure.
|
* The instruction data structure.
|
||||||
*/
|
*/
|
||||||
struct bpf_insn {
|
struct bpf_insn {
|
||||||
unsigned short code;
|
unsigned short code;
|
||||||
unsigned char jt;
|
unsigned char jt;
|
||||||
unsigned char jf;
|
unsigned char jf;
|
||||||
bpf_u_int32 k;
|
bpf_u_int32 k;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Structure for "pcap_compile()", "pcap_setfilter()", etc..
|
* Structure for "pcap_compile()", "pcap_setfilter()", etc..
|
||||||
*/
|
*/
|
||||||
struct bpf_program {
|
struct bpf_program {
|
||||||
unsigned int bf_len;
|
unsigned int bf_len;
|
||||||
struct bpf_insn *bf_insns;
|
struct bpf_insn *bf_insns;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct pcap_if pcap_if_t;
|
typedef struct pcap_if pcap_if_t;
|
||||||
|
|
||||||
#define PCAP_ERRBUF_SIZE 256
|
# define PCAP_ERRBUF_SIZE 256
|
||||||
|
|
||||||
struct pcap_pkthdr {
|
struct pcap_pkthdr {
|
||||||
struct timeval ts;
|
struct timeval ts;
|
||||||
bpf_u_int32 caplen;
|
bpf_u_int32 caplen;
|
||||||
bpf_u_int32 len;
|
bpf_u_int32 len;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pcap_if {
|
struct pcap_if {
|
||||||
struct pcap_if *next;
|
struct pcap_if *next;
|
||||||
char *name;
|
char *name;
|
||||||
char *description;
|
char *description;
|
||||||
void *addresses;
|
void *addresses;
|
||||||
bpf_u_int32 flags;
|
bpf_u_int32 flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pcap_send_queue {
|
struct pcap_send_queue {
|
||||||
@@ -154,39 +154,39 @@ typedef struct {
|
|||||||
uint8_t *mac_addr;
|
uint8_t *mac_addr;
|
||||||
} net_pcap_params_t;
|
} net_pcap_params_t;
|
||||||
|
|
||||||
static volatile void *libpcap_handle; /* handle to WinPcap DLL */
|
static volatile void *libpcap_handle; /* handle to WinPcap DLL */
|
||||||
|
|
||||||
/* Pointers to the real functions. */
|
/* Pointers to the real functions. */
|
||||||
static const char *(*f_pcap_lib_version)(void);
|
static const char *(*f_pcap_lib_version)(void);
|
||||||
static int (*f_pcap_findalldevs)(pcap_if_t **,char *);
|
static int (*f_pcap_findalldevs)(pcap_if_t **, char *);
|
||||||
static void (*f_pcap_freealldevs)(void *);
|
static void (*f_pcap_freealldevs)(void *);
|
||||||
static void *(*f_pcap_open_live)(const char *,int,int,int,char *);
|
static void *(*f_pcap_open_live)(const char *, int, int, int, char *);
|
||||||
static int (*f_pcap_compile)(void *,void *, const char *,int,bpf_u_int32);
|
static int (*f_pcap_compile)(void *, void *, const char *, int, bpf_u_int32);
|
||||||
static int (*f_pcap_setfilter)(void *,void *);
|
static int (*f_pcap_setfilter)(void *, void *);
|
||||||
static const unsigned char
|
static const unsigned char
|
||||||
*(*f_pcap_next)(void *,void *);
|
*(*f_pcap_next)(void *, void *);
|
||||||
static int (*f_pcap_sendpacket)(void *,const unsigned char *,int);
|
static int (*f_pcap_sendpacket)(void *, const unsigned char *, int);
|
||||||
static void (*f_pcap_close)(void *);
|
static void (*f_pcap_close)(void *);
|
||||||
static int (*f_pcap_setnonblock)(void*, int, char*);
|
static int (*f_pcap_setnonblock)(void *, int, char *);
|
||||||
static int (*f_pcap_set_immediate_mode)(void *, int);
|
static int (*f_pcap_set_immediate_mode)(void *, int);
|
||||||
static int (*f_pcap_set_promisc)(void *, int);
|
static int (*f_pcap_set_promisc)(void *, int);
|
||||||
static int (*f_pcap_set_snaplen)(void *, int);
|
static int (*f_pcap_set_snaplen)(void *, int);
|
||||||
static int (*f_pcap_dispatch)(void *, int, pcap_handler callback, u_char *user);
|
static int (*f_pcap_dispatch)(void *, int, pcap_handler callback, u_char *user);
|
||||||
static void *(*f_pcap_create)(const char *, char*);
|
static void *(*f_pcap_create)(const char *, char *);
|
||||||
static int (*f_pcap_activate)(void *);
|
static int (*f_pcap_activate)(void *);
|
||||||
static void *(*f_pcap_geterr)(void *);
|
static void *(*f_pcap_geterr)(void *);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static HANDLE (*f_pcap_getevent)(void *);
|
static HANDLE (*f_pcap_getevent)(void *);
|
||||||
static int (*f_pcap_sendqueue_queue)(void *, void *, void *);
|
static int (*f_pcap_sendqueue_queue)(void *, void *, void *);
|
||||||
static u_int (*f_pcap_sendqueue_transmit)(void *, void *, int sync);
|
static u_int (*f_pcap_sendqueue_transmit)(void *, void *, int sync);
|
||||||
static void *(*f_pcap_sendqueue_alloc)(u_int memsize);
|
static void *(*f_pcap_sendqueue_alloc)(u_int memsize);
|
||||||
static void (*f_pcap_sendqueue_destroy)(void *);
|
static void (*f_pcap_sendqueue_destroy)(void *);
|
||||||
#else
|
#else
|
||||||
static int (*f_pcap_get_selectable_fd)(void *);
|
static int (*f_pcap_get_selectable_fd)(void *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static dllimp_t pcap_imports[] = {
|
static dllimp_t pcap_imports[] = {
|
||||||
{ "pcap_lib_version", &f_pcap_lib_version },
|
{"pcap_lib_version", &f_pcap_lib_version },
|
||||||
{ "pcap_findalldevs", &f_pcap_findalldevs },
|
{ "pcap_findalldevs", &f_pcap_findalldevs },
|
||||||
{ "pcap_freealldevs", &f_pcap_freealldevs },
|
{ "pcap_freealldevs", &f_pcap_freealldevs },
|
||||||
{ "pcap_open_live", &f_pcap_open_live },
|
{ "pcap_open_live", &f_pcap_open_live },
|
||||||
@@ -210,7 +210,7 @@ static dllimp_t pcap_imports[] = {
|
|||||||
{ "pcap_sendqueue_alloc", &f_pcap_sendqueue_alloc },
|
{ "pcap_sendqueue_alloc", &f_pcap_sendqueue_alloc },
|
||||||
{ "pcap_sendqueue_destroy", &f_pcap_sendqueue_destroy },
|
{ "pcap_sendqueue_destroy", &f_pcap_sendqueue_destroy },
|
||||||
#else
|
#else
|
||||||
{ "pcap_get_selectable_fd", &f_pcap_get_selectable_fd },
|
{ "pcap_get_selectable_fd", &f_pcap_get_selectable_fd },
|
||||||
#endif
|
#endif
|
||||||
{ NULL, NULL },
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
@@ -224,20 +224,19 @@ pcap_log(const char *fmt, ...)
|
|||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (pcap_do_log) {
|
if (pcap_do_log) {
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
pclog_ex(fmt, ap);
|
pclog_ex(fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define pcap_log(fmt, ...)
|
# define pcap_log(fmt, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
net_pcap_rx_handler(uint8_t *user, const struct pcap_pkthdr *h, const uint8_t *bytes)
|
net_pcap_rx_handler(uint8_t *user, const struct pcap_pkthdr *h, const uint8_t *bytes)
|
||||||
{
|
{
|
||||||
net_pcap_t *pcap = (net_pcap_t*)user;
|
net_pcap_t *pcap = (net_pcap_t *) user;
|
||||||
memcpy(pcap->pkt.data, bytes, h->caplen);
|
memcpy(pcap->pkt.data, bytes, h->caplen);
|
||||||
pcap->pkt.len = h->caplen;
|
pcap->pkt.len = h->caplen;
|
||||||
network_rx_put_pkt(pcap->card, &pcap->pkt);
|
network_rx_put_pkt(pcap->card, &pcap->pkt);
|
||||||
@@ -248,15 +247,15 @@ void
|
|||||||
net_pcap_in(void *pcap, uint8_t *bufp, int len)
|
net_pcap_in(void *pcap, uint8_t *bufp, int len)
|
||||||
{
|
{
|
||||||
if (pcap == NULL)
|
if (pcap == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
f_pcap_sendpacket((void *)pcap, bufp, len);
|
f_pcap_sendpacket((void *) pcap, bufp, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
net_pcap_in_available(void *priv)
|
net_pcap_in_available(void *priv)
|
||||||
{
|
{
|
||||||
net_pcap_t *pcap = (net_pcap_t *)priv;
|
net_pcap_t *pcap = (net_pcap_t *) priv;
|
||||||
net_event_set(&pcap->tx_event);
|
net_event_set(&pcap->tx_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,14 +263,14 @@ net_pcap_in_available(void *priv)
|
|||||||
static void
|
static void
|
||||||
net_pcap_thread(void *priv)
|
net_pcap_thread(void *priv)
|
||||||
{
|
{
|
||||||
net_pcap_t *pcap = (net_pcap_t*)priv;
|
net_pcap_t *pcap = (net_pcap_t *) priv;
|
||||||
|
|
||||||
pcap_log("PCAP: polling started.\n");
|
pcap_log("PCAP: polling started.\n");
|
||||||
|
|
||||||
HANDLE events[NET_EVENT_MAX];
|
HANDLE events[NET_EVENT_MAX];
|
||||||
events[NET_EVENT_STOP] = net_event_get_handle(&pcap->stop_event);
|
events[NET_EVENT_STOP] = net_event_get_handle(&pcap->stop_event);
|
||||||
events[NET_EVENT_TX] = net_event_get_handle(&pcap->tx_event);
|
events[NET_EVENT_TX] = net_event_get_handle(&pcap->tx_event);
|
||||||
events[NET_EVENT_RX] = f_pcap_getevent((void *)pcap->pcap);
|
events[NET_EVENT_RX] = f_pcap_getevent((void *) pcap->pcap);
|
||||||
|
|
||||||
bool run = true;
|
bool run = true;
|
||||||
|
|
||||||
@@ -297,7 +296,7 @@ net_pcap_thread(void *priv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case NET_EVENT_RX:
|
case NET_EVENT_RX:
|
||||||
f_pcap_dispatch(pcap->pcap, PCAP_PKT_BATCH, net_pcap_rx_handler, (u_char *)pcap);
|
f_pcap_dispatch(pcap->pcap, PCAP_PKT_BATCH, net_pcap_rx_handler, (u_char *) pcap);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -308,7 +307,7 @@ net_pcap_thread(void *priv)
|
|||||||
static void
|
static void
|
||||||
net_pcap_thread(void *priv)
|
net_pcap_thread(void *priv)
|
||||||
{
|
{
|
||||||
net_pcap_t *pcap = (net_pcap_t*)priv;
|
net_pcap_t *pcap = (net_pcap_t *) priv;
|
||||||
|
|
||||||
pcap_log("PCAP: polling started.\n");
|
pcap_log("PCAP: polling started.\n");
|
||||||
|
|
||||||
@@ -341,9 +340,8 @@ net_pcap_thread(void *priv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (pfd[NET_EVENT_RX].revents & POLLIN) {
|
if (pfd[NET_EVENT_RX].revents & POLLIN) {
|
||||||
f_pcap_dispatch(pcap->pcap, PCAP_PKT_BATCH, net_pcap_rx_handler, (u_char *)pcap);
|
f_pcap_dispatch(pcap->pcap, PCAP_PKT_BATCH, net_pcap_rx_handler, (u_char *) pcap);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pcap_log("PCAP: polling stopped.\n");
|
pcap_log("PCAP: polling stopped.\n");
|
||||||
@@ -360,9 +358,9 @@ net_pcap_thread(void *priv)
|
|||||||
int
|
int
|
||||||
net_pcap_prepare(netdev_t *list)
|
net_pcap_prepare(netdev_t *list)
|
||||||
{
|
{
|
||||||
char errbuf[PCAP_ERRBUF_SIZE];
|
char errbuf[PCAP_ERRBUF_SIZE];
|
||||||
pcap_if_t *devlist, *dev;
|
pcap_if_t *devlist, *dev;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
/* Try loading the DLL. */
|
/* Try loading the DLL. */
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@@ -374,44 +372,44 @@ net_pcap_prepare(netdev_t *list)
|
|||||||
#endif
|
#endif
|
||||||
if (libpcap_handle == NULL) {
|
if (libpcap_handle == NULL) {
|
||||||
pcap_log("PCAP: error loading pcap module\n");
|
pcap_log("PCAP: error loading pcap module\n");
|
||||||
return(-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Retrieve the device list from the local machine */
|
/* Retrieve the device list from the local machine */
|
||||||
if (f_pcap_findalldevs(&devlist, errbuf) == -1) {
|
if (f_pcap_findalldevs(&devlist, errbuf) == -1) {
|
||||||
pcap_log("PCAP: error in pcap_findalldevs: %s\n", errbuf);
|
pcap_log("PCAP: error in pcap_findalldevs: %s\n", errbuf);
|
||||||
return(-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (dev=devlist; dev!=NULL; dev=dev->next) {
|
for (dev = devlist; dev != NULL; dev = dev->next) {
|
||||||
if (i >= (NET_HOST_INTF_MAX - 1))
|
if (i >= (NET_HOST_INTF_MAX - 1))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* we initialize the strings to NULL first for strncpy
|
* we initialize the strings to NULL first for strncpy
|
||||||
*/
|
*/
|
||||||
|
|
||||||
memset(list->device, '\0', sizeof(list->device));
|
memset(list->device, '\0', sizeof(list->device));
|
||||||
memset(list->description, '\0', sizeof(list->description));
|
memset(list->description, '\0', sizeof(list->description));
|
||||||
|
|
||||||
strncpy(list->device, dev->name, sizeof(list->device) - 1);
|
strncpy(list->device, dev->name, sizeof(list->device) - 1);
|
||||||
if (dev->description) {
|
if (dev->description) {
|
||||||
strncpy(list->description, dev->description, sizeof(list->description) - 1);
|
strncpy(list->description, dev->description, sizeof(list->description) - 1);
|
||||||
} else {
|
} else {
|
||||||
/* if description is NULL, set the name. This allows pcap to display *something* useful under WINE */
|
/* if description is NULL, set the name. This allows pcap to display *something* useful under WINE */
|
||||||
strncpy(list->description, dev->name, sizeof(list->description) - 1);
|
strncpy(list->description, dev->name, sizeof(list->description) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
list++; i++;
|
list++;
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release the memory. */
|
/* Release the memory. */
|
||||||
f_pcap_freealldevs(devlist);
|
f_pcap_freealldevs(devlist);
|
||||||
|
|
||||||
return(i);
|
return (i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize (Win)Pcap for use.
|
* Initialize (Win)Pcap for use.
|
||||||
*
|
*
|
||||||
@@ -422,12 +420,12 @@ net_pcap_prepare(netdev_t *list)
|
|||||||
void *
|
void *
|
||||||
net_pcap_init(const netcard_t *card, const uint8_t *mac_addr, void *priv)
|
net_pcap_init(const netcard_t *card, const uint8_t *mac_addr, void *priv)
|
||||||
{
|
{
|
||||||
char errbuf[PCAP_ERRBUF_SIZE];
|
char errbuf[PCAP_ERRBUF_SIZE];
|
||||||
char *str;
|
char *str;
|
||||||
char filter_exp[255];
|
char filter_exp[255];
|
||||||
struct bpf_program fp;
|
struct bpf_program fp;
|
||||||
|
|
||||||
char *intf_name = (char*)priv;
|
char *intf_name = (char *) priv;
|
||||||
|
|
||||||
/* Did we already load the library? */
|
/* Did we already load the library? */
|
||||||
if (libpcap_handle == NULL) {
|
if (libpcap_handle == NULL) {
|
||||||
@@ -451,7 +449,7 @@ net_pcap_init(const netcard_t *card, const uint8_t *mac_addr, void *priv)
|
|||||||
pcap_log("PCAP: interface: %s\n", intf_name);
|
pcap_log("PCAP: interface: %s\n", intf_name);
|
||||||
|
|
||||||
net_pcap_t *pcap = calloc(1, sizeof(net_pcap_t));
|
net_pcap_t *pcap = calloc(1, sizeof(net_pcap_t));
|
||||||
pcap->card = (netcard_t *)card;
|
pcap->card = (netcard_t *) card;
|
||||||
memcpy(pcap->mac_addr, mac_addr, sizeof(pcap->mac_addr));
|
memcpy(pcap->mac_addr, mac_addr, sizeof(pcap->mac_addr));
|
||||||
|
|
||||||
if ((pcap->pcap = f_pcap_create(intf_name, errbuf)) == NULL) {
|
if ((pcap->pcap = f_pcap_create(intf_name, errbuf)) == NULL) {
|
||||||
@@ -494,7 +492,7 @@ net_pcap_init(const netcard_t *card, const uint8_t *mac_addr, void *priv)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pcap_log("PCAP: could not compile filter (%s) : %s!\n", filter_exp, f_pcap_geterr((void*)pcap->pcap));
|
pcap_log("PCAP: could not compile filter (%s) : %s!\n", filter_exp, f_pcap_geterr((void *) pcap->pcap));
|
||||||
f_pcap_close((void *) pcap->pcap);
|
f_pcap_close((void *) pcap->pcap);
|
||||||
free(pcap);
|
free(pcap);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -523,7 +521,7 @@ net_pcap_close(void *priv)
|
|||||||
if (!priv)
|
if (!priv)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
net_pcap_t *pcap = (net_pcap_t *)priv;
|
net_pcap_t *pcap = (net_pcap_t *) priv;
|
||||||
|
|
||||||
pcap_log("PCAP: closing.\n");
|
pcap_log("PCAP: closing.\n");
|
||||||
|
|
||||||
@@ -541,10 +539,10 @@ net_pcap_close(void *priv)
|
|||||||
free(pcap->pkt.data);
|
free(pcap->pkt.data);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
f_pcap_sendqueue_destroy((void*)pcap->pcap_queue);
|
f_pcap_sendqueue_destroy((void *) pcap->pcap_queue);
|
||||||
#endif
|
#endif
|
||||||
/* OK, now shut down Pcap itself. */
|
/* OK, now shut down Pcap itself. */
|
||||||
f_pcap_close((void*)pcap->pcap);
|
f_pcap_close((void *) pcap->pcap);
|
||||||
|
|
||||||
net_event_close(&pcap->tx_event);
|
net_event_close(&pcap->tx_event);
|
||||||
net_event_close(&pcap->stop_event);
|
net_event_close(&pcap->stop_event);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -36,9 +36,8 @@
|
|||||||
#include <86box/network.h>
|
#include <86box/network.h>
|
||||||
#include <86box/net_plip.h>
|
#include <86box/net_plip.h>
|
||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
PLIP_START = 0x00,
|
PLIP_START = 0x00,
|
||||||
PLIP_TX_LEN_LSB_LOW = 0x10,
|
PLIP_TX_LEN_LSB_LOW = 0x10,
|
||||||
PLIP_TX_LEN_LSB_HIGH,
|
PLIP_TX_LEN_LSB_HIGH,
|
||||||
PLIP_TX_LEN_MSB_LOW,
|
PLIP_TX_LEN_MSB_LOW,
|
||||||
@@ -60,26 +59,24 @@ enum {
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint8_t mac[6];
|
uint8_t mac[6];
|
||||||
|
|
||||||
void *lpt;
|
void *lpt;
|
||||||
pc_timer_t rx_timer;
|
pc_timer_t rx_timer;
|
||||||
pc_timer_t timeout_timer;
|
pc_timer_t timeout_timer;
|
||||||
uint8_t status, ctrl;
|
uint8_t status, ctrl;
|
||||||
|
|
||||||
uint8_t state, ack, tx_checksum, tx_checksum_calc, *tx_pkt;
|
uint8_t state, ack, tx_checksum, tx_checksum_calc, *tx_pkt;
|
||||||
uint16_t tx_len, tx_ptr;
|
uint16_t tx_len, tx_ptr;
|
||||||
|
|
||||||
uint8_t *rx_pkt, rx_checksum, rx_return_state;
|
uint8_t *rx_pkt, rx_checksum, rx_return_state;
|
||||||
uint16_t rx_len, rx_ptr;
|
uint16_t rx_len, rx_ptr;
|
||||||
netcard_t *card;
|
netcard_t *card;
|
||||||
} plip_t;
|
} plip_t;
|
||||||
|
|
||||||
|
static void plip_receive_packet(plip_t *dev);
|
||||||
|
|
||||||
static void plip_receive_packet(plip_t *dev);
|
plip_t *instance;
|
||||||
|
|
||||||
plip_t *instance;
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENABLE_PLIP_LOG
|
#ifdef ENABLE_PLIP_LOG
|
||||||
int plip_do_log = ENABLE_PLIP_LOG;
|
int plip_do_log = ENABLE_PLIP_LOG;
|
||||||
@@ -90,16 +87,15 @@ plip_log(uint8_t lvl, const char *fmt, ...)
|
|||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (plip_do_log >= lvl) {
|
if (plip_do_log >= lvl) {
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
pclog_ex(fmt, ap);
|
pclog_ex(fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define plip_log(lvl, fmt, ...)
|
# define plip_log(lvl, fmt, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
timeout_timer(void *priv)
|
timeout_timer(void *priv)
|
||||||
{
|
{
|
||||||
@@ -108,22 +104,21 @@ timeout_timer(void *priv)
|
|||||||
plip_log(1, "PLIP: timeout at state %d status %02X\n", dev->state, dev->status);
|
plip_log(1, "PLIP: timeout at state %d status %02X\n", dev->state, dev->status);
|
||||||
|
|
||||||
/* Throw everything out the window. */
|
/* Throw everything out the window. */
|
||||||
dev->state = PLIP_START;
|
dev->state = PLIP_START;
|
||||||
dev->status = 0x80;
|
dev->status = 0x80;
|
||||||
|
|
||||||
if (dev->tx_pkt) {
|
if (dev->tx_pkt) {
|
||||||
free(dev->tx_pkt);
|
free(dev->tx_pkt);
|
||||||
dev->tx_pkt = NULL;
|
dev->tx_pkt = NULL;
|
||||||
}
|
}
|
||||||
if (dev->rx_pkt) {
|
if (dev->rx_pkt) {
|
||||||
free(dev->rx_pkt);
|
free(dev->rx_pkt);
|
||||||
dev->rx_pkt = NULL;
|
dev->rx_pkt = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
timer_disable(&dev->timeout_timer);
|
timer_disable(&dev->timeout_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
plip_write_data(uint8_t val, void *priv)
|
plip_write_data(uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
@@ -132,220 +127,219 @@ plip_write_data(uint8_t val, void *priv)
|
|||||||
plip_log(3, "PLIP: write_data(%02X)\n", val);
|
plip_log(3, "PLIP: write_data(%02X)\n", val);
|
||||||
|
|
||||||
switch (dev->state) {
|
switch (dev->state) {
|
||||||
case PLIP_START:
|
case PLIP_START:
|
||||||
if (val == 0x08) { /* D3/ACK wakes us up */
|
if (val == 0x08) { /* D3/ACK wakes us up */
|
||||||
plip_log(2, "PLIP: ACK wakeup\n");
|
plip_log(2, "PLIP: ACK wakeup\n");
|
||||||
dev->state = PLIP_TX_LEN_LSB_LOW;
|
dev->state = PLIP_TX_LEN_LSB_LOW;
|
||||||
dev->status = 0x08;
|
dev->status = 0x08;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case PLIP_TX_LEN_LSB_LOW:
|
case PLIP_TX_LEN_LSB_LOW:
|
||||||
if (!(val & 0x10))
|
if (!(val & 0x10))
|
||||||
return; /* D4/BUSY not high yet */
|
return; /* D4/BUSY not high yet */
|
||||||
dev->tx_len = val & 0xf;
|
dev->tx_len = val & 0xf;
|
||||||
plip_log(2, "PLIP: tx_len = %04X (1/4)\n", dev->tx_len);
|
plip_log(2, "PLIP: tx_len = %04X (1/4)\n", dev->tx_len);
|
||||||
dev->state = PLIP_TX_LEN_LSB_HIGH;
|
dev->state = PLIP_TX_LEN_LSB_HIGH;
|
||||||
dev->status &= ~0x88;
|
dev->status &= ~0x88;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PLIP_TX_LEN_LSB_HIGH:
|
case PLIP_TX_LEN_LSB_HIGH:
|
||||||
if (val & 0x10)
|
if (val & 0x10)
|
||||||
return; /* D4/BUSY not low yet */
|
return; /* D4/BUSY not low yet */
|
||||||
dev->tx_len |= (val & 0xf) << 4;
|
dev->tx_len |= (val & 0xf) << 4;
|
||||||
plip_log(2, "PLIP: tx_len = %04X (2/4)\n", dev->tx_len);
|
plip_log(2, "PLIP: tx_len = %04X (2/4)\n", dev->tx_len);
|
||||||
dev->state = PLIP_TX_LEN_MSB_LOW;
|
dev->state = PLIP_TX_LEN_MSB_LOW;
|
||||||
dev->status |= 0x80;
|
dev->status |= 0x80;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PLIP_TX_LEN_MSB_LOW:
|
case PLIP_TX_LEN_MSB_LOW:
|
||||||
if (!(val & 0x10))
|
if (!(val & 0x10))
|
||||||
return; /* D4/BUSY not high yet */
|
return; /* D4/BUSY not high yet */
|
||||||
dev->tx_len |= (val & 0xf) << 8;
|
dev->tx_len |= (val & 0xf) << 8;
|
||||||
plip_log(2, "PLIP: tx_len = %04X (3/4)\n", dev->tx_len);
|
plip_log(2, "PLIP: tx_len = %04X (3/4)\n", dev->tx_len);
|
||||||
dev->state = PLIP_TX_LEN_MSB_HIGH;
|
dev->state = PLIP_TX_LEN_MSB_HIGH;
|
||||||
dev->status &= ~0x80;
|
dev->status &= ~0x80;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PLIP_TX_LEN_MSB_HIGH:
|
case PLIP_TX_LEN_MSB_HIGH:
|
||||||
if (val & 0x10)
|
if (val & 0x10)
|
||||||
return; /* D4/BUSY not low yet */
|
return; /* D4/BUSY not low yet */
|
||||||
dev->tx_len |= (val & 0xf) << 12;
|
dev->tx_len |= (val & 0xf) << 12;
|
||||||
plip_log(2, "PLIP: tx_len = %04X (4/4)\n", dev->tx_len);
|
plip_log(2, "PLIP: tx_len = %04X (4/4)\n", dev->tx_len);
|
||||||
|
|
||||||
/* We have the length, allocate a packet. */
|
/* We have the length, allocate a packet. */
|
||||||
if (!(dev->tx_pkt = malloc(dev->tx_len))) /* unlikely */
|
if (!(dev->tx_pkt = malloc(dev->tx_len))) /* unlikely */
|
||||||
fatal("PLIP: unable to allocate tx_pkt\n");
|
fatal("PLIP: unable to allocate tx_pkt\n");
|
||||||
dev->tx_ptr = 0;
|
dev->tx_ptr = 0;
|
||||||
dev->tx_checksum_calc = 0;
|
dev->tx_checksum_calc = 0;
|
||||||
|
|
||||||
dev->state = PLIP_TX_DATA_LOW;
|
dev->state = PLIP_TX_DATA_LOW;
|
||||||
dev->status |= 0x80;
|
dev->status |= 0x80;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PLIP_TX_DATA_LOW:
|
case PLIP_TX_DATA_LOW:
|
||||||
if (!(val & 0x10))
|
if (!(val & 0x10))
|
||||||
return; /* D4/BUSY not high yet */
|
return; /* D4/BUSY not high yet */
|
||||||
dev->tx_pkt[dev->tx_ptr] = val & 0x0f;
|
dev->tx_pkt[dev->tx_ptr] = val & 0x0f;
|
||||||
plip_log(2, "PLIP: tx_pkt[%d] = %02X (1/2)\n", dev->tx_ptr, dev->tx_pkt[dev->tx_ptr]);
|
plip_log(2, "PLIP: tx_pkt[%d] = %02X (1/2)\n", dev->tx_ptr, dev->tx_pkt[dev->tx_ptr]);
|
||||||
dev->state = PLIP_TX_DATA_HIGH;
|
dev->state = PLIP_TX_DATA_HIGH;
|
||||||
dev->status &= ~0x80;
|
dev->status &= ~0x80;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PLIP_TX_DATA_HIGH:
|
case PLIP_TX_DATA_HIGH:
|
||||||
if (val & 0x10)
|
if (val & 0x10)
|
||||||
return; /* D4/BUSY not low yet */
|
return; /* D4/BUSY not low yet */
|
||||||
dev->tx_pkt[dev->tx_ptr] |= (val & 0x0f) << 4;
|
dev->tx_pkt[dev->tx_ptr] |= (val & 0x0f) << 4;
|
||||||
plip_log(2, "PLIP: tx_pkt[%d] = %02X (2/2)\n", dev->tx_ptr, dev->tx_pkt[dev->tx_ptr]);
|
plip_log(2, "PLIP: tx_pkt[%d] = %02X (2/2)\n", dev->tx_ptr, dev->tx_pkt[dev->tx_ptr]);
|
||||||
dev->tx_checksum_calc += dev->tx_pkt[dev->tx_ptr++];
|
dev->tx_checksum_calc += dev->tx_pkt[dev->tx_ptr++];
|
||||||
|
|
||||||
/* Are we done yet? */
|
/* Are we done yet? */
|
||||||
if (dev->tx_ptr < dev->tx_len) /* no, receive another byte */
|
if (dev->tx_ptr < dev->tx_len) /* no, receive another byte */
|
||||||
dev->state = PLIP_TX_DATA_LOW;
|
dev->state = PLIP_TX_DATA_LOW;
|
||||||
else /* yes, move on to checksum */
|
else /* yes, move on to checksum */
|
||||||
dev->state = PLIP_TX_CHECKSUM_LOW;
|
dev->state = PLIP_TX_CHECKSUM_LOW;
|
||||||
dev->status |= 0x80;
|
dev->status |= 0x80;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PLIP_TX_CHECKSUM_LOW:
|
case PLIP_TX_CHECKSUM_LOW:
|
||||||
if (!(val & 0x10))
|
if (!(val & 0x10))
|
||||||
return; /* D4/BUSY not high yet */
|
return; /* D4/BUSY not high yet */
|
||||||
dev->tx_checksum = val & 0x0f;
|
dev->tx_checksum = val & 0x0f;
|
||||||
plip_log(2, "PLIP: tx_checksum = %02X (1/2)\n", dev->tx_checksum);
|
plip_log(2, "PLIP: tx_checksum = %02X (1/2)\n", dev->tx_checksum);
|
||||||
dev->state = PLIP_TX_CHECKSUM_HIGH;
|
dev->state = PLIP_TX_CHECKSUM_HIGH;
|
||||||
dev->status &= ~0x80;
|
dev->status &= ~0x80;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PLIP_TX_CHECKSUM_HIGH:
|
case PLIP_TX_CHECKSUM_HIGH:
|
||||||
if (val & 0x10)
|
if (val & 0x10)
|
||||||
return; /* D4/BUSY not low yet */
|
return; /* D4/BUSY not low yet */
|
||||||
dev->tx_checksum |= (val & 0x0f) << 4;
|
dev->tx_checksum |= (val & 0x0f) << 4;
|
||||||
plip_log(2, "PLIP: tx_checksum = %02X (2/2)\n", dev->tx_checksum);
|
plip_log(2, "PLIP: tx_checksum = %02X (2/2)\n", dev->tx_checksum);
|
||||||
|
|
||||||
/* Verify checksum. */
|
/* Verify checksum. */
|
||||||
if (dev->tx_checksum_calc == dev->tx_checksum) {
|
if (dev->tx_checksum_calc == dev->tx_checksum) {
|
||||||
/* Make sure we know the other end's MAC address. */
|
/* Make sure we know the other end's MAC address. */
|
||||||
memcpy(dev->mac, dev->tx_pkt + 6, 6);
|
memcpy(dev->mac, dev->tx_pkt + 6, 6);
|
||||||
|
|
||||||
/* Transmit packet. */
|
/* Transmit packet. */
|
||||||
plip_log(2, "PLIP: transmitting %d-byte packet\n", dev->tx_len);
|
plip_log(2, "PLIP: transmitting %d-byte packet\n", dev->tx_len);
|
||||||
network_tx(dev->card, dev->tx_pkt, dev->tx_len);
|
network_tx(dev->card, dev->tx_pkt, dev->tx_len);
|
||||||
} else {
|
} else {
|
||||||
plip_log(1, "PLIP: checksum error: expected %02X, got %02X\n", dev->tx_checksum_calc, dev->tx_checksum);
|
plip_log(1, "PLIP: checksum error: expected %02X, got %02X\n", dev->tx_checksum_calc, dev->tx_checksum);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We're done with this packet. */
|
/* We're done with this packet. */
|
||||||
free(dev->tx_pkt);
|
free(dev->tx_pkt);
|
||||||
dev->tx_pkt = NULL;
|
dev->tx_pkt = NULL;
|
||||||
dev->tx_len = 0;
|
dev->tx_len = 0;
|
||||||
|
|
||||||
dev->state = PLIP_END;
|
dev->state = PLIP_END;
|
||||||
dev->status |= 0x80;
|
dev->status |= 0x80;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PLIP_RX_LEN_LSB_LOW:
|
case PLIP_RX_LEN_LSB_LOW:
|
||||||
if (!(val & 0x01))
|
if (!(val & 0x01))
|
||||||
return; /* D3/ACK not high yet */
|
return; /* D3/ACK not high yet */
|
||||||
plip_log(2, "PLIP: rx_len = %04X (1/4)\n", dev->rx_len);
|
plip_log(2, "PLIP: rx_len = %04X (1/4)\n", dev->rx_len);
|
||||||
dev->status = (dev->rx_len & 0x0f) << 3;
|
dev->status = (dev->rx_len & 0x0f) << 3;
|
||||||
dev->state = PLIP_RX_LEN_LSB_HIGH;
|
dev->state = PLIP_RX_LEN_LSB_HIGH;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PLIP_RX_LEN_LSB_HIGH:
|
case PLIP_RX_LEN_LSB_HIGH:
|
||||||
if (!(val & 0x10))
|
if (!(val & 0x10))
|
||||||
return; /* D4/BUSY not high yet */
|
return; /* D4/BUSY not high yet */
|
||||||
plip_log(2, "PLIP: rx_len = %04X (2/4)\n", dev->rx_len);
|
plip_log(2, "PLIP: rx_len = %04X (2/4)\n", dev->rx_len);
|
||||||
dev->status = ((dev->rx_len >> 4) & 0x0f) << 3;
|
dev->status = ((dev->rx_len >> 4) & 0x0f) << 3;
|
||||||
dev->status |= 0x80;
|
dev->status |= 0x80;
|
||||||
dev->state = PLIP_RX_LEN_MSB_LOW;
|
dev->state = PLIP_RX_LEN_MSB_LOW;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PLIP_RX_LEN_MSB_LOW:
|
case PLIP_RX_LEN_MSB_LOW:
|
||||||
if (val & 0x10)
|
if (val & 0x10)
|
||||||
return; /* D4/BUSY not low yet */
|
return; /* D4/BUSY not low yet */
|
||||||
plip_log(2, "PLIP: rx_len = %04X (3/4)\n", dev->rx_len);
|
plip_log(2, "PLIP: rx_len = %04X (3/4)\n", dev->rx_len);
|
||||||
dev->status = ((dev->rx_len >> 8) & 0x0f) << 3;
|
dev->status = ((dev->rx_len >> 8) & 0x0f) << 3;
|
||||||
dev->state = PLIP_RX_LEN_MSB_HIGH;
|
dev->state = PLIP_RX_LEN_MSB_HIGH;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PLIP_RX_LEN_MSB_HIGH:
|
case PLIP_RX_LEN_MSB_HIGH:
|
||||||
if (!(val & 0x10))
|
if (!(val & 0x10))
|
||||||
return; /* D4/BUSY not high yet */
|
return; /* D4/BUSY not high yet */
|
||||||
plip_log(2, "PLIP: rx_len = %04X (4/4)\n", dev->rx_len);
|
plip_log(2, "PLIP: rx_len = %04X (4/4)\n", dev->rx_len);
|
||||||
dev->status = ((dev->rx_len >> 12) & 0x0f) << 3;
|
dev->status = ((dev->rx_len >> 12) & 0x0f) << 3;
|
||||||
dev->status |= 0x80;
|
dev->status |= 0x80;
|
||||||
|
|
||||||
dev->rx_ptr = 0;
|
dev->rx_ptr = 0;
|
||||||
dev->rx_checksum = 0;
|
dev->rx_checksum = 0;
|
||||||
dev->state = PLIP_RX_DATA_LOW;
|
dev->state = PLIP_RX_DATA_LOW;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PLIP_RX_DATA_LOW:
|
case PLIP_RX_DATA_LOW:
|
||||||
if (val & 0x10)
|
if (val & 0x10)
|
||||||
return; /* D4/BUSY not low yet */
|
return; /* D4/BUSY not low yet */
|
||||||
plip_log(2, "PLIP: rx_pkt[%d] = %02X (1/2)\n", dev->rx_ptr, dev->rx_pkt[dev->rx_ptr]);
|
plip_log(2, "PLIP: rx_pkt[%d] = %02X (1/2)\n", dev->rx_ptr, dev->rx_pkt[dev->rx_ptr]);
|
||||||
dev->status = (dev->rx_pkt[dev->rx_ptr] & 0x0f) << 3;
|
dev->status = (dev->rx_pkt[dev->rx_ptr] & 0x0f) << 3;
|
||||||
dev->state = PLIP_RX_DATA_HIGH;
|
dev->state = PLIP_RX_DATA_HIGH;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PLIP_RX_DATA_HIGH:
|
case PLIP_RX_DATA_HIGH:
|
||||||
if (!(val & 0x10))
|
if (!(val & 0x10))
|
||||||
return; /* D4/BUSY not high yet */
|
return; /* D4/BUSY not high yet */
|
||||||
plip_log(2, "PLIP: rx_pkt[%d] = %02X (2/2)\n", dev->rx_ptr, dev->rx_pkt[dev->rx_ptr]);
|
plip_log(2, "PLIP: rx_pkt[%d] = %02X (2/2)\n", dev->rx_ptr, dev->rx_pkt[dev->rx_ptr]);
|
||||||
dev->status = ((dev->rx_pkt[dev->rx_ptr] >> 4) & 0x0f) << 3;
|
dev->status = ((dev->rx_pkt[dev->rx_ptr] >> 4) & 0x0f) << 3;
|
||||||
dev->status |= 0x80;
|
dev->status |= 0x80;
|
||||||
dev->rx_checksum += dev->rx_pkt[dev->rx_ptr++];
|
dev->rx_checksum += dev->rx_pkt[dev->rx_ptr++];
|
||||||
|
|
||||||
/* Are we done yet? */
|
/* Are we done yet? */
|
||||||
if (dev->rx_ptr < dev->rx_len) /* no, send another byte */
|
if (dev->rx_ptr < dev->rx_len) /* no, send another byte */
|
||||||
dev->state = PLIP_RX_DATA_LOW;
|
dev->state = PLIP_RX_DATA_LOW;
|
||||||
else /* yes, move on to checksum */
|
else /* yes, move on to checksum */
|
||||||
dev->state = PLIP_RX_CHECKSUM_LOW;
|
dev->state = PLIP_RX_CHECKSUM_LOW;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PLIP_RX_CHECKSUM_LOW:
|
case PLIP_RX_CHECKSUM_LOW:
|
||||||
if (val & 0x10)
|
if (val & 0x10)
|
||||||
return; /* D4/BUSY not low yet */
|
return; /* D4/BUSY not low yet */
|
||||||
plip_log(2, "PLIP: rx_checksum = %02X (1/2)\n", dev->rx_checksum);
|
plip_log(2, "PLIP: rx_checksum = %02X (1/2)\n", dev->rx_checksum);
|
||||||
dev->status = (dev->rx_checksum & 0x0f) << 3;
|
dev->status = (dev->rx_checksum & 0x0f) << 3;
|
||||||
dev->state = PLIP_RX_CHECKSUM_HIGH;
|
dev->state = PLIP_RX_CHECKSUM_HIGH;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PLIP_RX_CHECKSUM_HIGH:
|
case PLIP_RX_CHECKSUM_HIGH:
|
||||||
if (!(val & 0x10))
|
if (!(val & 0x10))
|
||||||
return; /* D4/BUSY not high yet */
|
return; /* D4/BUSY not high yet */
|
||||||
plip_log(2, "PLIP: rx_checksum = %02X (2/2)\n", dev->rx_checksum);
|
plip_log(2, "PLIP: rx_checksum = %02X (2/2)\n", dev->rx_checksum);
|
||||||
dev->status = ((dev->rx_checksum >> 4) & 0x0f) << 3;
|
dev->status = ((dev->rx_checksum >> 4) & 0x0f) << 3;
|
||||||
dev->status |= 0x80;
|
dev->status |= 0x80;
|
||||||
|
|
||||||
/* We're done with this packet. */
|
/* We're done with this packet. */
|
||||||
free(dev->rx_pkt);
|
free(dev->rx_pkt);
|
||||||
dev->rx_pkt = NULL;
|
dev->rx_pkt = NULL;
|
||||||
dev->rx_len = 0;
|
dev->rx_len = 0;
|
||||||
|
|
||||||
dev->state = PLIP_END;
|
dev->state = PLIP_END;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PLIP_END:
|
case PLIP_END:
|
||||||
if (val == 0x00) { /* written after TX or RX is done */
|
if (val == 0x00) { /* written after TX or RX is done */
|
||||||
plip_log(2, "PLIP: end\n");
|
plip_log(2, "PLIP: end\n");
|
||||||
dev->status = 0x80;
|
dev->status = 0x80;
|
||||||
dev->state = PLIP_START;
|
dev->state = PLIP_START;
|
||||||
|
|
||||||
timer_set_delay_u64(&dev->rx_timer, ISACONST); /* for DOS */
|
timer_set_delay_u64(&dev->rx_timer, ISACONST); /* for DOS */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disengage timeout timer. */
|
/* Disengage timeout timer. */
|
||||||
timer_disable(&dev->timeout_timer);
|
timer_disable(&dev->timeout_timer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Engage timeout timer unless otherwise specified. */
|
/* Engage timeout timer unless otherwise specified. */
|
||||||
timer_set_delay_u64(&dev->timeout_timer, 1000000 * TIMER_USEC);
|
timer_set_delay_u64(&dev->timeout_timer, 1000000 * TIMER_USEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
plip_write_ctrl(uint8_t val, void *priv)
|
plip_write_ctrl(uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
@@ -356,10 +350,9 @@ plip_write_ctrl(uint8_t val, void *priv)
|
|||||||
dev->ctrl = val;
|
dev->ctrl = val;
|
||||||
|
|
||||||
if (val & 0x10) /* for Linux */
|
if (val & 0x10) /* for Linux */
|
||||||
timer_set_delay_u64(&dev->rx_timer, ISACONST);
|
timer_set_delay_u64(&dev->rx_timer, ISACONST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
plip_read_status(void *priv)
|
plip_read_status(void *priv)
|
||||||
{
|
{
|
||||||
@@ -370,31 +363,30 @@ plip_read_status(void *priv)
|
|||||||
return dev->status;
|
return dev->status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
plip_receive_packet(plip_t *dev)
|
plip_receive_packet(plip_t *dev)
|
||||||
{
|
{
|
||||||
/* At least the Linux driver supports being interrupted
|
/* At least the Linux driver supports being interrupted
|
||||||
in the PLIP_TX_LEN_LSB_LOW state, but let's be safe. */
|
in the PLIP_TX_LEN_LSB_LOW state, but let's be safe. */
|
||||||
if (dev->state > PLIP_START) {
|
if (dev->state > PLIP_START) {
|
||||||
plip_log(3, "PLIP: cannot receive, operation already in progress\n");
|
plip_log(3, "PLIP: cannot receive, operation already in progress\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dev->rx_pkt || !dev->rx_len) { /* unpause RX queue if there's no packet to receive */
|
if (!dev->rx_pkt || !dev->rx_len) { /* unpause RX queue if there's no packet to receive */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(dev->ctrl & 0x10)) { /* checking this is essential to avoid collisions */
|
if (!(dev->ctrl & 0x10)) { /* checking this is essential to avoid collisions */
|
||||||
plip_log(3, "PLIP: cannot receive, interrupts are off\n");
|
plip_log(3, "PLIP: cannot receive, interrupts are off\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
plip_log(2, "PLIP: receiving %d-byte packet\n", dev->rx_len);
|
plip_log(2, "PLIP: receiving %d-byte packet\n", dev->rx_len);
|
||||||
|
|
||||||
/* Set up to receive a packet. */
|
/* Set up to receive a packet. */
|
||||||
dev->status = 0xc7; /* DOS expects exactly 0xc7, while Linux masks the 7 off */
|
dev->status = 0xc7; /* DOS expects exactly 0xc7, while Linux masks the 7 off */
|
||||||
dev->state = PLIP_RX_LEN_LSB_LOW;
|
dev->state = PLIP_RX_LEN_LSB_LOW;
|
||||||
|
|
||||||
/* Engage timeout timer. */
|
/* Engage timeout timer. */
|
||||||
timer_set_delay_u64(&dev->timeout_timer, 1000000 * TIMER_USEC);
|
timer_set_delay_u64(&dev->timeout_timer, 1000000 * TIMER_USEC);
|
||||||
@@ -403,7 +395,6 @@ plip_receive_packet(plip_t *dev)
|
|||||||
lpt_irq(dev->lpt, 1);
|
lpt_irq(dev->lpt, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This timer defers a call to plip_receive_packet to
|
/* This timer defers a call to plip_receive_packet to
|
||||||
the next ISA clock, in order to avoid IRQ weirdness. */
|
the next ISA clock, in order to avoid IRQ weirdness. */
|
||||||
static void
|
static void
|
||||||
@@ -416,7 +407,6 @@ rx_timer(void *priv)
|
|||||||
timer_disable(&dev->rx_timer);
|
timer_disable(&dev->rx_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
plip_rx(void *priv, uint8_t *buf, int io_len)
|
plip_rx(void *priv, uint8_t *buf, int io_len)
|
||||||
{
|
{
|
||||||
@@ -425,12 +415,12 @@ plip_rx(void *priv, uint8_t *buf, int io_len)
|
|||||||
plip_log(2, "PLIP: incoming %d-byte packet\n", io_len);
|
plip_log(2, "PLIP: incoming %d-byte packet\n", io_len);
|
||||||
|
|
||||||
if (dev->rx_pkt) { /* shouldn't really happen with the RX queue paused */
|
if (dev->rx_pkt) { /* shouldn't really happen with the RX queue paused */
|
||||||
plip_log(3, "PLIP: already have a packet to receive");
|
plip_log(3, "PLIP: already have a packet to receive");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(dev->rx_pkt = malloc(io_len))) /* unlikely */
|
if (!(dev->rx_pkt = malloc(io_len))) /* unlikely */
|
||||||
fatal("PLIP: unable to allocate rx_pkt\n");
|
fatal("PLIP: unable to allocate rx_pkt\n");
|
||||||
|
|
||||||
/* Copy this packet to our buffer. */
|
/* Copy this packet to our buffer. */
|
||||||
dev->rx_len = io_len;
|
dev->rx_len = io_len;
|
||||||
@@ -442,7 +432,6 @@ plip_rx(void *priv, uint8_t *buf, int io_len)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
plip_lpt_init(void *lpt)
|
plip_lpt_init(void *lpt)
|
||||||
{
|
{
|
||||||
@@ -464,15 +453,14 @@ plip_lpt_init(void *lpt)
|
|||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
plip_net_init(const device_t *info)
|
plip_net_init(const device_t *info)
|
||||||
{
|
{
|
||||||
plip_log(1, "PLIP: net_init()");
|
plip_log(1, "PLIP: net_init()");
|
||||||
|
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
plip_log(1, " (not attached to LPT)\n");
|
plip_log(1, " (not attached to LPT)\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
plip_log(1, " (attached to LPT)\n");
|
plip_log(1, " (attached to LPT)\n");
|
||||||
@@ -481,38 +469,37 @@ plip_net_init(const device_t *info)
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
plip_close(void *priv)
|
plip_close(void *priv)
|
||||||
{
|
{
|
||||||
if (instance->card) {
|
if (instance->card) {
|
||||||
netcard_close(instance->card);
|
netcard_close(instance->card);
|
||||||
}
|
}
|
||||||
free(priv);
|
free(priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
const lpt_device_t lpt_plip_device = {
|
const lpt_device_t lpt_plip_device = {
|
||||||
.name = "Parallel Line Internet Protocol",
|
.name = "Parallel Line Internet Protocol",
|
||||||
.internal_name = "plip",
|
.internal_name = "plip",
|
||||||
.init = plip_lpt_init,
|
.init = plip_lpt_init,
|
||||||
.close = plip_close,
|
.close = plip_close,
|
||||||
.write_data = plip_write_data,
|
.write_data = plip_write_data,
|
||||||
.write_ctrl = plip_write_ctrl,
|
.write_ctrl = plip_write_ctrl,
|
||||||
.read_data = NULL,
|
.read_data = NULL,
|
||||||
.read_status = plip_read_status,
|
.read_status = plip_read_status,
|
||||||
.read_ctrl = NULL
|
.read_ctrl = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const device_t plip_device = {
|
const device_t plip_device = {
|
||||||
.name = "Parallel Line Internet Protocol",
|
.name = "Parallel Line Internet Protocol",
|
||||||
.internal_name = "plip",
|
.internal_name = "plip",
|
||||||
.flags = DEVICE_LPT,
|
.flags = DEVICE_LPT,
|
||||||
.local = 0,
|
.local = 0,
|
||||||
.init = plip_net_init,
|
.init = plip_net_init,
|
||||||
.close = NULL,
|
.close = NULL,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
@@ -39,10 +39,10 @@
|
|||||||
#include <86box/config.h>
|
#include <86box/config.h>
|
||||||
#include <86box/video.h>
|
#include <86box/video.h>
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define WIN32_LEAN_AND_MEAN
|
# define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
# include <windows.h>
|
||||||
#else
|
#else
|
||||||
#include <poll.h>
|
# include <poll.h>
|
||||||
#endif
|
#endif
|
||||||
#include <86box/net_event.h>
|
#include <86box/net_event.h>
|
||||||
|
|
||||||
@@ -75,37 +75,33 @@ typedef struct {
|
|||||||
#ifdef ENABLE_SLIRP_LOG
|
#ifdef ENABLE_SLIRP_LOG
|
||||||
int slirp_do_log = ENABLE_SLIRP_LOG;
|
int slirp_do_log = ENABLE_SLIRP_LOG;
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
slirp_log(const char *fmt, ...)
|
slirp_log(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (slirp_do_log) {
|
if (slirp_do_log) {
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
pclog_ex(fmt, ap);
|
pclog_ex(fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define slirp_log(fmt, ...)
|
# define slirp_log(fmt, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
net_slirp_guest_error(const char *msg, void *opaque)
|
net_slirp_guest_error(const char *msg, void *opaque)
|
||||||
{
|
{
|
||||||
slirp_log("SLiRP: guest_error(): %s\n", msg);
|
slirp_log("SLiRP: guest_error(): %s\n", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int64_t
|
static int64_t
|
||||||
net_slirp_clock_get_ns(void *opaque)
|
net_slirp_clock_get_ns(void *opaque)
|
||||||
{
|
{
|
||||||
return (int64_t)((double)tsc / cpuclock * 1000000000.0);
|
return (int64_t) ((double) tsc / cpuclock * 1000000000.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
net_slirp_timer_new(SlirpTimerCb cb, void *cb_opaque, void *opaque)
|
net_slirp_timer_new(SlirpTimerCb cb, void *cb_opaque, void *opaque)
|
||||||
{
|
{
|
||||||
@@ -114,7 +110,6 @@ net_slirp_timer_new(SlirpTimerCb cb, void *cb_opaque, void *opaque)
|
|||||||
return timer;
|
return timer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
net_slirp_timer_free(void *timer, void *opaque)
|
net_slirp_timer_free(void *timer, void *opaque)
|
||||||
{
|
{
|
||||||
@@ -122,14 +117,12 @@ net_slirp_timer_free(void *timer, void *opaque)
|
|||||||
free(timer);
|
free(timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
net_slirp_timer_mod(void *timer, int64_t expire_timer, void *opaque)
|
net_slirp_timer_mod(void *timer, int64_t expire_timer, void *opaque)
|
||||||
{
|
{
|
||||||
timer_on_auto(timer, expire_timer * 1000);
|
timer_on_auto(timer, expire_timer * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
net_slirp_register_poll_fd(int fd, void *opaque)
|
net_slirp_register_poll_fd(int fd, void *opaque)
|
||||||
{
|
{
|
||||||
@@ -137,7 +130,6 @@ net_slirp_register_poll_fd(int fd, void *opaque)
|
|||||||
(void) opaque;
|
(void) opaque;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
net_slirp_unregister_poll_fd(int fd, void *opaque)
|
net_slirp_unregister_poll_fd(int fd, void *opaque)
|
||||||
{
|
{
|
||||||
@@ -145,14 +137,12 @@ net_slirp_unregister_poll_fd(int fd, void *opaque)
|
|||||||
(void) opaque;
|
(void) opaque;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
net_slirp_notify(void *opaque)
|
net_slirp_notify(void *opaque)
|
||||||
{
|
{
|
||||||
(void) opaque;
|
(void) opaque;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
net_slirp_send_packet(const void *qp, size_t pkt_len, void *opaque)
|
net_slirp_send_packet(const void *qp, size_t pkt_len, void *opaque)
|
||||||
{
|
{
|
||||||
@@ -160,20 +150,19 @@ net_slirp_send_packet(const void *qp, size_t pkt_len, void *opaque)
|
|||||||
|
|
||||||
slirp_log("SLiRP: received %d-byte packet\n", pkt_len);
|
slirp_log("SLiRP: received %d-byte packet\n", pkt_len);
|
||||||
|
|
||||||
memcpy(slirp->pkt.data, (uint8_t*) qp, pkt_len);
|
memcpy(slirp->pkt.data, (uint8_t *) qp, pkt_len);
|
||||||
slirp->pkt.len = pkt_len;
|
slirp->pkt.len = pkt_len;
|
||||||
network_rx_put_pkt(slirp->card, &slirp->pkt);
|
network_rx_put_pkt(slirp->card, &slirp->pkt);
|
||||||
|
|
||||||
return pkt_len;
|
return pkt_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static int
|
static int
|
||||||
net_slirp_add_poll(int fd, int events, void *opaque)
|
net_slirp_add_poll(int fd, int events, void *opaque)
|
||||||
{
|
{
|
||||||
net_slirp_t *slirp = (net_slirp_t *) opaque;
|
net_slirp_t *slirp = (net_slirp_t *) opaque;
|
||||||
long bitmask = 0;
|
long bitmask = 0;
|
||||||
if (events & SLIRP_POLL_IN)
|
if (events & SLIRP_POLL_IN)
|
||||||
bitmask |= FD_READ | FD_ACCEPT;
|
bitmask |= FD_READ | FD_ACCEPT;
|
||||||
if (events & SLIRP_POLL_OUT)
|
if (events & SLIRP_POLL_OUT)
|
||||||
@@ -193,17 +182,17 @@ net_slirp_add_poll(int fd, int events, void *opaque)
|
|||||||
net_slirp_t *slirp = (net_slirp_t *) opaque;
|
net_slirp_t *slirp = (net_slirp_t *) opaque;
|
||||||
|
|
||||||
if (slirp->pfd_len >= slirp->pfd_size) {
|
if (slirp->pfd_len >= slirp->pfd_size) {
|
||||||
int newsize = slirp->pfd_size + 16;
|
int newsize = slirp->pfd_size + 16;
|
||||||
struct pollfd *new = realloc(slirp->pfd, newsize * sizeof(struct pollfd));
|
struct pollfd *new = realloc(slirp->pfd, newsize * sizeof(struct pollfd));
|
||||||
if (new) {
|
if (new) {
|
||||||
slirp->pfd = new;
|
slirp->pfd = new;
|
||||||
slirp->pfd_size = newsize;
|
slirp->pfd_size = newsize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((slirp->pfd_len < slirp->pfd_size)) {
|
if ((slirp->pfd_len < slirp->pfd_size)) {
|
||||||
int idx = slirp->pfd_len++;
|
int idx = slirp->pfd_len++;
|
||||||
slirp->pfd[idx].fd = fd;
|
slirp->pfd[idx].fd = fd;
|
||||||
int pevents = 0;
|
int pevents = 0;
|
||||||
if (events & SLIRP_POLL_IN)
|
if (events & SLIRP_POLL_IN)
|
||||||
pevents |= POLLIN;
|
pevents |= POLLIN;
|
||||||
if (events & SLIRP_POLL_OUT)
|
if (events & SLIRP_POLL_OUT)
|
||||||
@@ -225,8 +214,8 @@ net_slirp_add_poll(int fd, int events, void *opaque)
|
|||||||
static int
|
static int
|
||||||
net_slirp_get_revents(int idx, void *opaque)
|
net_slirp_get_revents(int idx, void *opaque)
|
||||||
{
|
{
|
||||||
net_slirp_t *slirp = (net_slirp_t *) opaque;
|
net_slirp_t *slirp = (net_slirp_t *) opaque;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
WSANETWORKEVENTS ev;
|
WSANETWORKEVENTS ev;
|
||||||
if (WSAEnumNetworkEvents(idx, slirp->sock_event, &ev) != 0) {
|
if (WSAEnumNetworkEvents(idx, slirp->sock_event, &ev) != 0) {
|
||||||
return ret;
|
return ret;
|
||||||
@@ -242,9 +231,9 @@ net_slirp_get_revents(int idx, void *opaque)
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
WSA_TO_POLL(FD_READ, SLIRP_POLL_IN);
|
WSA_TO_POLL(FD_READ, SLIRP_POLL_IN);
|
||||||
WSA_TO_POLL(FD_ACCEPT, SLIRP_POLL_IN);
|
WSA_TO_POLL(FD_ACCEPT, SLIRP_POLL_IN);
|
||||||
WSA_TO_POLL(FD_WRITE, SLIRP_POLL_OUT);
|
WSA_TO_POLL(FD_WRITE, SLIRP_POLL_OUT);
|
||||||
WSA_TO_POLL(FD_CONNECT, SLIRP_POLL_OUT);
|
WSA_TO_POLL(FD_CONNECT, SLIRP_POLL_OUT);
|
||||||
WSA_TO_POLL(FD_OOB, SLIRP_POLL_PRI);
|
WSA_TO_POLL(FD_OOB, SLIRP_POLL_PRI);
|
||||||
WSA_TO_POLL(FD_CLOSE, SLIRP_POLL_HUP);
|
WSA_TO_POLL(FD_CLOSE, SLIRP_POLL_HUP);
|
||||||
@@ -255,9 +244,9 @@ net_slirp_get_revents(int idx, void *opaque)
|
|||||||
static int
|
static int
|
||||||
net_slirp_get_revents(int idx, void *opaque)
|
net_slirp_get_revents(int idx, void *opaque)
|
||||||
{
|
{
|
||||||
net_slirp_t *slirp = (net_slirp_t *) opaque;
|
net_slirp_t *slirp = (net_slirp_t *) opaque;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int events = slirp->pfd[idx].revents;
|
int events = slirp->pfd[idx].revents;
|
||||||
if (events & POLLIN)
|
if (events & POLLIN)
|
||||||
ret |= SLIRP_POLL_IN;
|
ret |= SLIRP_POLL_IN;
|
||||||
if (events & POLLOUT)
|
if (events & POLLOUT)
|
||||||
@@ -273,15 +262,15 @@ net_slirp_get_revents(int idx, void *opaque)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const SlirpCb slirp_cb = {
|
static const SlirpCb slirp_cb = {
|
||||||
.send_packet = net_slirp_send_packet,
|
.send_packet = net_slirp_send_packet,
|
||||||
.guest_error = net_slirp_guest_error,
|
.guest_error = net_slirp_guest_error,
|
||||||
.clock_get_ns = net_slirp_clock_get_ns,
|
.clock_get_ns = net_slirp_clock_get_ns,
|
||||||
.timer_new = net_slirp_timer_new,
|
.timer_new = net_slirp_timer_new,
|
||||||
.timer_free = net_slirp_timer_free,
|
.timer_free = net_slirp_timer_free,
|
||||||
.timer_mod = net_slirp_timer_mod,
|
.timer_mod = net_slirp_timer_mod,
|
||||||
.register_poll_fd = net_slirp_register_poll_fd,
|
.register_poll_fd = net_slirp_register_poll_fd,
|
||||||
.unregister_poll_fd = net_slirp_unregister_poll_fd,
|
.unregister_poll_fd = net_slirp_unregister_poll_fd,
|
||||||
.notify = net_slirp_notify
|
.notify = net_slirp_notify
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Send a packet to the SLiRP interface. */
|
/* Send a packet to the SLiRP interface. */
|
||||||
@@ -299,7 +288,7 @@ net_slirp_in(net_slirp_t *slirp, uint8_t *pkt, int pkt_len)
|
|||||||
void
|
void
|
||||||
net_slirp_in_available(void *priv)
|
net_slirp_in_available(void *priv)
|
||||||
{
|
{
|
||||||
net_slirp_t *slirp = (net_slirp_t *)priv;
|
net_slirp_t *slirp = (net_slirp_t *) priv;
|
||||||
net_event_set(&slirp->tx_event);
|
net_event_set(&slirp->tx_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,16 +303,16 @@ net_slirp_thread(void *priv)
|
|||||||
|
|
||||||
HANDLE events[3];
|
HANDLE events[3];
|
||||||
events[NET_EVENT_STOP] = net_event_get_handle(&slirp->stop_event);
|
events[NET_EVENT_STOP] = net_event_get_handle(&slirp->stop_event);
|
||||||
events[NET_EVENT_TX] = net_event_get_handle(&slirp->tx_event);
|
events[NET_EVENT_TX] = net_event_get_handle(&slirp->tx_event);
|
||||||
events[NET_EVENT_RX] = slirp->sock_event;
|
events[NET_EVENT_RX] = slirp->sock_event;
|
||||||
bool run = true;
|
bool run = true;
|
||||||
while (run) {
|
while (run) {
|
||||||
uint32_t timeout = -1;
|
uint32_t timeout = -1;
|
||||||
slirp_pollfds_fill(slirp->slirp, &timeout, net_slirp_add_poll, slirp);
|
slirp_pollfds_fill(slirp->slirp, &timeout, net_slirp_add_poll, slirp);
|
||||||
if (timeout < 0)
|
if (timeout < 0)
|
||||||
timeout = INFINITE;
|
timeout = INFINITE;
|
||||||
|
|
||||||
int ret = WaitForMultipleObjects(3, events, FALSE, (DWORD)timeout);
|
int ret = WaitForMultipleObjects(3, events, FALSE, (DWORD) timeout);
|
||||||
switch (ret - WAIT_OBJECT_0) {
|
switch (ret - WAIT_OBJECT_0) {
|
||||||
case NET_EVENT_STOP:
|
case NET_EVENT_STOP:
|
||||||
run = false;
|
run = false;
|
||||||
@@ -341,7 +330,6 @@ net_slirp_thread(void *priv)
|
|||||||
default:
|
default:
|
||||||
slirp_pollfds_poll(slirp->slirp, ret == WAIT_FAILED, net_slirp_get_revents, slirp);
|
slirp_pollfds_poll(slirp->slirp, ret == WAIT_FAILED, net_slirp_get_revents, slirp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -398,11 +386,11 @@ net_slirp_init(const netcard_t *card, const uint8_t *mac_addr, void *priv)
|
|||||||
slirp_log("SLiRP: initializing...\n");
|
slirp_log("SLiRP: initializing...\n");
|
||||||
net_slirp_t *slirp = calloc(1, sizeof(net_slirp_t));
|
net_slirp_t *slirp = calloc(1, sizeof(net_slirp_t));
|
||||||
memcpy(slirp->mac_addr, mac_addr, sizeof(slirp->mac_addr));
|
memcpy(slirp->mac_addr, mac_addr, sizeof(slirp->mac_addr));
|
||||||
slirp->card = (netcard_t*)card;
|
slirp->card = (netcard_t *) card;
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
slirp->pfd_size = 16 * sizeof(struct pollfd);
|
slirp->pfd_size = 16 * sizeof(struct pollfd);
|
||||||
slirp->pfd = malloc(slirp->pfd_size);
|
slirp->pfd = malloc(slirp->pfd_size);
|
||||||
memset(slirp->pfd, 0, slirp->pfd_size);
|
memset(slirp->pfd, 0, slirp->pfd_size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -412,7 +400,7 @@ net_slirp_init(const netcard_t *card, const uint8_t *mac_addr, void *priv)
|
|||||||
struct in_addr host = { .s_addr = htonl(0x0a000002 | (slirp_card_num << 8)) }; /* 10.0.x.2 */
|
struct in_addr host = { .s_addr = htonl(0x0a000002 | (slirp_card_num << 8)) }; /* 10.0.x.2 */
|
||||||
struct in_addr dhcp = { .s_addr = htonl(0x0a00000f | (slirp_card_num << 8)) }; /* 10.0.x.15 */
|
struct in_addr dhcp = { .s_addr = htonl(0x0a00000f | (slirp_card_num << 8)) }; /* 10.0.x.15 */
|
||||||
struct in_addr dns = { .s_addr = htonl(0x0a000003 | (slirp_card_num << 8)) }; /* 10.0.x.3 */
|
struct in_addr dns = { .s_addr = htonl(0x0a000003 | (slirp_card_num << 8)) }; /* 10.0.x.3 */
|
||||||
struct in_addr bind = { .s_addr = htonl(0x00000000) }; /* 0.0.0.0 */
|
struct in_addr bind = { .s_addr = htonl(0x00000000) }; /* 0.0.0.0 */
|
||||||
struct in6_addr ipv6_dummy = { 0 }; /* contents don't matter; we're not using IPv6 */
|
struct in6_addr ipv6_dummy = { 0 }; /* contents don't matter; we're not using IPv6 */
|
||||||
|
|
||||||
/* Initialize SLiRP. */
|
/* Initialize SLiRP. */
|
||||||
@@ -424,10 +412,10 @@ net_slirp_init(const netcard_t *card, const uint8_t *mac_addr, void *priv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Set up port forwarding. */
|
/* Set up port forwarding. */
|
||||||
int udp, external, internal, i = 0;
|
int udp, external, internal, i = 0;
|
||||||
char category[32];
|
char category[32];
|
||||||
snprintf(category, sizeof(category), "SLiRP Port Forwarding #%i", card->card_num + 1);
|
snprintf(category, sizeof(category), "SLiRP Port Forwarding #%i", card->card_num + 1);
|
||||||
char key[20];
|
char key[20];
|
||||||
while (1) {
|
while (1) {
|
||||||
sprintf(key, "%d_protocol", i);
|
sprintf(key, "%d_protocol", i);
|
||||||
udp = strcmp(config_get_string(category, key, "tcp"), "udp") == 0;
|
udp = strcmp(config_get_string(category, key, "tcp"), "udp") == 0;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -73,26 +73,25 @@
|
|||||||
#include <86box/net_wd8003.h>
|
#include <86box/net_wd8003.h>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define WIN32_LEAN_AND_MEAN
|
# define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
# include <windows.h>
|
||||||
#include <winsock2.h>
|
# include <winsock2.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const device_t net_none_device = {
|
static const device_t net_none_device = {
|
||||||
.name = "None",
|
.name = "None",
|
||||||
.internal_name = "none",
|
.internal_name = "none",
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.local = NET_TYPE_NONE,
|
.local = NET_TYPE_NONE,
|
||||||
.init = NULL,
|
.init = NULL,
|
||||||
.close = NULL,
|
.close = NULL,
|
||||||
.reset = NULL,
|
.reset = NULL,
|
||||||
{ .available = NULL },
|
{ .available = NULL },
|
||||||
.speed_changed = NULL,
|
.speed_changed = NULL,
|
||||||
.force_redraw = NULL,
|
.force_redraw = NULL,
|
||||||
.config = NULL
|
.config = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static const device_t *net_cards[] = {
|
static const device_t *net_cards[] = {
|
||||||
&net_none_device,
|
&net_none_device,
|
||||||
&threec503_device,
|
&threec503_device,
|
||||||
@@ -118,72 +117,68 @@ static const device_t *net_cards[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
netcard_conf_t net_cards_conf[NET_CARD_MAX];
|
netcard_conf_t net_cards_conf[NET_CARD_MAX];
|
||||||
int net_card_current = 0;
|
int net_card_current = 0;
|
||||||
|
|
||||||
/* Global variables. */
|
/* Global variables. */
|
||||||
int network_ndev;
|
int network_ndev;
|
||||||
netdev_t network_devs[NET_HOST_INTF_MAX];
|
netdev_t network_devs[NET_HOST_INTF_MAX];
|
||||||
|
|
||||||
|
|
||||||
/* Local variables. */
|
/* Local variables. */
|
||||||
|
|
||||||
#ifdef ENABLE_NETWORK_LOG
|
#ifdef ENABLE_NETWORK_LOG
|
||||||
int network_do_log = ENABLE_NETWORK_LOG;
|
int network_do_log = ENABLE_NETWORK_LOG;
|
||||||
static FILE *network_dump = NULL;
|
static FILE *network_dump = NULL;
|
||||||
static mutex_t *network_dump_mutex;
|
static mutex_t *network_dump_mutex;
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
network_log(const char *fmt, ...)
|
network_log(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (network_do_log) {
|
if (network_do_log) {
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
pclog_ex(fmt, ap);
|
pclog_ex(fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
network_dump_packet(netpkt_t *pkt)
|
network_dump_packet(netpkt_t *pkt)
|
||||||
{
|
{
|
||||||
if (!network_dump)
|
if (!network_dump)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
struct {
|
struct {
|
||||||
uint32_t ts_sec, ts_usec, incl_len, orig_len;
|
uint32_t ts_sec, ts_usec, incl_len, orig_len;
|
||||||
} pcap_packet_hdr = {
|
} pcap_packet_hdr = {
|
||||||
tv.tv_sec, tv.tv_usec, pkt->len, pkt->len
|
tv.tv_sec, tv.tv_usec, pkt->len, pkt->len
|
||||||
};
|
};
|
||||||
|
|
||||||
if (network_dump_mutex)
|
if (network_dump_mutex)
|
||||||
thread_wait_mutex(network_dump_mutex);
|
thread_wait_mutex(network_dump_mutex);
|
||||||
|
|
||||||
size_t written;
|
size_t written;
|
||||||
if ((written = fwrite(&pcap_packet_hdr, 1, sizeof(pcap_packet_hdr), network_dump)) < sizeof(pcap_packet_hdr)) {
|
if ((written = fwrite(&pcap_packet_hdr, 1, sizeof(pcap_packet_hdr), network_dump)) < sizeof(pcap_packet_hdr)) {
|
||||||
network_log("NETWORK: failed to write dump packet header\n");
|
network_log("NETWORK: failed to write dump packet header\n");
|
||||||
fseek(network_dump, -written, SEEK_CUR);
|
fseek(network_dump, -written, SEEK_CUR);
|
||||||
} else {
|
} else {
|
||||||
if ((written = fwrite(pkt->data, 1, pkt->len, network_dump)) < pkt->len) {
|
if ((written = fwrite(pkt->data, 1, pkt->len, network_dump)) < pkt->len) {
|
||||||
network_log("NETWORK: failed to write dump packet data\n");
|
network_log("NETWORK: failed to write dump packet data\n");
|
||||||
fseek(network_dump, -written - sizeof(pcap_packet_hdr), SEEK_CUR);
|
fseek(network_dump, -written - sizeof(pcap_packet_hdr), SEEK_CUR);
|
||||||
}
|
}
|
||||||
fflush(network_dump);
|
fflush(network_dump);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (network_dump_mutex)
|
if (network_dump_mutex)
|
||||||
thread_release_mutex(network_dump_mutex);
|
thread_release_mutex(network_dump_mutex);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define network_log(fmt, ...)
|
# define network_log(fmt, ...)
|
||||||
#define network_dump_packet(pkt)
|
# define network_dump_packet(pkt)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static void
|
static void
|
||||||
network_winsock_clean(void)
|
network_winsock_clean(void)
|
||||||
@@ -218,22 +213,22 @@ network_init(void)
|
|||||||
/* Initialize the Pcap system module, if present. */
|
/* Initialize the Pcap system module, if present. */
|
||||||
i = net_pcap_prepare(&network_devs[network_ndev]);
|
i = net_pcap_prepare(&network_devs[network_ndev]);
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
network_ndev += i;
|
network_ndev += i;
|
||||||
|
|
||||||
#ifdef ENABLE_NETWORK_LOG
|
#ifdef ENABLE_NETWORK_LOG
|
||||||
/* Start packet dump. */
|
/* Start packet dump. */
|
||||||
network_dump = fopen("network.pcap", "wb");
|
network_dump = fopen("network.pcap", "wb");
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint32_t magic_number;
|
uint32_t magic_number;
|
||||||
uint16_t version_major, version_minor;
|
uint16_t version_major, version_minor;
|
||||||
int32_t thiszone;
|
int32_t thiszone;
|
||||||
uint32_t sigfigs, snaplen, network;
|
uint32_t sigfigs, snaplen, network;
|
||||||
} pcap_hdr = {
|
} pcap_hdr = {
|
||||||
0xa1b2c3d4,
|
0xa1b2c3d4,
|
||||||
2, 4,
|
2, 4,
|
||||||
0,
|
0,
|
||||||
0, 65535, 1
|
0, 65535, 1
|
||||||
};
|
};
|
||||||
fwrite(&pcap_hdr, sizeof(pcap_hdr), 1, network_dump);
|
fwrite(&pcap_hdr, sizeof(pcap_hdr), 1, network_dump);
|
||||||
fflush(network_dump);
|
fflush(network_dump);
|
||||||
@@ -244,11 +239,10 @@ void
|
|||||||
network_queue_init(netqueue_t *queue)
|
network_queue_init(netqueue_t *queue)
|
||||||
{
|
{
|
||||||
queue->head = queue->tail = 0;
|
queue->head = queue->tail = 0;
|
||||||
for (int i=0; i<NET_QUEUE_LEN; i++) {
|
for (int i = 0; i < NET_QUEUE_LEN; i++) {
|
||||||
queue->packets[i].data = calloc(1, NET_MAX_FRAME);
|
queue->packets[i].data = calloc(1, NET_MAX_FRAME);
|
||||||
queue->packets[i].len = 0;
|
queue->packets[i].len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@@ -267,8 +261,8 @@ static inline void
|
|||||||
network_swap_packet(netpkt_t *pkt1, netpkt_t *pkt2)
|
network_swap_packet(netpkt_t *pkt1, netpkt_t *pkt2)
|
||||||
{
|
{
|
||||||
netpkt_t tmp = *pkt2;
|
netpkt_t tmp = *pkt2;
|
||||||
*pkt2 = *pkt1;
|
*pkt2 = *pkt1;
|
||||||
*pkt1 = tmp;
|
*pkt1 = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -280,7 +274,7 @@ network_queue_put(netqueue_t *queue, uint8_t *data, int len)
|
|||||||
|
|
||||||
netpkt_t *pkt = &queue->packets[queue->head];
|
netpkt_t *pkt = &queue->packets[queue->head];
|
||||||
memcpy(pkt->data, data, len);
|
memcpy(pkt->data, data, len);
|
||||||
pkt->len = len;
|
pkt->len = len;
|
||||||
queue->head = (queue->head + 1) & NET_QUEUE_LEN_MASK;
|
queue->head = (queue->head + 1) & NET_QUEUE_LEN_MASK;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -300,7 +294,8 @@ network_queue_put_swap(netqueue_t *queue, netpkt_t *src_pkt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
network_queue_get_swap(netqueue_t *queue, netpkt_t *dst_pkt) {
|
network_queue_get_swap(netqueue_t *queue, netpkt_t *dst_pkt)
|
||||||
|
{
|
||||||
if (network_queue_empty(queue))
|
if (network_queue_empty(queue))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -333,18 +328,17 @@ network_queue_move(netqueue_t *dst_q, netqueue_t *src_q)
|
|||||||
void
|
void
|
||||||
network_queue_clear(netqueue_t *queue)
|
network_queue_clear(netqueue_t *queue)
|
||||||
{
|
{
|
||||||
for (int i=0; i<NET_QUEUE_LEN; i++) {
|
for (int i = 0; i < NET_QUEUE_LEN; i++) {
|
||||||
free(queue->packets[i].data);
|
free(queue->packets[i].data);
|
||||||
queue->packets[i].len = 0;
|
queue->packets[i].len = 0;
|
||||||
}
|
}
|
||||||
queue->tail = queue->head = 0;
|
queue->tail = queue->head = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
network_rx_queue(void *priv)
|
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;
|
uint32_t new_link_state = net_cards_conf[card->card_num].link_state;
|
||||||
if (new_link_state != card->link_state) {
|
if (new_link_state != card->link_state) {
|
||||||
@@ -393,7 +387,7 @@ 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;
|
||||||
bool led_on = card->led_timer & 0x80000000;
|
bool led_on = card->led_timer & 0x80000000;
|
||||||
if ((activity && !led_on) || (card->led_timer & 0x7fffffff) >= 150000) {
|
if ((activity && !led_on) || (card->led_timer & 0x7fffffff) >= 150000) {
|
||||||
ui_sb_update_icon(SB_NETWORK | card->card_num, activity);
|
ui_sb_update_icon(SB_NETWORK | card->card_num, activity);
|
||||||
card->led_timer = 0 | (activity << 31);
|
card->led_timer = 0 | (activity << 31);
|
||||||
@@ -402,7 +396,6 @@ network_rx_queue(void *priv)
|
|||||||
card->led_timer += timer_period;
|
card->led_timer += timer_period;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attach a network card to the system.
|
* Attach a network card to the system.
|
||||||
*
|
*
|
||||||
@@ -413,29 +406,29 @@ network_rx_queue(void *priv)
|
|||||||
netcard_t *
|
netcard_t *
|
||||||
network_attach(void *card_drv, uint8_t *mac, NETRXCB rx, 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->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();
|
||||||
card->card_num = net_card_current;
|
card->card_num = net_card_current;
|
||||||
card->byte_period = NET_PERIOD_10M;
|
card->byte_period = NET_PERIOD_10M;
|
||||||
|
|
||||||
for (int i=0; i<3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
network_queue_init(&card->queues[i]);
|
network_queue_init(&card->queues[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (net_cards_conf[net_card_current].net_type) {
|
switch (net_cards_conf[net_card_current].net_type) {
|
||||||
case NET_TYPE_SLIRP:
|
case NET_TYPE_SLIRP:
|
||||||
default:
|
default:
|
||||||
card->host_drv = net_slirp_drv;
|
card->host_drv = net_slirp_drv;
|
||||||
card->host_drv.priv = card->host_drv.init(card, mac, NULL);
|
card->host_drv.priv = card->host_drv.init(card, mac, NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NET_TYPE_PCAP:
|
case NET_TYPE_PCAP:
|
||||||
card->host_drv = net_pcap_drv;
|
card->host_drv = net_pcap_drv;
|
||||||
card->host_drv.priv = card->host_drv.init(card, mac, net_cards_conf[net_card_current].host_dev_name);
|
card->host_drv.priv = card->host_drv.init(card, mac, net_cards_conf[net_card_current].host_dev_name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -443,7 +436,7 @@ network_attach(void *card_drv, uint8_t *mac, NETRXCB rx, NETSETLINKSTATE set_lin
|
|||||||
if (!card->host_drv.priv) {
|
if (!card->host_drv.priv) {
|
||||||
thread_close_mutex(card->tx_mutex);
|
thread_close_mutex(card->tx_mutex);
|
||||||
thread_close_mutex(card->rx_mutex);
|
thread_close_mutex(card->rx_mutex);
|
||||||
for (int i=0; i<3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
network_queue_clear(&card->queues[i]);
|
network_queue_clear(&card->queues[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -466,7 +459,7 @@ netcard_close(netcard_t *card)
|
|||||||
|
|
||||||
thread_close_mutex(card->tx_mutex);
|
thread_close_mutex(card->tx_mutex);
|
||||||
thread_close_mutex(card->rx_mutex);
|
thread_close_mutex(card->rx_mutex);
|
||||||
for (int i=0; i<3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
network_queue_clear(&card->queues[i]);
|
network_queue_clear(&card->queues[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -474,7 +467,6 @@ netcard_close(netcard_t *card)
|
|||||||
free(card);
|
free(card);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Stop any network activity. */
|
/* Stop any network activity. */
|
||||||
void
|
void
|
||||||
network_close(void)
|
network_close(void)
|
||||||
@@ -487,7 +479,6 @@ network_close(void)
|
|||||||
network_log("NETWORK: closed.\n");
|
network_log("NETWORK: closed.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reset the network card(s).
|
* Reset the network card(s).
|
||||||
*
|
*
|
||||||
@@ -508,16 +499,15 @@ network_reset(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (i = 0; i < NET_CARD_MAX; i++) {
|
for (i = 0; i < NET_CARD_MAX; i++) {
|
||||||
if (!network_dev_available(i)) {
|
if (!network_dev_available(i)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
net_card_current = i;
|
net_card_current = i;
|
||||||
device_add_inst(net_cards[net_cards_conf[i].device_num], i + 1);
|
device_add_inst(net_cards[net_cards_conf[i].device_num], i + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Queue a packet for transmission to one of the network providers. */
|
/* Queue a packet for transmission to one of the network providers. */
|
||||||
void
|
void
|
||||||
network_tx(netcard_t *card, uint8_t *bufp, int len)
|
network_tx(netcard_t *card, uint8_t *bufp, int len)
|
||||||
@@ -525,7 +515,8 @@ network_tx(netcard_t *card, uint8_t *bufp, int len)
|
|||||||
network_queue_put(&card->queues[NET_QUEUE_TX_VM], bufp, len);
|
network_queue_put(&card->queues[NET_QUEUE_TX_VM], bufp, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
int network_tx_pop(netcard_t *card, netpkt_t *out_pkt)
|
int
|
||||||
|
network_tx_pop(netcard_t *card, netpkt_t *out_pkt)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
@@ -536,7 +527,8 @@ int network_tx_pop(netcard_t *card, netpkt_t *out_pkt)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int network_tx_popv(netcard_t *card, netpkt_t *pkt_vec, int vec_size)
|
int
|
||||||
|
network_tx_popv(netcard_t *card, netpkt_t *pkt_vec, int vec_size)
|
||||||
{
|
{
|
||||||
int pkt_count = 0;
|
int pkt_count = 0;
|
||||||
|
|
||||||
@@ -553,7 +545,8 @@ int network_tx_popv(netcard_t *card, netpkt_t *pkt_vec, int vec_size)
|
|||||||
return pkt_count;
|
return pkt_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
int network_rx_put(netcard_t *card, uint8_t *bufp, int len)
|
int
|
||||||
|
network_rx_put(netcard_t *card, uint8_t *bufp, int len)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
@@ -564,7 +557,8 @@ int network_rx_put(netcard_t *card, uint8_t *bufp, int len)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int network_rx_put_pkt(netcard_t *card, netpkt_t *pkt)
|
int
|
||||||
|
network_rx_put_pkt(netcard_t *card, netpkt_t *pkt)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
@@ -602,16 +596,15 @@ network_dev_to_id(char *devname)
|
|||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
for (i=0; i<network_ndev; i++) {
|
for (i = 0; i < network_ndev; i++) {
|
||||||
if (! strcmp((char *)network_devs[i].device, devname)) {
|
if (!strcmp((char *) network_devs[i].device, devname)) {
|
||||||
return(i);
|
return (i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return(-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* UI */
|
/* UI */
|
||||||
int
|
int
|
||||||
network_dev_available(int id)
|
network_dev_available(int id)
|
||||||
@@ -629,43 +622,40 @@ 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 |= network_dev_available(i);
|
available |= network_dev_available(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
return available;
|
return available;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* UI */
|
/* UI */
|
||||||
int
|
int
|
||||||
network_card_available(int card)
|
network_card_available(int card)
|
||||||
{
|
{
|
||||||
if (net_cards[card])
|
if (net_cards[card])
|
||||||
return(device_available(net_cards[card]));
|
return (device_available(net_cards[card]));
|
||||||
|
|
||||||
return(1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* UI */
|
/* UI */
|
||||||
const device_t *
|
const device_t *
|
||||||
network_card_getdevice(int card)
|
network_card_getdevice(int card)
|
||||||
{
|
{
|
||||||
return(net_cards[card]);
|
return (net_cards[card]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* UI */
|
/* UI */
|
||||||
int
|
int
|
||||||
network_card_has_config(int card)
|
network_card_has_config(int card)
|
||||||
{
|
{
|
||||||
if (!net_cards[card]) return(0);
|
if (!net_cards[card])
|
||||||
|
return (0);
|
||||||
|
|
||||||
return(device_has_config(net_cards[card]) ? 1 : 0);
|
return (device_has_config(net_cards[card]) ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* UI */
|
/* UI */
|
||||||
char *
|
char *
|
||||||
network_card_get_internal_name(int card)
|
network_card_get_internal_name(int card)
|
||||||
@@ -673,7 +663,6 @@ network_card_get_internal_name(int card)
|
|||||||
return device_get_internal_name(net_cards[card]);
|
return device_get_internal_name(net_cards[card]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* UI */
|
/* UI */
|
||||||
int
|
int
|
||||||
network_card_get_from_internal_name(char *s)
|
network_card_get_from_internal_name(char *s)
|
||||||
@@ -681,9 +670,9 @@ network_card_get_from_internal_name(char *s)
|
|||||||
int c = 0;
|
int c = 0;
|
||||||
|
|
||||||
while (net_cards[c] != NULL) {
|
while (net_cards[c] != NULL) {
|
||||||
if (! strcmp((char *)net_cards[c]->internal_name, s))
|
if (!strcmp((char *) net_cards[c]->internal_name, s))
|
||||||
return(c);
|
return (c);
|
||||||
c++;
|
c++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@@ -58,108 +58,101 @@
|
|||||||
#include <86box/plat.h>
|
#include <86box/plat.h>
|
||||||
#include <86box/plat_dynld.h>
|
#include <86box/plat_dynld.h>
|
||||||
|
|
||||||
|
static void *pcap_handle; /* handle to WinPcap DLL */
|
||||||
static void *pcap_handle; /* handle to WinPcap DLL */
|
|
||||||
|
|
||||||
|
|
||||||
/* Pointers to the real functions. */
|
/* Pointers to the real functions. */
|
||||||
static int (*f_pcap_findalldevs)(pcap_if_t **,char *);
|
static int (*f_pcap_findalldevs)(pcap_if_t **, char *);
|
||||||
static void (*f_pcap_freealldevs)(pcap_if_t *);
|
static void (*f_pcap_freealldevs)(pcap_if_t *);
|
||||||
static pcap_t *(*f_pcap_open_live)(const char *,int,int,int,char *);
|
static pcap_t *(*f_pcap_open_live)(const char *, int, int, int, char *);
|
||||||
static int (*f_pcap_next_ex)(pcap_t*,struct pcap_pkthdr**,const unsigned char**);
|
static int (*f_pcap_next_ex)(pcap_t *, struct pcap_pkthdr **, const unsigned char **);
|
||||||
static void (*f_pcap_close)(pcap_t *);
|
static void (*f_pcap_close)(pcap_t *);
|
||||||
static dllimp_t pcap_imports[] = {
|
static dllimp_t pcap_imports[] = {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
{ "pcap_findalldevs", &f_pcap_findalldevs },
|
{ "pcap_findalldevs", &f_pcap_findalldevs },
|
||||||
{ "pcap_freealldevs", &f_pcap_freealldevs },
|
{ "pcap_freealldevs", &f_pcap_freealldevs },
|
||||||
{ "pcap_open_live", &f_pcap_open_live },
|
{ "pcap_open_live", &f_pcap_open_live },
|
||||||
{ "pcap_next_ex", &f_pcap_next_ex },
|
{ "pcap_next_ex", &f_pcap_next_ex },
|
||||||
{ "pcap_close", &f_pcap_close },
|
{ "pcap_close", &f_pcap_close },
|
||||||
{ NULL, NULL },
|
{ NULL, NULL },
|
||||||
// clang-format on
|
// clang-format on
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char device[128];
|
char device[128];
|
||||||
char description[128];
|
char description[128];
|
||||||
} capdev_t;
|
} capdev_t;
|
||||||
|
|
||||||
|
|
||||||
/* Retrieve an easy-to-use list of devices. */
|
/* Retrieve an easy-to-use list of devices. */
|
||||||
static int
|
static int
|
||||||
get_devlist(capdev_t *list)
|
get_devlist(capdev_t *list)
|
||||||
{
|
{
|
||||||
char errbuf[PCAP_ERRBUF_SIZE];
|
char errbuf[PCAP_ERRBUF_SIZE];
|
||||||
pcap_if_t *devlist, *dev;
|
pcap_if_t *devlist, *dev;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
/* Retrieve the device list from the local machine */
|
/* Retrieve the device list from the local machine */
|
||||||
if (f_pcap_findalldevs(&devlist, errbuf) == -1) {
|
if (f_pcap_findalldevs(&devlist, errbuf) == -1) {
|
||||||
fprintf(stderr,"Error in pcap_findalldevs_ex: %s\n", errbuf);
|
fprintf(stderr, "Error in pcap_findalldevs_ex: %s\n", errbuf);
|
||||||
return(-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (dev=devlist; dev!=NULL; dev=dev->next) {
|
for (dev = devlist; dev != NULL; dev = dev->next) {
|
||||||
strcpy(list->device, dev->name);
|
strcpy(list->device, dev->name);
|
||||||
if (dev->description)
|
if (dev->description)
|
||||||
strcpy(list->description, dev->description);
|
strcpy(list->description, dev->description);
|
||||||
else
|
else
|
||||||
memset(list->description, '\0', sizeof(list->description));
|
memset(list->description, '\0', sizeof(list->description));
|
||||||
list++;
|
list++;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release the memory. */
|
/* Release the memory. */
|
||||||
f_pcap_freealldevs(devlist);
|
f_pcap_freealldevs(devlist);
|
||||||
|
|
||||||
return(i);
|
return (i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Simple HEXDUMP routine for raw data. */
|
/* Simple HEXDUMP routine for raw data. */
|
||||||
static void
|
static void
|
||||||
hex_dump(unsigned char *bufp, int len)
|
hex_dump(unsigned char *bufp, int len)
|
||||||
{
|
{
|
||||||
char asci[20];
|
char asci[20];
|
||||||
unsigned char c;
|
unsigned char c;
|
||||||
long addr;
|
long addr;
|
||||||
|
|
||||||
addr = 0;
|
addr = 0;
|
||||||
while (len-- > 0) {
|
while (len-- > 0) {
|
||||||
c = bufp[addr];
|
c = bufp[addr];
|
||||||
if ((addr % 16) == 0)
|
if ((addr % 16) == 0)
|
||||||
printf("%04lx %02x", addr, c);
|
printf("%04lx %02x", addr, c);
|
||||||
else
|
else
|
||||||
printf(" %02x", c);
|
printf(" %02x", c);
|
||||||
asci[(addr & 15)] = (uint8_t)isprint(c) ? c : '.';
|
asci[(addr & 15)] = (uint8_t) isprint(c) ? c : '.';
|
||||||
if ((++addr % 16) == 0) {
|
if ((++addr % 16) == 0) {
|
||||||
asci[16] = '\0';
|
asci[16] = '\0';
|
||||||
printf(" | %s |\n", asci);
|
printf(" | %s |\n", asci);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr % 16) {
|
if (addr % 16) {
|
||||||
while (addr % 16) {
|
while (addr % 16) {
|
||||||
printf(" ");
|
printf(" ");
|
||||||
asci[(addr & 15)] = ' ';
|
asci[(addr & 15)] = ' ';
|
||||||
addr++;
|
addr++;
|
||||||
}
|
}
|
||||||
asci[16] = '\0';
|
asci[16] = '\0';
|
||||||
printf(" | %s |\n", asci);
|
printf(" | %s |\n", asci);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Print a standard Ethernet MAC address. */
|
/* Print a standard Ethernet MAC address. */
|
||||||
static void
|
static void
|
||||||
eth_praddr(unsigned char *ptr)
|
eth_praddr(unsigned char *ptr)
|
||||||
{
|
{
|
||||||
printf("%02x:%02x:%02x:%02x:%02x:%02x",
|
printf("%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]);
|
ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Print a standard Ethernet header. */
|
/* Print a standard Ethernet header. */
|
||||||
static int
|
static int
|
||||||
eth_prhdr(unsigned char *ptr)
|
eth_prhdr(unsigned char *ptr)
|
||||||
@@ -167,66 +160,66 @@ eth_prhdr(unsigned char *ptr)
|
|||||||
unsigned short type;
|
unsigned short type;
|
||||||
|
|
||||||
printf("Ethernet ");
|
printf("Ethernet ");
|
||||||
eth_praddr(ptr+6);
|
eth_praddr(ptr + 6);
|
||||||
printf(" > ");
|
printf(" > ");
|
||||||
eth_praddr(ptr);
|
eth_praddr(ptr);
|
||||||
type = (ptr[12] << 8) | ptr[13];
|
type = (ptr[12] << 8) | ptr[13];
|
||||||
printf(" type %04x\n", type);
|
printf(" type %04x\n", type);
|
||||||
|
|
||||||
return(14);
|
return (14);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Capture packets from the network, and print them. */
|
/* Capture packets from the network, and print them. */
|
||||||
static int
|
static int
|
||||||
start_cap(char *dev)
|
start_cap(char *dev)
|
||||||
{
|
{
|
||||||
char temp[PCAP_ERRBUF_SIZE];
|
char temp[PCAP_ERRBUF_SIZE];
|
||||||
struct pcap_pkthdr *hdr;
|
struct pcap_pkthdr *hdr;
|
||||||
const unsigned char *pkt;
|
const unsigned char *pkt;
|
||||||
struct tm *ltime;
|
struct tm *ltime;
|
||||||
time_t now;
|
time_t now;
|
||||||
pcap_t *pcap;
|
pcap_t *pcap;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Open the device for reading from it. */
|
/* Open the device for reading from it. */
|
||||||
pcap = f_pcap_open_live(dev,
|
pcap = f_pcap_open_live(dev,
|
||||||
1518, /* MTU */
|
1518, /* MTU */
|
||||||
1, /* promisc mode */
|
1, /* promisc mode */
|
||||||
10, /* timeout */
|
10, /* timeout */
|
||||||
temp);
|
temp);
|
||||||
if (pcap == NULL) {
|
if (pcap == NULL) {
|
||||||
fprintf(stderr, "Pcap: open_live(%s): %s\n", dev, temp);
|
fprintf(stderr, "Pcap: open_live(%s): %s\n", dev, temp);
|
||||||
return(2);
|
return (2);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Listening on '%s'..\n", dev);
|
printf("Listening on '%s'..\n", dev);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
rc = f_pcap_next_ex(pcap, &hdr, &pkt);
|
rc = f_pcap_next_ex(pcap, &hdr, &pkt);
|
||||||
if (rc < 0) break;
|
if (rc < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
/* Did we time out? */
|
/* Did we time out? */
|
||||||
if (rc == 0) continue;
|
if (rc == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* Convert the timestamp to readable format. */
|
/* Convert the timestamp to readable format. */
|
||||||
now = hdr->ts.tv_sec;
|
now = hdr->ts.tv_sec;
|
||||||
ltime = localtime(&now);
|
ltime = localtime(&now);
|
||||||
strftime(temp, sizeof(temp), "%H:%M:%S", ltime);
|
strftime(temp, sizeof(temp), "%H:%M:%S", ltime);
|
||||||
|
|
||||||
/* Process and print the packet. */
|
/* Process and print the packet. */
|
||||||
printf("\n<< %s,%.6ld len=%u\n",
|
printf("\n<< %s,%.6ld len=%u\n",
|
||||||
temp, hdr->ts.tv_usec, hdr->len);
|
temp, hdr->ts.tv_usec, hdr->len);
|
||||||
rc = eth_prhdr((unsigned char *)pkt);
|
rc = eth_prhdr((unsigned char *) pkt);
|
||||||
hex_dump((unsigned char *)pkt+rc, hdr->len-rc);
|
hex_dump((unsigned char *) pkt + rc, hdr->len - rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* All done, close up. */
|
/* All done, close up. */
|
||||||
f_pcap_close(pcap);
|
f_pcap_close(pcap);
|
||||||
|
|
||||||
return(0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Show a list of available network interfaces. */
|
/* Show a list of available network interfaces. */
|
||||||
static void
|
static void
|
||||||
show_devs(capdev_t *list, int num)
|
show_devs(capdev_t *list, int num)
|
||||||
@@ -234,23 +227,22 @@ show_devs(capdev_t *list, int num)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (num > 0) {
|
if (num > 0) {
|
||||||
printf("Available network interfaces:\n\n");
|
printf("Available network interfaces:\n\n");
|
||||||
|
|
||||||
for (i=0; i<num; i++) {
|
for (i = 0; i < num; i++) {
|
||||||
printf(" %d - %s\n", i+1, list->device);
|
printf(" %d - %s\n", i + 1, list->device);
|
||||||
if (list->description[0] != '\0')
|
if (list->description[0] != '\0')
|
||||||
printf(" (%s)\n", list->description);
|
printf(" (%s)\n", list->description);
|
||||||
else
|
else
|
||||||
printf(" (No description available)\n");
|
printf(" (No description available)\n");
|
||||||
list++;
|
list++;
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printf("No interfaces found!\nMake sure WinPcap is installed.\n");
|
printf("No interfaces found!\nMake sure WinPcap is installed.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
pclog(const char *fmt, ...)
|
pclog(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
@@ -261,12 +253,11 @@ pclog(const char *fmt, ...)
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
capdev_t interfaces[32];
|
capdev_t interfaces[32];
|
||||||
int numdev, i;
|
int numdev, i;
|
||||||
|
|
||||||
/* Try loading the DLL. */
|
/* Try loading the DLL. */
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@@ -278,39 +269,39 @@ main(int argc, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
if (pcap_handle == NULL) {
|
if (pcap_handle == NULL) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
fprintf(stderr, "Unable to load WinPcap DLL !\n");
|
fprintf(stderr, "Unable to load WinPcap DLL !\n");
|
||||||
#else
|
#else
|
||||||
fprintf(stderr, "Unable to load libpcap.so !\n");
|
fprintf(stderr, "Unable to load libpcap.so !\n");
|
||||||
#endif
|
#endif
|
||||||
return(1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the list. */
|
/* Get the list. */
|
||||||
numdev = get_devlist(interfaces);
|
numdev = get_devlist(interfaces);
|
||||||
|
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
/* No arguments, just show the list. */
|
/* No arguments, just show the list. */
|
||||||
show_devs(interfaces, numdev);
|
show_devs(interfaces, numdev);
|
||||||
|
|
||||||
dynld_close(pcap_handle);
|
dynld_close(pcap_handle);
|
||||||
|
|
||||||
return(numdev);
|
return (numdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assume argument to be the interface number to listen on. */
|
/* Assume argument to be the interface number to listen on. */
|
||||||
i = atoi(argv[1]);
|
i = atoi(argv[1]);
|
||||||
if (i < 0 || i > numdev) {
|
if (i < 0 || i > numdev) {
|
||||||
fprintf(stderr, "Invalid interface number %d !\n", i);
|
fprintf(stderr, "Invalid interface number %d !\n", i);
|
||||||
|
|
||||||
dynld_close(pcap_handle);
|
dynld_close(pcap_handle);
|
||||||
|
|
||||||
return(1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Looks good, go and listen.. */
|
/* Looks good, go and listen.. */
|
||||||
i = start_cap(interfaces[i-1].device);
|
i = start_cap(interfaces[i - 1].device);
|
||||||
|
|
||||||
dynld_close(pcap_handle);
|
dynld_close(pcap_handle);
|
||||||
|
|
||||||
return(i);
|
return (i);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user