]> git.proxmox.com Git - qemu.git/blobdiff - hw/ne2000.c
PowerPC system emulation fixes (Jocelyn Mayer)
[qemu.git] / hw / ne2000.c
index 0b35495f99eebd6ec9104a67251f153bbdd630cf..e9ad6f9f8184dbac14e6ef8c7c9bcd44975d8b2b 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <getopt.h>
-#include <inttypes.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <time.h>
-#include <sys/time.h>
-#include <malloc.h>
-#include <termios.h>
-#include <sys/poll.h>
-#include <errno.h>
-#include <sys/wait.h>
-#include <netinet/in.h>
-
-#include "cpu.h"
 #include "vl.h"
 
 /* debug NE2000 card */
 //#define DEBUG_NE2000
 
-/***********************************************************/
-/* ne2000 emulation */
+#define MAX_ETH_FRAME_SIZE 1514
 
 #define E8390_CMD      0x00  /* The command register (for all pages) */
 /* Page 0 register offsets. */
@@ -143,23 +122,16 @@ typedef struct NE2000State {
     uint8_t curpag;
     uint8_t mult[8]; /* multicast mask array */
     int irq;
+    NetDriverState *nd;
     uint8_t mem[NE2000_MEM_SIZE];
 } NE2000State;
 
-static NE2000State ne2000_state;
-int net_fd = -1;
-
 static void ne2000_reset(NE2000State *s)
 {
     int i;
 
     s->isr = ENISR_RESET;
-    s->mem[0] = 0x52;
-    s->mem[1] = 0x54;
-    s->mem[2] = 0x00;
-    s->mem[3] = 0x12;
-    s->mem[4] = 0x34;
-    s->mem[5] = 0x56;
+    memcpy(s->mem, s->nd->macaddr, 6);
     s->mem[14] = 0x57;
     s->mem[15] = 0x57;
 
@@ -174,16 +146,20 @@ static void ne2000_update_irq(NE2000State *s)
 {
     int isr;
     isr = s->isr & s->imr;
+#if defined(DEBUG_NE2000)
+    printf("NE2000: Set IRQ line %d to %d (%02x %02x)\n",
+          s->irq, isr ? 1 : 0, s->isr, s->imr);
+#endif
     if (isr)
         pic_set_irq(s->irq, 1);
     else
         pic_set_irq(s->irq, 0);
 }
 
-/* return true if the NE2000 can receive more data */
-int ne2000_can_receive(void)
+/* return the max buffer size if the NE2000 can receive more data */
+static int ne2000_can_receive(void *opaque)
 {
-    NE2000State *s = &ne2000_state;
+    NE2000State *s = opaque;
     int avail, index, boundary;
     
     if (s->cmd & E8390_STOP)
@@ -196,19 +172,30 @@ int ne2000_can_receive(void)
         avail = (s->stop - s->start) - (index - boundary);
     if (avail < (MAX_ETH_FRAME_SIZE + 4))
         return 0;
-    return 1;
+    return MAX_ETH_FRAME_SIZE;
 }
 
-void ne2000_receive(uint8_t *buf, int size)
+#define MIN_BUF_SIZE 60
+
+static void ne2000_receive(void *opaque, const uint8_t *buf, int size)
 {
-    NE2000State *s = &ne2000_state;
+    NE2000State *s = opaque;
     uint8_t *p;
     int total_len, next, avail, len, index;
-
+    uint8_t buf1[60];
+    
 #if defined(DEBUG_NE2000)
     printf("NE2000: received len=%d\n", size);
 #endif
 
+    /* if too small buffer, then expand it */
+    if (size < MIN_BUF_SIZE) {
+        memcpy(buf1, buf, size);
+        memset(buf1 + size, 0, MIN_BUF_SIZE - size);
+        buf = buf1;
+        size = MIN_BUF_SIZE;
+    }
+
     index = s->curpag << 8;
     /* 4 bytes for header */
     total_len = size + 4;
@@ -244,9 +231,9 @@ void ne2000_receive(uint8_t *buf, int size)
     ne2000_update_irq(s);
 }
 
-static void ne2000_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
+static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 {
-    NE2000State *s = &ne2000_state;
+    NE2000State *s = opaque;
     int offset, page;
 
     addr &= 0xf;
@@ -264,7 +251,7 @@ static void ne2000_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
                 ne2000_update_irq(s);
             }
             if (val & E8390_TRANS) {
-                net_send_packet(net_fd, s->mem + (s->tpsr << 8), s->tcnt);
+                net_send_packet(s->nd, s->mem + (s->tpsr << 8), s->tcnt);
                 /* signal end of transfert */
                 s->tsr = ENTSR_PTX;
                 s->isr |= ENISR_TX;
@@ -329,9 +316,9 @@ static void ne2000_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
     }
 }
 
-static uint32_t ne2000_ioport_read(CPUState *env, uint32_t addr)
+static uint32_t ne2000_ioport_read(void *opaque, uint32_t addr)
 {
-    NE2000State *s = &ne2000_state;
+    NE2000State *s = opaque;
     int offset, page, ret;
 
     addr &= 0xf;
@@ -370,9 +357,9 @@ static uint32_t ne2000_ioport_read(CPUState *env, uint32_t addr)
     return ret;
 }
 
-static void ne2000_asic_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
+static void ne2000_asic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 {
-    NE2000State *s = &ne2000_state;
+    NE2000State *s = opaque;
     uint8_t *p;
 
 #ifdef DEBUG_NE2000
@@ -401,9 +388,9 @@ static void ne2000_asic_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
     }
 }
 
-static uint32_t ne2000_asic_ioport_read(CPUState *env, uint32_t addr)
+static uint32_t ne2000_asic_ioport_read(void *opaque, uint32_t addr)
 {
-    NE2000State *s = &ne2000_state;
+    NE2000State *s = opaque;
     uint8_t *p;
     int ret;
 
@@ -433,33 +420,40 @@ static uint32_t ne2000_asic_ioport_read(CPUState *env, uint32_t addr)
     return ret;
 }
 
-static void ne2000_reset_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
+static void ne2000_reset_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 {
     /* nothing to do (end of reset pulse) */
 }
 
-static uint32_t ne2000_reset_ioport_read(CPUState *env, uint32_t addr)
+static uint32_t ne2000_reset_ioport_read(void *opaque, uint32_t addr)
 {
-    NE2000State *s = &ne2000_state;
+    NE2000State *s = opaque;
     ne2000_reset(s);
     return 0;
 }
 
-void ne2000_init(int base, int irq)
+void ne2000_init(int base, int irq, NetDriverState *nd)
 {
-    NE2000State *s = &ne2000_state;
+    NE2000State *s;
 
-    register_ioport_write(base, 16, ne2000_ioport_write, 1);
-    register_ioport_read(base, 16, ne2000_ioport_read, 1);
+    s = qemu_mallocz(sizeof(NE2000State));
+    if (!s)
+        return;
+    
+    register_ioport_write(base, 16, 1, ne2000_ioport_write, s);
+    register_ioport_read(base, 16, 1, ne2000_ioport_read, s);
 
-    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 + 0x10, 1, 1, ne2000_asic_ioport_write, s);
+    register_ioport_read(base + 0x10, 1, 1, ne2000_asic_ioport_read, s);
+    register_ioport_write(base + 0x10, 2, 2, ne2000_asic_ioport_write, s);
+    register_ioport_read(base + 0x10, 2, 2, ne2000_asic_ioport_read, s);
 
-    register_ioport_write(base + 0x1f, 1, ne2000_reset_ioport_write, 1);
-    register_ioport_read(base + 0x1f, 1, ne2000_reset_ioport_read, 1);
+    register_ioport_write(base + 0x1f, 1, 1, ne2000_reset_ioport_write, s);
+    register_ioport_read(base + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
     s->irq = irq;
+    s->nd = nd;
 
     ne2000_reset(s);
+
+    qemu_add_fd_read_handler(nd->fd, ne2000_can_receive, ne2000_receive, s);
 }