^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Amiga Linux/m68k Ariadne Ethernet Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * © Copyright 1995-2003 by Geert Uytterhoeven (geert@linux-m68k.org)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Peter De Schrijver (p2@mind.be)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * ---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * This program is based on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * lance.c: An AMD LANCE ethernet driver for linux.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Written 1993-94 by Donald Becker.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Am79C960: PCnet(tm)-ISA Single-Chip Ethernet Controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Advanced Micro Devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Publication #16907, Rev. B, Amendment/0, May 1994
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * MC68230: Parallel Interface/Timer (PI/T)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * Motorola Semiconductors, December, 1983
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * ---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * License. See the file COPYING in the main directory of the Linux
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * distribution for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * ---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * The Ariadne is a Zorro-II board made by Village Tronic. It contains:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * - an Am79C960 PCnet-ISA Single-Chip Ethernet Controller with both
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * 10BASE-2 (thin coax) and 10BASE-T (UTP) connectors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * - an MC68230 Parallel Interface/Timer configured as 2 parallel ports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /*#define DEBUG*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/stddef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <linux/etherdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include <linux/zorro.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #include <asm/byteorder.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #include <asm/amigaints.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #include <asm/amigahw.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #include "ariadne.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #ifdef ARIADNE_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) int ariadne_debug = ARIADNE_DEBUG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) int ariadne_debug = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /* Macros to Fix Endianness problems */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* Swap the Bytes in a WORD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define swapw(x) (((x >> 8) & 0x00ff) | ((x << 8) & 0xff00))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /* Get the Low BYTE in a WORD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define lowb(x) (x & 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* Get the Swapped High WORD in a LONG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define swhighw(x) ((((x) >> 8) & 0xff00) | (((x) >> 24) & 0x00ff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /* Get the Swapped Low WORD in a LONG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define swloww(x) ((((x) << 8) & 0xff00) | (((x) >> 8) & 0x00ff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /* Transmit/Receive Ring Definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define TX_RING_SIZE 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define RX_RING_SIZE 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define PKT_BUF_SIZE 1520
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /* Private Device Data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct ariadne_private {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) volatile struct TDRE *tx_ring[TX_RING_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) volatile struct RDRE *rx_ring[RX_RING_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) volatile u_short *tx_buff[TX_RING_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) volatile u_short *rx_buff[RX_RING_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) int cur_tx, cur_rx; /* The next free ring entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int dirty_tx; /* The ring entries to be free()ed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) char tx_full;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /* Structure Created in the Ariadne's RAM Buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct lancedata {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct TDRE tx_ring[TX_RING_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct RDRE rx_ring[RX_RING_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) u_short tx_buff[TX_RING_SIZE][PKT_BUF_SIZE / sizeof(u_short)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) u_short rx_buff[RX_RING_SIZE][PKT_BUF_SIZE / sizeof(u_short)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static void memcpyw(volatile u_short *dest, u_short *src, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) while (len >= 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) *(dest++) = *(src++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) len -= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (len == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) *dest = (*(u_char *)src) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static void ariadne_init_ring(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct ariadne_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) volatile struct lancedata *lancedata = (struct lancedata *)dev->mem_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) netif_stop_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) priv->tx_full = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) priv->cur_rx = priv->cur_tx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) priv->dirty_tx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /* Set up TX Ring */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) for (i = 0; i < TX_RING_SIZE; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) volatile struct TDRE *t = &lancedata->tx_ring[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) t->TMD0 = swloww(ARIADNE_RAM +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) offsetof(struct lancedata, tx_buff[i]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) t->TMD1 = swhighw(ARIADNE_RAM +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) offsetof(struct lancedata, tx_buff[i])) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) TF_STP | TF_ENP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) t->TMD2 = swapw((u_short)-PKT_BUF_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) t->TMD3 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) priv->tx_ring[i] = &lancedata->tx_ring[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) priv->tx_buff[i] = lancedata->tx_buff[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) netdev_dbg(dev, "TX Entry %2d at %p, Buf at %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) i, &lancedata->tx_ring[i], lancedata->tx_buff[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) /* Set up RX Ring */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) for (i = 0; i < RX_RING_SIZE; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) volatile struct RDRE *r = &lancedata->rx_ring[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) r->RMD0 = swloww(ARIADNE_RAM +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) offsetof(struct lancedata, rx_buff[i]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) r->RMD1 = swhighw(ARIADNE_RAM +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) offsetof(struct lancedata, rx_buff[i])) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) RF_OWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) r->RMD2 = swapw((u_short)-PKT_BUF_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) r->RMD3 = 0x0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) priv->rx_ring[i] = &lancedata->rx_ring[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) priv->rx_buff[i] = lancedata->rx_buff[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) netdev_dbg(dev, "RX Entry %2d at %p, Buf at %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) i, &lancedata->rx_ring[i], lancedata->rx_buff[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static int ariadne_rx(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) struct ariadne_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) int entry = priv->cur_rx % RX_RING_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) /* If we own the next entry, it's a new packet. Send it up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) while (!(lowb(priv->rx_ring[entry]->RMD1) & RF_OWN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) int status = lowb(priv->rx_ring[entry]->RMD1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (status != (RF_STP | RF_ENP)) { /* There was an error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /* There is a tricky error noted by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * John Murphy <murf@perftech.com> to Russ Nelson:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * Even with full-sized buffers it's possible for a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * jabber packet to use two buffers, with only the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * last correctly noting the error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) /* Only count a general error at the end of a packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (status & RF_ENP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) dev->stats.rx_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (status & RF_FRAM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) dev->stats.rx_frame_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (status & RF_OFLO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) dev->stats.rx_over_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (status & RF_CRC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) dev->stats.rx_crc_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (status & RF_BUFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) dev->stats.rx_fifo_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) priv->rx_ring[entry]->RMD1 &= 0xff00 | RF_STP | RF_ENP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) /* Malloc up new buffer, compatible with net-3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) short pkt_len = swapw(priv->rx_ring[entry]->RMD3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) skb = netdev_alloc_skb(dev, pkt_len + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (skb == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) for (i = 0; i < RX_RING_SIZE; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (lowb(priv->rx_ring[(entry + i) % RX_RING_SIZE]->RMD1) & RF_OWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (i > RX_RING_SIZE - 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) dev->stats.rx_dropped++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) priv->rx_ring[entry]->RMD1 |= RF_OWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) priv->cur_rx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) skb_reserve(skb, 2); /* 16 byte align */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) skb_put(skb, pkt_len); /* Make room */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) skb_copy_to_linear_data(skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) (const void *)priv->rx_buff[entry],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) pkt_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) skb->protocol = eth_type_trans(skb, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) netdev_dbg(dev, "RX pkt type 0x%04x from %pM to %pM data %p len %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) ((u_short *)skb->data)[6],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) skb->data + 6, skb->data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) skb->data, skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) netif_rx(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) dev->stats.rx_packets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) dev->stats.rx_bytes += pkt_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) priv->rx_ring[entry]->RMD1 |= RF_OWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) entry = (++priv->cur_rx) % RX_RING_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) priv->cur_rx = priv->cur_rx % RX_RING_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) /* We should check that at least two ring entries are free.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * If not, we should free one and mark stats->rx_dropped++
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) static irqreturn_t ariadne_interrupt(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) struct net_device *dev = (struct net_device *)data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) struct ariadne_private *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) int csr0, boguscnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) int handled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) lance->RAP = CSR0; /* PCnet-ISA Controller Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (!(lance->RDP & INTR)) /* Check if any interrupt has been */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return IRQ_NONE; /* generated by the board */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) boguscnt = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) while ((csr0 = lance->RDP) & (ERR | RINT | TINT) && --boguscnt >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /* Acknowledge all of the current interrupt sources ASAP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) lance->RDP = csr0 & ~(INEA | TDMD | STOP | STRT | INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (ariadne_debug > 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) netdev_dbg(dev, "interrupt csr0=%#02x new csr=%#02x [",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) csr0, lance->RDP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (csr0 & INTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) pr_cont(" INTR");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (csr0 & INEA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) pr_cont(" INEA");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (csr0 & RXON)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) pr_cont(" RXON");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (csr0 & TXON)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) pr_cont(" TXON");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (csr0 & TDMD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) pr_cont(" TDMD");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (csr0 & STOP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) pr_cont(" STOP");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (csr0 & STRT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) pr_cont(" STRT");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (csr0 & INIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) pr_cont(" INIT");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (csr0 & ERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) pr_cont(" ERR");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (csr0 & BABL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) pr_cont(" BABL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (csr0 & CERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) pr_cont(" CERR");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (csr0 & MISS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) pr_cont(" MISS");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (csr0 & MERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) pr_cont(" MERR");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (csr0 & RINT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) pr_cont(" RINT");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (csr0 & TINT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) pr_cont(" TINT");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (csr0 & IDON)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) pr_cont(" IDON");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) pr_cont(" ]\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (csr0 & RINT) { /* Rx interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) handled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) ariadne_rx(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (csr0 & TINT) { /* Tx-done interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) int dirty_tx = priv->dirty_tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) handled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) while (dirty_tx < priv->cur_tx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) int entry = dirty_tx % TX_RING_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) int status = lowb(priv->tx_ring[entry]->TMD1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (status & TF_OWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) break; /* It still hasn't been Txed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) priv->tx_ring[entry]->TMD1 &= 0xff00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (status & TF_ERR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) /* There was an major error, log it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) int err_status = priv->tx_ring[entry]->TMD3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) dev->stats.tx_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (err_status & EF_RTRY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) dev->stats.tx_aborted_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (err_status & EF_LCAR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) dev->stats.tx_carrier_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (err_status & EF_LCOL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) dev->stats.tx_window_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (err_status & EF_UFLO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) /* Ackk! On FIFO errors the Tx unit is turned off! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) dev->stats.tx_fifo_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) /* Remove this verbosity later! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) netdev_err(dev, "Tx FIFO error! Status %04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) csr0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) /* Restart the chip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) lance->RDP = STRT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (status & (TF_MORE | TF_ONE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) dev->stats.collisions++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) dev->stats.tx_packets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) dirty_tx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) #ifndef final_version
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (priv->cur_tx - dirty_tx >= TX_RING_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) netdev_err(dev, "out-of-sync dirty pointer, %d vs. %d, full=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) dirty_tx, priv->cur_tx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) priv->tx_full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) dirty_tx += TX_RING_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (priv->tx_full && netif_queue_stopped(dev) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) dirty_tx > priv->cur_tx - TX_RING_SIZE + 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) /* The ring is no longer full */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) priv->tx_full = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) netif_wake_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) priv->dirty_tx = dirty_tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /* Log misc errors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (csr0 & BABL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) handled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) dev->stats.tx_errors++; /* Tx babble */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (csr0 & MISS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) handled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) dev->stats.rx_errors++; /* Missed a Rx frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (csr0 & MERR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) handled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) netdev_err(dev, "Bus master arbitration failure, status %04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) csr0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) /* Restart the chip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) lance->RDP = STRT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) /* Clear any other interrupt, and set interrupt enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) lance->RAP = CSR0; /* PCnet-ISA Controller Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) lance->RDP = INEA | BABL | CERR | MISS | MERR | IDON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (ariadne_debug > 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) netdev_dbg(dev, "exiting interrupt, csr%d=%#04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) lance->RAP, lance->RDP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return IRQ_RETVAL(handled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) static int ariadne_open(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) u_short in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) u_long version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) /* Reset the LANCE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) in = lance->Reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) /* Stop the LANCE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) lance->RAP = CSR0; /* PCnet-ISA Controller Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) lance->RDP = STOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) /* Check the LANCE version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) lance->RAP = CSR88; /* Chip ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) version = swapw(lance->RDP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) lance->RAP = CSR89; /* Chip ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) version |= swapw(lance->RDP) << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if ((version & 0x00000fff) != 0x00000003) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) pr_warn("Couldn't find AMD Ethernet Chip\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if ((version & 0x0ffff000) != 0x00003000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) pr_warn("Couldn't find Am79C960 (Wrong part number = %ld)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) (version & 0x0ffff000) >> 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) netdev_dbg(dev, "Am79C960 (PCnet-ISA) Revision %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) (version & 0xf0000000) >> 28);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) ariadne_init_ring(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) /* Miscellaneous Stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) lance->RAP = CSR3; /* Interrupt Masks and Deferral Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) lance->RDP = 0x0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) lance->RAP = CSR4; /* Test and Features Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) lance->RDP = DPOLL | APAD_XMT | MFCOM | RCVCCOM | TXSTRTM | JABM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) /* Set the Multicast Table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) lance->RAP = CSR8; /* Logical Address Filter, LADRF[15:0] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) lance->RDP = 0x0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) lance->RAP = CSR9; /* Logical Address Filter, LADRF[31:16] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) lance->RDP = 0x0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) lance->RAP = CSR10; /* Logical Address Filter, LADRF[47:32] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) lance->RDP = 0x0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) lance->RAP = CSR11; /* Logical Address Filter, LADRF[63:48] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) lance->RDP = 0x0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) /* Set the Ethernet Hardware Address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) lance->RAP = CSR12; /* Physical Address Register, PADR[15:0] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) lance->RDP = ((u_short *)&dev->dev_addr[0])[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) lance->RAP = CSR13; /* Physical Address Register, PADR[31:16] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) lance->RDP = ((u_short *)&dev->dev_addr[0])[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) lance->RAP = CSR14; /* Physical Address Register, PADR[47:32] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) lance->RDP = ((u_short *)&dev->dev_addr[0])[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) /* Set the Init Block Mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) lance->RAP = CSR15; /* Mode Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) lance->RDP = 0x0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) /* Set the Transmit Descriptor Ring Pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) lance->RAP = CSR30; /* Base Address of Transmit Ring */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) lance->RDP = swloww(ARIADNE_RAM + offsetof(struct lancedata, tx_ring));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) lance->RAP = CSR31; /* Base Address of transmit Ring */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) lance->RDP = swhighw(ARIADNE_RAM + offsetof(struct lancedata, tx_ring));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) /* Set the Receive Descriptor Ring Pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) lance->RAP = CSR24; /* Base Address of Receive Ring */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) lance->RDP = swloww(ARIADNE_RAM + offsetof(struct lancedata, rx_ring));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) lance->RAP = CSR25; /* Base Address of Receive Ring */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) lance->RDP = swhighw(ARIADNE_RAM + offsetof(struct lancedata, rx_ring));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) /* Set the Number of RX and TX Ring Entries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) lance->RAP = CSR76; /* Receive Ring Length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) lance->RDP = swapw(((u_short)-RX_RING_SIZE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) lance->RAP = CSR78; /* Transmit Ring Length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) lance->RDP = swapw(((u_short)-TX_RING_SIZE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) /* Enable Media Interface Port Auto Select (10BASE-2/10BASE-T) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) lance->RAP = ISACSR2; /* Miscellaneous Configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) lance->IDP = ASEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) /* LED Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) lance->RAP = ISACSR5; /* LED1 Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) lance->IDP = PSE|XMTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) lance->RAP = ISACSR6; /* LED2 Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) lance->IDP = PSE|COLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) lance->RAP = ISACSR7; /* LED3 Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) lance->IDP = PSE|RCVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) netif_start_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) i = request_irq(IRQ_AMIGA_PORTS, ariadne_interrupt, IRQF_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) dev->name, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) lance->RAP = CSR0; /* PCnet-ISA Controller Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) lance->RDP = INEA | STRT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) static int ariadne_close(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) netif_stop_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) lance->RAP = CSR112; /* Missed Frame Count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) dev->stats.rx_missed_errors = swapw(lance->RDP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) lance->RAP = CSR0; /* PCnet-ISA Controller Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (ariadne_debug > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) netdev_dbg(dev, "Shutting down ethercard, status was %02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) lance->RDP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) netdev_dbg(dev, "%lu packets missed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) dev->stats.rx_missed_errors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) /* We stop the LANCE here -- it occasionally polls memory if we don't */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) lance->RDP = STOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) free_irq(IRQ_AMIGA_PORTS, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) static inline void ariadne_reset(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) lance->RAP = CSR0; /* PCnet-ISA Controller Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) lance->RDP = STOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) ariadne_init_ring(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) lance->RDP = INEA | STRT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) netif_start_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) static void ariadne_tx_timeout(struct net_device *dev, unsigned int txqueue)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) netdev_err(dev, "transmit timed out, status %04x, resetting\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) lance->RDP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) ariadne_reset(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) netif_wake_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) static netdev_tx_t ariadne_start_xmit(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) struct ariadne_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) int entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) int len = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (ariadne_debug > 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) lance->RAP = CSR0; /* PCnet-ISA Controller Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) netdev_dbg(dev, "%s: csr0 %04x\n", __func__, lance->RDP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) lance->RDP = 0x0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) /* FIXME: is the 79C960 new enough to do its own padding right ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) if (skb->len < ETH_ZLEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (skb_padto(skb, ETH_ZLEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) return NETDEV_TX_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) len = ETH_ZLEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) /* Fill in a Tx ring entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) netdev_dbg(dev, "TX pkt type 0x%04x from %pM to %pM data %p len %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) ((u_short *)skb->data)[6],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) skb->data + 6, skb->data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) skb->data, skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) entry = priv->cur_tx % TX_RING_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) /* Caution: the write order is important here, set the base address with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) the "ownership" bits last */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) priv->tx_ring[entry]->TMD2 = swapw((u_short)-skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) priv->tx_ring[entry]->TMD3 = 0x0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) memcpyw(priv->tx_buff[entry], (u_short *)skb->data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) print_hex_dump(KERN_DEBUG, "tx_buff: ", DUMP_PREFIX_OFFSET, 16, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) (void *)priv->tx_buff[entry],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) skb->len > 64 ? 64 : skb->len, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) priv->tx_ring[entry]->TMD1 = (priv->tx_ring[entry]->TMD1 & 0xff00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) | TF_OWN | TF_STP | TF_ENP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) priv->cur_tx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if ((priv->cur_tx >= TX_RING_SIZE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) (priv->dirty_tx >= TX_RING_SIZE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) netdev_dbg(dev, "*** Subtracting TX_RING_SIZE from cur_tx (%d) and dirty_tx (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) priv->cur_tx, priv->dirty_tx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) priv->cur_tx -= TX_RING_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) priv->dirty_tx -= TX_RING_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) dev->stats.tx_bytes += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) /* Trigger an immediate send poll */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) lance->RAP = CSR0; /* PCnet-ISA Controller Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) lance->RDP = INEA | TDMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if (lowb(priv->tx_ring[(entry + 1) % TX_RING_SIZE]->TMD1) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) netif_stop_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) priv->tx_full = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) return NETDEV_TX_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) static struct net_device_stats *ariadne_get_stats(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) short saved_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) saved_addr = lance->RAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) lance->RAP = CSR112; /* Missed Frame Count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) dev->stats.rx_missed_errors = swapw(lance->RDP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) lance->RAP = saved_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) return &dev->stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) /* Set or clear the multicast filter for this adaptor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) * num_addrs == -1 Promiscuous mode, receive all packets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) * num_addrs == 0 Normal mode, clear multicast list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) * num_addrs > 0 Multicast mode, receive normal and MC packets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) * and do best-effort filtering.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) static void set_multicast_list(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) volatile struct Am79C960 *lance = (struct Am79C960 *)dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (!netif_running(dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) netif_stop_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) /* We take the simple way out and always enable promiscuous mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) lance->RAP = CSR0; /* PCnet-ISA Controller Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) lance->RDP = STOP; /* Temporarily stop the lance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) ariadne_init_ring(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (dev->flags & IFF_PROMISC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) lance->RAP = CSR15; /* Mode Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) lance->RDP = PROM; /* Set promiscuous mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) short multicast_table[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) int num_addrs = netdev_mc_count(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) /* We don't use the multicast table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) * but rely on upper-layer filtering
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) memset(multicast_table, (num_addrs == 0) ? 0 : -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) sizeof(multicast_table));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) lance->RAP = CSR8 + (i << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) /* Logical Address Filter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) lance->RDP = swapw(multicast_table[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) lance->RAP = CSR15; /* Mode Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) lance->RDP = 0x0000; /* Unset promiscuous mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) lance->RAP = CSR0; /* PCnet-ISA Controller Status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) lance->RDP = INEA | STRT | IDON;/* Resume normal operation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) netif_wake_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) static void ariadne_remove_one(struct zorro_dev *z)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) struct net_device *dev = zorro_get_drvdata(z);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) unregister_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) release_mem_region(ZTWO_PADDR(dev->base_addr), sizeof(struct Am79C960));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) release_mem_region(ZTWO_PADDR(dev->mem_start), ARIADNE_RAM_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) free_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) static const struct zorro_device_id ariadne_zorro_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) { 0 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) MODULE_DEVICE_TABLE(zorro, ariadne_zorro_tbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) static const struct net_device_ops ariadne_netdev_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) .ndo_open = ariadne_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) .ndo_stop = ariadne_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) .ndo_start_xmit = ariadne_start_xmit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) .ndo_tx_timeout = ariadne_tx_timeout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) .ndo_get_stats = ariadne_get_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) .ndo_set_rx_mode = set_multicast_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) .ndo_validate_addr = eth_validate_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) .ndo_set_mac_address = eth_mac_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) static int ariadne_init_one(struct zorro_dev *z,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) const struct zorro_device_id *ent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) unsigned long board = z->resource.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) unsigned long base_addr = board + ARIADNE_LANCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) unsigned long mem_start = board + ARIADNE_RAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) struct resource *r1, *r2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) u32 serial;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) r1 = request_mem_region(base_addr, sizeof(struct Am79C960), "Am79C960");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (!r1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) r2 = request_mem_region(mem_start, ARIADNE_RAM_SIZE, "RAM");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) if (!r2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) release_mem_region(base_addr, sizeof(struct Am79C960));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) dev = alloc_etherdev(sizeof(struct ariadne_private));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (dev == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) release_mem_region(base_addr, sizeof(struct Am79C960));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) release_mem_region(mem_start, ARIADNE_RAM_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) r1->name = dev->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) r2->name = dev->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) serial = be32_to_cpu(z->rom.er_SerialNumber);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) dev->dev_addr[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) dev->dev_addr[1] = 0x60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) dev->dev_addr[2] = 0x30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) dev->dev_addr[3] = (serial >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) dev->dev_addr[4] = (serial >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) dev->dev_addr[5] = serial & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) dev->base_addr = (unsigned long)ZTWO_VADDR(base_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) dev->mem_start = (unsigned long)ZTWO_VADDR(mem_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) dev->mem_end = dev->mem_start + ARIADNE_RAM_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) dev->netdev_ops = &ariadne_netdev_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) dev->watchdog_timeo = 5 * HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) err = register_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) release_mem_region(base_addr, sizeof(struct Am79C960));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) release_mem_region(mem_start, ARIADNE_RAM_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) free_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) zorro_set_drvdata(z, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) netdev_info(dev, "Ariadne at 0x%08lx, Ethernet Address %pM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) board, dev->dev_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) static struct zorro_driver ariadne_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) .name = "ariadne",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) .id_table = ariadne_zorro_tbl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) .probe = ariadne_init_one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) .remove = ariadne_remove_one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) static int __init ariadne_init_module(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) return zorro_register_driver(&ariadne_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) static void __exit ariadne_cleanup_module(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) zorro_unregister_driver(&ariadne_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) module_init(ariadne_init_module);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) module_exit(ariadne_cleanup_module);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) MODULE_LICENSE("GPL");