?? pcnet.c
字號:
xmit_cxda = PHYSADDR(s,CSR_CXDA(s)); } 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), s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s)); s->xmit_pos += bcnt; } else if (s->xmit_pos >= 0) { int bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT); s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr), s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s)); s->xmit_pos += bcnt;#ifdef PCNET_DEBUG printf("pcnet_transmit size=%d\n", s->xmit_pos);#endif if (CSR_LOOP(s)) pcnet_receive(s, s->buffer, s->xmit_pos); else if (s->vc) qemu_send_packet(s->vc, s->buffer, s->xmit_pos); s->csr[0] &= ~0x0008; /* clear TDMD */ s->csr[4] |= 0x0004; /* set TXSTRT */ s->xmit_pos = -1; } 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))) s->csr[0] |= 0x0200; /* set TINT */ if (CSR_XMTRC(s)<=1) CSR_XMTRC(s) = CSR_XMTRL(s); else CSR_XMTRC(s)--; if (count--) goto txagain; } else if (s->xmit_pos >= 0) { struct pcnet_TMD tmd; TMDLOAD(&tmd, PHYSADDR(s,xmit_cxda)); SET_FIELD(&tmd.misc, TMDM, BUFF, 1); SET_FIELD(&tmd.misc, TMDM, UFLO, 1); SET_FIELD(&tmd.status, TMDS, ERR, 1); SET_FIELD(&tmd.status, TMDS, OWN, 0); TMDSTORE(&tmd, PHYSADDR(s,xmit_cxda)); s->csr[0] |= 0x0200; /* set TINT */ if (!CSR_DXSUFLO(s)) { s->csr[0] &= ~0x0010; } else if (count--) goto txagain; } s->tx_busy = 0;}static void pcnet_poll(PCNetState *s){ if (CSR_RXON(s)) { pcnet_rdte_poll(s); } if (CSR_TDMD(s) || (CSR_TXON(s) && !CSR_DPOLL(s) && pcnet_tdte_poll(s))) { /* prevent recursion */ if (s->tx_busy) return; pcnet_transmit(s); }}static void pcnet_poll_timer(void *opaque){ PCNetState *s = opaque; qemu_del_timer(s->poll_timer); if (CSR_TDMD(s)) { pcnet_transmit(s); } pcnet_update_irq(s); if (!CSR_STOP(s) && !CSR_SPND(s) && !CSR_DPOLL(s)) { uint64_t now = qemu_get_clock(vm_clock) * 33; if (!s->timer || !now) s->timer = now; else { uint64_t t = now - s->timer + CSR_POLL(s); if (t > 0xffffLL) { pcnet_poll(s); CSR_POLL(s) = CSR_PINT(s); } else CSR_POLL(s) = t; } qemu_mod_timer(s->poll_timer, pcnet_get_next_poll_time(s,qemu_get_clock(vm_clock))); }}static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value){ uint16_t val = new_value;#ifdef PCNET_DEBUG_CSR printf("pcnet_csr_writew rap=%d val=0x%04x\n", rap, val);#endif switch (rap) { case 0: s->csr[0] &= ~(val & 0x7f00); /* Clear any interrupt flags */ s->csr[0] = (s->csr[0] & ~0x0040) | (val & 0x0048); val = (val & 0x007f) | (s->csr[0] & 0x7f00); /* IFF STOP, STRT and INIT are set, clear STRT and INIT */ if ((val&7) == 7) val &= ~3; if (!CSR_STOP(s) && (val & 4)) pcnet_stop(s); if (!CSR_INIT(s) && (val & 1)) pcnet_init(s); if (!CSR_STRT(s) && (val & 2)) pcnet_start(s); if (CSR_TDMD(s)) pcnet_transmit(s); return; case 1: case 2: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 18: /* CRBAL */ case 19: /* CRBAU */ case 20: /* CXBAL */ case 21: /* CXBAU */ case 22: /* NRBAU */ case 23: /* NRBAU */ case 24: case 25: case 26: case 27: case 28: case 29: case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37: case 38: case 39: case 40: /* CRBC */ case 41: case 42: /* CXBC */ case 43: case 44: case 45: case 46: /* POLL */ case 47: /* POLLINT */ case 72: case 74: case 76: /* RCVRL */ case 78: /* XMTRL */ case 112: if (CSR_STOP(s) || CSR_SPND(s)) break; return; case 3: break; case 4: s->csr[4] &= ~(val & 0x026a); val &= ~0x026a; val |= s->csr[4] & 0x026a; break; case 5: s->csr[5] &= ~(val & 0x0a90); val &= ~0x0a90; val |= s->csr[5] & 0x0a90; break; case 16: pcnet_csr_writew(s,1,val); return; case 17: pcnet_csr_writew(s,2,val); return; case 58: pcnet_bcr_writew(s,BCR_SWS,val); break; default: return; } s->csr[rap] = val;}static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap){ uint32_t val; switch (rap) { case 0: pcnet_update_irq(s); val = s->csr[0]; val |= (val & 0x7800) ? 0x8000 : 0; break; case 16: return pcnet_csr_readw(s,1); case 17: return pcnet_csr_readw(s,2); case 58: return pcnet_bcr_readw(s,BCR_SWS); case 88: val = s->csr[89]; val <<= 16; val |= s->csr[88]; break; default: val = s->csr[rap]; }#ifdef PCNET_DEBUG_CSR printf("pcnet_csr_readw rap=%d val=0x%04x\n", rap, val);#endif return val;}static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val){ rap &= 127;#ifdef PCNET_DEBUG_BCR printf("pcnet_bcr_writew rap=%d val=0x%04x\n", rap, val);#endif switch (rap) { case BCR_SWS: if (!(CSR_STOP(s) || CSR_SPND(s))) return; val &= ~0x0300; switch (val & 0x00ff) { case 0: val |= 0x0200; break; case 1: val |= 0x0100; break; case 2: case 3: val |= 0x0300; break; default: printf("Bad SWSTYLE=0x%02x\n", val & 0xff); val = 0x0200; break; }#ifdef PCNET_DEBUG printf("BCR_SWS=0x%04x\n", val);#endif case BCR_LNKST: case BCR_LED1: case BCR_LED2: case BCR_LED3: case BCR_MC: case BCR_FDC: case BCR_BSBC: case BCR_EECAS: case BCR_PLAT: s->bcr[rap] = val; break; default: break; }}static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap){ uint32_t val; rap &= 127; switch (rap) { case BCR_LNKST: case BCR_LED1: case BCR_LED2: case BCR_LED3: val = s->bcr[rap] & ~0x8000; val |= (val & 0x017f & s->lnkst) ? 0x8000 : 0; break; default: val = rap < 32 ? s->bcr[rap] : 0; break; }#ifdef PCNET_DEBUG_BCR printf("pcnet_bcr_readw rap=%d val=0x%04x\n", rap, val);#endif return val;}static void pcnet_h_reset(void *opaque){ PCNetState *s = opaque; int i; uint16_t checksum; /* Initialize the PROM */ if (s->nd) memcpy(s->prom, s->nd->macaddr, 6); s->prom[12] = s->prom[13] = 0x00; s->prom[14] = s->prom[15] = 0x57; for (i = 0,checksum = 0; i < 16; i++) checksum += s->prom[i]; *(uint16_t *)&s->prom[12] = cpu_to_le16(checksum); s->bcr[BCR_MSRDA] = 0x0005; s->bcr[BCR_MSWRA] = 0x0005; s->bcr[BCR_MC ] = 0x0002; s->bcr[BCR_LNKST] = 0x00c0; s->bcr[BCR_LED1 ] = 0x0084; s->bcr[BCR_LED2 ] = 0x0088; s->bcr[BCR_LED3 ] = 0x0090; s->bcr[BCR_FDC ] = 0x0000; s->bcr[BCR_BSBC ] = 0x9001; s->bcr[BCR_EECAS] = 0x0002; s->bcr[BCR_SWS ] = 0x0200; s->bcr[BCR_PLAT ] = 0xff06; pcnet_s_reset(s);}static void pcnet_aprom_writeb(void *opaque, uint32_t addr, uint32_t val){ PCNetState *s = opaque;#ifdef PCNET_DEBUG printf("pcnet_aprom_writeb addr=0x%08x val=0x%02x\n", addr, val);#endif /* Check APROMWE bit to enable write access */ if (pcnet_bcr_readw(s,2) & 0x80) s->prom[addr & 15] = val;}static uint32_t pcnet_aprom_readb(void *opaque, uint32_t addr){ PCNetState *s = opaque; uint32_t val = s->prom[addr &= 15];#ifdef PCNET_DEBUG printf("pcnet_aprom_readb addr=0x%08x val=0x%02x\n", addr, val);#endif return val;}static void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val){ PCNetState *s = opaque; pcnet_poll_timer(s);#ifdef PCNET_DEBUG_IO printf("pcnet_ioport_writew addr=0x%08x val=0x%04x\n", addr, val);#endif if (!BCR_DWIO(s)) { switch (addr & 0x0f) { case 0x00: /* RDP */ pcnet_csr_writew(s, s->rap, val); break; case 0x02: s->rap = val & 0x7f; break; case 0x06: pcnet_bcr_writew(s, s->rap, val); break; } } pcnet_update_irq(s);}static uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr){ PCNetState *s = opaque; uint32_t val = -1; pcnet_poll_timer(s); if (!BCR_DWIO(s)) { switch (addr & 0x0f) { case 0x00: /* RDP */ val = pcnet_csr_readw(s, s->rap); break; case 0x02: val = s->rap; break; case 0x04: pcnet_s_reset(s); val = 0; break; case 0x06: val = pcnet_bcr_readw(s, s->rap); break; } } pcnet_update_irq(s);#ifdef PCNET_DEBUG_IO printf("pcnet_ioport_readw addr=0x%08x val=0x%04x\n", addr, val & 0xffff);#endif return val;}static void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val){ PCNetState *s = opaque; pcnet_poll_timer(s);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -