Copyright 1994 David C. Davies
- and
+ and
United States Government
- (as represented by the Director, National Security Agency).
+ (as represented by the Director, National Security Agency).
Copyright 1995 Digital Equipment Corporation.
Digital Equipment Corporation, 1989
8) "DEC EtherWORKS Turbo_(TP BNC) Ethernet Controller Owners Manual",
Digital Equipment corporation, 1991, Pub. #EK-DE202-OM.001
-
+
Peter Bauer's depca.c (V0.5) was referred to when debugging V0.1 of this
driver.
[Alan Cox: Changed the code to allow command line irq/io assignments]
[Dave Davies: Changed the code to allow command line mem/name
assignments]
- 6) run the net startup bits for your eth?? interface manually
- (usually /etc/rc.inet[12] at boot time).
+ 6) run the net startup bits for your eth?? interface manually
+ (usually /etc/rc.inet[12] at boot time).
7) enjoy!
Note that autoprobing is not allowed in loadable modules - the system is
already up and running and you're messing with interrupts.
- To unload a module, turn off the associated interface
+ To unload a module, turn off the associated interface
'ifconfig eth?? down' then 'rmmod depca'.
To assign a base memory address for the shared memory when running as a
loadable module, see 5 above. To include the adapter name (if you have
no PROM but know the card name) also see 5 above. Note that this last
- option will not work with kernel built-in depca's.
+ option will not work with kernel built-in depca's.
The shared memory assignment for a loadable module makes sense to avoid
the 'memory autoprobe' picking the wrong shared memory (for the case of
************************************************************************
Support for MCA EtherWORKS cards added 11-3-98.
Verified to work with up to 2 DE212 cards in a system (although not
- fully stress-tested).
+ fully stress-tested).
Currently known bugs/limitations:
----------------
Version Date Description
-
+
0.1 25-jan-94 Initial writing.
0.2 27-jan-94 Added LANCE TX hardware buffer chaining.
0.3 1-feb-94 Added multiple DEPCA support.
0.351 30-apr-94 Added EISA support. Added DE422 recognition.
0.36 16-may-94 DE422 fix released.
0.37 22-jul-94 Added MODULE support
- 0.38 15-aug-94 Added DBR ROM switch in depca_close().
+ 0.38 15-aug-94 Added DBR ROM switch in depca_close().
Multi DEPCA bug fix.
0.38axp 15-sep-94 Special version for Alpha AXP Linux V1.0.
0.381 12-dec-94 Added DE101 recognition, fix multicast bug.
0.383 22-feb-95 Fix for conflict with VESA SCSI reported by
<stromain@alf.dec.com>
0.384 17-mar-95 Fix a ring full bug reported by <bkm@star.rl.ac.uk>
- 0.385 3-apr-95 Fix a recognition bug reported by
+ 0.385 3-apr-95 Fix a recognition bug reported by
<ryan.niemi@lastfrontier.com>
0.386 21-apr-95 Fix the last fix...sorry, must be galloping senility
0.40 25-May-95 Rewrite for portability & updated.
ALPHA support from <jestabro@amt.tay1.dec.com>
0.41 26-Jun-95 Added verify_area() calls in depca_ioctl() from
suggestion by <heiko@colossus.escape.de>
- 0.42 27-Dec-95 Add 'mem' shared memory assignment for loadable
+ 0.42 27-Dec-95 Add 'mem' shared memory assignment for loadable
modules.
Add 'adapter_name' for loadable modules when no PROM.
- Both above from a suggestion by
+ Both above from a suggestion by
<pchen@woodruffs121.residence.gatech.edu>.
Add new multicasting code.
0.421 22-Apr-96 Fix alloc_device() bug <jari@markkus2.fimr.fi>
0.44 1-Sep-97 Fix *_probe() to test check_region() first - bug
reported by <mmogilvi@elbert.uccs.edu>
0.45 3-Nov-98 Added support for MCA EtherWORKS (DE210/DE212) cards
- by <tymm@computer.org>
+ by <tymm@computer.org>
0.451 5-Nov-98 Fixed mca stuff cuz I'm a dummy. <tymm@computer.org>
0.5 14-Nov-98 Re-spin for 2.1.x kernels.
0.51 27-Jun-99 Correct received packet length for CRC from
=========================================================================
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/unistd.h>
#include <linux/ctype.h>
#include <linux/moduleparam.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/bitops.h>
#include <asm/uaccess.h>
-#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/dma.h>
static int depca_device_remove (struct device *device);
#ifdef CONFIG_EISA
-struct eisa_device_id depca_eisa_ids[] = {
+static struct eisa_device_id depca_eisa_ids[] = {
{ "DEC4220", de422 },
{ "" }
};
+MODULE_DEVICE_TABLE(eisa, depca_eisa_ids);
static int depca_eisa_probe (struct device *device);
-struct eisa_driver depca_eisa_driver = {
+static struct eisa_driver depca_eisa_driver = {
.id_table = depca_eisa_ids,
.driver = {
.name = depca_string,
};
#endif
-static int depca_isa_probe (struct device *);
+static int depca_isa_probe (struct platform_device *);
+
+static int __devexit depca_isa_remove(struct platform_device *pdev)
+{
+ return depca_device_remove(&pdev->dev);
+}
-static struct device_driver depca_isa_driver = {
- .name = depca_string,
- .bus = &platform_bus_type,
+static struct platform_driver depca_isa_driver = {
.probe = depca_isa_probe,
- .remove = __devexit_p(depca_device_remove),
+ .remove = __devexit_p(depca_isa_remove),
+ .driver = {
+ .name = depca_string,
+ },
};
-
+
/*
** Miscellaneous info...
*/
** Memory Alignment. Each descriptor is 4 longwords long. To force a
** particular alignment on the TX descriptor, adjust DESC_SKIP_LEN and
** DESC_ALIGN. DEPCA_ALIGN aligns the start address of the private memory area
-** and hence the RX descriptor ring's first entry.
+** and hence the RX descriptor ring's first entry.
*/
#define DEPCA_ALIGN4 ((u_long)4 - 1) /* 1 longword align */
#define DEPCA_ALIGN8 ((u_long)8 - 1) /* 2 longword (quadword) align */
#define DEPCA_ALIGN DEPCA_ALIGN8 /* Keep the LANCE happy... */
/*
-** The DEPCA Rx and Tx ring descriptors.
+** The DEPCA Rx and Tx ring descriptors.
*/
struct depca_rx_desc {
volatile s32 base;
} depca_bus; /* type of bus */
struct depca_init init_block; /* Shadow Initialization block */
/* CPU address space fields */
- struct depca_rx_desc *rx_ring; /* Pointer to start of RX descriptor ring */
- struct depca_tx_desc *tx_ring; /* Pointer to start of TX descriptor ring */
- void *rx_buff[NUM_RX_DESC]; /* CPU virt address of sh'd memory buffs */
- void *tx_buff[NUM_TX_DESC]; /* CPU virt address of sh'd memory buffs */
- void *sh_mem; /* CPU mapped virt address of device RAM */
+ struct depca_rx_desc __iomem *rx_ring; /* Pointer to start of RX descriptor ring */
+ struct depca_tx_desc __iomem *tx_ring; /* Pointer to start of TX descriptor ring */
+ void __iomem *rx_buff[NUM_RX_DESC]; /* CPU virt address of sh'd memory buffs */
+ void __iomem *tx_buff[NUM_TX_DESC]; /* CPU virt address of sh'd memory buffs */
+ void __iomem *sh_mem; /* CPU mapped virt address of device RAM */
u_long mem_start; /* Bus address of device RAM (before remap) */
u_long mem_len; /* device memory size */
/* Device address space fields */
*/
static int depca_open(struct net_device *dev);
static int depca_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t depca_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t depca_interrupt(int irq, void *dev_id);
static int depca_close(struct net_device *dev);
static int depca_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static void depca_tx_timeout(struct net_device *dev);
*/
ioaddr = dev->base_addr;
-
+
STOP_DEPCA;
nicsr = inb(DEPCA_NICSR);
printk ("%s: %s at 0x%04lx",
device->bus_id, depca_signature[lp->adapter], ioaddr);
-
+
switch (lp->depca_bus) {
#ifdef CONFIG_MCA
case DEPCA_BUS_MCA:
if (lp->depca_bus != DEPCA_BUS_MCA)
mem_start += 0x8000;
}
-
+
if ((mem_len = (NUM_RX_DESC * (sizeof(struct depca_rx_desc) + RX_BUFF_SZ) + NUM_TX_DESC * (sizeof(struct depca_tx_desc) + TX_BUFF_SZ) + sizeof(struct depca_init)))
> (netRAM << 10)) {
printk(",\n requests %dkB RAM: only %dkB is available!\n", (mem_len >> 10), netRAM);
outb(nicsr, DEPCA_NICSR);
}
- lp->lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(&lp->lock);
sprintf(lp->adapter_name, "%s (%s)",
depca_signature[lp->adapter], device->bus_id);
status = -EBUSY;
printk(KERN_ERR "depca: cannot request ISA memory, aborting\n");
goto out_priv;
}
-
+
status = -EIO;
lp->sh_mem = ioremap(mem_start, mem_len);
if (lp->sh_mem == NULL) {
/* Tx & Rx descriptors (aligned to a quadword boundary) */
offset = (offset + DEPCA_ALIGN) & ~DEPCA_ALIGN;
- lp->rx_ring = (struct depca_rx_desc *) (lp->sh_mem + offset);
+ lp->rx_ring = (struct depca_rx_desc __iomem *) (lp->sh_mem + offset);
lp->rx_ring_offset = offset;
offset += (sizeof(struct depca_rx_desc) * NUM_RX_DESC);
- lp->tx_ring = (struct depca_tx_desc *) (lp->sh_mem + offset);
+ lp->tx_ring = (struct depca_tx_desc __iomem *) (lp->sh_mem + offset);
lp->tx_ring_offset = offset;
offset += (sizeof(struct depca_tx_desc) * NUM_TX_DESC);
device->driver_data = dev;
SET_NETDEV_DEV (dev, device);
-
+
status = register_netdev(dev);
if (status == 0)
return 0;
out_priv:
return status;
}
-\f
+
static int depca_open(struct net_device *dev)
{
}
-/*
-** Writes a socket buffer to TX descriptor ring and starts transmission
+/*
+** Writes a socket buffer to TX descriptor ring and starts transmission
*/
static int depca_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
if (skb->len < 1)
goto out;
- if (skb->len < ETH_ZLEN) {
- skb = skb_padto(skb, ETH_ZLEN);
- if (skb == NULL)
- goto out;
- }
-
+ if (skb_padto(skb, ETH_ZLEN))
+ goto out;
+
netif_stop_queue(dev);
if (TX_BUFFS_AVAIL) { /* Fill in a Tx ring entry */
}
/*
-** The DEPCA interrupt handler.
+** The DEPCA interrupt handler.
*/
-static irqreturn_t depca_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t depca_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
struct depca_private *lp;
memcpy_fromio(buf, lp->rx_buff[lp->rx_old], pkt_len);
}
- /*
- ** Notify the upper protocol layers that there is another
+ /*
+ ** Notify the upper protocol layers that there is another
** packet to handle
*/
skb->protocol = eth_type_trans(skb, dev);
printk("%s: Shutting down ethercard, status was %2.2x.\n", dev->name, inw(DEPCA_DATA));
}
- /*
+ /*
** We stop the DEPCA here -- it occasionally polls
- ** memory if we don't.
+ ** memory if we don't.
*/
outw(STOP, DEPCA_DATA);
/* clear IDON by writing a "1", enable interrupts and start lance */
outw(IDON | INEA | STRT, DEPCA_DATA);
if (depca_debug > 2) {
- printk("%s: DEPCA open after %d ticks, init block 0x%08lx csr0 %4.4x.\n", dev->name, i, virt_to_phys(lp->sh_mem), inw(DEPCA_DATA));
+ printk("%s: DEPCA open after %d ticks, init block 0x%08lx csr0 %4.4x.\n", dev->name, i, lp->mem_start, inw(DEPCA_DATA));
}
} else {
- printk("%s: DEPCA unopen after %d ticks, init block 0x%08lx csr0 %4.4x.\n", dev->name, i, virt_to_phys(lp->sh_mem), inw(DEPCA_DATA));
+ printk("%s: DEPCA unopen after %d ticks, init block 0x%08lx csr0 %4.4x.\n", dev->name, i, lp->mem_start, inw(DEPCA_DATA));
status = -1;
}
struct depca_private *lp = (struct depca_private *) dev->priv;
u_long ioaddr = dev->base_addr;
- if (dev) {
- netif_stop_queue(dev);
- while (lp->tx_old != lp->tx_new); /* Wait for the ring to empty */
-
- STOP_DEPCA; /* Temporarily stop the depca. */
- depca_init_ring(dev); /* Initialize the descriptor rings */
+ netif_stop_queue(dev);
+ while (lp->tx_old != lp->tx_new); /* Wait for the ring to empty */
- if (dev->flags & IFF_PROMISC) { /* Set promiscuous mode */
- lp->init_block.mode |= PROM;
- } else {
- SetMulticastFilter(dev);
- lp->init_block.mode &= ~PROM; /* Unset promiscuous mode */
- }
+ STOP_DEPCA; /* Temporarily stop the depca. */
+ depca_init_ring(dev); /* Initialize the descriptor rings */
- LoadCSRs(dev); /* Reload CSR3 */
- InitRestartDepca(dev); /* Resume normal operation. */
- netif_start_queue(dev); /* Unlock the TX ring */
+ if (dev->flags & IFF_PROMISC) { /* Set promiscuous mode */
+ lp->init_block.mode |= PROM;
+ } else {
+ SetMulticastFilter(dev);
+ lp->init_block.mode &= ~PROM; /* Unset promiscuous mode */
}
+
+ LoadCSRs(dev); /* Reload CSR3 */
+ InitRestartDepca(dev); /* Resume normal operation. */
+ netif_start_queue(dev); /* Unlock the TX ring */
}
/*
static int __init depca_common_init (u_long ioaddr, struct net_device **devp)
{
int status = 0;
-
+
if (!request_region (ioaddr, DEPCA_TOTAL_SIZE, depca_string)) {
status = -EBUSY;
goto out;
}
-
+
if (DevicePresent(ioaddr)) {
status = -ENODEV;
goto out_release;
}
return 0;
-
+
out_release:
release_region (ioaddr, DEPCA_TOTAL_SIZE);
out:
struct depca_private *lp;
/*
- ** Search for the adapter. If an address has been given, search
+ ** Search for the adapter. If an address has been given, search
** specifically for the card at that address. Otherwise find the
** first card in the system.
*/
-
+
pos[0] = mca_device_read_stored_pos(mdev, 2);
pos[1] = mca_device_read_stored_pos(mdev, 3);
/*
- ** IO of card is handled by bits 1 and 2 of pos0.
+ ** IO of card is handled by bits 1 and 2 of pos0.
**
** bit2 bit1 IO
** 0 0 0x2c00
/*
** Found the adapter we were looking for. Now start setting it up.
- **
+ **
** First work on decoding the IRQ. It's stored in the lower 4 bits
** of pos1. Bits are as follows (from the ADF file):
**
- ** Bits
- ** 3 2 1 0 IRQ
+ ** Bits
+ ** 3 2 1 0 IRQ
** --------------------
** 0 0 1 0 5
** 0 0 0 1 9
irq = 11;
break;
default:
- printk("%s: mca_probe IRQ error. You should never get here (%d).\n", dev->name, where);
+ printk("%s: mca_probe IRQ error. You should never get here (%d).\n", mdev->name, where);
return -EINVAL;
}
strncpy(mdev->name, depca_mca_adapter_name[mdev->index],
sizeof(mdev->name));
mca_device_set_claim(mdev, 1);
-
+
/*
** Get everything allocated and initialized... (almost just
** like the ISA and EISA probes)
lp->depca_bus = DEPCA_BUS_MCA;
lp->adapter = depca_mca_adapter_type[mdev->index];
lp->mem_start = mem_start;
-
+
if ((err = depca_hw_init(dev, device)))
goto out_free;
-
+
return 0;
out_free:
** ISA bus I/O device probe
*/
-static void depca_platform_release (struct device *device)
-{
- struct platform_device *pldev;
-
- /* free device */
- pldev = to_platform_device (device);
- kfree (pldev);
-}
-
static void __init depca_platform_probe (void)
{
int i;
for (i = 0; depca_io_ports[i].iobase; i++) {
depca_io_ports[i].device = NULL;
-
+
/* if an address has been specified on the command
* line, use it (if valid) */
if (io && io != depca_io_ports[i].iobase)
continue;
-
- if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL)))
+
+ pldev = platform_device_alloc(depca_string, i);
+ if (!pldev)
continue;
- memset (pldev, 0, sizeof (*pldev));
- pldev->name = depca_string;
- pldev->id = i;
pldev->dev.platform_data = (void *) depca_io_ports[i].iobase;
- pldev->dev.release = depca_platform_release;
depca_io_ports[i].device = pldev;
- if (platform_device_register (pldev)) {
- kfree (pldev);
+ if (platform_device_add(pldev)) {
+ platform_device_put(pldev);
depca_io_ports[i].device = NULL;
continue;
}
* no hardware at this address. Unregister it, as the
* release fuction will take care of freeing the
* allocated structure */
-
+
depca_io_ports[i].device = NULL;
+ pldev->dev.platform_data = NULL;
platform_device_unregister (pldev);
}
}
return adapter;
}
-static int __init depca_isa_probe (struct device *device)
+static int __init depca_isa_probe (struct platform_device *device)
{
struct net_device *dev;
struct depca_private *lp;
enum depca_type adapter = unknown;
int status = 0;
- ioaddr = (u_long) device->platform_data;
+ ioaddr = (u_long) device->dev.platform_data;
if ((status = depca_common_init (ioaddr, &dev)))
goto out;
adapter = depca_shmem_probe (&mem_start);
-
+
if (adapter == unknown) {
status = -ENODEV;
goto out_free;
lp->depca_bus = DEPCA_BUS_ISA;
lp->adapter = adapter;
lp->mem_start = mem_start;
-
- if ((status = depca_hw_init(dev, device)))
+
+ if ((status = depca_hw_init(dev, &device->dev)))
goto out_free;
-
+
return 0;
out_free:
* it's address with the ethernet prom)... As we don't parse
* the EISA configuration structures (yet... :-), just rely on
* the ISA probing to sort it out... */
-
+
depca_shmem_probe (&mem_start);
dev->base_addr = ioaddr;
lp->depca_bus = DEPCA_BUS_EISA;
lp->adapter = edev->id.driver_data;
lp->mem_start = mem_start;
-
+
if ((status = depca_hw_init(dev, device)))
goto out_free;
-
+
return 0;
out_free:
static int __init DepcaSignature(char *name, u_long base_addr)
{
u_int i, j, k;
- void *ptr;
+ void __iomem *ptr;
char tmpstr[16];
u_long prom_addr = base_addr + 0xc000;
u_long mem_addr = base_addr + 0x8000; /* 32KB */
* used, at least on x86. Instead, reserve a memory region a
* board would certainly use. If it works, go ahead. If not,
* run like hell... */
-
+
if (!request_mem_region (mem_addr, 16, depca_string))
return unknown;
** if the first address octet is a 0x08 - this minimises the chances of
** messing around with some other hardware, but it assumes that this DEPCA
** card initialized itself correctly.
-**
+**
** Search the Ethernet address ROM for the signature. Since the ROM address
** counter can start at an arbitrary point, the search must include the entire
** probe sequence length plus the (length_of_the_signature - 1).
entry = lp->tx_new; /* Ring around buffer number. */
end = (entry + (skb->len - 1) / TX_BUFF_SZ) & lp->txRingMask;
if (!(readl(&lp->tx_ring[end].base) & T_OWN)) { /* Enough room? */
- /*
+ /*
** Caution: the write order is important here... don't set up the
** ownership rights until all the other information is in place.
*/
/* set up the buffer descriptors */
len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
- for (i = entry; i != end; i = (++i) & lp->txRingMask) {
+ for (i = entry; i != end; i = (i+1) & lp->txRingMask) {
/* clean out flags */
writel(readl(&lp->tx_ring[i].base) & ~T_FLAGS, &lp->tx_ring[i].base);
writew(0x0000, &lp->tx_ring[i].misc); /* clears other error flags */
printk("Descriptor addresses (CPU):\nRX: ");
for (i = 0; i < lp->rxRingMask; i++) {
if (i < 3) {
- printk("0x%8.8lx ", (long) &lp->rx_ring[i].base);
+ printk("%p ", &lp->rx_ring[i].base);
}
}
- printk("...0x%8.8lx\n", (long) &lp->rx_ring[i].base);
+ printk("...%p\n", &lp->rx_ring[i].base);
printk("TX: ");
for (i = 0; i < lp->txRingMask; i++) {
if (i < 3) {
- printk("0x%8.8lx ", (long) &lp->tx_ring[i].base);
+ printk("%p ", &lp->tx_ring[i].base);
}
}
- printk("...0x%8.8lx\n", (long) &lp->tx_ring[i].base);
+ printk("...%p\n", &lp->tx_ring[i].base);
printk("\nDescriptor buffers (Device):\nRX: ");
for (i = 0; i < lp->rxRingMask; i++) {
if (i < 3) {
}
}
printk("...0x%8.8x\n", readl(&lp->tx_ring[i].base));
- printk("Initialisation block at 0x%8.8lx(Phys)\n", virt_to_phys(lp->sh_mem));
+ printk("Initialisation block at 0x%8.8lx(Phys)\n", lp->mem_start);
printk(" mode: 0x%4.4x\n", p->mode);
printk(" physical address: ");
for (i = 0; i < ETH_ALEN - 1; i++) {
printk("%2.2x\n", p->mcast_table[i]);
printk(" rx_ring at: 0x%8.8x\n", p->rx_ring);
printk(" tx_ring at: 0x%8.8x\n", p->tx_ring);
- printk("buffers (Phys): 0x%8.8lx\n", virt_to_phys(lp->sh_mem) + lp->buffs_offset);
+ printk("buffers (Phys): 0x%8.8lx\n", lp->mem_start + lp->buffs_offset);
printk("Ring size:\nRX: %d Log2(rxRingMask): 0x%8.8x\n", (int) lp->rxRingMask + 1, lp->rx_rlen);
printk("TX: %d Log2(txRingMask): 0x%8.8x\n", (int) lp->txRingMask + 1, lp->tx_rlen);
outw(CSR2, DEPCA_ADDR);
#ifdef CONFIG_EISA
err |= eisa_driver_register (&depca_eisa_driver);
#endif
- err |= driver_register (&depca_isa_driver);
+ err |= platform_driver_register (&depca_isa_driver);
depca_platform_probe ();
-
+
return err;
}
#ifdef CONFIG_EISA
eisa_driver_unregister (&depca_eisa_driver);
#endif
- driver_unregister (&depca_isa_driver);
+ platform_driver_unregister (&depca_isa_driver);
for (i = 0; depca_io_ports[i].iobase; i++) {
if (depca_io_ports[i].device) {
+ depca_io_ports[i].device->dev.platform_data = NULL;
platform_device_unregister (depca_io_ports[i].device);
depca_io_ports[i].device = NULL;
}