Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 168e06ae authored by Paul Gortmaker's avatar Paul Gortmaker
Browse files

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: default avatarPaul Gortmaker <paul.gortmaker@windriver.com>
parent de8270ff
Loading
Loading
Loading
Loading
+0 −203
Original line number Diff line number Diff line
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
+1 −12
Original line number Diff line number Diff line
@@ -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. */
+1 −31
Original line number Diff line number Diff line
@@ -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
+0 −2
Original line number Diff line number Diff line
@@ -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
+0 −529
Original line number Diff line number Diff line
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");
Loading