1
0
Fork 0

drivers/net: delete old parallel port de600/de620 drivers

The parallel port is largely replaced by USB, and even in the
day where these drivers were current, the documented speed was
less than 100kB/s.  Let us not pretend that anyone cares about
these drivers anymore, or worse - pretend that anyone is using
them on a modern kernel.

As a side bonus, this is the end of legacy parallel port ethernet,
so we get to drop the whole chunk relating to that in the legacy
Space.c file containing the non-PCI unified probe dispatch.

Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
hifive-unleashed-5.1
Paul Gortmaker 2013-01-09 20:30:26 -05:00
parent de8270ff46
commit 168e06ae26
8 changed files with 2 additions and 2049 deletions

View File

@ -1,203 +0,0 @@
Released 1994-06-13
CONTENTS:
1. Introduction.
2. License.
3. Files in this release.
4. Installation.
5. Problems and tuning.
6. Using the drivers with earlier releases.
7. Acknowledgments.
1. INTRODUCTION.
This is a set of Ethernet drivers for the D-Link DE-600/DE-620
pocket adapters, for the parallel port on a Linux based machine.
Some adapter "clones" will also work. Xircom is _not_ a clone...
These drivers _can_ be used as loadable modules,
and were developed for use on Linux 1.1.13 and above.
For use on Linux 1.0.X, or earlier releases, see below.
I have used these drivers for NFS, ftp, telnet and X-clients on
remote machines. Transmissions with ftp seems to work as
good as can be expected (i.e. > 80k bytes/sec) from a
parallel port...:-) Receive speeds will be about 60-80% of this.
Depending on your machine, somewhat higher speeds can be achieved.
All comments/fixes to Bjorn Ekwall (bj0rn@blox.se).
2. LICENSE.
This program is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2, or (at your option) any later version.
This program is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU General Public License for more
details.
You should have received a copy of the GNU General Public
License along with this program; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
02139, USA.
3. FILES IN THIS RELEASE.
README.DLINK This file.
de600.c The Source (may it be with You :-) for the DE-600
de620.c ditto for the DE-620
de620.h Macros for de620.c
If you are upgrading from the d-link tar release, there will
also be a "dlink-patches" file that will patch Linux 1.1.18:
linux/drivers/net/Makefile
linux/drivers/net/CONFIG
linux/drivers/net/MODULES
linux/drivers/net/Space.c
linux/config.in
Apply the patch by:
"cd /usr/src; patch -p0 < linux/drivers/net/dlink-patches"
The old source, "linux/drivers/net/d_link.c", can be removed.
4. INSTALLATION.
o Get the latest net binaries, according to current net.wisdom.
o Read the NET-2 and Ethernet HOWTOs and modify your setup.
o If your parallel port has a strange address or irq,
modify "linux/drivers/net/CONFIG" accordingly, or adjust
the parameters in the "tuning" section in the sources.
If you are going to use the drivers as loadable modules, do _not_
enable them while doing "make config", but instead make sure that
the drivers are included in "linux/drivers/net/MODULES".
If you are _not_ going to use the driver(s) as loadable modules,
but instead have them included in the kernel, remember to enable
the drivers while doing "make config".
o To include networking and DE600/DE620 support in your kernel:
# cd /linux
(as modules:)
# make config (answer yes on CONFIG_NET and CONFIG_INET)
(else included in the kernel:)
# make config (answer yes on CONFIG _NET, _INET and _DE600 or _DE620)
# make clean
# make zImage (or whatever magic you usually do)
o I use lilo to boot multiple kernels, so that I at least
can have one working kernel :-). If you do too, append
these lines to /etc/lilo/config:
image = /linux/zImage
label = newlinux
root = /dev/hda2 (or whatever YOU have...)
# /etc/lilo/install
o Do "sync" and reboot the new kernel with a D-Link
DE-600/DE-620 pocket adapter connected.
o The adapter can be configured with ifconfig eth?
where the actual number is decided by the kernel
when the drivers are initialized.
5. "PROBLEMS" AND TUNING,
o If you see error messages from the driver, and if the traffic
stops on the adapter, try to do "ifconfig" and "route" once
more, just as in "rc.inet1". This should take care of most
problems, including effects from power loss, or adapters that
aren't connected to the printer port in some way or another.
You can somewhat change the behaviour by enabling/disabling
the macro SHUTDOWN_WHEN_LOST in the "tuning" section.
For the DE-600 there is another macro, CHECK_LOST_DE600,
that you might want to read about in the "tuning" section.
o Some machines have trouble handling the parallel port and
the adapter at high speed. If you experience problems:
DE-600:
- The adapter is not recognized at boot, i.e. an Ethernet
address of 00:80:c8:... is not shown, try to add another
"; SLOW_DOWN_IO"
at DE600_SLOW_DOWN in the "tuning" section. As a last resort,
uncomment: "#define REALLY_SLOW_IO" (see <asm/io.h> for hints).
- You experience "timeout" messages: first try to add another
"; SLOW_DOWN_IO"
at DE600_SLOW_DOWN in the "tuning" section, _then_ try to
increase the value (original value: 5) at
"if (tickssofar < 5)" near line 422.
DE-620:
- Your parallel port might be "sluggish". To cater for
this, there are the macros LOWSPEED and READ_DELAY/WRITE_DELAY
in the "tuning" section. Your first step should be to enable
LOWSPEED, and after that you can "tune" the XXX_DELAY values.
o If the adapter _is_ recognized at boot but you get messages
about "Network Unreachable", then the problem is probably
_not_ with the driver. Check your net configuration instead
(ifconfig and route) in "rc.inet1".
o There is some rudimentary support for debugging, look at
the source. Use "-DDE600_DEBUG=3" or "-DDE620_DEBUG=3"
when compiling, or include it in "linux/drivers/net/CONFIG".
IF YOU HAVE PROBLEMS YOU CAN'T SOLVE: PLEASE COMPILE THE DRIVER
WITH DEBUGGING ENABLED, AND SEND ME THE RESULTING OUTPUT!
6. USING THE DRIVERS WITH EARLIER RELEASES.
The later 1.1.X releases of the Linux kernel include some
changes in the networking layer (a.k.a. NET3). This affects
these drivers in a few places. The hints that follow are
_not_ tested by me, since I don't have the disk space to keep
all releases on-line.
Known needed changes to date:
- release patchfile: some patches will fail, but they should
be easy to apply "by hand", since they are trivial.
(Space.c: d_link_init() is now called de600_probe())
- de600.c: change "mark_bh(NET_BH)" to "mark_bh(INET_BH)".
- de620.c: (maybe) change the code around "netif_rx(skb);" to be
similar to the code around "dev_rint(...)" in de600.c
7. ACKNOWLEDGMENTS.
These drivers wouldn't have been done without the base
(and support) from Ross Biro, and D-Link Systems Inc.
The driver relies upon GPL-ed source from D-Link Systems Inc.
and from Russel Nelson at Crynwr Software <nelson@crynwr.com>.
Additional input also from:
Donald Becker <becker@super.org>, Alan Cox <A.Cox@swansea.ac.uk>
and Fred N. van Kempen <waltje@uWalt.NL.Mugnet.ORG>
DE-600 alpha release primary victim^H^H^H^H^H^Htester:
- Erik Proper <erikp@cs.kun.nl>.
Good input also from several users, most notably
- Mark Burton <markb@ordern.demon.co.uk>.
DE-620 alpha release victims^H^H^H^H^H^H^Htesters:
- J. Joshua Kopper <kopper@rtsg.mot.com>
- Olav Kvittem <Olav.Kvittem@uninett.no>
- Germano Caronni <caronni@nessie.cs.id.ethz.ch>
- Jeremy Fitzhardinge <jeremy@suite.sw.oz.au>
Happy hacking!
Bjorn Ekwall == bj0rn@blox.se

View File

@ -73,9 +73,6 @@ extern struct net_device *mac89x0_probe(int unit);
extern struct net_device *cops_probe(int unit);
extern struct net_device *ltpc_probe(void);
/* Detachable devices ("pocket adaptors") */
extern struct net_device *de620_probe(int unit);
/* Fibre Channel adapters */
extern int iph5526_probe(struct net_device *dev);
@ -185,13 +182,6 @@ static struct devprobe2 isa_probes[] __initdata = {
{NULL, 0},
};
static struct devprobe2 parport_probes[] __initdata = {
#ifdef CONFIG_DE620 /* D-Link DE-620 adapter */
{de620_probe, 0},
#endif
{NULL, 0},
};
static struct devprobe2 m68k_probes[] __initdata = {
#ifdef CONFIG_ATARILANCE /* Lance-based Atari ethernet boards */
{atarilance_probe, 0},
@ -230,8 +220,7 @@ static void __init ethif_probe2(int unit)
return;
(void)( probe_list2(unit, m68k_probes, base_addr == 0) &&
probe_list2(unit, isa_probes, base_addr == 0) &&
probe_list2(unit, parport_probes, base_addr == 0));
probe_list2(unit, isa_probes, base_addr == 0));
}
/* Statically configured drivers -- order matters here. */

View File

@ -5,7 +5,7 @@
config NET_VENDOR_DLINK
bool "D-Link devices"
default y
depends on PCI || PARPORT
depends on PCI
---help---
If you have a network (Ethernet) card belonging to this class, say Y
and read the Ethernet-HOWTO, available from
@ -18,36 +18,6 @@ config NET_VENDOR_DLINK
if NET_VENDOR_DLINK
config DE600
tristate "D-Link DE600 pocket adapter support"
depends on PARPORT
---help---
This is a network (Ethernet) device which attaches to your parallel
port. Read <file:Documentation/networking/DLINK.txt> as well as the
Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>, if you want to use
this. It is possible to have several devices share a single parallel
port and it is safe to compile the corresponding drivers into the
kernel.
To compile this driver as a module, choose M here: the module
will be called de600.
config DE620
tristate "D-Link DE620 pocket adapter support"
depends on PARPORT
---help---
This is a network (Ethernet) device which attaches to your parallel
port. Read <file:Documentation/networking/DLINK.txt> as well as the
Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>, if you want to use
this. It is possible to have several devices share a single parallel
port and it is safe to compile the corresponding drivers into the
kernel.
To compile this driver as a module, choose M here: the module
will be called de620.
config DL2K
tristate "DL2000/TC902x-based Gigabit Ethernet support"
depends on PCI

View File

@ -2,7 +2,5 @@
# Makefile for the D-Link network device drivers.
#
obj-$(CONFIG_DE600) += de600.o
obj-$(CONFIG_DE620) += de620.o
obj-$(CONFIG_DL2K) += dl2k.o
obj-$(CONFIG_SUNDANCE) += sundance.o

View File

@ -1,529 +0,0 @@
static const char version[] = "de600.c: $Revision: 1.41-2.5 $, Bjorn Ekwall (bj0rn@blox.se)\n";
/*
* de600.c
*
* Linux driver for the D-Link DE-600 Ethernet pocket adapter.
*
* Portions (C) Copyright 1993, 1994 by Bjorn Ekwall
* The Author may be reached as bj0rn@blox.se
*
* Based on adapter information gathered from DE600.ASM by D-Link Inc.,
* as included on disk C in the v.2.11 of PC/TCP from FTP Software.
* For DE600.asm:
* Portions (C) Copyright 1990 D-Link, Inc.
* Copyright, 1988-1992, Russell Nelson, Crynwr Software
*
* Adapted to the sample network driver core for linux,
* written by: Donald Becker <becker@super.org>
* (Now at <becker@scyld.com>)
*
**************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
**************************************************************/
/* Add more time here if your adapter won't work OK: */
#define DE600_SLOW_DOWN udelay(delay_time)
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/string.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/in.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <asm/io.h>
#include "de600.h"
static bool check_lost = true;
module_param(check_lost, bool, 0);
MODULE_PARM_DESC(check_lost, "If set then check for unplugged de600");
static unsigned int delay_time = 10;
module_param(delay_time, int, 0);
MODULE_PARM_DESC(delay_time, "DE-600 deley on I/O in microseconds");
/*
* D-Link driver variables:
*/
static volatile int rx_page;
#define TX_PAGES 2
static volatile int tx_fifo[TX_PAGES];
static volatile int tx_fifo_in;
static volatile int tx_fifo_out;
static volatile int free_tx_pages = TX_PAGES;
static int was_down;
static DEFINE_SPINLOCK(de600_lock);
static inline u8 de600_read_status(struct net_device *dev)
{
u8 status;
outb_p(STATUS, DATA_PORT);
status = inb(STATUS_PORT);
outb_p(NULL_COMMAND | HI_NIBBLE, DATA_PORT);
return status;
}
static inline u8 de600_read_byte(unsigned char type, struct net_device *dev)
{
/* dev used by macros */
u8 lo;
outb_p((type), DATA_PORT);
lo = ((unsigned char)inb(STATUS_PORT)) >> 4;
outb_p((type) | HI_NIBBLE, DATA_PORT);
return ((unsigned char)inb(STATUS_PORT) & (unsigned char)0xf0) | lo;
}
/*
* Open/initialize the board. This is called (in the current kernel)
* after booting when 'ifconfig <dev->name> $IP_ADDR' is run (in rc.inet1).
*
* This routine should set everything up anew at each open, even
* registers that "should" only need to be set once at boot, so that
* there is a non-reboot way to recover if something goes wrong.
*/
static int de600_open(struct net_device *dev)
{
unsigned long flags;
int ret = request_irq(DE600_IRQ, de600_interrupt, 0, dev->name, dev);
if (ret) {
printk(KERN_ERR "%s: unable to get IRQ %d\n", dev->name, DE600_IRQ);
return ret;
}
spin_lock_irqsave(&de600_lock, flags);
ret = adapter_init(dev);
spin_unlock_irqrestore(&de600_lock, flags);
return ret;
}
/*
* The inverse routine to de600_open().
*/
static int de600_close(struct net_device *dev)
{
select_nic();
rx_page = 0;
de600_put_command(RESET);
de600_put_command(STOP_RESET);
de600_put_command(0);
select_prn();
free_irq(DE600_IRQ, dev);
return 0;
}
static inline void trigger_interrupt(struct net_device *dev)
{
de600_put_command(FLIP_IRQ);
select_prn();
DE600_SLOW_DOWN;
select_nic();
de600_put_command(0);
}
/*
* Copy a buffer to the adapter transmit page memory.
* Start sending.
*/
static int de600_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
unsigned long flags;
int transmit_from;
int len;
int tickssofar;
u8 *buffer = skb->data;
int i;
if (free_tx_pages <= 0) { /* Do timeouts, to avoid hangs. */
tickssofar = jiffies - dev_trans_start(dev);
if (tickssofar < HZ/20)
return NETDEV_TX_BUSY;
/* else */
printk(KERN_WARNING "%s: transmit timed out (%d), %s?\n", dev->name, tickssofar, "network cable problem");
/* Restart the adapter. */
spin_lock_irqsave(&de600_lock, flags);
if (adapter_init(dev)) {
spin_unlock_irqrestore(&de600_lock, flags);
return NETDEV_TX_BUSY;
}
spin_unlock_irqrestore(&de600_lock, flags);
}
/* Start real output */
pr_debug("de600_start_xmit:len=%d, page %d/%d\n", skb->len, tx_fifo_in, free_tx_pages);
if ((len = skb->len) < RUNT)
len = RUNT;
spin_lock_irqsave(&de600_lock, flags);
select_nic();
tx_fifo[tx_fifo_in] = transmit_from = tx_page_adr(tx_fifo_in) - len;
tx_fifo_in = (tx_fifo_in + 1) % TX_PAGES; /* Next free tx page */
if(check_lost)
{
/* This costs about 40 instructions per packet... */
de600_setup_address(NODE_ADDRESS, RW_ADDR);
de600_read_byte(READ_DATA, dev);
if (was_down || (de600_read_byte(READ_DATA, dev) != 0xde)) {
if (adapter_init(dev)) {
spin_unlock_irqrestore(&de600_lock, flags);
return NETDEV_TX_BUSY;
}
}
}
de600_setup_address(transmit_from, RW_ADDR);
for (i = 0; i < skb->len ; ++i, ++buffer)
de600_put_byte(*buffer);
for (; i < len; ++i)
de600_put_byte(0);
if (free_tx_pages-- == TX_PAGES) { /* No transmission going on */
dev->trans_start = jiffies;
netif_start_queue(dev); /* allow more packets into adapter */
/* Send page and generate a faked interrupt */
de600_setup_address(transmit_from, TX_ADDR);
de600_put_command(TX_ENABLE);
}
else {
if (free_tx_pages)
netif_start_queue(dev);
else
netif_stop_queue(dev);
select_prn();
}
spin_unlock_irqrestore(&de600_lock, flags);
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
/*
* The typical workload of the driver:
* Handle the network interface interrupts.
*/
static irqreturn_t de600_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
u8 irq_status;
int retrig = 0;
int boguscount = 0;
spin_lock(&de600_lock);
select_nic();
irq_status = de600_read_status(dev);
do {
pr_debug("de600_interrupt (%02X)\n", irq_status);
if (irq_status & RX_GOOD)
de600_rx_intr(dev);
else if (!(irq_status & RX_BUSY))
de600_put_command(RX_ENABLE);
/* Any transmission in progress? */
if (free_tx_pages < TX_PAGES)
retrig = de600_tx_intr(dev, irq_status);
else
retrig = 0;
irq_status = de600_read_status(dev);
} while ( (irq_status & RX_GOOD) || ((++boguscount < 100) && retrig) );
/*
* Yeah, it _looks_ like busy waiting, smells like busy waiting
* and I know it's not PC, but please, it will only occur once
* in a while and then only for a loop or so (< 1ms for sure!)
*/
/* Enable adapter interrupts */
select_prn();
if (retrig)
trigger_interrupt(dev);
spin_unlock(&de600_lock);
return IRQ_HANDLED;
}
static int de600_tx_intr(struct net_device *dev, int irq_status)
{
/*
* Returns 1 if tx still not done
*/
/* Check if current transmission is done yet */
if (irq_status & TX_BUSY)
return 1; /* tx not done, try again */
/* else */
/* If last transmission OK then bump fifo index */
if (!(irq_status & TX_FAILED16)) {
tx_fifo_out = (tx_fifo_out + 1) % TX_PAGES;
++free_tx_pages;
dev->stats.tx_packets++;
netif_wake_queue(dev);
}
/* More to send, or resend last packet? */
if ((free_tx_pages < TX_PAGES) || (irq_status & TX_FAILED16)) {
dev->trans_start = jiffies;
de600_setup_address(tx_fifo[tx_fifo_out], TX_ADDR);
de600_put_command(TX_ENABLE);
return 1;
}
/* else */
return 0;
}
/*
* We have a good packet, get it out of the adapter.
*/
static void de600_rx_intr(struct net_device *dev)
{
struct sk_buff *skb;
int i;
int read_from;
int size;
unsigned char *buffer;
/* Get size of received packet */
size = de600_read_byte(RX_LEN, dev); /* low byte */
size += (de600_read_byte(RX_LEN, dev) << 8); /* high byte */
size -= 4; /* Ignore trailing 4 CRC-bytes */
/* Tell adapter where to store next incoming packet, enable receiver */
read_from = rx_page_adr();
next_rx_page();
de600_put_command(RX_ENABLE);
if ((size < 32) || (size > 1535)) {
printk(KERN_WARNING "%s: Bogus packet size %d.\n", dev->name, size);
if (size > 10000)
adapter_init(dev);
return;
}
skb = netdev_alloc_skb(dev, size + 2);
if (skb == NULL) {
printk("%s: Couldn't allocate a sk_buff of size %d.\n", dev->name, size);
return;
}
/* else */
skb_reserve(skb,2); /* Align */
/* 'skb->data' points to the start of sk_buff data area. */
buffer = skb_put(skb,size);
/* copy the packet into the buffer */
de600_setup_address(read_from, RW_ADDR);
for (i = size; i > 0; --i, ++buffer)
*buffer = de600_read_byte(READ_DATA, dev);
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
/* update stats */
dev->stats.rx_packets++; /* count all receives */
dev->stats.rx_bytes += size; /* count all received bytes */
/*
* If any worth-while packets have been received, netif_rx()
* will work on them when we get to the tasklets.
*/
}
static const struct net_device_ops de600_netdev_ops = {
.ndo_open = de600_open,
.ndo_stop = de600_close,
.ndo_start_xmit = de600_start_xmit,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
static struct net_device * __init de600_probe(void)
{
int i;
struct net_device *dev;
int err;
dev = alloc_etherdev(0);
if (!dev)
return ERR_PTR(-ENOMEM);
if (!request_region(DE600_IO, 3, "de600")) {
printk(KERN_WARNING "DE600: port 0x%x busy\n", DE600_IO);
err = -EBUSY;
goto out;
}
printk(KERN_INFO "%s: D-Link DE-600 pocket adapter", dev->name);
/* Alpha testers must have the version number to report bugs. */
pr_debug("%s", version);
/* probe for adapter */
err = -ENODEV;
rx_page = 0;
select_nic();
(void)de600_read_status(dev);
de600_put_command(RESET);
de600_put_command(STOP_RESET);
if (de600_read_status(dev) & 0xf0) {
printk(": not at I/O %#3x.\n", DATA_PORT);
goto out1;
}
/*
* Maybe we found one,
* have to check if it is a D-Link DE-600 adapter...
*/
/* Get the adapter ethernet address from the ROM */
de600_setup_address(NODE_ADDRESS, RW_ADDR);
for (i = 0; i < ETH_ALEN; i++) {
dev->dev_addr[i] = de600_read_byte(READ_DATA, dev);
dev->broadcast[i] = 0xff;
}
/* Check magic code */
if ((dev->dev_addr[1] == 0xde) && (dev->dev_addr[2] == 0x15)) {
/* OK, install real address */
dev->dev_addr[0] = 0x00;
dev->dev_addr[1] = 0x80;
dev->dev_addr[2] = 0xc8;
dev->dev_addr[3] &= 0x0f;
dev->dev_addr[3] |= 0x70;
} else {
printk(" not identified in the printer port\n");
goto out1;
}
printk(", Ethernet Address: %pM\n", dev->dev_addr);
dev->netdev_ops = &de600_netdev_ops;
dev->flags&=~IFF_MULTICAST;
select_prn();
err = register_netdev(dev);
if (err)
goto out1;
return dev;
out1:
release_region(DE600_IO, 3);
out:
free_netdev(dev);
return ERR_PTR(err);
}
static int adapter_init(struct net_device *dev)
{
int i;
select_nic();
rx_page = 0; /* used by RESET */
de600_put_command(RESET);
de600_put_command(STOP_RESET);
/* Check if it is still there... */
/* Get the some bytes of the adapter ethernet address from the ROM */
de600_setup_address(NODE_ADDRESS, RW_ADDR);
de600_read_byte(READ_DATA, dev);
if ((de600_read_byte(READ_DATA, dev) != 0xde) ||
(de600_read_byte(READ_DATA, dev) != 0x15)) {
/* was: if (de600_read_status(dev) & 0xf0) { */
printk("Something has happened to the DE-600! Please check it and do a new ifconfig!\n");
/* Goodbye, cruel world... */
dev->flags &= ~IFF_UP;
de600_close(dev);
was_down = 1;
netif_stop_queue(dev); /* Transmit busy... */
return 1; /* failed */
}
if (was_down) {
printk(KERN_INFO "%s: Thanks, I feel much better now!\n", dev->name);
was_down = 0;
}
tx_fifo_in = 0;
tx_fifo_out = 0;
free_tx_pages = TX_PAGES;
/* set the ether address. */
de600_setup_address(NODE_ADDRESS, RW_ADDR);
for (i = 0; i < ETH_ALEN; i++)
de600_put_byte(dev->dev_addr[i]);
/* where to start saving incoming packets */
rx_page = RX_BP | RX_BASE_PAGE;
de600_setup_address(MEM_4K, RW_ADDR);
/* Enable receiver */
de600_put_command(RX_ENABLE);
select_prn();
netif_start_queue(dev);
return 0; /* OK */
}
static struct net_device *de600_dev;
static int __init de600_init(void)
{
de600_dev = de600_probe();
if (IS_ERR(de600_dev))
return PTR_ERR(de600_dev);
return 0;
}
static void __exit de600_exit(void)
{
unregister_netdev(de600_dev);
release_region(DE600_IO, 3);
free_netdev(de600_dev);
}
module_init(de600_init);
module_exit(de600_exit);
MODULE_LICENSE("GPL");

View File

@ -1,168 +0,0 @@
/**************************************************
* *
* Definition of D-Link Ethernet Pocket adapter *
* *
**************************************************/
/*
* D-Link Ethernet pocket adapter ports
*/
/*
* OK, so I'm cheating, but there are an awful lot of
* reads and writes in order to get anything in and out
* of the DE-600 with 4 bits at a time in the parallel port,
* so every saved instruction really helps :-)
*/
#ifndef DE600_IO
#define DE600_IO 0x378
#endif
#define DATA_PORT (DE600_IO)
#define STATUS_PORT (DE600_IO + 1)
#define COMMAND_PORT (DE600_IO + 2)
#ifndef DE600_IRQ
#define DE600_IRQ 7
#endif
/*
* It really should look like this, and autoprobing as well...
*
#define DATA_PORT (dev->base_addr + 0)
#define STATUS_PORT (dev->base_addr + 1)
#define COMMAND_PORT (dev->base_addr + 2)
#define DE600_IRQ dev->irq
*/
/*
* D-Link COMMAND_PORT commands
*/
#define SELECT_NIC 0x04 /* select Network Interface Card */
#define SELECT_PRN 0x1c /* select Printer */
#define NML_PRN 0xec /* normal Printer situation */
#define IRQEN 0x10 /* enable IRQ line */
/*
* D-Link STATUS_PORT
*/
#define RX_BUSY 0x80
#define RX_GOOD 0x40
#define TX_FAILED16 0x10
#define TX_BUSY 0x08
/*
* D-Link DATA_PORT commands
* command in low 4 bits
* data in high 4 bits
* select current data nibble with HI_NIBBLE bit
*/
#define WRITE_DATA 0x00 /* write memory */
#define READ_DATA 0x01 /* read memory */
#define STATUS 0x02 /* read status register */
#define COMMAND 0x03 /* write command register (see COMMAND below) */
#define NULL_COMMAND 0x04 /* null command */
#define RX_LEN 0x05 /* read received packet length */
#define TX_ADDR 0x06 /* set adapter transmit memory address */
#define RW_ADDR 0x07 /* set adapter read/write memory address */
#define HI_NIBBLE 0x08 /* read/write the high nibble of data,
or-ed with rest of command */
/*
* command register, accessed through DATA_PORT with low bits = COMMAND
*/
#define RX_ALL 0x01 /* PROMISCUOUS */
#define RX_BP 0x02 /* default: BROADCAST & PHYSICAL ADDRESS */
#define RX_MBP 0x03 /* MULTICAST, BROADCAST & PHYSICAL ADDRESS */
#define TX_ENABLE 0x04 /* bit 2 */
#define RX_ENABLE 0x08 /* bit 3 */
#define RESET 0x80 /* set bit 7 high */
#define STOP_RESET 0x00 /* set bit 7 low */
/*
* data to command register
* (high 4 bits in write to DATA_PORT)
*/
#define RX_PAGE2_SELECT 0x10 /* bit 4, only 2 pages to select */
#define RX_BASE_PAGE 0x20 /* bit 5, always set when specifying RX_ADDR */
#define FLIP_IRQ 0x40 /* bit 6 */
/*
* D-Link adapter internal memory:
*
* 0-2K 1:st transmit page (send from pointer up to 2K)
* 2-4K 2:nd transmit page (send from pointer up to 4K)
*
* 4-6K 1:st receive page (data from 4K upwards)
* 6-8K 2:nd receive page (data from 6K upwards)
*
* 8K+ Adapter ROM (contains magic code and last 3 bytes of Ethernet address)
*/
#define MEM_2K 0x0800 /* 2048 */
#define MEM_4K 0x1000 /* 4096 */
#define MEM_6K 0x1800 /* 6144 */
#define NODE_ADDRESS 0x2000 /* 8192 */
#define RUNT 60 /* Too small Ethernet packet */
/**************************************************
* *
* End of definition *
* *
**************************************************/
/*
* Index to functions, as function prototypes.
*/
/* Routines used internally. (See "convenience macros") */
static u8 de600_read_status(struct net_device *dev);
static u8 de600_read_byte(unsigned char type, struct net_device *dev);
/* Put in the device structure. */
static int de600_open(struct net_device *dev);
static int de600_close(struct net_device *dev);
static int de600_start_xmit(struct sk_buff *skb, struct net_device *dev);
/* Dispatch from interrupts. */
static irqreturn_t de600_interrupt(int irq, void *dev_id);
static int de600_tx_intr(struct net_device *dev, int irq_status);
static void de600_rx_intr(struct net_device *dev);
/* Initialization */
static void trigger_interrupt(struct net_device *dev);
static int adapter_init(struct net_device *dev);
/*
* Convenience macros/functions for D-Link adapter
*/
#define select_prn() outb_p(SELECT_PRN, COMMAND_PORT); DE600_SLOW_DOWN
#define select_nic() outb_p(SELECT_NIC, COMMAND_PORT); DE600_SLOW_DOWN
/* Thanks for hints from Mark Burton <markb@ordern.demon.co.uk> */
#define de600_put_byte(data) ( \
outb_p(((data) << 4) | WRITE_DATA , DATA_PORT), \
outb_p(((data) & 0xf0) | WRITE_DATA | HI_NIBBLE, DATA_PORT))
/*
* The first two outb_p()'s below could perhaps be deleted if there
* would be more delay in the last two. Not certain about it yet...
*/
#define de600_put_command(cmd) ( \
outb_p(( rx_page << 4) | COMMAND , DATA_PORT), \
outb_p(( rx_page & 0xf0) | COMMAND | HI_NIBBLE, DATA_PORT), \
outb_p(((rx_page | cmd) << 4) | COMMAND , DATA_PORT), \
outb_p(((rx_page | cmd) & 0xf0) | COMMAND | HI_NIBBLE, DATA_PORT))
#define de600_setup_address(addr,type) ( \
outb_p((((addr) << 4) & 0xf0) | type , DATA_PORT), \
outb_p(( (addr) & 0xf0) | type | HI_NIBBLE, DATA_PORT), \
outb_p((((addr) >> 4) & 0xf0) | type , DATA_PORT), \
outb_p((((addr) >> 8) & 0xf0) | type | HI_NIBBLE, DATA_PORT))
#define rx_page_adr() ((rx_page & RX_PAGE2_SELECT)?(MEM_6K):(MEM_4K))
/* Flip bit, only 2 pages */
#define next_rx_page() (rx_page ^= RX_PAGE2_SELECT)
#define tx_page_adr(a) (((a) + 1) * MEM_2K)

View File

@ -1,987 +0,0 @@
/*
* de620.c $Revision: 1.40 $ BETA
*
*
* Linux driver for the D-Link DE-620 Ethernet pocket adapter.
*
* Portions (C) Copyright 1993, 1994 by Bjorn Ekwall <bj0rn@blox.se>
*
* Based on adapter information gathered from DOS packetdriver
* sources from D-Link Inc: (Special thanks to Henry Ngai of D-Link.)
* Portions (C) Copyright D-Link SYSTEM Inc. 1991, 1992
* Copyright, 1988, Russell Nelson, Crynwr Software
*
* Adapted to the sample network driver core for linux,
* written by: Donald Becker <becker@super.org>
* (Now at <becker@scyld.com>)
*
* Valuable assistance from:
* J. Joshua Kopper <kopper@rtsg.mot.com>
* Olav Kvittem <Olav.Kvittem@uninett.no>
* Germano Caronni <caronni@nessie.cs.id.ethz.ch>
* Jeremy Fitzhardinge <jeremy@suite.sw.oz.au>
*
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*****************************************************************************/
static const char version[] =
"de620.c: $Revision: 1.40 $, Bjorn Ekwall <bj0rn@blox.se>\n";
/***********************************************************************
*
* "Tuning" section.
*
* Compile-time options: (see below for descriptions)
* -DDE620_IO=0x378 (lpt1)
* -DDE620_IRQ=7 (lpt1)
* -DSHUTDOWN_WHEN_LOST
* -DCOUNT_LOOPS
* -DLOWSPEED
* -DREAD_DELAY
* -DWRITE_DELAY
*/
/*
* This driver assumes that the printer port is a "normal",
* dumb, uni-directional port!
* If your port is "fancy" in any way, please try to set it to "normal"
* with your BIOS setup. I have no access to machines with bi-directional
* ports, so I can't test such a driver :-(
* (Yes, I _know_ it is possible to use DE620 with bidirectional ports...)
*
* There are some clones of DE620 out there, with different names.
* If the current driver does not recognize a clone, try to change
* the following #define to:
*
* #define DE620_CLONE 1
*/
#define DE620_CLONE 0
/*
* If the adapter has problems with high speeds, enable this #define
* otherwise full printerport speed will be attempted.
*
* You can tune the READ_DELAY/WRITE_DELAY below if you enable LOWSPEED
*
#define LOWSPEED
*/
#ifndef READ_DELAY
#define READ_DELAY 100 /* adapter internal read delay in 100ns units */
#endif
#ifndef WRITE_DELAY
#define WRITE_DELAY 100 /* adapter internal write delay in 100ns units */
#endif
/*
* Enable this #define if you want the adapter to do a "ifconfig down" on
* itself when we have detected that something is possibly wrong with it.
* The default behaviour is to retry with "adapter_init()" until success.
* This should be used for debugging purposes only.
*
#define SHUTDOWN_WHEN_LOST
*/
#ifdef LOWSPEED
/*
* Enable this #define if you want to see debugging output that show how long
* we have to wait before the DE-620 is ready for the next read/write/command.
*
#define COUNT_LOOPS
*/
#endif
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/string.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/in.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <asm/io.h>
/* Constant definitions for the DE-620 registers, commands and bits */
#include "de620.h"
typedef unsigned char byte;
/*******************************************************
* *
* Definition of D-Link DE-620 Ethernet Pocket adapter *
* See also "de620.h" *
* *
*******************************************************/
#ifndef DE620_IO /* Compile-time configurable */
#define DE620_IO 0x378
#endif
#ifndef DE620_IRQ /* Compile-time configurable */
#define DE620_IRQ 7
#endif
#define DATA_PORT (dev->base_addr)
#define STATUS_PORT (dev->base_addr + 1)
#define COMMAND_PORT (dev->base_addr + 2)
#define RUNT 60 /* Too small Ethernet packet */
#define GIANT 1514 /* largest legal size packet, no fcs */
/*
* Force media with insmod:
* insmod de620.o bnc=1
* or
* insmod de620.o utp=1
*
* Force io and/or irq with insmod:
* insmod de620.o io=0x378 irq=7
*
* Make a clone skip the Ethernet-address range check:
* insmod de620.o clone=1
*/
static int bnc;
static int utp;
static int io = DE620_IO;
static int irq = DE620_IRQ;
static int clone = DE620_CLONE;
static spinlock_t de620_lock;
module_param(bnc, int, 0);
module_param(utp, int, 0);
module_param(io, int, 0);
module_param(irq, int, 0);
module_param(clone, int, 0);
MODULE_PARM_DESC(bnc, "DE-620 set BNC medium (0-1)");
MODULE_PARM_DESC(utp, "DE-620 set UTP medium (0-1)");
MODULE_PARM_DESC(io, "DE-620 I/O base address,required");
MODULE_PARM_DESC(irq, "DE-620 IRQ number,required");
MODULE_PARM_DESC(clone, "Check also for non-D-Link DE-620 clones (0-1)");
/***********************************************
* *
* Index to functions, as function prototypes. *
* *
***********************************************/
/*
* Routines used internally. (See also "convenience macros.. below")
*/
/* Put in the device structure. */
static int de620_open(struct net_device *);
static int de620_close(struct net_device *);
static void de620_set_multicast_list(struct net_device *);
static int de620_start_xmit(struct sk_buff *, struct net_device *);
/* Dispatch from interrupts. */
static irqreturn_t de620_interrupt(int, void *);
static int de620_rx_intr(struct net_device *);
/* Initialization */
static int adapter_init(struct net_device *);
static int read_eeprom(struct net_device *);
/*
* D-Link driver variables:
*/
#define SCR_DEF NIBBLEMODE |INTON | SLEEP | AUTOTX
#define TCR_DEF RXPB /* not used: | TXSUCINT | T16INT */
#define DE620_RX_START_PAGE 12 /* 12 pages (=3k) reserved for tx */
#define DEF_NIC_CMD IRQEN | ICEN | DS1
static volatile byte NIC_Cmd;
static volatile byte next_rx_page;
static byte first_rx_page;
static byte last_rx_page;
static byte EIPRegister;
static struct nic {
byte NodeID[6];
byte RAM_Size;
byte Model;
byte Media;
byte SCR;
} nic_data;
/**********************************************************
* *
* Convenience macros/functions for D-Link DE-620 adapter *
* *
**********************************************************/
#define de620_tx_buffs(dd) (inb(STATUS_PORT) & (TXBF0 | TXBF1))
#define de620_flip_ds(dd) NIC_Cmd ^= DS0 | DS1; outb(NIC_Cmd, COMMAND_PORT);
/* Check for ready-status, and return a nibble (high 4 bits) for data input */
#ifdef COUNT_LOOPS
static int tot_cnt;
#endif
static inline byte
de620_ready(struct net_device *dev)
{
byte value;
register short int cnt = 0;
while ((((value = inb(STATUS_PORT)) & READY) == 0) && (cnt <= 1000))
++cnt;
#ifdef COUNT_LOOPS
tot_cnt += cnt;
#endif
return value & 0xf0; /* nibble */
}
static inline void
de620_send_command(struct net_device *dev, byte cmd)
{
de620_ready(dev);
if (cmd == W_DUMMY)
outb(NIC_Cmd, COMMAND_PORT);
outb(cmd, DATA_PORT);
outb(NIC_Cmd ^ CS0, COMMAND_PORT);
de620_ready(dev);
outb(NIC_Cmd, COMMAND_PORT);
}
static inline void
de620_put_byte(struct net_device *dev, byte value)
{
/* The de620_ready() makes 7 loops, on the average, on a DX2/66 */
de620_ready(dev);
outb(value, DATA_PORT);
de620_flip_ds(dev);
}
static inline byte
de620_read_byte(struct net_device *dev)
{
byte value;
/* The de620_ready() makes 7 loops, on the average, on a DX2/66 */
value = de620_ready(dev); /* High nibble */
de620_flip_ds(dev);
value |= de620_ready(dev) >> 4; /* Low nibble */
return value;
}
static inline void
de620_write_block(struct net_device *dev, byte *buffer, int count, int pad)
{
#ifndef LOWSPEED
byte uflip = NIC_Cmd ^ (DS0 | DS1);
byte dflip = NIC_Cmd;
#else /* LOWSPEED */
#ifdef COUNT_LOOPS
int bytes = count;
#endif /* COUNT_LOOPS */
#endif /* LOWSPEED */
#ifdef LOWSPEED
#ifdef COUNT_LOOPS
tot_cnt = 0;
#endif /* COUNT_LOOPS */
/* No further optimization useful, the limit is in the adapter. */
for ( ; count > 0; --count, ++buffer) {
de620_put_byte(dev,*buffer);
}
for ( count = pad ; count > 0; --count, ++buffer) {
de620_put_byte(dev, 0);
}
de620_send_command(dev,W_DUMMY);
#ifdef COUNT_LOOPS
/* trial debug output: loops per byte in de620_ready() */
printk("WRITE(%d)\n", tot_cnt/((bytes?bytes:1)));
#endif /* COUNT_LOOPS */
#else /* not LOWSPEED */
for ( ; count > 0; count -=2) {
outb(*buffer++, DATA_PORT);
outb(uflip, COMMAND_PORT);
outb(*buffer++, DATA_PORT);
outb(dflip, COMMAND_PORT);
}
de620_send_command(dev,W_DUMMY);
#endif /* LOWSPEED */
}
static inline void
de620_read_block(struct net_device *dev, byte *data, int count)
{
#ifndef LOWSPEED
byte value;
byte uflip = NIC_Cmd ^ (DS0 | DS1);
byte dflip = NIC_Cmd;
#else /* LOWSPEED */
#ifdef COUNT_LOOPS
int bytes = count;
tot_cnt = 0;
#endif /* COUNT_LOOPS */
#endif /* LOWSPEED */
#ifdef LOWSPEED
/* No further optimization useful, the limit is in the adapter. */
while (count-- > 0) {
*data++ = de620_read_byte(dev);
de620_flip_ds(dev);
}
#ifdef COUNT_LOOPS
/* trial debug output: loops per byte in de620_ready() */
printk("READ(%d)\n", tot_cnt/(2*(bytes?bytes:1)));
#endif /* COUNT_LOOPS */
#else /* not LOWSPEED */
while (count-- > 0) {
value = inb(STATUS_PORT) & 0xf0; /* High nibble */
outb(uflip, COMMAND_PORT);
*data++ = value | inb(STATUS_PORT) >> 4; /* Low nibble */
outb(dflip , COMMAND_PORT);
}
#endif /* LOWSPEED */
}
static inline void
de620_set_delay(struct net_device *dev)
{
de620_ready(dev);
outb(W_DFR, DATA_PORT);
outb(NIC_Cmd ^ CS0, COMMAND_PORT);
de620_ready(dev);
#ifdef LOWSPEED
outb(WRITE_DELAY, DATA_PORT);
#else
outb(0, DATA_PORT);
#endif
de620_flip_ds(dev);
de620_ready(dev);
#ifdef LOWSPEED
outb(READ_DELAY, DATA_PORT);
#else
outb(0, DATA_PORT);
#endif
de620_flip_ds(dev);
}
static inline void
de620_set_register(struct net_device *dev, byte reg, byte value)
{
de620_ready(dev);
outb(reg, DATA_PORT);
outb(NIC_Cmd ^ CS0, COMMAND_PORT);
de620_put_byte(dev, value);
}
static inline byte
de620_get_register(struct net_device *dev, byte reg)
{
byte value;
de620_send_command(dev,reg);
value = de620_read_byte(dev);
de620_send_command(dev,W_DUMMY);
return value;
}
/*********************************************************************
*
* Open/initialize the board.
*
* This routine should set everything up anew at each open, even
* registers that "should" only need to be set once at boot, so that
* there is a non-reboot way to recover if something goes wrong.
*
*/
static int de620_open(struct net_device *dev)
{
int ret = request_irq(dev->irq, de620_interrupt, 0, dev->name, dev);
if (ret) {
printk (KERN_ERR "%s: unable to get IRQ %d\n", dev->name, dev->irq);
return ret;
}
if (adapter_init(dev)) {
ret = -EIO;
goto out_free_irq;
}
netif_start_queue(dev);
return 0;
out_free_irq:
free_irq(dev->irq, dev);
return ret;
}
/************************************************
*
* The inverse routine to de620_open().
*
*/
static int de620_close(struct net_device *dev)
{
netif_stop_queue(dev);
/* disable recv */
de620_set_register(dev, W_TCR, RXOFF);
free_irq(dev->irq, dev);
return 0;
}
/*********************************************
*
* Set or clear the multicast filter for this adaptor.
* (no real multicast implemented for the DE-620, but she can be promiscuous...)
*
*/
static void de620_set_multicast_list(struct net_device *dev)
{
if (!netdev_mc_empty(dev) || dev->flags&(IFF_ALLMULTI|IFF_PROMISC))
{ /* Enable promiscuous mode */
de620_set_register(dev, W_TCR, (TCR_DEF & ~RXPBM) | RXALL);
}
else
{ /* Disable promiscuous mode, use normal mode */
de620_set_register(dev, W_TCR, TCR_DEF);
}
}
/*******************************************************
*
* Handle timeouts on transmit
*/
static void de620_timeout(struct net_device *dev)
{
printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name, "network cable problem");
/* Restart the adapter. */
if (!adapter_init(dev)) /* maybe close it */
netif_wake_queue(dev);
}
/*******************************************************
*
* Copy a buffer to the adapter transmit page memory.
* Start sending.
*/
static int de620_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
unsigned long flags;
int len;
byte *buffer = skb->data;
byte using_txbuf;
using_txbuf = de620_tx_buffs(dev); /* Peek at the adapter */
netif_stop_queue(dev);
if ((len = skb->len) < RUNT)
len = RUNT;
if (len & 1) /* send an even number of bytes */
++len;
/* Start real output */
spin_lock_irqsave(&de620_lock, flags);
pr_debug("de620_start_xmit: len=%d, bufs 0x%02x\n",
(int)skb->len, using_txbuf);
/* select a free tx buffer. if there is one... */
switch (using_txbuf) {
default: /* both are free: use TXBF0 */
case TXBF1: /* use TXBF0 */
de620_send_command(dev,W_CR | RW0);
using_txbuf |= TXBF0;
break;
case TXBF0: /* use TXBF1 */
de620_send_command(dev,W_CR | RW1);
using_txbuf |= TXBF1;
break;
case (TXBF0 | TXBF1): /* NONE!!! */
printk(KERN_WARNING "%s: No tx-buffer available!\n", dev->name);
spin_unlock_irqrestore(&de620_lock, flags);
return NETDEV_TX_BUSY;
}
de620_write_block(dev, buffer, skb->len, len-skb->len);
if(!(using_txbuf == (TXBF0 | TXBF1)))
netif_wake_queue(dev);
dev->stats.tx_packets++;
spin_unlock_irqrestore(&de620_lock, flags);
dev_kfree_skb (skb);
return NETDEV_TX_OK;
}
/*****************************************************
*
* Handle the network interface interrupts.
*
*/
static irqreturn_t
de620_interrupt(int irq_in, void *dev_id)
{
struct net_device *dev = dev_id;
byte irq_status;
int bogus_count = 0;
int again = 0;
spin_lock(&de620_lock);
/* Read the status register (_not_ the status port) */
irq_status = de620_get_register(dev, R_STS);
pr_debug("de620_interrupt (%2.2X)\n", irq_status);
if (irq_status & RXGOOD) {
do {
again = de620_rx_intr(dev);
pr_debug("again=%d\n", again);
}
while (again && (++bogus_count < 100));
}
if(de620_tx_buffs(dev) != (TXBF0 | TXBF1))
netif_wake_queue(dev);
spin_unlock(&de620_lock);
return IRQ_HANDLED;
}
/**************************************
*
* Get a packet from the adapter
*
* Send it "upstairs"
*
*/
static int de620_rx_intr(struct net_device *dev)
{
struct header_buf {
byte status;
byte Rx_NextPage;
unsigned short Rx_ByteCount;
} header_buf;
struct sk_buff *skb;
int size;
byte *buffer;
byte pagelink;
byte curr_page;
pr_debug("de620_rx_intr: next_rx_page = %d\n", next_rx_page);
/* Tell the adapter that we are going to read data, and from where */
de620_send_command(dev, W_CR | RRN);
de620_set_register(dev, W_RSA1, next_rx_page);
de620_set_register(dev, W_RSA0, 0);
/* Deep breath, and away we goooooo */
de620_read_block(dev, (byte *)&header_buf, sizeof(struct header_buf));
pr_debug("page status=0x%02x, nextpage=%d, packetsize=%d\n",
header_buf.status, header_buf.Rx_NextPage,
header_buf.Rx_ByteCount);
/* Plausible page header? */
pagelink = header_buf.Rx_NextPage;
if ((pagelink < first_rx_page) || (last_rx_page < pagelink)) {
/* Ouch... Forget it! Skip all and start afresh... */
printk(KERN_WARNING "%s: Ring overrun? Restoring...\n", dev->name);
/* You win some, you lose some. And sometimes plenty... */
adapter_init(dev);
netif_wake_queue(dev);
dev->stats.rx_over_errors++;
return 0;
}
/* OK, this look good, so far. Let's see if it's consistent... */
/* Let's compute the start of the next packet, based on where we are */
pagelink = next_rx_page +
((header_buf.Rx_ByteCount + (4 - 1 + 0x100)) >> 8);
/* Are we going to wrap around the page counter? */
if (pagelink > last_rx_page)
pagelink -= (last_rx_page - first_rx_page + 1);
/* Is the _computed_ next page number equal to what the adapter says? */
if (pagelink != header_buf.Rx_NextPage) {
/* Naah, we'll skip this packet. Probably bogus data as well */
printk(KERN_WARNING "%s: Page link out of sync! Restoring...\n", dev->name);
next_rx_page = header_buf.Rx_NextPage; /* at least a try... */
de620_send_command(dev, W_DUMMY);
de620_set_register(dev, W_NPRF, next_rx_page);
dev->stats.rx_over_errors++;
return 0;
}
next_rx_page = pagelink;
size = header_buf.Rx_ByteCount - 4;
if ((size < RUNT) || (GIANT < size)) {
printk(KERN_WARNING "%s: Illegal packet size: %d!\n", dev->name, size);
}
else { /* Good packet? */
skb = netdev_alloc_skb(dev, size + 2);
if (skb == NULL) { /* Yeah, but no place to put it... */
printk(KERN_WARNING "%s: Couldn't allocate a sk_buff of size %d.\n", dev->name, size);
dev->stats.rx_dropped++;
}
else { /* Yep! Go get it! */
skb_reserve(skb,2); /* Align */
/* skb->data points to the start of sk_buff data area */
buffer = skb_put(skb,size);
/* copy the packet into the buffer */
de620_read_block(dev, buffer, size);
pr_debug("Read %d bytes\n", size);
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb); /* deliver it "upstairs" */
/* count all receives */
dev->stats.rx_packets++;
dev->stats.rx_bytes += size;
}
}
/* Let's peek ahead to see if we have read the last current packet */
/* NOTE! We're _not_ checking the 'EMPTY'-flag! This seems better... */
curr_page = de620_get_register(dev, R_CPR);
de620_set_register(dev, W_NPRF, next_rx_page);
pr_debug("next_rx_page=%d CPR=%d\n", next_rx_page, curr_page);
return next_rx_page != curr_page; /* That was slightly tricky... */
}
/*********************************************
*
* Reset the adapter to a known state
*
*/
static int adapter_init(struct net_device *dev)
{
int i;
static int was_down;
if ((nic_data.Model == 3) || (nic_data.Model == 0)) { /* CT */
EIPRegister = NCTL0;
if (nic_data.Media != 1)
EIPRegister |= NIS0; /* not BNC */
}
else if (nic_data.Model == 2) { /* UTP */
EIPRegister = NCTL0 | NIS0;
}
if (utp)
EIPRegister = NCTL0 | NIS0;
if (bnc)
EIPRegister = NCTL0;
de620_send_command(dev, W_CR | RNOP | CLEAR);
de620_send_command(dev, W_CR | RNOP);
de620_set_register(dev, W_SCR, SCR_DEF);
/* disable recv to wait init */
de620_set_register(dev, W_TCR, RXOFF);
/* Set the node ID in the adapter */
for (i = 0; i < 6; ++i) { /* W_PARn = 0xaa + n */
de620_set_register(dev, W_PAR0 + i, dev->dev_addr[i]);
}
de620_set_register(dev, W_EIP, EIPRegister);
next_rx_page = first_rx_page = DE620_RX_START_PAGE;
if (nic_data.RAM_Size)
last_rx_page = nic_data.RAM_Size - 1;
else /* 64k RAM */
last_rx_page = 255;
de620_set_register(dev, W_SPR, first_rx_page); /* Start Page Register*/
de620_set_register(dev, W_EPR, last_rx_page); /* End Page Register */
de620_set_register(dev, W_CPR, first_rx_page);/*Current Page Register*/
de620_send_command(dev, W_NPR | first_rx_page); /* Next Page Register*/
de620_send_command(dev, W_DUMMY);
de620_set_delay(dev);
/* Final sanity check: Anybody out there? */
/* Let's hope some bits from the statusregister make a good check */
#define CHECK_MASK ( 0 | TXSUC | T16 | 0 | RXCRC | RXSHORT | 0 | 0 )
#define CHECK_OK ( 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 )
/* success: X 0 0 X 0 0 X X */
/* ignore: EEDI RXGOOD COLS LNKS*/
if (((i = de620_get_register(dev, R_STS)) & CHECK_MASK) != CHECK_OK) {
printk(KERN_ERR "%s: Something has happened to the DE-620! Please check it"
#ifdef SHUTDOWN_WHEN_LOST
" and do a new ifconfig"
#endif
"! (%02x)\n", dev->name, i);
#ifdef SHUTDOWN_WHEN_LOST
/* Goodbye, cruel world... */
dev->flags &= ~IFF_UP;
de620_close(dev);
#endif
was_down = 1;
return 1; /* failed */
}
if (was_down) {
printk(KERN_WARNING "%s: Thanks, I feel much better now!\n", dev->name);
was_down = 0;
}
/* All OK, go ahead... */
de620_set_register(dev, W_TCR, TCR_DEF);
return 0; /* all ok */
}
static const struct net_device_ops de620_netdev_ops = {
.ndo_open = de620_open,
.ndo_stop = de620_close,
.ndo_start_xmit = de620_start_xmit,
.ndo_tx_timeout = de620_timeout,
.ndo_set_rx_mode = de620_set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
/******************************************************************************
*
* Only start-up code below
*
*/
/****************************************
*
* Check if there is a DE-620 connected
*/
struct net_device * __init de620_probe(int unit)
{
byte checkbyte = 0xa5;
struct net_device *dev;
int err = -ENOMEM;
int i;
dev = alloc_etherdev(0);
if (!dev)
goto out;
spin_lock_init(&de620_lock);
/*
* This is where the base_addr and irq gets set.
* Tunable at compile-time and insmod-time
*/
dev->base_addr = io;
dev->irq = irq;
/* allow overriding parameters on command line */
if (unit >= 0) {
sprintf(dev->name, "eth%d", unit);
netdev_boot_setup_check(dev);
}
pr_debug("%s", version);
printk(KERN_INFO "D-Link DE-620 pocket adapter");
if (!request_region(dev->base_addr, 3, "de620")) {
printk(" io 0x%3lX, which is busy.\n", dev->base_addr);
err = -EBUSY;
goto out1;
}
/* Initially, configure basic nibble mode, so we can read the EEPROM */
NIC_Cmd = DEF_NIC_CMD;
de620_set_register(dev, W_EIP, EIPRegister);
/* Anybody out there? */
de620_set_register(dev, W_CPR, checkbyte);
checkbyte = de620_get_register(dev, R_CPR);
if ((checkbyte != 0xa5) || (read_eeprom(dev) != 0)) {
printk(" not identified in the printer port\n");
err = -ENODEV;
goto out2;
}
/* else, got it! */
dev->dev_addr[0] = nic_data.NodeID[0];
for (i = 1; i < ETH_ALEN; i++) {
dev->dev_addr[i] = nic_data.NodeID[i];
dev->broadcast[i] = 0xff;
}
printk(", Ethernet Address: %pM", dev->dev_addr);
printk(" (%dk RAM,",
(nic_data.RAM_Size) ? (nic_data.RAM_Size >> 2) : 64);
if (nic_data.Media == 1)
printk(" BNC)\n");
else
printk(" UTP)\n");
dev->netdev_ops = &de620_netdev_ops;
dev->watchdog_timeo = HZ*2;
/* base_addr and irq are already set, see above! */
/* dump eeprom */
pr_debug("\nEEPROM contents:\n"
"RAM_Size = 0x%02X\n"
"NodeID = %pM\n"
"Model = %d\n"
"Media = %d\n"
"SCR = 0x%02x\n", nic_data.RAM_Size, nic_data.NodeID,
nic_data.Model, nic_data.Media, nic_data.SCR);
err = register_netdev(dev);
if (err)
goto out2;
return dev;
out2:
release_region(dev->base_addr, 3);
out1:
free_netdev(dev);
out:
return ERR_PTR(err);
}
/**********************************
*
* Read info from on-board EEPROM
*
* Note: Bitwise serial I/O to/from the EEPROM vi the status _register_!
*/
#define sendit(dev,data) de620_set_register(dev, W_EIP, data | EIPRegister);
static unsigned short __init ReadAWord(struct net_device *dev, int from)
{
unsigned short data;
int nbits;
/* cs [__~~] SET SEND STATE */
/* di [____] */
/* sck [_~~_] */
sendit(dev, 0); sendit(dev, 1); sendit(dev, 5); sendit(dev, 4);
/* Send the 9-bit address from where we want to read the 16-bit word */
for (nbits = 9; nbits > 0; --nbits, from <<= 1) {
if (from & 0x0100) { /* bit set? */
/* cs [~~~~] SEND 1 */
/* di [~~~~] */
/* sck [_~~_] */
sendit(dev, 6); sendit(dev, 7); sendit(dev, 7); sendit(dev, 6);
}
else {
/* cs [~~~~] SEND 0 */
/* di [____] */
/* sck [_~~_] */
sendit(dev, 4); sendit(dev, 5); sendit(dev, 5); sendit(dev, 4);
}
}
/* Shift in the 16-bit word. The bits appear serially in EEDI (=0x80) */
for (data = 0, nbits = 16; nbits > 0; --nbits) {
/* cs [~~~~] SEND 0 */
/* di [____] */
/* sck [_~~_] */
sendit(dev, 4); sendit(dev, 5); sendit(dev, 5); sendit(dev, 4);
data = (data << 1) | ((de620_get_register(dev, R_STS) & EEDI) >> 7);
}
/* cs [____] RESET SEND STATE */
/* di [____] */
/* sck [_~~_] */
sendit(dev, 0); sendit(dev, 1); sendit(dev, 1); sendit(dev, 0);
return data;
}
static int __init read_eeprom(struct net_device *dev)
{
unsigned short wrd;
/* D-Link Ethernet addresses are in the series 00:80:c8:7X:XX:XX:XX */
wrd = ReadAWord(dev, 0x1aa); /* bytes 0 + 1 of NodeID */
if (!clone && (wrd != htons(0x0080))) /* Valid D-Link ether sequence? */
return -1; /* Nope, not a DE-620 */
nic_data.NodeID[0] = wrd & 0xff;
nic_data.NodeID[1] = wrd >> 8;
wrd = ReadAWord(dev, 0x1ab); /* bytes 2 + 3 of NodeID */
if (!clone && ((wrd & 0xff) != 0xc8)) /* Valid D-Link ether sequence? */
return -1; /* Nope, not a DE-620 */
nic_data.NodeID[2] = wrd & 0xff;
nic_data.NodeID[3] = wrd >> 8;
wrd = ReadAWord(dev, 0x1ac); /* bytes 4 + 5 of NodeID */
nic_data.NodeID[4] = wrd & 0xff;
nic_data.NodeID[5] = wrd >> 8;
wrd = ReadAWord(dev, 0x1ad); /* RAM size in pages (256 bytes). 0 = 64k */
nic_data.RAM_Size = (wrd >> 8);
wrd = ReadAWord(dev, 0x1ae); /* hardware model (CT = 3) */
nic_data.Model = (wrd & 0xff);
wrd = ReadAWord(dev, 0x1af); /* media (indicates BNC/UTP) */
nic_data.Media = (wrd & 0xff);
wrd = ReadAWord(dev, 0x1a8); /* System Configuration Register */
nic_data.SCR = (wrd >> 8);
return 0; /* no errors */
}
/******************************************************************************
*
* Loadable module skeleton
*
*/
#ifdef MODULE
static struct net_device *de620_dev;
int __init init_module(void)
{
de620_dev = de620_probe(-1);
if (IS_ERR(de620_dev))
return PTR_ERR(de620_dev);
return 0;
}
void cleanup_module(void)
{
unregister_netdev(de620_dev);
release_region(de620_dev->base_addr, 3);
free_netdev(de620_dev);
}
#endif /* MODULE */
MODULE_LICENSE("GPL");

View File

@ -1,117 +0,0 @@
/*********************************************************
* *
* Definition of D-Link DE-620 Ethernet Pocket adapter *
* *
*********************************************************/
/* DE-620's CMD port Command */
#define CS0 0x08 /* 1->0 command strobe */
#define ICEN 0x04 /* 0=enable DL3520 host interface */
#define DS0 0x02 /* 1->0 data strobe 0 */
#define DS1 0x01 /* 1->0 data strobe 1 */
#define WDIR 0x20 /* general 0=read 1=write */
#define RDIR 0x00 /* (not 100% confirm ) */
#define PS2WDIR 0x00 /* ps/2 mode 1=read, 0=write */
#define PS2RDIR 0x20
#define IRQEN 0x10 /* 1 = enable printer IRQ line */
#define SELECTIN 0x08 /* 1 = select printer */
#define INITP 0x04 /* 0 = initial printer */
#define AUTOFEED 0x02 /* 1 = printer auto form feed */
#define STROBE 0x01 /* 0->1 data strobe */
#define RESET 0x08
#define NIS0 0x20 /* 0 = BNC, 1 = UTP */
#define NCTL0 0x10
/* DE-620 DIC Command */
#define W_DUMMY 0x00 /* DIC reserved command */
#define W_CR 0x20 /* DIC write command register */
#define W_NPR 0x40 /* DIC write Next Page Register */
#define W_TBR 0x60 /* DIC write Tx Byte Count 1 reg */
#define W_RSA 0x80 /* DIC write Remote Start Addr 1 */
/* DE-620's STAT port bits 7-4 */
#define EMPTY 0x80 /* 1 = receive buffer empty */
#define INTLEVEL 0x40 /* 1 = interrupt level is high */
#define TXBF1 0x20 /* 1 = transmit buffer 1 is in use */
#define TXBF0 0x10 /* 1 = transmit buffer 0 is in use */
#define READY 0x08 /* 1 = h/w ready to accept cmd/data */
/* IDC 1 Command */
#define W_RSA1 0xa0 /* write remote start address 1 */
#define W_RSA0 0xa1 /* write remote start address 0 */
#define W_NPRF 0xa2 /* write next page register NPR15-NPR8 */
#define W_DFR 0xa3 /* write delay factor register */
#define W_CPR 0xa4 /* write current page register */
#define W_SPR 0xa5 /* write start page register */
#define W_EPR 0xa6 /* write end page register */
#define W_SCR 0xa7 /* write system configuration register */
#define W_TCR 0xa8 /* write Transceiver Configuration reg */
#define W_EIP 0xa9 /* write EEPM Interface port */
#define W_PAR0 0xaa /* write physical address register 0 */
#define W_PAR1 0xab /* write physical address register 1 */
#define W_PAR2 0xac /* write physical address register 2 */
#define W_PAR3 0xad /* write physical address register 3 */
#define W_PAR4 0xae /* write physical address register 4 */
#define W_PAR5 0xaf /* write physical address register 5 */
/* IDC 2 Command */
#define R_STS 0xc0 /* read status register */
#define R_CPR 0xc1 /* read current page register */
#define R_BPR 0xc2 /* read boundary page register */
#define R_TDR 0xc3 /* read time domain reflectometry reg */
/* STATUS Register */
#define EEDI 0x80 /* EEPM DO pin */
#define TXSUC 0x40 /* tx success */
#define T16 0x20 /* tx fail 16 times */
#define TS1 0x40 /* 0=Tx success, 1=T16 */
#define TS0 0x20 /* 0=Tx success, 1=T16 */
#define RXGOOD 0x10 /* rx a good packet */
#define RXCRC 0x08 /* rx a CRC error packet */
#define RXSHORT 0x04 /* rx a short packet */
#define COLS 0x02 /* coaxial collision status */
#define LNKS 0x01 /* UTP link status */
/* Command Register */
#define CLEAR 0x10 /* reset part of hardware */
#define NOPER 0x08 /* No Operation */
#define RNOP 0x08
#define RRA 0x06 /* After RR then auto-advance NPR & BPR(=NPR-1) */
#define RRN 0x04 /* Normal Remote Read mode */
#define RW1 0x02 /* Remote Write tx buffer 1 ( page 6 - 11 ) */
#define RW0 0x00 /* Remote Write tx buffer 0 ( page 0 - 5 ) */
#define TXEN 0x01 /* 0->1 tx enable */
/* System Configuration Register */
#define TESTON 0x80 /* test host data transfer reliability */
#define SLEEP 0x40 /* sleep mode */
#if 0
#define FASTMODE 0x04 /* fast mode for intel 82360SL fast mode */
#define BYTEMODE 0x02 /* byte mode */
#else
#define FASTMODE 0x20 /* fast mode for intel 82360SL fast mode */
#define BYTEMODE 0x10 /* byte mode */
#endif
#define NIBBLEMODE 0x00 /* nibble mode */
#define IRQINV 0x08 /* turn off IRQ line inverter */
#define IRQNML 0x00 /* turn on IRQ line inverter */
#define INTON 0x04
#define AUTOFFSET 0x02 /* auto shift address to TPR+12 */
#define AUTOTX 0x01 /* auto tx when leave RW mode */
/* Transceiver Configuration Register */
#define JABBER 0x80 /* generate jabber condition */
#define TXSUCINT 0x40 /* enable tx success interrupt */
#define T16INT 0x20 /* enable T16 interrupt */
#define RXERRPKT 0x10 /* accept CRC error or short packet */
#define EXTERNALB2 0x0C /* external loopback 2 */
#define EXTERNALB1 0x08 /* external loopback 1 */
#define INTERNALB 0x04 /* internal loopback */
#define NMLOPERATE 0x00 /* normal operation */
#define RXPBM 0x03 /* rx physical, broadcast, multicast */
#define RXPB 0x02 /* rx physical, broadcast */
#define RXALL 0x01 /* rx all packet */
#define RXOFF 0x00 /* rx disable */