]> Git Repo - qemu.git/blobdiff - hw/ne2000.c
ARM PL181 MMCI fixes.
[qemu.git] / hw / ne2000.c
index 2940abd35cba72326345f043ddf0957f83fc0d1e..1625c5538895881bcf83f6de5213cbace1e7a7f8 100644 (file)
@@ -136,7 +136,7 @@ typedef struct NE2000State {
     uint8_t phys[6]; /* mac address */
     uint8_t curpag;
     uint8_t mult[8]; /* multicast mask array */
-    int irq;
+    qemu_irq irq;
     PCIDevice *pci_dev;
     VLANClientState *vc;
     uint8_t macaddr[6];
@@ -164,16 +164,10 @@ static void ne2000_update_irq(NE2000State *s)
     int isr;
     isr = (s->isr & s->imr) & 0x7f;
 #if defined(DEBUG_NE2000)
-    printf("NE2000: Set IRQ line %d to %d (%02x %02x)\n",
-          s->irq, isr ? 1 : 0, s->isr, s->imr);
+    printf("NE2000: Set IRQ to %d (%02x %02x)\n",
+          isr ? 1 : 0, s->isr, s->imr);
 #endif
-    if (s->irq == 16) {
-        /* PCI irq */
-        pci_set_irq(s->pci_dev, 0, (isr != 0));
-    } else {
-        /* ISA irq */
-        pic_set_irq(s->irq, (isr != 0));
-    }
+    qemu_set_irq(s->irq, (isr != 0));
 }
 
 #define POLYNOMIAL 0x04c11db6
@@ -200,14 +194,10 @@ static int compute_mcast_idx(const uint8_t *ep)
     return (crc >> 26);
 }
 
-/* return the max buffer size if the NE2000 can receive more data */
-static int ne2000_can_receive(void *opaque)
+static int ne2000_buffer_full(NE2000State *s)
 {
-    NE2000State *s = opaque;
     int avail, index, boundary;
-    
-    if (s->cmd & E8390_STOP)
-        return 0;
+
     index = s->curpag << 8;
     boundary = s->boundary << 8;
     if (index < boundary)
@@ -215,8 +205,17 @@ static int ne2000_can_receive(void *opaque)
     else
         avail = (s->stop - s->start) - (index - boundary);
     if (avail < (MAX_ETH_FRAME_SIZE + 4))
-        return 0;
-    return MAX_ETH_FRAME_SIZE;
+        return 1;
+    return 0;
+}
+
+static int ne2000_can_receive(void *opaque)
+{
+    NE2000State *s = opaque;
+    
+    if (s->cmd & E8390_STOP)
+        return 1;
+    return !ne2000_buffer_full(s);
 }
 
 #define MIN_BUF_SIZE 60
@@ -234,7 +233,7 @@ static void ne2000_receive(void *opaque, const uint8_t *buf, int size)
     printf("NE2000: received len=%d\n", size);
 #endif
 
-    if (!ne2000_can_receive(s))
+    if (s->cmd & E8390_STOP || ne2000_buffer_full(s))
         return;
     
     /* XXX: check this */
@@ -307,7 +306,7 @@ static void ne2000_receive(void *opaque, const uint8_t *buf, int size)
     }
     s->curpag = next >> 8;
 
-    /* now we can signal we have receive something */
+    /* now we can signal we have received something */
     s->isr |= ENISR_RX;
     ne2000_update_irq(s);
 }
@@ -326,7 +325,7 @@ static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val)
         s->cmd = val;
         if (!(val & E8390_STOP)) { /* START bit makes no sense on RTL8029... */
             s->isr &= ~ENISR_RESET;
-            /* test specific case: zero length transfert */
+            /* test specific case: zero length transfer */
             if ((val & (E8390_RREAD | E8390_RWRITE)) &&
                 s->rcnt == 0) {
                 s->isr |= ENISR_RDC;
@@ -341,7 +340,7 @@ static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val)
                 if (index + s->tcnt <= NE2000_PMEM_END) {
                     qemu_send_packet(s->vc, s->mem + index, s->tcnt);
                 }
-                /* signal end of transfert */
+                /* signal end of transfer */
                 s->tsr = ENTSR_PTX;
                 s->isr |= ENISR_TX;
                 s->cmd &= ~E8390_TRANS; 
@@ -551,7 +550,7 @@ static inline void ne2000_dma_update(NE2000State *s, int len)
 
     if (s->rcnt <= len) {
         s->rcnt = 0;
-        /* signal end of transfert */
+        /* signal end of transfer */
         s->isr |= ENISR_RDC;
         ne2000_update_irq(s);
     } else {
@@ -642,6 +641,12 @@ static uint32_t ne2000_reset_ioport_read(void *opaque, uint32_t addr)
 static void ne2000_save(QEMUFile* f,void* opaque)
 {
        NE2000State* s=(NE2000State*)opaque;
+        int tmp;
+
+        if (s->pci_dev)
+            pci_device_save(s->pci_dev, f);
+
+        qemu_put_8s(f, &s->rxcr);
 
        qemu_put_8s(f, &s->cmd);
        qemu_put_be32s(f, &s->start);
@@ -659,17 +664,32 @@ static void ne2000_save(QEMUFile* f,void* opaque)
        qemu_put_buffer(f, s->phys, 6);
        qemu_put_8s(f, &s->curpag);
        qemu_put_buffer(f, s->mult, 8);
-       qemu_put_be32s(f, &s->irq);
+        tmp = 0;
+       qemu_put_be32s(f, &tmp); /* ignored, was irq */
        qemu_put_buffer(f, s->mem, NE2000_MEM_SIZE);
 }
 
 static int ne2000_load(QEMUFile* f,void* opaque,int version_id)
 {
        NE2000State* s=(NE2000State*)opaque;
+        int ret;
+        int tmp;
 
-       if (version_id != 1)
+        if (version_id > 3)
             return -EINVAL;
 
+        if (s->pci_dev && version_id >= 3) {
+            ret = pci_device_load(s->pci_dev, f);
+            if (ret < 0)
+                return ret;
+        }
+
+        if (version_id >= 2) {
+            qemu_get_8s(f, &s->rxcr);
+        } else {
+            s->rxcr = 0x0c;
+        }
+
        qemu_get_8s(f, &s->cmd);
        qemu_get_be32s(f, &s->start);
        qemu_get_be32s(f, &s->stop);
@@ -686,13 +706,13 @@ static int ne2000_load(QEMUFile* f,void* opaque,int version_id)
        qemu_get_buffer(f, s->phys, 6);
        qemu_get_8s(f, &s->curpag);
        qemu_get_buffer(f, s->mult, 8);
-       qemu_get_be32s(f, &s->irq);
+       qemu_get_be32s(f, &tmp); /* ignored */
        qemu_get_buffer(f, s->mem, NE2000_MEM_SIZE);
 
        return 0;
 }
 
-void isa_ne2000_init(int base, int irq, NICInfo *nd)
+void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd)
 {
     NE2000State *s;
     
@@ -715,7 +735,8 @@ void isa_ne2000_init(int base, int irq, NICInfo *nd)
 
     ne2000_reset(s);
 
-    s->vc = qemu_new_vlan_client(nd->vlan, ne2000_receive, s);
+    s->vc = qemu_new_vlan_client(nd->vlan, ne2000_receive,
+                                 ne2000_can_receive, s);
 
     snprintf(s->vc->info_str, sizeof(s->vc->info_str),
              "ne2000 macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
@@ -726,7 +747,7 @@ void isa_ne2000_init(int base, int irq, NICInfo *nd)
              s->macaddr[4],
              s->macaddr[5]);
              
-    register_savevm("ne2000", 0, 1, ne2000_save, ne2000_load, s);
+    register_savevm("ne2000", 0, 2, ne2000_save, ne2000_load, s);
 }
 
 /***********************************************************/
@@ -757,7 +778,7 @@ static void ne2000_map(PCIDevice *pci_dev, int region_num,
     register_ioport_read(addr + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
 }
 
-void pci_ne2000_init(PCIBus *bus, NICInfo *nd)
+void pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn)
 {
     PCINE2000State *d;
     NE2000State *s;
@@ -765,7 +786,7 @@ void pci_ne2000_init(PCIBus *bus, NICInfo *nd)
     
     d = (PCINE2000State *)pci_register_device(bus,
                                               "NE2000", sizeof(PCINE2000State),
-                                              -1
+                                              devfn
                                               NULL, NULL);
     pci_conf = d->dev.config;
     pci_conf[0x00] = 0xec; // Realtek 8029
@@ -780,11 +801,12 @@ void pci_ne2000_init(PCIBus *bus, NICInfo *nd)
     pci_register_io_region(&d->dev, 0, 0x100, 
                            PCI_ADDRESS_SPACE_IO, ne2000_map);
     s = &d->ne2000;
-    s->irq = 16; // PCI interrupt
+    s->irq = d->dev.irq[0];
     s->pci_dev = (PCIDevice *)d;
     memcpy(s->macaddr, nd->macaddr, 6);
     ne2000_reset(s);
-    s->vc = qemu_new_vlan_client(nd->vlan, ne2000_receive, s);
+    s->vc = qemu_new_vlan_client(nd->vlan, ne2000_receive,
+                                 ne2000_can_receive, s);
 
     snprintf(s->vc->info_str, sizeof(s->vc->info_str),
              "ne2000 pci macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
@@ -796,7 +818,5 @@ void pci_ne2000_init(PCIBus *bus, NICInfo *nd)
              s->macaddr[5]);
              
     /* XXX: instance number ? */
-    register_savevm("ne2000", 0, 1, ne2000_save, ne2000_load, s);
-    register_savevm("ne2000_pci", 0, 1, generic_pci_save, generic_pci_load, 
-                    &d->dev);
+    register_savevm("ne2000", 0, 3, ne2000_save, ne2000_load, s);
 }
This page took 0.029335 seconds and 4 git commands to generate.