summary refs log tree commit diff stats
path: root/hw/pcnet.c
diff options
context:
space:
mode:
authorAnthony Liguori <aliguori@us.ibm.com>2012-04-16 12:56:28 -0500
committerAnthony Liguori <aliguori@us.ibm.com>2012-04-16 12:56:28 -0500
commitfc34e77bb3dd41a9932ec5830c06bcade1f5a08e (patch)
tree93a7c849cc543757381e0fd230e46debf377dcbb /hw/pcnet.c
parent52346e8c75eba1ece4a782565d5a5ce2e23d5117 (diff)
parent9bea6a2956e5d473b8914b2a5483fbf187b33844 (diff)
downloadfocaccia-qemu-fc34e77bb3dd41a9932ec5830c06bcade1f5a08e.tar.gz
focaccia-qemu-fc34e77bb3dd41a9932ec5830c06bcade1f5a08e.zip
Merge remote-tracking branch 'kiszka/queues/pending' into staging
* kiszka/queues/pending:
  vapic: Disable for pre-1.1 machines
  Kick io-thread on qemu_chr_accept_input
  pcnet: Properly handle TX requests during Link Fail
  pcnet: Clear ERR in CSR0 on stop
  signrom: Rewrite as python script

Conflicts:
	hw/pc_piix.c

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'hw/pcnet.c')
-rw-r--r--hw/pcnet.c13
1 files changed, 12 insertions, 1 deletions
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)))