From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by monty-python.gnu.org with tmda-scanned (Exim 4.24) id 1Apbi3-0004zf-RW for qemu-devel@nongnu.org; Sat, 07 Feb 2004 18:17:59 -0500 Received: from mail by monty-python.gnu.org with spam-scanned (Exim 4.24) id 1ApbhX-0004pl-0z for qemu-devel@nongnu.org; Sat, 07 Feb 2004 18:17:58 -0500 Received: from [212.16.62.51] (helo=mail.13thfloor.at) by monty-python.gnu.org with esmtp (Exim 4.24) id 1ApbhV-0004p0-QF for qemu-devel@nongnu.org; Sat, 07 Feb 2004 18:17:25 -0500 Date: Sun, 8 Feb 2004 00:17:22 +0100 From: Herbert Poetzl Message-ID: <20040207231722.GA17086@MAIL.13thfloor.at> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="r5Pyd7+fXNt84Ff3" Content-Disposition: inline Subject: [Qemu-devel] multiple nics in QEMU Reply-To: qemu-devel@nongnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Fabrice Bellard Cc: qemu-devel@nongnu.org --r5Pyd7+fXNt84Ff3 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline 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 --r5Pyd7+fXNt84Ff3 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="qemu-ethX-hack.diff" 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; nicisr = 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 --r5Pyd7+fXNt84Ff3--