summary refs log tree commit diff stats
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/pc_piix.c4
-rw-r--r--hw/pcnet.c13
-rw-r--r--hw/pcnet.h1
3 files changed, 17 insertions, 1 deletions
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 5c08245fed..907d723728 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -373,6 +373,10 @@ static QEMUMachine pc_machine_v1_1 = {
             .driver   = "virtio-balloon-pci",\
             .property = "class",\
             .value    = stringify(PCI_CLASS_MEMORY_RAM),\
+        },{\
+            .driver   = "apic",\
+            .property = "vapic",\
+            .value    = "off",\
         }
 
 static QEMUMachine pc_machine_v1_0 = {
diff --git a/hw/pcnet.c b/hw/pcnet.c
index c53f06ef3b..d769b08b78 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -77,6 +77,7 @@ struct qemu_ether_header {
 #define CSR_DTX(S)       !!(((S)->csr[15])&0x0002)
 #define CSR_LOOP(S)      !!(((S)->csr[15])&0x0004)
 #define CSR_DXMTFCS(S)   !!(((S)->csr[15])&0x0008)
+#define CSR_INTL(S)      !!(((S)->csr[15])&0x0040)
 #define CSR_DRCVPA(S)    !!(((S)->csr[15])&0x2000)
 #define CSR_DRCVBC(S)    !!(((S)->csr[15])&0x4000)
 #define CSR_PROM(S)      !!(((S)->csr[15])&0x8000)
@@ -884,7 +885,7 @@ static void pcnet_stop(PCNetState *s)
 #ifdef PCNET_DEBUG
     printf("pcnet_stop\n");
 #endif
-    s->csr[0] &= ~0x7feb;
+    s->csr[0] &= ~0xffeb;
     s->csr[0] |= 0x0014;
     s->csr[4] &= ~0x02c2;
     s->csr[5] &= ~0x0011;
@@ -1234,6 +1235,15 @@ static void pcnet_transmit(PCNetState *s)
             if (BCR_SWSTYLE(s) != 1)
                 add_crc = GET_FIELD(tmd.status, TMDS, ADDFCS);
         }
+        if (s->lnkst == 0 &&
+            (!CSR_LOOP(s) || (!CSR_INTL(s) && !BCR_TMAULOOP(s)))) {
+            SET_FIELD(&tmd.misc, TMDM, LCAR, 1);
+            SET_FIELD(&tmd.status, TMDS, ERR, 1);
+            SET_FIELD(&tmd.status, TMDS, OWN, 0);
+            s->csr[0] |= 0xa000; /* ERR | CERR */
+            s->xmit_pos = -1;
+            goto txdone;
+        }
         if (!GET_FIELD(tmd.status, TMDS, ENP)) {
             int bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
             s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
@@ -1262,6 +1272,7 @@ static void pcnet_transmit(PCNetState *s)
             s->xmit_pos = -1;
         }
 
+    txdone:
         SET_FIELD(&tmd.status, TMDS, OWN, 0);
         TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
         if (!CSR_TOKINTD(s) || (CSR_LTINTEN(s) && GET_FIELD(tmd.status, TMDS, LTINT)))
diff --git a/hw/pcnet.h b/hw/pcnet.h
index edc81c90ac..803a2cc1ec 100644
--- a/hw/pcnet.h
+++ b/hw/pcnet.h
@@ -20,6 +20,7 @@
 #define BCR_SWS      20
 #define BCR_PLAT     22
 
+#define BCR_TMAULOOP(S)  !!((S)->bcr[BCR_MC  ] & 0x4000)
 #define BCR_APROMWE(S)   !!((S)->bcr[BCR_MC  ] & 0x0100)
 #define BCR_DWIO(S)      !!((S)->bcr[BCR_BSBC] & 0x0080)
 #define BCR_SSIZE32(S)   !!((S)->bcr[BCR_SWS ] & 0x0100)