#include "qemu/timer.h"
#include "qemu/sockets.h"
#include "sysemu/sysemu.h"
+#include "trace.h"
#include "pcnet.h"
static void pcnet_s_reset(PCNetState *s)
{
-#ifdef PCNET_DEBUG
- printf("pcnet_s_reset\n");
-#endif
+ trace_pcnet_s_reset(s);
s->rdra = 0;
s->tdra = 0;
s->csr[4] |= 0x0040;
s->csr[0] |= 0x0080;
isr = 1;
-#ifdef PCNET_DEBUG
- printf("pcnet user int\n");
-#endif
+ trace_pcnet_user_int(s);
}
#if 1
}
if (isr != s->isr) {
-#ifdef PCNET_DEBUG
- printf("pcnet: INTA=%d\n", isr);
-#endif
+ trace_pcnet_isr_change(s, isr, s->isr);
}
qemu_set_irq(s->irq, isr);
s->isr = isr;
uint16_t padr[3], ladrf[4], mode;
uint32_t rdra, tdra;
-#ifdef PCNET_DEBUG
- printf("pcnet_init init_addr=0x%08x\n", PHYSADDR(s,CSR_IADR(s)));
-#endif
+ trace_pcnet_init(s, PHYSADDR(s, CSR_IADR(s)));
if (BCR_SSIZE32(s)) {
struct pcnet_initblk32 initblk;
tdra &= 0x00ffffff;
}
-#if defined(PCNET_DEBUG)
- printf("rlen=%d tlen=%d\n", rlen, tlen);
-#endif
+ trace_pcnet_rlen_tlen(s, rlen, tlen);
CSR_RCVRL(s) = (rlen < 9) ? (1 << rlen) : 512;
CSR_XMTRL(s) = (tlen < 9) ? (1 << tlen) : 512;
CSR_RCVRC(s) = CSR_RCVRL(s);
CSR_XMTRC(s) = CSR_XMTRL(s);
-#ifdef PCNET_DEBUG
- printf("pcnet ss32=%d rdra=0x%08x[%d] tdra=0x%08x[%d]\n",
- BCR_SSIZE32(s),
- s->rdra, CSR_RCVRL(s), s->tdra, CSR_XMTRL(s));
-#endif
+ trace_pcnet_ss32_rdra_tdra(s, BCR_SSIZE32(s),
+ s->rdra, CSR_RCVRL(s), s->tdra, CSR_XMTRL(s));
s->csr[0] |= 0x0101;
s->csr[0] &= ~0x0004; /* clear STOP bit */
return !!(CSR_CXST(s) & 0x8000);
}
-int pcnet_can_receive(NetClientState *nc)
-{
- PCNetState *s = qemu_get_nic_opaque(nc);
- if (CSR_STOP(s) || CSR_SPND(s))
- return 0;
-
- return sizeof(s->buffer)-16;
-}
-
#define MIN_BUF_SIZE 60
ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_)
hwaddr xmit_cxda = 0;
int count = CSR_XMTRL(s)-1;
int add_crc = 0;
-
+ int bcnt;
s->xmit_pos = -1;
if (!CSR_TXON(s)) {
s->xmit_pos = -1;
goto txdone;
}
+
+ if (s->xmit_pos < 0) {
+ goto txdone;
+ }
+
+ bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
+
+ /* if multi-tmd packet outsizes s->buffer then skip it silently.
+ Note: this is not what real hw does */
+ if (s->xmit_pos + bcnt > sizeof(s->buffer)) {
+ s->xmit_pos = -1;
+ goto txdone;
+ }
+
+ s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
+ s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s));
+ s->xmit_pos += bcnt;
+
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;
+ goto txdone;
+ }
+
#ifdef PCNET_DEBUG
- printf("pcnet_transmit size=%d\n", s->xmit_pos);
+ printf("pcnet_transmit size=%d\n", s->xmit_pos);
#endif
- if (CSR_LOOP(s)) {
- if (BCR_SWSTYLE(s) == 1)
- add_crc = !GET_FIELD(tmd.status, TMDS, NOFCS);
- s->looptest = add_crc ? PCNET_LOOPTEST_CRC : PCNET_LOOPTEST_NOCRC;
- pcnet_receive(qemu_get_queue(s->nic), s->buffer, s->xmit_pos);
- s->looptest = 0;
- } else
- if (s->nic)
- qemu_send_packet(qemu_get_queue(s->nic), s->buffer,
- s->xmit_pos);
-
- s->csr[0] &= ~0x0008; /* clear TDMD */
- s->csr[4] |= 0x0004; /* set TXSTRT */
- s->xmit_pos = -1;
+ if (CSR_LOOP(s)) {
+ if (BCR_SWSTYLE(s) == 1)
+ add_crc = !GET_FIELD(tmd.status, TMDS, NOFCS);
+ s->looptest = add_crc ? PCNET_LOOPTEST_CRC : PCNET_LOOPTEST_NOCRC;
+ pcnet_receive(qemu_get_queue(s->nic), s->buffer, s->xmit_pos);
+ s->looptest = 0;
+ } else {
+ if (s->nic) {
+ qemu_send_packet(qemu_get_queue(s->nic), s->buffer,
+ s->xmit_pos);
+ }
}
+ s->csr[0] &= ~0x0008; /* clear TDMD */
+ s->csr[4] |= 0x0004; /* set TXSTRT */
+ s->xmit_pos = -1;
+
txdone:
SET_FIELD(&tmd.status, TMDS, OWN, 0);
TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
VMSTATE_BUFFER(buffer, PCNetState),
VMSTATE_UNUSED_TEST(is_version_2, 4),
VMSTATE_INT32(tx_busy, PCNetState),
- VMSTATE_TIMER(poll_timer, PCNetState),
+ VMSTATE_TIMER_PTR(poll_timer, PCNetState),
VMSTATE_END_OF_LIST()
}
};
-void pcnet_common_cleanup(PCNetState *d)
-{
- d->nic = NULL;
-}
-
-int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info)
+void pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info)
{
int i;
uint16_t checksum;
*(uint16_t *)&s->prom[12] = cpu_to_le16(checksum);
s->lnkst = 0x40; /* initial link state: up */
-
- return 0;
}