summaryrefslogtreecommitdiffstats
path: root/drivers/net/bmac.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-09-19 19:15:08 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-09-19 19:15:08 +0000
commit03ba4131783cc9e872f8bb26a03f15bc11f27564 (patch)
tree88db8dba75ae06ba3bad08e42c5e52efc162535c /drivers/net/bmac.c
parent257730f99381dd26e10b832fce4c94cae7ac1176 (diff)
- Merge with Linux 2.1.121.
- Bugfixes.
Diffstat (limited to 'drivers/net/bmac.c')
-rw-r--r--drivers/net/bmac.c1248
1 files changed, 631 insertions, 617 deletions
diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c
index 536df548b..aef810322 100644
--- a/drivers/net/bmac.c
+++ b/drivers/net/bmac.c
@@ -27,6 +27,9 @@
*/
#define ENET_CRCPOLY 0x04c11db7
+/* switch to use multicast code lifted from sunhme driver */
+#define SUNHME_MULTICAST
+
/* a bunch of constants for the "Heathrow" interrupt controller.
These really should be in an include file somewhere */
#define IoBaseHeathrow ((unsigned *)0xf3000000)
@@ -51,7 +54,7 @@
#define XXDEBUG(args)
struct bmac_data {
-/* volatile struct bmac *bmac; */
+ /* volatile struct bmac *bmac; */
struct sk_buff_head *queue;
volatile struct dbdma_regs *tx_dma;
int tx_dma_intr;
@@ -82,7 +85,7 @@ typedef struct bmac_reg_entry {
unsigned short reg_offset;
} bmac_reg_entry_t;
-#define N_REG_ENTRIES 30
+#define N_REG_ENTRIES 31
bmac_reg_entry_t reg_entries[N_REG_ENTRIES] = {
{"MEMADD", MEMADD},
@@ -98,6 +101,7 @@ bmac_reg_entry_t reg_entries[N_REG_ENTRIES] = {
{"PAPAT", PAPAT},
{"TXSFD", TXSFD},
{"JAM", JAM},
+ {"TXCFG", TXCFG},
{"TXMAX", TXMAX},
{"TXMIN", TXMIN},
{"PAREG", PAREG},
@@ -133,8 +137,8 @@ static unsigned char dummy_buf[RX_BUFLEN];
* buffers on a 16 byte boundary.
*/
#define PRIV_BYTES (sizeof(struct bmac_data) \
- + (N_RX_RING + N_TX_RING + 4) * sizeof(struct dbdma_cmd) \
- + sizeof(struct sk_buff_head))
+ + (N_RX_RING + N_TX_RING + 4) * sizeof(struct dbdma_cmd) \
+ + sizeof(struct sk_buff_head))
static unsigned char bitrev(unsigned char b);
static int bmac_open(struct device *dev);
@@ -263,6 +267,7 @@ bmac_reset_chip(struct device *dev)
udelay(50000);
out_le32(heathrowFCR, fcrValue);
+ udelay(50000);
}
static void
@@ -273,7 +278,7 @@ bmac_init_registers(struct device *dev)
unsigned short *pWord16;
int i;
-/* XXDEBUG(("bmac: enter init_registers\n")); */
+ /* XXDEBUG(("bmac: enter init_registers\n")); */
bmwrite(dev, TXRST, TxResetBit);
@@ -468,6 +473,7 @@ bmac_init_tx_ring(struct bmac_data *bp)
if (!bp->tx_allocated) {
/* zero out tx cmds, alloc space for double buffering */
addr = (char *)kmalloc(ETHERMTU * N_TX_RING, GFP_DMA);
+ if (addr == NULL) return 0;
for (i = 0; i < N_TX_RING; i++, addr += ETHERMTU) bp->tx_double[i] = addr;
bp->tx_allocated = 1;
}
@@ -500,6 +506,7 @@ bmac_init_rx_ring(struct bmac_data *bp)
if (!bp->rx_allocated) {
for (i = 0; i < N_RX_RING; i++) {
bp->rx_bufs[i] = dev_alloc_skb(RX_BUFLEN+2);
+ if (bp->rx_bufs[i] == NULL) return 0;
skb_reserve(bp->rx_bufs[i], 2);
}
bp->rx_allocated = 1;
@@ -531,8 +538,8 @@ static int bmac_transmit_packet(struct sk_buff *skb, struct device *dev)
int i;
/* see if there's a free slot in the tx ring */
-/* XXDEBUG(("bmac_xmit_start: empty=%d fill=%d\n", */
-/* bp->tx_empty, bp->tx_fill)); */
+ /* XXDEBUG(("bmac_xmit_start: empty=%d fill=%d\n", */
+ /* bp->tx_empty, bp->tx_fill)); */
i = bp->tx_fill + 1;
if (i >= N_TX_RING) i = 0;
if (i == bp->tx_empty) {
@@ -637,8 +644,8 @@ static void bmac_txdma_intr(int irq, void *dev_id, struct pt_regs *regs)
XXDEBUG(("bmac_txdma_intr\n"));
}
-/* del_timer(&bp->tx_timeout); */
-/* bp->timeout_active = 0; */
+ /* del_timer(&bp->tx_timeout); */
+ /* bp->timeout_active = 0; */
while (1) {
cp = &bp->tx_cmds[bp->tx_empty];
@@ -655,8 +662,8 @@ static void bmac_txdma_intr(int irq, void *dev_id, struct pt_regs *regs)
bp->tx_bufs[bp->tx_empty] = NULL;
bp->tx_fullup = 0;
dev->tbusy = 0;
-/* XXDEBUG(("bmac_intr: cleared tbusy, empty=%d fill=%d\n", */
-/* i, bp->tx_fill)); */
+ /* XXDEBUG(("bmac_intr: cleared tbusy, empty=%d fill=%d\n", */
+ /* i, bp->tx_fill)); */
mark_bh(NET_BH);
if (++bp->tx_empty >= N_TX_RING) bp->tx_empty = 0;
if (bp->tx_empty == bp->tx_fill) break;
@@ -678,7 +685,7 @@ static struct net_device_stats *bmac_stats(struct device *dev)
return &p->stats;
}
-#if 0
+#ifndef SUNHME_MULTICAST
/* Real fast bit-reversal algorithm, 6-bit values */
static int reverse6[64] = {
0x0,0x20,0x10,0x30,0x8,0x28,0x18,0x38,
@@ -743,98 +750,98 @@ bmac_addhash(struct bmac_data *bp, unsigned char *addr)
unsigned int crc;
unsigned short mask;
- if (!(*addr
- crc = bmac_crc((unsigned short *)addr) & 0x3f; /* Big-endian alert! */
- crc = reverse6[crc]; /* Hyperfast bit-reversing algorithm */
- if (bp->hash_use_count[crc]++) return; /* This bit is already set */
- mask = crc % 16;
- mask = (unsigned char)1 << mask;
- bp->hash_use_count[crc/16] |= mask;
- }
-
- static void
- bmac_removehash(struct bmac_data *bp, unsigned char *addr)
- {
- unsigned int crc;
- unsigned char mask;
-
- /* Now, delete the address from the filter copy, as indicated */
- crc = bmac_crc((unsigned short *)addr) & 0x3f; /* Big-endian alert! */
- crc = reverse6[crc]; /* Hyperfast bit-reversing algorithm */
- if (bp->hash_use_count[crc] == 0) return; /* That bit wasn't in use! */
- if (--bp->hash_use_count[crc]) return; /* That bit is still in use */
- mask = crc % 16;
- mask = ((unsigned char)1 << mask) ^ 0xffff; /* To turn off bit */
- bp->hash_table_mask[crc/16] &= mask;
- }
+ if (!(*addr)) return;
+ crc = bmac_crc((unsigned short *)addr) & 0x3f; /* Big-endian alert! */
+ crc = reverse6[crc]; /* Hyperfast bit-reversing algorithm */
+ if (bp->hash_use_count[crc]++) return; /* This bit is already set */
+ mask = crc % 16;
+ mask = (unsigned char)1 << mask;
+ bp->hash_use_count[crc/16] |= mask;
+}
+
+static void
+bmac_removehash(struct bmac_data *bp, unsigned char *addr)
+{
+ unsigned int crc;
+ unsigned char mask;
+
+ /* Now, delete the address from the filter copy, as indicated */
+ crc = bmac_crc((unsigned short *)addr) & 0x3f; /* Big-endian alert! */
+ crc = reverse6[crc]; /* Hyperfast bit-reversing algorithm */
+ if (bp->hash_use_count[crc] == 0) return; /* That bit wasn't in use! */
+ if (--bp->hash_use_count[crc]) return; /* That bit is still in use */
+ mask = crc % 16;
+ mask = ((unsigned char)1 << mask) ^ 0xffff; /* To turn off bit */
+ bp->hash_table_mask[crc/16] &= mask;
+}
/*
* Sync the adapter with the software copy of the multicast mask
* (logical address filter).
*/
- static void
- bmac_rx_off(struct device *dev)
- {
- unsigned short rx_cfg;
-
- rx_cfg = bmread(dev, RXCFG);
- rx_cfg &= ~RxMACEnable;
- bmwrite(dev, RXCFG, rx_cfg);
- do {
- rx_cfg = bmread(dev, RXCFG);
- } while (rx_cfg & RxMACEnable);
- }
-
- unsigned short
- bmac_rx_on(struct device *dev, int hash_enable, int promisc_enable)
- {
- unsigned short rx_cfg;
-
- rx_cfg = bmread(dev, RXCFG);
- rx_cfg |= RxMACEnable;
- if (hash_enable) rx_cfg |= RxHashFilterEnable;
- else rx_cfg &= ~RxHashFilterEnable;
- if (promisc_enable) rx_cfg |= RxPromiscEnable;
- else rx_cfg &= ~RxPromiscEnable;
- bmwrite(dev, RXRST, RxResetValue);
- bmwrite(dev, RXFIFOCSR, 0); /* first disable rxFIFO */
- bmwrite(dev, RXFIFOCSR, RxFIFOEnable );
- bmwrite(dev, RXCFG, rx_cfg );
- return rx_cfg;
- }
-
- static void
- bmac_update_hash_table_mask(struct device *dev, struct bmac_data *bp)
- {
- bmwrite(dev, BHASH3, bp->hash_table_mask[0]); /* bits 15 - 0 */
- bmwrite(dev, BHASH2, bp->hash_table_mask[1]); /* bits 31 - 16 */
- bmwrite(dev, BHASH1, bp->hash_table_mask[2]); /* bits 47 - 32 */
- bmwrite(dev, BHASH0, bp->hash_table_mask[3]); /* bits 63 - 48 */
- }
+static void
+bmac_rx_off(struct device *dev)
+{
+ unsigned short rx_cfg;
+
+ rx_cfg = bmread(dev, RXCFG);
+ rx_cfg &= ~RxMACEnable;
+ bmwrite(dev, RXCFG, rx_cfg);
+ do {
+ rx_cfg = bmread(dev, RXCFG);
+ } while (rx_cfg & RxMACEnable);
+}
+
+unsigned short
+bmac_rx_on(struct device *dev, int hash_enable, int promisc_enable)
+{
+ unsigned short rx_cfg;
+
+ rx_cfg = bmread(dev, RXCFG);
+ rx_cfg |= RxMACEnable;
+ if (hash_enable) rx_cfg |= RxHashFilterEnable;
+ else rx_cfg &= ~RxHashFilterEnable;
+ if (promisc_enable) rx_cfg |= RxPromiscEnable;
+ else rx_cfg &= ~RxPromiscEnable;
+ bmwrite(dev, RXRST, RxResetValue);
+ bmwrite(dev, RXFIFOCSR, 0); /* first disable rxFIFO */
+ bmwrite(dev, RXFIFOCSR, RxFIFOEnable );
+ bmwrite(dev, RXCFG, rx_cfg );
+ return rx_cfg;
+}
+
+static void
+bmac_update_hash_table_mask(struct device *dev, struct bmac_data *bp)
+{
+ bmwrite(dev, BHASH3, bp->hash_table_mask[0]); /* bits 15 - 0 */
+ bmwrite(dev, BHASH2, bp->hash_table_mask[1]); /* bits 31 - 16 */
+ bmwrite(dev, BHASH1, bp->hash_table_mask[2]); /* bits 47 - 32 */
+ bmwrite(dev, BHASH0, bp->hash_table_mask[3]); /* bits 63 - 48 */
+}
#if 0
- static void
- bmac_add_multi(struct device *dev,
- struct bmac_data *bp, unsigned char *addr)
- {
-/* XXDEBUG(("bmac: enter bmac_add_multi\n")); */
- bmac_addhash(bp, addr);
- bmac_rx_off(dev);
- bmac_update_hash_table_mask(dev, bp);
- bmac_rx_on(dev, 1, (dev->flags & IFF_PROMISC)? 1 : 0);
-/* XXDEBUG(("bmac: exit bmac_add_multi\n")); */
- }
-
- static void
- bmac_remove_multi(struct device *dev,
- struct bmac_data *bp, unsigned char *addr)
- {
- bmac_removehash(bp, addr);
- bmac_rx_off(dev);
- bmac_update_hash_table_mask(dev, bp);
- bmac_rx_on(dev, 1, (dev->flags & IFF_PROMISC)? 1 : 0);
- }
+static void
+bmac_add_multi(struct device *dev,
+ struct bmac_data *bp, unsigned char *addr)
+{
+ /* XXDEBUG(("bmac: enter bmac_add_multi\n")); */
+ bmac_addhash(bp, addr);
+ bmac_rx_off(dev);
+ bmac_update_hash_table_mask(dev, bp);
+ bmac_rx_on(dev, 1, (dev->flags & IFF_PROMISC)? 1 : 0);
+ /* XXDEBUG(("bmac: exit bmac_add_multi\n")); */
+}
+
+static void
+bmac_remove_multi(struct device *dev,
+ struct bmac_data *bp, unsigned char *addr)
+{
+ bmac_removehash(bp, addr);
+ bmac_rx_off(dev);
+ bmac_update_hash_table_mask(dev, bp);
+ bmac_rx_on(dev, 1, (dev->flags & IFF_PROMISC)? 1 : 0);
+}
#endif
/* Set or clear the multicast filter for this adaptor.
@@ -843,134 +850,138 @@ bmac_addhash(struct bmac_data *bp, unsigned char *addr)
num_addrs > 0 Multicast mode, receive normal and MC packets, and do
best-effort filtering.
*/
- static void bmac_set_multicast(struct device *dev)
- {
- struct dev_mc_list *dmi;
- struct bmac_data *bp = (struct bmac_data *) dev->priv;
- int num_addrs = dev->mc_count;
- unsigned short rx_cfg;
- int i;
-
- XXDEBUG(("bmac: enter bmac_set_multicast, n_addrs=%d\n", num_addrs));
-
- if((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) {
- for (i=0; i<4; i++) bp->hash_table_mask[i] = 0xffff;
- bmac_update_hash_table_mask(dev, bp);
- rx_cfg = bmac_rx_on(dev, 1, 0);
- XXDEBUG(("bmac: all multi, rx_cfg=%#08x\n"));
- } else if if ((dev->flags & IFF_PROMISC) || (num_addrs < 0)) {
- rx_cfg = bmread(dev, RXCFG);
- rx_cfg |= RxPromiscEnable;
- bmwrite(dev, RXCFG, rx_cfg);
- rx_cfg = bmac_rx_on(dev, 0, 1);
- XXDEBUG(("bmac: promisc mode enabled, rx_cfg=%#08x\n", rx_cfg));
- } else {
- for (i=0; i<4; i++) bp->hash_table_mask[i] = 0;
- for (i=0; i<64; i++) bp->hash_use_count[i] = 0;
- if (num_addrs == 0) {
- rx_cfg = bmac_rx_on(dev, 0, 0);
- XXDEBUG(("bmac: multi disabled, rx_cfg=%#08x\n", rx_cfg));
- } else {
- for (dmi=dev->mc_list; dmi!=NULL; dmi=dmi->next)
- bmac_addhash(bp, dmi->dmi_addr);
- bmac_update_hash_table_mask(dev, bp);
- rx_cfg = bmac_rx_on(dev, 1, 0);
- XXDEBUG(("bmac: multi enabled, rx_cfg=%#08x\n", rx_cfg));
- }
- }
-/* XXDEBUG(("bmac: exit bmac_set_multicast\n")); */
- }
-#endif
+static void bmac_set_multicast(struct device *dev)
+{
+ struct dev_mc_list *dmi;
+ struct bmac_data *bp = (struct bmac_data *) dev->priv;
+ int num_addrs = dev->mc_count;
+ unsigned short rx_cfg;
+ int i;
+
+ XXDEBUG(("bmac: enter bmac_set_multicast, n_addrs=%d\n", num_addrs));
+
+ if((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) {
+ for (i=0; i<4; i++) bp->hash_table_mask[i] = 0xffff;
+ bmac_update_hash_table_mask(dev, bp);
+ rx_cfg = bmac_rx_on(dev, 1, 0);
+ XXDEBUG(("bmac: all multi, rx_cfg=%#08x\n"));
+ } else if ((dev->flags & IFF_PROMISC) || (num_addrs < 0)) {
+ rx_cfg = bmread(dev, RXCFG);
+ rx_cfg |= RxPromiscEnable;
+ bmwrite(dev, RXCFG, rx_cfg);
+ rx_cfg = bmac_rx_on(dev, 0, 1);
+ XXDEBUG(("bmac: promisc mode enabled, rx_cfg=%#08x\n", rx_cfg));
+ } else {
+ for (i=0; i<4; i++) bp->hash_table_mask[i] = 0;
+ for (i=0; i<64; i++) bp->hash_use_count[i] = 0;
+ if (num_addrs == 0) {
+ rx_cfg = bmac_rx_on(dev, 0, 0);
+ XXDEBUG(("bmac: multi disabled, rx_cfg=%#08x\n", rx_cfg));
+ } else {
+ for (dmi=dev->mc_list; dmi!=NULL; dmi=dmi->next)
+ bmac_addhash(bp, dmi->dmi_addr);
+ bmac_update_hash_table_mask(dev, bp);
+ rx_cfg = bmac_rx_on(dev, 1, 0);
+ XXDEBUG(("bmac: multi enabled, rx_cfg=%#08x\n", rx_cfg));
+ }
+ }
+ /* XXDEBUG(("bmac: exit bmac_set_multicast\n")); */
+}
+#else /* ifdef SUNHME_MULTICAST */
/* The version of set_multicast below was lifted from sunhme.c */
#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */
#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */
- static void bmac_set_multicast(struct device *dev)
- {
- struct dev_mc_list *dmi = dev->mc_list;
- char *addrs;
- int i, j, bit, byte;
- unsigned short rx_cfg;
- u32 crc, poly = CRC_POLYNOMIAL_LE;
+static void bmac_set_multicast(struct device *dev)
+{
+ struct dev_mc_list *dmi = dev->mc_list;
+ char *addrs;
+ int i, j, bit, byte;
+ unsigned short rx_cfg;
+ u32 crc, poly = CRC_POLYNOMIAL_LE;
- /* Let the transmits drain. */
-/* while(dev->tbusy) schedule(); */
+ /* Let the transmits drain. */
+ /* while(dev->tbusy) schedule(); */
- /* Lock out others. */
-/* set_bit(0, (void *) &dev->tbusy); */
+ /* Lock out others. */
+ /* set_bit(0, (void *) &dev->tbusy); */
- if((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) {
- bmwrite(dev, BHASH0, 0xffff);
- bmwrite(dev, BHASH1, 0xffff);
- bmwrite(dev, BHASH2, 0xffff);
- bmwrite(dev, BHASH3, 0xffff);
- } else if(dev->flags & IFF_PROMISC) {
- rx_cfg = bmread(dev, RXCFG);
- rx_cfg |= RxPromiscEnable;
- bmwrite(dev, RXCFG, rx_cfg);
- } else {
- u16 hash_table[4];
+ if((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) {
+ bmwrite(dev, BHASH0, 0xffff);
+ bmwrite(dev, BHASH1, 0xffff);
+ bmwrite(dev, BHASH2, 0xffff);
+ bmwrite(dev, BHASH3, 0xffff);
+ } else if(dev->flags & IFF_PROMISC) {
+ rx_cfg = bmread(dev, RXCFG);
+ rx_cfg |= RxPromiscEnable;
+ bmwrite(dev, RXCFG, rx_cfg);
+ } else {
+ u16 hash_table[4];
- for(i = 0; i < 4; i++) hash_table[i] = 0;
+ rx_cfg = bmread(dev, RXCFG);
+ rx_cfg &= ~RxPromiscEnable;
+ bmwrite(dev, RXCFG, rx_cfg);
+
+ for(i = 0; i < 4; i++) hash_table[i] = 0;
- for(i = 0; i < dev->mc_count; i++) {
- addrs = dmi->dmi_addr;
- dmi = dmi->next;
+ for(i = 0; i < dev->mc_count; i++) {
+ addrs = dmi->dmi_addr;
+ dmi = dmi->next;
- if(!(*addrs & 1))
- continue;
+ if(!(*addrs & 1))
+ continue;
- crc = 0xffffffffU;
- for(byte = 0; byte < 6; byte++) {
- for(bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) {
- int test;
+ crc = 0xffffffffU;
+ for(byte = 0; byte < 6; byte++) {
+ for(bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) {
+ int test;
- test = ((bit ^ crc) & 0x01);
- crc >>= 1;
- if(test)
- crc = crc ^ poly;
- }
- }
- crc >>= 26;
- hash_table[crc >> 4] |= 1 << (crc & 0xf);
- }
- bmwrite(dev, BHASH0, hash_table[0]);
- bmwrite(dev, BHASH1, hash_table[1]);
- bmwrite(dev, BHASH2, hash_table[2]);
- bmwrite(dev, BHASH3, hash_table[3]);
- }
+ test = ((bit ^ crc) & 0x01);
+ crc >>= 1;
+ if(test)
+ crc = crc ^ poly;
+ }
+ }
+ crc >>= 26;
+ hash_table[crc >> 4] |= 1 << (crc & 0xf);
+ }
+ bmwrite(dev, BHASH0, hash_table[0]);
+ bmwrite(dev, BHASH1, hash_table[1]);
+ bmwrite(dev, BHASH2, hash_table[2]);
+ bmwrite(dev, BHASH3, hash_table[3]);
+ }
- /* Let us get going again. */
-/* dev->tbusy = 0; */
- }
-
-
- static int miscintcount = 0;
-
- static void bmac_misc_intr(int irq, void *dev_id, struct pt_regs *regs)
- {
- struct device *dev = (struct device *) dev_id;
- struct bmac_data *bp = (struct bmac_data *)dev->priv;
- unsigned int status = bmread(dev, STATUS);
- if (miscintcount++ < 10) {
- XXDEBUG(("bmac_misc_intr\n"));
- }
-/* XXDEBUG(("bmac_misc_intr, status=%#08x\n", status)); */
-/* bmac_txdma_intr_inner(irq, dev_id, regs); */
-/* if (status & FrameReceived) bp->stats.rx_dropped++; */
- if (status & RxErrorMask) bp->stats.rx_errors++;
- if (status & RxCRCCntExp) bp->stats.rx_crc_errors++;
- if (status & RxLenCntExp) bp->stats.rx_length_errors++;
- if (status & RxOverFlow) bp->stats.rx_over_errors++;
- if (status & RxAlignCntExp) bp->stats.rx_frame_errors++;
-
-/* if (status & FrameSent) bp->stats.tx_dropped++; */
- if (status & TxErrorMask) bp->stats.tx_errors++;
- if (status & TxUnderrun) bp->stats.tx_fifo_errors++;
- if (status & TxNormalCollExp) bp->stats.collisions++;
- }
+ /* Let us get going again. */
+ /* dev->tbusy = 0; */
+}
+#endif /* SUNHME_MULTICAST */
+
+static int miscintcount = 0;
+
+static void bmac_misc_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct device *dev = (struct device *) dev_id;
+ struct bmac_data *bp = (struct bmac_data *)dev->priv;
+ unsigned int status = bmread(dev, STATUS);
+ if (miscintcount++ < 10) {
+ XXDEBUG(("bmac_misc_intr\n"));
+ }
+ /* XXDEBUG(("bmac_misc_intr, status=%#08x\n", status)); */
+ /* bmac_txdma_intr_inner(irq, dev_id, regs); */
+ /* if (status & FrameReceived) bp->stats.rx_dropped++; */
+ if (status & RxErrorMask) bp->stats.rx_errors++;
+ if (status & RxCRCCntExp) bp->stats.rx_crc_errors++;
+ if (status & RxLenCntExp) bp->stats.rx_length_errors++;
+ if (status & RxOverFlow) bp->stats.rx_over_errors++;
+ if (status & RxAlignCntExp) bp->stats.rx_frame_errors++;
+
+ /* if (status & FrameSent) bp->stats.tx_dropped++; */
+ if (status & TxErrorMask) bp->stats.tx_errors++;
+ if (status & TxUnderrun) bp->stats.tx_fifo_errors++;
+ if (status & TxNormalCollExp) bp->stats.collisions++;
+}
/*
* Procedure for reading EEPROM
@@ -988,464 +999,467 @@ bmac_addhash(struct bmac_data *bp, unsigned char *addr)
#define SROMAddressBits 6
#define EnetAddressOffset 20
- static unsigned char
- bmac_clock_out_bit(struct device *dev)
- {
- unsigned short data;
- unsigned short val;
+static unsigned char
+bmac_clock_out_bit(struct device *dev)
+{
+ unsigned short data;
+ unsigned short val;
- bmwrite(dev, SROMCSR, ChipSelect | Clk);
- udelay(DelayValue);
+ bmwrite(dev, SROMCSR, ChipSelect | Clk);
+ udelay(DelayValue);
- data = bmread(dev, SROMCSR);
- udelay(DelayValue);
- val = (data >> SD0ShiftCount) & 1;
+ data = bmread(dev, SROMCSR);
+ udelay(DelayValue);
+ val = (data >> SD0ShiftCount) & 1;
- bmwrite(dev, SROMCSR, ChipSelect);
- udelay(DelayValue);
+ bmwrite(dev, SROMCSR, ChipSelect);
+ udelay(DelayValue);
- return val;
- }
+ return val;
+}
- static void
- bmac_clock_in_bit(struct device *dev, unsigned int val)
- {
- unsigned short data;
+static void
+bmac_clock_in_bit(struct device *dev, unsigned int val)
+{
+ unsigned short data;
- if (val != 0 && val != 1) return;
+ if (val != 0 && val != 1) return;
- data = (val << SDIShiftCount);
- bmwrite(dev, SROMCSR, data | ChipSelect );
- udelay(DelayValue);
+ data = (val << SDIShiftCount);
+ bmwrite(dev, SROMCSR, data | ChipSelect );
+ udelay(DelayValue);
- bmwrite(dev, SROMCSR, data | ChipSelect | Clk );
- udelay(DelayValue);
-
- bmwrite(dev, SROMCSR, data | ChipSelect);
- udelay(DelayValue);
- }
-
- static void
- reset_and_select_srom(struct device *dev)
- {
- /* first reset */
- bmwrite(dev, SROMCSR, 0);
- udelay(DelayValue);
+ bmwrite(dev, SROMCSR, data | ChipSelect | Clk );
+ udelay(DelayValue);
+
+ bmwrite(dev, SROMCSR, data | ChipSelect);
+ udelay(DelayValue);
+}
+
+static void
+reset_and_select_srom(struct device *dev)
+{
+ /* first reset */
+ bmwrite(dev, SROMCSR, 0);
+ udelay(DelayValue);
- /* send it the read command (110) */
- bmac_clock_in_bit(dev, 1);
- bmac_clock_in_bit(dev, 1);
- bmac_clock_in_bit(dev, 0);
- }
-
- static unsigned short
- read_srom(struct device *dev, unsigned int addr, unsigned int addr_len)
- {
- unsigned short data, val;
- int i;
+ /* send it the read command (110) */
+ bmac_clock_in_bit(dev, 1);
+ bmac_clock_in_bit(dev, 1);
+ bmac_clock_in_bit(dev, 0);
+}
+
+static unsigned short
+read_srom(struct device *dev, unsigned int addr, unsigned int addr_len)
+{
+ unsigned short data, val;
+ int i;
- /* send out the address we want to read from */
- for (i = 0; i < addr_len; i++) {
- val = addr >> (addr_len-i-1);
- bmac_clock_in_bit(dev, val & 1);
- }
+ /* send out the address we want to read from */
+ for (i = 0; i < addr_len; i++) {
+ val = addr >> (addr_len-i-1);
+ bmac_clock_in_bit(dev, val & 1);
+ }
- /* Now read in the 16-bit data */
- data = 0;
- for (i = 0; i < 16; i++) {
- val = bmac_clock_out_bit(dev);
- data <<= 1;
- data |= val;
- }
- bmwrite(dev, SROMCSR, 0);
+ /* Now read in the 16-bit data */
+ data = 0;
+ for (i = 0; i < 16; i++) {
+ val = bmac_clock_out_bit(dev);
+ data <<= 1;
+ data |= val;
+ }
+ bmwrite(dev, SROMCSR, 0);
- return data;
- }
+ return data;
+}
/*
* It looks like Cogent and SMC use different methods for calculating
* checksums. What a pain..
*/
- static int
- bmac_verify_checksum(struct device *dev)
- {
- unsigned short data, storedCS;
+static int
+bmac_verify_checksum(struct device *dev)
+{
+ unsigned short data, storedCS;
- reset_and_select_srom(dev);
- data = read_srom(dev, 3, SROMAddressBits);
- storedCS = ((data >> 8) & 0x0ff) | ((data << 8) & 0xff00);
+ reset_and_select_srom(dev);
+ data = read_srom(dev, 3, SROMAddressBits);
+ storedCS = ((data >> 8) & 0x0ff) | ((data << 8) & 0xff00);
- return 0;
- }
-
-
- static void
- bmac_get_station_address(struct device *dev, unsigned char *ea)
- {
- int i;
- unsigned short data;
-
- for (i = 0; i < 6; i++)
- {
- reset_and_select_srom(dev);
- data = read_srom(dev, i + EnetAddressOffset/2, SROMAddressBits);
- ea[2*i] = bitrev(data & 0x0ff);
- ea[2*i+1] = bitrev((data >> 8) & 0x0ff);
- }
- }
-
- static int bmac_reset_and_enable(struct device *dev, int enable)
- {
- struct bmac_data *bp = dev->priv;
- unsigned long flags;
-
- save_flags(flags); cli();
- bp->reset_and_enabled = 0;
- bmac_reset_chip(dev);
- if (enable) {
- if (!bmac_init_tx_ring(bp) || !bmac_init_rx_ring(bp)) return 0;
- if (!bmac_init_chip(dev)) return 0;
- bmac_start_chip(dev);
- bmwrite(dev, INTDISABLE, EnableNormal);
- bp->reset_and_enabled = 1;
-/* { */
-/* unsigned char random_packet[100]; */
-/* unsigned int i; */
-/* struct sk_buff *skb = dev_alloc_skb(RX_BUFLEN+2); */
-/* unsigned char *data = skb_put(skb, sizeof(random_packet)); */
-/* XXDEBUG(("transmitting random packet\n")); */
-/* for (i = 0; i < sizeof(random_packet); i++) data[i] = i; */
-/* bmac_transmit_packet(skb, dev); */
-/* XXDEBUG(("done transmitting random packet\n")); */
-/* } */
- }
- restore_flags(flags);
- return 1;
- }
-
- int
- bmac_probe(struct device *dev)
- {
- int j, rev;
- struct bmac_data *bp;
- struct device_node *bmacs;
- unsigned char *addr;
-
- bmacs = find_devices("bmac");
- if (bmacs == NULL) return ENODEV;
-
- bmac_devs = dev; /* KLUDGE!! */
-
- if (bmacs->n_addrs != 3 || bmacs->n_intrs != 3) {
- printk(KERN_ERR "can't use BMAC %s: expect 3 addrs and 3 intrs\n",
- bmacs->full_name);
- return EINVAL;
- }
+ return 0;
+}
+
+
+static void
+bmac_get_station_address(struct device *dev, unsigned char *ea)
+{
+ int i;
+ unsigned short data;
+
+ for (i = 0; i < 6; i++)
+ {
+ reset_and_select_srom(dev);
+ data = read_srom(dev, i + EnetAddressOffset/2, SROMAddressBits);
+ ea[2*i] = bitrev(data & 0x0ff);
+ ea[2*i+1] = bitrev((data >> 8) & 0x0ff);
+ }
+}
+
+static int bmac_reset_and_enable(struct device *dev, int enable)
+{
+ struct bmac_data *bp = dev->priv;
+ unsigned long flags;
+
+ save_flags(flags); cli();
+ bp->reset_and_enabled = 0;
+ bmac_reset_chip(dev);
+ if (enable) {
+ if (!bmac_init_tx_ring(bp) || !bmac_init_rx_ring(bp)) return 0;
+ if (!bmac_init_chip(dev)) return 0;
+ bmac_start_chip(dev);
+ bmwrite(dev, INTDISABLE, EnableNormal);
+ bp->reset_and_enabled = 1;
+ /* { */
+ /* unsigned char random_packet[100]; */
+ /* unsigned int i; */
+ /* struct sk_buff *skb = dev_alloc_skb(RX_BUFLEN+2); */
+ /* unsigned char *data = skb_put(skb, sizeof(random_packet)); */
+ /* XXDEBUG(("transmitting random packet\n")); */
+ /* for (i = 0; i < sizeof(random_packet); i++) data[i] = i; */
+ /* bmac_transmit_packet(skb, dev); */
+ /* XXDEBUG(("done transmitting random packet\n")); */
+ /* } */
+ }
+ restore_flags(flags);
+ return 1;
+}
+
+int
+bmac_probe(struct device *dev)
+{
+ int j, rev;
+ struct bmac_data *bp;
+ struct device_node *bmacs;
+ unsigned char *addr;
+ static struct device_node *all_bmacs = NULL, *next_bmac;
+
+ if (all_bmacs == NULL)
+ all_bmacs = next_bmac = find_devices("bmac");
+ bmacs = next_bmac;
+ if (bmacs == NULL) return -ENODEV;
+ next_bmac = bmacs->next;
+
+ bmac_devs = dev; /* KLUDGE!! */
+
+ if (bmacs->n_addrs != 3 || bmacs->n_intrs != 3) {
+ printk(KERN_ERR "can't use BMAC %s: expect 3 addrs and 3 intrs\n",
+ bmacs->full_name);
+ return -EINVAL;
+ }
- if (dev == NULL) {
- dev = init_etherdev(NULL, PRIV_BYTES);
- bmac_devs = dev; /*KLUDGE!!*/
- } else {
- /* XXX this doesn't look right (but it's never used :-) */
- dev->priv = kmalloc(PRIV_BYTES, GFP_KERNEL);
- if (dev->priv == 0) return -ENOMEM;
- }
+ if (dev == NULL) {
+ dev = init_etherdev(NULL, PRIV_BYTES);
+ bmac_devs = dev; /*KLUDGE!!*/
+ } else {
+ /* XXX this doesn't look right (but it's never used :-) */
+ dev->priv = kmalloc(PRIV_BYTES, GFP_KERNEL);
+ if (dev->priv == 0) return -ENOMEM;
+ }
- dev->base_addr = bmacs->addrs[0].address;
- dev->irq = bmacs->intrs[0].line;
+ dev->base_addr = bmacs->addrs[0].address;
+ dev->irq = bmacs->intrs[0].line;
- bmwrite(dev, INTDISABLE, DisableAll);
-
- if (request_irq(dev->irq, bmac_misc_intr, 0, "BMAC-misc", dev)) {
- printk(KERN_ERR "BMAC: can't get irq %d\n", dev->irq);
- return -EAGAIN;
- }
- if (request_irq(bmacs->intrs[1].line, bmac_txdma_intr, 0, "BMAC-txdma",
- dev)) {
- printk(KERN_ERR "BMAC: can't get irq %d\n", bmacs->intrs[1].line);
- return -EAGAIN;
- }
- if (request_irq(bmacs->intrs[2].line, bmac_rxdma_intr, 0, "BMAC-rxdma",
- dev)) {
- printk(KERN_ERR "BMAC: can't get irq %d\n", bmacs->intrs[2].line);
- return -EAGAIN;
- }
+ bmwrite(dev, INTDISABLE, DisableAll);
- addr = get_property(bmacs, "mac-address", NULL);
- if (addr == NULL) {
- addr = get_property(bmacs, "local-mac-address", NULL);
- if (addr == NULL) {
- printk(KERN_ERR "Can't get mac-address for BMAC at %lx\n",
- dev->base_addr);
- return -EAGAIN;
- }
- }
+ addr = get_property(bmacs, "mac-address", NULL);
+ if (addr == NULL) {
+ addr = get_property(bmacs, "local-mac-address", NULL);
+ if (addr == NULL) {
+ printk(KERN_ERR "Can't get mac-address for BMAC at %lx\n",
+ dev->base_addr);
+ return -EAGAIN;
+ }
+ }
- printk(KERN_INFO "%s: BMAC at", dev->name);
- rev = addr[0] == 0 && addr[1] == 0xA0;
- for (j = 0; j < 6; ++j) {
- dev->dev_addr[j] = rev? bitrev(addr[j]): addr[j];
- printk("%c%.2x", (j? ':': ' '), dev->dev_addr[j]);
- }
- XXDEBUG((", base_addr=%#0lx", dev->base_addr));
- printk("\n");
+ printk(KERN_INFO "%s: BMAC at", dev->name);
+ rev = addr[0] == 0 && addr[1] == 0xA0;
+ for (j = 0; j < 6; ++j) {
+ dev->dev_addr[j] = rev? bitrev(addr[j]): addr[j];
+ printk("%c%.2x", (j? ':': ' '), dev->dev_addr[j]);
+ }
+ XXDEBUG((", base_addr=%#0lx", dev->base_addr));
+ printk("\n");
- dev->open = bmac_open;
- dev->stop = bmac_close;
- dev->hard_start_xmit = bmac_output;
- dev->get_stats = bmac_stats;
- dev->set_multicast_list = bmac_set_multicast;
- dev->set_mac_address = bmac_set_address;
-
- bmac_get_station_address(dev, addr);
- if (bmac_verify_checksum(dev) != 0) return EINVAL;
+ dev->open = bmac_open;
+ dev->stop = bmac_close;
+ dev->hard_start_xmit = bmac_output;
+ dev->get_stats = bmac_stats;
+ dev->set_multicast_list = bmac_set_multicast;
+ dev->set_mac_address = bmac_set_address;
+
+ bmac_get_station_address(dev, addr);
+ if (bmac_verify_checksum(dev) != 0) return -EINVAL;
- ether_setup(dev);
+ ether_setup(dev);
- bp = (struct bmac_data *) dev->priv;
- memset(bp, 0, sizeof(struct bmac_data));
- bp->tx_dma = (volatile struct dbdma_regs *) bmacs->addrs[1].address;
- bp->tx_dma_intr = bmacs->intrs[1].line;
- bp->rx_dma = (volatile struct dbdma_regs *) bmacs->addrs[2].address;
- bp->rx_dma_intr = bmacs->intrs[2].line;
+ bp = (struct bmac_data *) dev->priv;
+ memset(bp, 0, sizeof(struct bmac_data));
+ bp->tx_dma = (volatile struct dbdma_regs *) bmacs->addrs[1].address;
+ bp->tx_dma_intr = bmacs->intrs[1].line;
+ bp->rx_dma = (volatile struct dbdma_regs *) bmacs->addrs[2].address;
+ bp->rx_dma_intr = bmacs->intrs[2].line;
- bp->tx_cmds = (volatile struct dbdma_cmd *) DBDMA_ALIGN(bp + 1);
- bp->rx_cmds = bp->tx_cmds + N_TX_RING + 1;
+ bp->tx_cmds = (volatile struct dbdma_cmd *) DBDMA_ALIGN(bp + 1);
+ bp->rx_cmds = bp->tx_cmds + N_TX_RING + 1;
- bp->queue = (struct sk_buff_head *)(bp->rx_cmds + N_RX_RING + 1);
- skb_queue_head_init(bp->queue);
+ bp->queue = (struct sk_buff_head *)(bp->rx_cmds + N_RX_RING + 1);
+ skb_queue_head_init(bp->queue);
- memset(&bp->stats, 0, sizeof(bp->stats));
- memset((char *) bp->tx_cmds, 0,
- (N_TX_RING + N_RX_RING + 2) * sizeof(struct dbdma_cmd));
-/* init_timer(&bp->tx_timeout); */
-/* bp->timeout_active = 0; */
+ memset(&bp->stats, 0, sizeof(bp->stats));
+ memset((char *) bp->tx_cmds, 0,
+ (N_TX_RING + N_RX_RING + 2) * sizeof(struct dbdma_cmd));
+ /* init_timer(&bp->tx_timeout); */
+ /* bp->timeout_active = 0; */
+
+ if (request_irq(dev->irq, bmac_misc_intr, 0, "BMAC-misc", dev)) {
+ printk(KERN_ERR "BMAC: can't get irq %d\n", dev->irq);
+ return -EAGAIN;
+ }
+ if (request_irq(bmacs->intrs[1].line, bmac_txdma_intr, 0, "BMAC-txdma",
+ dev)) {
+ printk(KERN_ERR "BMAC: can't get irq %d\n", bmacs->intrs[1].line);
+ return -EAGAIN;
+ }
+ if (request_irq(bmacs->intrs[2].line, bmac_rxdma_intr, 0, "BMAC-rxdma",
+ dev)) {
+ printk(KERN_ERR "BMAC: can't get irq %d\n", bmacs->intrs[2].line);
+ return -EAGAIN;
+ }
+
+ if (!bmac_reset_and_enable(dev, 0)) return -ENOMEM;
- if (!bmac_reset_and_enable(dev, 0)) return EINVAL;
-
#ifdef CONFIG_PROC_FS
- proc_net_register(&(struct proc_dir_entry) {
- PROC_NET_BMAC, 4, "bmac",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_net_inode_operations,
- bmac_proc_info
- });
+ proc_net_register(&(struct proc_dir_entry) {
+ PROC_NET_BMAC, 4, "bmac",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ bmac_proc_info
+ });
#endif
- return 0;
- }
-
- static int bmac_open(struct device *dev)
- {
-/* XXDEBUG(("bmac: enter open\n")); */
- /* reset the chip */
- bmac_reset_and_enable(dev, 1);
-
- dev->flags |= IFF_UP | IFF_RUNNING;
-
- return 0;
- }
-
- static int bmac_close(struct device *dev)
- {
- struct bmac_data *bp = (struct bmac_data *) dev->priv;
- volatile struct dbdma_regs *rd = bp->rx_dma;
- volatile struct dbdma_regs *td = bp->tx_dma;
- unsigned short config;
- int i;
-
- dev->flags &= ~(IFF_UP | IFF_RUNNING);
-
- /* disable rx and tx */
- config = bmread(dev, RXCFG);
- bmwrite(dev, RXCFG, (config & ~RxMACEnable));
-
- config = bmread(dev, TXCFG);
- bmwrite(dev, TXCFG, (config & ~TxMACEnable));
-
- bmwrite(dev, INTDISABLE, DisableAll); /* disable all intrs */
-
- /* disable rx and tx dma */
- st_le32(&rd->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE)); /* clear run bit */
- st_le32(&td->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE)); /* clear run bit */
-
- /* free some skb's */
- XXDEBUG(("bmac: free rx bufs\n"));
- for (i=0; i<N_RX_RING; i++) {
- if (bp->rx_bufs[i] != NULL) {
- dev_kfree_skb(bp->rx_bufs[i]);
- bp->rx_bufs[i] = NULL;
- }
- }
- bp->rx_allocated = 0;
- XXDEBUG(("bmac: free doubles\n"));/*MEMORY LEAK BELOW!!! FIX!!! */
- if (bp->tx_double[0] != NULL) kfree(bp->tx_double[0]);
- XXDEBUG(("bmac: free tx bufs\n"));
- for (i = 0; i<N_TX_RING; i++) {
- if (bp->tx_bufs[i] != NULL) {
- dev_kfree_skb(bp->tx_bufs[i]);
- bp->tx_bufs[i] = NULL;
- }
- }
- bp->tx_allocated = 0;
- bp->reset_and_enabled = 0;
- XXDEBUG(("bmac: all bufs freed\n"));
-
- return 0;
- }
-
- static void
- bmac_start(struct device *dev)
- {
- struct bmac_data *bp = dev->priv;
- int i;
- struct sk_buff *skb;
- unsigned long flags;
+ return 0;
+}
+
+static int bmac_open(struct device *dev)
+{
+ /* XXDEBUG(("bmac: enter open\n")); */
+ /* reset the chip */
+ bmac_reset_and_enable(dev, 1);
+
+ dev->flags |= IFF_UP | IFF_RUNNING;
+
+ return 0;
+}
+
+static int bmac_close(struct device *dev)
+{
+ struct bmac_data *bp = (struct bmac_data *) dev->priv;
+ volatile struct dbdma_regs *rd = bp->rx_dma;
+ volatile struct dbdma_regs *td = bp->tx_dma;
+ unsigned short config;
+ int i;
+
+ dev->flags &= ~(IFF_UP | IFF_RUNNING);
+
+ /* disable rx and tx */
+ config = bmread(dev, RXCFG);
+ bmwrite(dev, RXCFG, (config & ~RxMACEnable));
+
+ config = bmread(dev, TXCFG);
+ bmwrite(dev, TXCFG, (config & ~TxMACEnable));
+
+ bmwrite(dev, INTDISABLE, DisableAll); /* disable all intrs */
+
+ /* disable rx and tx dma */
+ st_le32(&rd->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE)); /* clear run bit */
+ st_le32(&td->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE)); /* clear run bit */
+
+ /* free some skb's */
+ XXDEBUG(("bmac: free rx bufs\n"));
+ for (i=0; i<N_RX_RING; i++) {
+ if (bp->rx_bufs[i] != NULL) {
+ dev_kfree_skb(bp->rx_bufs[i]);
+ bp->rx_bufs[i] = NULL;
+ }
+ }
+ bp->rx_allocated = 0;
+ XXDEBUG(("bmac: free doubles\n"));/*MEMORY LEAK BELOW!!! FIX!!! */
+ if (bp->tx_double[0] != NULL) kfree(bp->tx_double[0]);
+ XXDEBUG(("bmac: free tx bufs\n"));
+ for (i = 0; i<N_TX_RING; i++) {
+ if (bp->tx_bufs[i] != NULL) {
+ dev_kfree_skb(bp->tx_bufs[i]);
+ bp->tx_bufs[i] = NULL;
+ }
+ }
+ bp->tx_allocated = 0;
+ bp->reset_and_enabled = 0;
+ XXDEBUG(("bmac: all bufs freed\n"));
+
+ return 0;
+}
+
+static void
+bmac_start(struct device *dev)
+{
+ struct bmac_data *bp = dev->priv;
+ int i;
+ struct sk_buff *skb;
+ unsigned long flags;
- save_flags(flags); cli();
- while (1) {
- i = bp->tx_fill + 1;
- if (i >= N_TX_RING) i = 0;
- if (i == bp->tx_empty) break;
- skb = skb_dequeue(bp->queue);
- if (skb == NULL) break;
- bmac_transmit_packet(skb, dev);
- }
- restore_flags(flags);
- }
-
- static int
- bmac_output(struct sk_buff *skb, struct device *dev)
- {
- struct bmac_data *bp = dev->priv;
- skb_queue_tail(bp->queue, skb);
- bmac_start(dev);
- return 0;
- }
-
- static void bmac_tx_timeout(unsigned long data)
- {
- struct device *dev = (struct device *) data;
- struct bmac_data *bp = (struct bmac_data *) dev->priv;
- volatile struct dbdma_regs *td = bp->tx_dma;
- volatile struct dbdma_regs *rd = bp->rx_dma;
- volatile struct dbdma_cmd *cp;
- unsigned long flags;
- unsigned short config, oldConfig;
- int i;
-
- XXDEBUG(("bmac: tx_timeout called\n"));
- save_flags(flags); cli();
- bp->timeout_active = 0;
-
- /* update various counters */
-/* bmac_handle_misc_intrs(bp, 0); */
-
- cp = &bp->tx_cmds[bp->tx_empty];
-/* XXDEBUG((KERN_DEBUG "bmac: tx dmastat=%x %x runt=%d pr=%x fs=%x fc=%x\n", */
+ save_flags(flags); cli();
+ while (1) {
+ i = bp->tx_fill + 1;
+ if (i >= N_TX_RING) i = 0;
+ if (i == bp->tx_empty) break;
+ skb = skb_dequeue(bp->queue);
+ if (skb == NULL) break;
+ bmac_transmit_packet(skb, dev);
+ }
+ restore_flags(flags);
+}
+
+static int
+bmac_output(struct sk_buff *skb, struct device *dev)
+{
+ struct bmac_data *bp = dev->priv;
+ skb_queue_tail(bp->queue, skb);
+ bmac_start(dev);
+ return 0;
+}
+
+static void bmac_tx_timeout(unsigned long data)
+{
+ struct device *dev = (struct device *) data;
+ struct bmac_data *bp = (struct bmac_data *) dev->priv;
+ volatile struct dbdma_regs *td = bp->tx_dma;
+ volatile struct dbdma_regs *rd = bp->rx_dma;
+ volatile struct dbdma_cmd *cp;
+ unsigned long flags;
+ unsigned short config, oldConfig;
+ int i;
+
+ XXDEBUG(("bmac: tx_timeout called\n"));
+ save_flags(flags); cli();
+ bp->timeout_active = 0;
+
+ /* update various counters */
+/* bmac_handle_misc_intrs(bp, 0); */
+
+ cp = &bp->tx_cmds[bp->tx_empty];
+/* XXDEBUG((KERN_DEBUG "bmac: tx dmastat=%x %x runt=%d pr=%x fs=%x fc=%x\n", */
/* ld_le32(&td->status), ld_le16(&cp->xfer_status), bp->tx_bad_runt, */
/* mb->pr, mb->xmtfs, mb->fifofc)); */
- /* turn off both tx and rx and reset the chip */
- config = bmread(dev, RXCFG);
- bmwrite(dev, RXCFG, (config & ~RxMACEnable));
- config = bmread(dev, TXCFG);
- bmwrite(dev, TXCFG, (config & ~TxMACEnable));
- out_le32(&td->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE|ACTIVE|DEAD));
- printk(KERN_ERR "bmac: transmit timeout - resetting\n");
- bmac_reset_chip(dev);
-
- /* restart rx dma */
- cp = bus_to_virt(ld_le32(&rd->cmdptr));
- out_le32(&rd->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE|ACTIVE|DEAD));
- out_le16(&cp->xfer_status, 0);
- out_le32(&rd->cmdptr, virt_to_bus(cp));
- out_le32(&rd->control, DBDMA_SET(RUN|WAKE));
-
- /* fix up the transmit side */
- XXDEBUG((KERN_DEBUG "bmac: tx empty=%d fill=%d fullup=%d\n",
- bp->tx_empty, bp->tx_fill, bp->tx_fullup));
- i = bp->tx_empty;
- ++bp->stats.tx_errors;
- if (i != bp->tx_fill) {
- dev_kfree_skb(bp->tx_bufs[i]);
- bp->tx_bufs[i] = NULL;
- if (++i >= N_TX_RING) i = 0;
- bp->tx_empty = i;
- }
- bp->tx_fullup = 0;
- dev->tbusy = 0;
- mark_bh(NET_BH);
- XXDEBUG((KERN_DEBUG "bmac: clearing tbusy\n"));
- if (i != bp->tx_fill) {
- cp = &bp->tx_cmds[i];
- out_le16(&cp->xfer_status, 0);
- out_le16(&cp->command, OUTPUT_LAST);
- out_le32(&td->cmdptr, virt_to_bus(cp));
- out_le32(&td->control, DBDMA_SET(RUN));
-/* bmac_set_timeout(dev); */
- XXDEBUG((KERN_DEBUG "bmac: starting %d\n", i));
- }
-
- /* turn it back on */
- oldConfig = bmread(dev, RXCFG);
- bmwrite(dev, RXCFG, oldConfig | RxMACEnable );
- oldConfig = bmread(dev, TXCFG);
- bmwrite(dev, TXCFG, oldConfig | TxMACEnable );
-
- restore_flags(flags);
- }
+ /* turn off both tx and rx and reset the chip */
+ config = bmread(dev, RXCFG);
+ bmwrite(dev, RXCFG, (config & ~RxMACEnable));
+ config = bmread(dev, TXCFG);
+ bmwrite(dev, TXCFG, (config & ~TxMACEnable));
+ out_le32(&td->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE|ACTIVE|DEAD));
+ printk(KERN_ERR "bmac: transmit timeout - resetting\n");
+ bmac_reset_chip(dev);
+
+ /* restart rx dma */
+ cp = bus_to_virt(ld_le32(&rd->cmdptr));
+ out_le32(&rd->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE|ACTIVE|DEAD));
+ out_le16(&cp->xfer_status, 0);
+ out_le32(&rd->cmdptr, virt_to_bus(cp));
+ out_le32(&rd->control, DBDMA_SET(RUN|WAKE));
+
+ /* fix up the transmit side */
+ XXDEBUG((KERN_DEBUG "bmac: tx empty=%d fill=%d fullup=%d\n",
+ bp->tx_empty, bp->tx_fill, bp->tx_fullup));
+ i = bp->tx_empty;
+ ++bp->stats.tx_errors;
+ if (i != bp->tx_fill) {
+ dev_kfree_skb(bp->tx_bufs[i]);
+ bp->tx_bufs[i] = NULL;
+ if (++i >= N_TX_RING) i = 0;
+ bp->tx_empty = i;
+ }
+ bp->tx_fullup = 0;
+ dev->tbusy = 0;
+ mark_bh(NET_BH);
+ XXDEBUG((KERN_DEBUG "bmac: clearing tbusy\n"));
+ if (i != bp->tx_fill) {
+ cp = &bp->tx_cmds[i];
+ out_le16(&cp->xfer_status, 0);
+ out_le16(&cp->command, OUTPUT_LAST);
+ out_le32(&td->cmdptr, virt_to_bus(cp));
+ out_le32(&td->control, DBDMA_SET(RUN));
+ /* bmac_set_timeout(dev); */
+ XXDEBUG((KERN_DEBUG "bmac: starting %d\n", i));
+ }
+
+ /* turn it back on */
+ oldConfig = bmread(dev, RXCFG);
+ bmwrite(dev, RXCFG, oldConfig | RxMACEnable );
+ oldConfig = bmread(dev, TXCFG);
+ bmwrite(dev, TXCFG, oldConfig | TxMACEnable );
+
+ restore_flags(flags);
+}
#if 0
- static void dump_dbdma(volatile struct dbdma_cmd *cp,int count)
- {
- int i,*ip;
+static void dump_dbdma(volatile struct dbdma_cmd *cp,int count)
+{
+ int i,*ip;
- for (i=0;i< count;i++)
- {
- ip = (int*)(cp+i);
+ for (i=0;i< count;i++) {
+ ip = (int*)(cp+i);
- printk("dbdma req 0x%x addr 0x%x baddr 0x%x xfer/res 0x%x\n",
- ld_le32(ip+0),
- ld_le32(ip+1),
- ld_le32(ip+2),
- ld_le32(ip+3));
- }
-
- }
+ printk("dbdma req 0x%x addr 0x%x baddr 0x%x xfer/res 0x%x\n",
+ ld_le32(ip+0),
+ ld_le32(ip+1),
+ ld_le32(ip+2),
+ ld_le32(ip+3));
+ }
+
+}
#endif
- static int
- bmac_proc_info ( char *buffer, char **start, off_t offset, int length, int dummy)
- {
- int len = 0;
- off_t pos = 0;
- off_t begin = 0;
- int i;
+static int
+bmac_proc_info(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+ int len = 0;
+ off_t pos = 0;
+ off_t begin = 0;
+ int i;
- if (bmac_devs == NULL) return (-ENOSYS);
+ if (bmac_devs == NULL) return (-ENOSYS);
- len += sprintf(buffer, "BMAC counters & registers\n");
+ len += sprintf(buffer, "BMAC counters & registers\n");
- for (i = 0; i<N_REG_ENTRIES; i++) {
- len += sprintf(buffer + len, "%s: %#08x\n",
- reg_entries[i].name,
- bmread(bmac_devs, reg_entries[i].reg_offset));
- pos = begin + len;
+ for (i = 0; i<N_REG_ENTRIES; i++) {
+ len += sprintf(buffer + len, "%s: %#08x\n",
+ reg_entries[i].name,
+ bmread(bmac_devs, reg_entries[i].reg_offset));
+ pos = begin + len;
- if (pos < offset) {
- len = 0;
- begin = pos;
- }
+ if (pos < offset) {
+ len = 0;
+ begin = pos;
+ }
- if (pos > offset+length) break;
- }
+ if (pos > offset+length) break;
+ }
- *start = buffer + (offset - begin);
- len -= (offset - begin);
+ *start = buffer + (offset - begin);
+ len -= (offset - begin);
- if (len > length) len = length;
+ if (len > length) len = length;
- return len;
- }
+ return len;
+}