/* Switch pcnet to 32bit mode */
pcnet_write_bcr(dev, 20, 2);
-#ifdef CONFIG_PN62
- /* Setup LED registers */
- val = pcnet_read_bcr(dev, 2) | 0x1000;
- pcnet_write_bcr(dev, 2, val); /* enable LEDPE */
- pcnet_write_bcr(dev, 4, 0x5080); /* 100MBit */
- pcnet_write_bcr(dev, 5, 0x40c0); /* LNKSE */
- pcnet_write_bcr(dev, 6, 0x4090); /* TX Activity */
- pcnet_write_bcr(dev, 7, 0x4084); /* RX Activity */
-#endif
-
/* Set/reset autoselect bit */
val = pcnet_read_bcr(dev, 2) & ~2;
val |= 2;
val |= 0x20;
pcnet_write_bcr(dev, 32, val);
+ /*
+ * Enable NOUFLO on supported controllers, with the transmit
+ * start point set to the full packet. This will cause entire
+ * packets to be buffered by the ethernet controller before
+ * transmission, eliminating underflows which are common on
+ * slower devices. Controllers which do not support NOUFLO will
+ * simply be left with a larger transmit FIFO threshold.
+ */
+ val = pcnet_read_bcr(dev, 18);
+ val |= 1 << 11;
+ pcnet_write_bcr(dev, 18, val);
+ val = pcnet_read_csr(dev, 80);
+ val |= 0x3 << 10;
+ pcnet_write_csr(dev, 80, val);
+
/*
* We only maintain one structure because the drivers will never
* be used concurrently. In 32bit mode the RX and TX ring entries
RX_RING_LEN_BITS);
lp->init_block.rx_ring = PCI_TO_MEM_LE(dev, lp->rx_ring);
lp->init_block.tx_ring = PCI_TO_MEM_LE(dev, lp->tx_ring);
+ flush_dcache_range((unsigned long)lp, (unsigned long)&lp->rx_buf);
PCNET_DEBUG1("\ntlen_rlen=0x%x rx_ring=0x%x tx_ring=0x%x\n",
lp->init_block.tlen_rlen,
PCNET_DEBUG2("Tx%d: %d bytes from 0x%p ", lp->cur_tx, pkt_len,
packet);
+ flush_dcache_range((unsigned long)packet,
+ (unsigned long)packet + pkt_len);
+
/* Wait for completion by testing the OWN bit */
for (i = 1000; i > 0; i--) {
+ invalidate_dcache_range((unsigned long)entry,
+ (unsigned long)entry + sizeof(*entry));
status = le16_to_cpu(entry->status);
if ((status & 0x8000) == 0)
break;
* set the status with the "ownership" bits last.
*/
status = 0x8300;
- entry->length = le16_to_cpu(-pkt_len);
+ entry->length = cpu_to_le16(-pkt_len);
entry->misc = 0x00000000;
entry->base = PCI_TO_MEM_LE(dev, packet);
- entry->status = le16_to_cpu(status);
+ entry->status = cpu_to_le16(status);
+ flush_dcache_range((unsigned long)entry,
+ (unsigned long)entry + sizeof(*entry));
/* Trigger an immediate send poll. */
pcnet_write_csr(dev, 0, 0x0008);
while (1) {
entry = &lp->rx_ring[lp->cur_rx];
+ invalidate_dcache_range((unsigned long)entry,
+ (unsigned long)entry + sizeof(*entry));
/*
* If we own the next entry, it's a new packet. Send it up.
*/
printf("%s: Rx%d: invalid packet length %d\n",
dev->name, lp->cur_rx, pkt_len);
} else {
+ invalidate_dcache_range(
+ (unsigned long)lp->rx_buf[lp->cur_rx],
+ (unsigned long)lp->rx_buf[lp->cur_rx] +
+ pkt_len);
NetReceive(lp->rx_buf[lp->cur_rx], pkt_len);
PCNET_DEBUG2("Rx%d: %d bytes from 0x%p\n",
lp->cur_rx, pkt_len,
}
}
entry->status |= cpu_to_le16(0x8000);
+ flush_dcache_range((unsigned long)entry,
+ (unsigned long)entry + sizeof(*entry));
if (++lp->cur_rx >= RX_RING_SIZE)
lp->cur_rx = 0;