From: Herbert Poetzl <herbert@13thfloor.at>
To: Fabrice Bellard <fabrice.bellard@free.fr>
Cc: qemu-devel@nongnu.org
Subject: [Qemu-devel] multiple nics in QEMU
Date: Sun, 8 Feb 2004 00:17:22 +0100 [thread overview]
Message-ID: <20040207231722.GA17086@MAIL.13thfloor.at> (raw)
[-- Attachment #1: Type: text/plain, Size: 467 bytes --]
Hi Fabrice!
it would be nice to have support for multiple nics
in QEMU, to test network stuff and routing with the
linux kernel for example ...
attached is a patch, which should be considered a
proof of concept code for that, and maybe the first
step, the next would require to adapt the command
line options to make use of this, and to move the
nic_fd into the NE2000 struct, so I didn't do that,
because I do not know your preferences there ...
HTH,
Herbert
[-- Attachment #2: qemu-ethX-hack.diff --]
[-- Type: text/plain, Size: 5654 bytes --]
diff -NurpP --minimal qemu-cvs-06.02.2004/vl.c qemu-cvs-06.02.2004-hack/vl.c
--- qemu-cvs-06.02.2004/vl.c 2004-02-04 00:37:12.000000000 +0100
+++ qemu-cvs-06.02.2004-hack/vl.c 2004-02-07 01:10:01.000000000 +0100
@@ -1817,10 +1817,10 @@ void serial_init(void)
/***********************************************************/
/* ne2000 emulation */
+// #define DEBUG_NE2000
#if defined (TARGET_I386)
-#define NE2000_IOPORT 0x300
-#define NE2000_IRQ 9
+#define NE2000_MAX_NIC 4
#define MAX_ETH_FRAME_SIZE 1514
@@ -1918,15 +1918,35 @@ typedef struct NE2000State {
uint8_t curpag;
uint8_t mult[8]; /* multicast mask array */
uint8_t mem[NE2000_MEM_SIZE];
+ uint8_t irq;
} NE2000State;
-NE2000State ne2000_state;
+NE2000State ne2000_state[NE2000_MAX_NIC];
int net_fd = -1;
char network_script[1024];
-void ne2000_reset(void)
+uint32_t ne2000_io[] = { 0x300, 0x320, 0x340, 0x360, 0x280, 0x380 };
+int ne2000_irq[] = { 9, 10, 11, 3, 4, 5 };
+
+static inline int ne2000_addr_to_nic(uint32_t addr)
{
- NE2000State *s = &ne2000_state;
+ uint32_t base = (addr & ~0x1f);
+ int nic;
+
+ for (nic=0; nic<NE2000_MAX_NIC; nic++)
+ if (base == ne2000_io[nic])
+ return nic;
+ return 0;
+}
+
+static inline uint32_t ne2000_nic_to_addr(int nic)
+{
+ return ne2000_io[nic % NE2000_MAX_NIC];
+}
+
+void ne2000_reset(nic)
+{
+ NE2000State *s = &ne2000_state[nic];
int i;
s->isr = ENISR_RESET;
@@ -1944,6 +1964,7 @@ void ne2000_reset(void)
s->mem[2 * i] = s->mem[i];
s->mem[2 * i + 1] = s->mem[i];
}
+ s->irq = ne2000_irq[nic];
}
void ne2000_update_irq(NE2000State *s)
@@ -1951,9 +1972,9 @@ void ne2000_update_irq(NE2000State *s)
int isr;
isr = s->isr & s->imr;
if (isr)
- pic_set_irq(NE2000_IRQ, 1);
+ pic_set_irq(s->irq, 1);
else
- pic_set_irq(NE2000_IRQ, 0);
+ pic_set_irq(s->irq, 0);
}
int net_init(void)
@@ -2068,12 +2089,13 @@ void ne2000_receive(NE2000State *s, uint
void ne2000_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
{
- NE2000State *s = &ne2000_state;
+ int nic = ne2000_addr_to_nic(addr);
+ NE2000State *s = &ne2000_state[nic];
int offset, page;
addr &= 0xf;
#ifdef DEBUG_NE2000
- printf("NE2000: write addr=0x%x val=0x%02x\n", addr, val);
+ printf("NE2000[%d]: write addr=0x%x val=0x%02x\n", nic, addr, val);
#endif
if (addr == E8390_CMD) {
/* control register */
@@ -2153,7 +2175,8 @@ void ne2000_ioport_write(CPUState *env,
uint32_t ne2000_ioport_read(CPUState *env, uint32_t addr)
{
- NE2000State *s = &ne2000_state;
+ int nic = ne2000_addr_to_nic(addr);
+ NE2000State *s = &ne2000_state[nic];
int offset, page, ret;
addr &= 0xf;
@@ -2187,18 +2210,19 @@ uint32_t ne2000_ioport_read(CPUState *en
}
}
#ifdef DEBUG_NE2000
- printf("NE2000: read addr=0x%x val=%02x\n", addr, ret);
+ printf("NE2000[%d]: read addr=0x%x val=%02x\n", nic, addr, ret);
#endif
return ret;
}
void ne2000_asic_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
{
- NE2000State *s = &ne2000_state;
+ int nic = ne2000_addr_to_nic(addr);
+ NE2000State *s = &ne2000_state[nic];
uint8_t *p;
#ifdef DEBUG_NE2000
- printf("NE2000: asic write val=0x%04x\n", val);
+ printf("NE2000[%d]: asic write val=0x%04x\n", nic, val);
#endif
p = s->mem + s->rsar;
if (s->dcfg & 0x01) {
@@ -2225,7 +2249,8 @@ void ne2000_asic_ioport_write(CPUState *
uint32_t ne2000_asic_ioport_read(CPUState *env, uint32_t addr)
{
- NE2000State *s = &ne2000_state;
+ int nic = ne2000_addr_to_nic(addr);
+ NE2000State *s = &ne2000_state[nic];
uint8_t *p;
int ret;
@@ -2250,7 +2275,7 @@ uint32_t ne2000_asic_ioport_read(CPUStat
ne2000_update_irq(s);
}
#ifdef DEBUG_NE2000
- printf("NE2000: asic read val=0x%04x\n", ret);
+ printf("NE2000[%d]: asic read val=0x%04x\n", nic, ret);
#endif
return ret;
}
@@ -2262,23 +2287,32 @@ void ne2000_reset_ioport_write(CPUState
uint32_t ne2000_reset_ioport_read(CPUState *env, uint32_t addr)
{
- ne2000_reset();
+ int nic = ne2000_addr_to_nic(addr);
+ ne2000_reset(nic);
return 0;
}
void ne2000_init(void)
{
- register_ioport_write(NE2000_IOPORT, 16, ne2000_ioport_write, 1);
- register_ioport_read(NE2000_IOPORT, 16, ne2000_ioport_read, 1);
+ int nic;
+
+ for (nic=0; nic < NE2000_MAX_NIC; nic++) {
+ uint32_t base = ne2000_nic_to_addr(nic);
- register_ioport_write(NE2000_IOPORT + 0x10, 1, ne2000_asic_ioport_write, 1);
- register_ioport_read(NE2000_IOPORT + 0x10, 1, ne2000_asic_ioport_read, 1);
- register_ioport_write(NE2000_IOPORT + 0x10, 2, ne2000_asic_ioport_write, 2);
- register_ioport_read(NE2000_IOPORT + 0x10, 2, ne2000_asic_ioport_read, 2);
+ register_ioport_write(base, 16, ne2000_ioport_write, 1);
+ register_ioport_read(base, 16, ne2000_ioport_read, 1);
- register_ioport_write(NE2000_IOPORT + 0x1f, 1, ne2000_reset_ioport_write, 1);
- register_ioport_read(NE2000_IOPORT + 0x1f, 1, ne2000_reset_ioport_read, 1);
- ne2000_reset();
+ register_ioport_write(base + 0x10, 1, ne2000_asic_ioport_write, 1);
+ register_ioport_read(base + 0x10, 1, ne2000_asic_ioport_read, 1);
+ register_ioport_write(base + 0x10, 2, ne2000_asic_ioport_write, 2);
+ register_ioport_read(base + 0x10, 2, ne2000_asic_ioport_read, 2);
+
+ register_ioport_write(base + 0x1f, 1, ne2000_reset_ioport_write, 1);
+ register_ioport_read(base + 0x1f, 1, ne2000_reset_ioport_read, 1);
+
+
+ ne2000_reset(nic);
+ }
}
#endif
next reply other threads:[~2004-02-07 23:17 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-02-07 23:17 Herbert Poetzl [this message]
2004-02-08 13:28 ` [Qemu-devel] Re: multiple nics in QEMU Fabrice Bellard
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20040207231722.GA17086@MAIL.13thfloor.at \
--to=herbert@13thfloor.at \
--cc=fabrice.bellard@free.fr \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).