/drivers/net/ariadne.c
C | 858 lines | 614 code | 147 blank | 97 comment | 84 complexity | a4e407f653d818812362e41ea55bfcb3 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
- /*
- * Amiga Linux/m68k Ariadne Ethernet Driver
- *
- * © Copyright 1995-2003 by Geert Uytterhoeven (geert@linux-m68k.org)
- * Peter De Schrijver (p2@mind.be)
- *
- * ---------------------------------------------------------------------------
- *
- * This program is based on
- *
- * lance.c: An AMD LANCE ethernet driver for linux.
- * Written 1993-94 by Donald Becker.
- *
- * Am79C960: PCnet(tm)-ISA Single-Chip Ethernet Controller
- * Advanced Micro Devices
- * Publication #16907, Rev. B, Amendment/0, May 1994
- *
- * MC68230: Parallel Interface/Timer (PI/T)
- * Motorola Semiconductors, December, 1983
- *
- * ---------------------------------------------------------------------------
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of the Linux
- * distribution for more details.
- *
- * ---------------------------------------------------------------------------
- *
- * The Ariadne is a Zorro-II board made by Village Tronic. It contains:
- *
- * - an Am79C960 PCnet-ISA Single-Chip Ethernet Controller with both
- * 10BASE-2 (thin coax) and 10BASE-T (UTP) connectors
- *
- * - an MC68230 Parallel Interface/Timer configured as 2 parallel ports
- */
- #include <linux/module.h>
- #include <linux/stddef.h>
- #include <linux/kernel.h>
- #include <linux/string.h>
- #include <linux/errno.h>
- #include <linux/ioport.h>
- #include <linux/netdevice.h>
- #include <linux/etherdevice.h>
- #include <linux/interrupt.h>
- #include <linux/skbuff.h>
- #include <linux/init.h>
- #include <linux/zorro.h>
- #include <linux/bitops.h>
- #include <asm/amigaints.h>
- #include <asm/amigahw.h>
- #include <asm/irq.h>
- #include "ariadne.h"
- #ifdef ARIADNE_DEBUG
- int ariadne_debug = ARIADNE_DEBUG;
- #else
- int ariadne_debug = 1;
- #endif
- /*
- * Macros to Fix Endianness problems
- */
- /* Swap the Bytes in a WORD */
- #define swapw(x) (((x>>8)&0x00ff)|((x<<8)&0xff00))
- /* Get the Low BYTE in a WORD */
- #define lowb(x) (x&0xff)
- /* Get the Swapped High WORD in a LONG */
- #define swhighw(x) ((((x)>>8)&0xff00)|(((x)>>24)&0x00ff))
- /* Get the Swapped Low WORD in a LONG */
- #define swloww(x) ((((x)<<8)&0xff00)|(((x)>>8)&0x00ff))
- /*
- * Transmit/Receive Ring Definitions
- */
- #define TX_RING_SIZE 5
- #define RX_RING_SIZE 16
- #define PKT_BUF_SIZE 1520
- /*
- * Private Device Data
- */
- struct ariadne_private {
- volatile struct TDRE *tx_ring[TX_RING_SIZE];
- volatile struct RDRE *rx_ring[RX_RING_SIZE];
- volatile u_short *tx_buff[TX_RING_SIZE];
- volatile u_short *rx_buff[RX_RING_SIZE];
- int cur_tx, cur_rx; /* The next free ring entry */
- int dirty_tx; /* The ring entries to be free()ed. */
- char tx_full;
- };
- /*
- * Structure Created in the Ariadne's RAM Buffer
- */
- struct lancedata {
- struct TDRE tx_ring[TX_RING_SIZE];
- struct RDRE rx_ring[RX_RING_SIZE];
- u_short tx_buff[TX_RING_SIZE][PKT_BUF_SIZE/sizeof(u_short)];
- u_short rx_buff[RX_RING_SIZE][PKT_BUF_SIZE/sizeof(u_short)];
- };
- static int ariadne_open(struct net_device *dev);
- static void ariadne_init_ring(struct net_device *dev);
- static netdev_tx_t ariadne_start_xmit(struct sk_buff *skb,
- struct net_device *dev);
- static void ariadne_tx_timeout(struct net_device *dev);
- static int ariadne_rx(struct net_device *dev);
- static void ariadne_reset(struct net_device *dev);
- static irqreturn_t ariadne_interrupt(int irq, void *data);
- static int ariadne_close(struct net_device *dev);
- static struct net_device_stats *ariadne_get_stats(struct net_device *dev);
- static void set_multicast_list(struct net_device *dev);
- static void memcpyw(volatile u_short *dest, u_short *src, int len)
- {
- while (len >= 2) {
- *(dest++) = *(src++);
- len -= 2;
- }
- if (len == 1)
- *dest = (*(u_char *)src)<<8;
- }
- static int __devinit ariadne_init_one(struct zorro_dev *z,
- const struct zorro_device_id *ent);
- static void __devexit ariadne_remove_one(struct zorro_dev *z);
- static struct zorro_device_id ariadne_zorro_tbl[] __devinitdata = {
- { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE },
- { 0 }
- };
- MODULE_DEVICE_TABLE(zorro, ariadne_zorro_tbl);
- static struct zorro_driver ariadne_driver = {
- .name = "ariadne",
- .id_table = ariadne_zorro_tbl,
- .probe = ariadne_init_one,
- .remove = __devexit_p(ariadne_remove_one),
- };
- static const struct net_device_ops ariadne_netdev_ops = {
- .ndo_open = ariadne_open,
- .ndo_stop = ariadne_close,
- .ndo_start_xmit = ariadne_start_xmit,
- .ndo_tx_timeout = ariadne_tx_timeout,
- .ndo_get_stats = ariadne_get_stats,
- .ndo_set_multicast_list = set_multicast_list,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_change_mtu = eth_change_mtu,
- .ndo_set_mac_address = eth_mac_addr,
- };
- static int __devinit ariadne_init_one(struct zorro_dev *z,
- const struct zorro_device_id *ent)
- {
- unsigned long board = z->resource.start;
- unsigned long base_addr = board+ARIADNE_LANCE;
- unsigned long mem_start = board+ARIADNE_RAM;
- struct resource *r1, *r2;
- struct net_device *dev;
- struct ariadne_private *priv;
- int err;
- r1 = request_mem_region(base_addr, sizeof(struct Am79C960), "Am79C960");
- if (!r1)
- return -EBUSY;
- r2 = request_mem_region(mem_start, ARIADNE_RAM_SIZE, "RAM");
- if (!r2) {
- release_mem_region(base_addr, sizeof(struct Am79C960));
- return -EBUSY;
- }
- dev = alloc_etherdev(sizeof(struct ariadne_private));
- if (dev == NULL) {
- release_mem_region(base_addr, sizeof(struct Am79C960));
- release_mem_region(mem_start, ARIADNE_RAM_SIZE);
- return -ENOMEM;
- }
- priv = netdev_priv(dev);
- r1->name = dev->name;
- r2->name = dev->name;
- dev->dev_addr[0] = 0x00;
- dev->dev_addr[1] = 0x60;
- dev->dev_addr[2] = 0x30;
- dev->dev_addr[3] = (z->rom.er_SerialNumber>>16) & 0xff;
- dev->dev_addr[4] = (z->rom.er_SerialNumber>>8) & 0xff;
- dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff;
- dev->base_addr = ZTWO_VADDR(base_addr);
- dev->mem_start = ZTWO_VADDR(mem_start);
- dev->mem_end = dev->mem_start+ARIADNE_RAM_SIZE;
- dev->netdev_ops = &ariadne_netdev_ops;
- dev->watchdog_timeo = 5*HZ;
- err = register_netdev(dev);
- if (err) {
- release_mem_region(base_addr, sizeof(struct Am79C960));
- release_mem_region(mem_start, ARIADNE_RAM_SIZE);
- free_netdev(dev);
- return err;
- }
- zorro_set_drvdata(z, dev);
- printk(KERN_INFO "%s: Ariadne at 0x%08lx, Ethernet Address %pM\n",
- dev->name, board, dev->dev_addr);
- return 0;
- }
- static int ariadne_open(struct net_device *dev)
- {
- volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
- u_short in;
- u_long version;
- int i;
- /* Reset the LANCE */
- in = lance->Reset;
- /* Stop the LANCE */
- lance->RAP = CSR0; /* PCnet-ISA Controller Status */
- lance->RDP = STOP;
- /* Check the LANCE version */
- lance->RAP = CSR88; /* Chip ID */
- version = swapw(lance->RDP);
- lance->RAP = CSR89; /* Chip ID */
-