/*
 * rtl8012.c
 *
 * Copyright (c)1999  S O L A M Y L W A R E ,  Stepan Skrob.
 * Author may be reached at <stepan@firma.seznam.cz>.
 *
 * This software may be used and distributed according to the terms
 * of the GNU Public License, incorporated herein by reference.
 *
 * This is a network driver for ethernet pocket adapters (pocket
 * means "attached to parallel port") with RTL8012 chip (most
 * adapters have this chip).
 */

static const char *version=
		"rtl8012.c: v1.02 16/10/1999 Stepan Skrob <stepan@firma.seznam.cz>\n";

/*
 * Sources of information:
 *
 * There is a network driver outline used for this driver in order
 * the function names, structure, etc. remain the same. Outline
 * "skeleton.c" was written by Donald Becker (becker@desdis.gsfc.nasa.gov).
 *
 * RTL8012 chip programing is documented in RealTek's 8012 datasheet.
 * RealTek (www.realtek.com.tw) does not support this chip yet,
 * so it is little problem to get the datasheet.
 *
 * Ethernet controller uses 1024-bit serial EEPROM (NM93C46) for
 * saving MAC address. I found that datasheet at Fairchild
 * Semiconductor Corporation (www.farchildsemi.com).
 *
 * Description of parallel port specifics (SPP & EPP mode) was found
 * at http://www.senet.com.au/~cpeacock/ and was written by Craig
 * Peacock. His site contains very good programer's information about
 * computer peripherials.
 *
 *
 * Theory of operation:
 *
 * Initializing.
 * Controller has built-in printer multiplexer. After powering device up, the
 * controller is in "transparent" mode, in which all parallel port signals are
 * forwarded directly to the printer. Before any further work this multiplexer
 * must be turned off. That is done by sending certain data pattern to the
 * data port. Printer multiplexer can be enabled again by setting MUX bit
 * in CMR1 register.
 * Controller reset is initiated by setting RST bit in CMR1 register. Reset
 * operation completes within about 400usec. Reset operation continues until
 * RST bit is cleared by the controler. You may wait or check if it is ready
 * yet. If reset is successful, then CMR1 register contains 0x01 and CMR2 0x20.
 * Checking these two registers is good probe procedure.
 * Ethernet hardware address must be manually shifted out from bit-serial
 * EEPROM. Hardware address must be written into IDR0-IDR5 by init procedure.
 *
 * Local receive/transmit buffers.
 * Controller uses one 64k*4bit DRAM memory chip as the local transmit/receive
 * buffer. First 4 kB are used as transmit buffer memory, which is divided
 * into two pages. Rest of memory is used as ring buffer for received
 * packets. Buffer pointers and structure are maintained by the controller
 * itself.
 *
 * Transmiting packets.
 * Two pages of transmit buffer are provided to allow the host to load packet
 * data into one page, while the packet in the other page is being transmitted.
 * At the end of downloaded data, a transmit jump-packet command must be
 * issued (set WRPAC bit in CMR1). This changes transmit buffer pages.
 * After data download, a packet length must be written into TBCR0 and TBCR1
 * registers. Packet transmition starts by setting TRA bit in CMR1. TRA is
 * automatically reset when transmittion is done.
 * You may not change TBCR0-1 registers and TRA bit when transmittion is in
 * progress. Packet is automatically retransmitted 16 times, when collision
 * occurs.
 *
 * Receiving packets.
 * Receive buffer has ring structure. Maximum number of 255 packets can be
 * stored in the buffer. Before reading any data, a receive jump-packet
 * command must be issued (set RDPAC bit in CMR1). After this, an 8-byte
 * header must be read. Header contains receive status, packet length and
 * pointer to next packet in the buffer (ignore it -- it is impossible to
 * use it). Received packet length is including CRC (4 bytes). Reading whole
 * packets including CRC should be OK, however this does not work and
 * probably destroys internal buffer structures (huh?).
 * PNR register shows number of received packets in the buffer. You can
 * also check BUFE bit in CMR1 to determine whether the buffer is empty.
 *
 * Receiving broadcasts and multicasts.
 * For receiving multicast packets, a multicast hash filter and proper
 * receive address mode must be set. RealTek datasheet says, that first
 * 6 MSB bits from ethernet address CRC is interpreted as a binary number
 * from range 0-63 and that number is used as index to set the n-th FB bit
 * in multicast address registers MAR0-MAR7. However, this did not work.
 * There must be used as index 6 LSB bits from CRC or CRC calcultaion is
 * made very strange, I don't really know. More, in RealTek datasheet is
 * mistake in AM0 & AM1 bit meanings. Controller also does not accept
 * broadcast packets by itself, as you may think when reading RealTek's
 * datasheet -- broadcast address (FF:FF:FF:FF:FF:FF) must be set in hash
 * filter as well.
 *
 * Transfering data.
 * For transfering packet data can be used one of SPP, PS/2 (bidirectional
 * SPP) or EPP parallel port modes (depending on your parallel port
 * capabilities). In RealTek's datasheet is data transfer refered as
 * "direct memory access".
 * SPP offers 8-bit data output and 4-bit data input. It is slow due to all
 * handshaking must be done by the software. Bidirectional SPP (alias
 * PS/2 parallel port) offers 8-bit data input/output. Handshaking is the
 * same as in SPP case. EPP is fastest, offers 8-bit data input/output and
 * handshaking implemented in hardware.
 */

#include <linux/module.h>

#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/interrupt.h>
#include <linux/ptrace.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/in.h>
#include <linux/malloc.h>
#include <linux/string.h>
#include <asm/system.h>
#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <linux/errno.h>

#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/parport.h>

/* definitions and macros */

/* I/O port macros */
#define DATA(addr)      (addr)
#define STAT(addr)      ((addr)+1)
#define CTRL(addr)      ((addr)+2)
#define EPPADDR(addr)   ((addr)+3)
#define EPPDATA(addr)   ((addr)+4)
#define IOSIZE(addr)    ((addr)&0x007 ? 4 : 8)

/* parallel port modes */
#define SPPMODE         0x01
#define BISPPMODE       0x02
#define EPPMODE         0x04

/* eeprom operations */
#define EEPROM_WDS              (((4<<6) | 0x00) << 17) /*write disable*/
#define EEPROM_WEN              (((4<<6) | 0x30) << 17) /*write enable*/
#define EEPROM_WRITE(addr,data) ((((5<<6) | ((addr)&0x3f)) << 17) \
                                        | ((data)&0xffff))
#define EEPROM_READ(addr)       (((6<<6) | ((addr)&0x3f)) << 17)

/* debug messages level
 *  0 = final product
 *  1 = verification
 * >2 = debug and more debug */
#ifndef NET_DEBUG
#define NET_DEBUG       0
#endif

// X /* jiffies before concluding the trasmitter is hung */
// X #define TX_TIMEOUT      ((400*HZ)/1000) /*0.4 sec*/

/* page #0 registers */
#define IDR0            0x00 /*network node ID registers 0-5*/
#define IDR1            0x01
#define IDR2            0x02
#define IDR3            0x03
#define IDR4            0x04
#define IDR5            0x05
#define PNR             0x06 /*R-received packet number register*/
#define TBCR0           0x06 /*W-transmit byte count register 0*/
#define COLR            0x07 /*R-collision number register*/
#define TBCR1           0x07 /*W-transmit byte count register 1*/
#define TSR             0x08 /*transmit status register*/
#define RSR             0x09 /*receive status register*/
#define ISR             0x0a /*interrupt status register*/
#define IMR             0x0b /*interrupt mask register*/
#define CMR1            0x0c /*command register 1*/
#define CMR2            0x0d /*command register 2*/
#define MODSEL          0x0e /*mode select register*/
#define MODDEL          0x0f /*mode delay register*/

/* page #1 registers */
#define MAR0            0x00 /*multicast address registers 0-7*/
#define MAR1            0x01
#define MAR2            0x02
#define MAR3            0x03
#define MAR4            0x04
#define MAR5            0x05
#define MAR6            0x06
#define MAR7            0x07
#define PCMR            0x08 /*port command register*/
#define PDR             0x09 /*port data register*/
/* registers 0x0a-0x0f are the same as in page #0 */

/* TSR bits */
#define TXOK            0x01 /*transmition OK*/
#define TABT            0x02 /*transmition aborted (due to collisions)*/
#define COL             0x04 /*at least one collision detected*/
#define CDH             0x08 /*CD heartbeat signal detectd*/

/* RSR bits */
#define RXOK            0x01 /*receive OK*/
#define CRC             0x02 /*CRC error*/
#define FA              0x04 /*frame alignment error*/
#define BUFO            0x10 /*receive buffer overflow*/
#define PUN             0x20 /*packet count underflow*/
#define POV             0x40 /*packet count overflow*/

/* ISR bits */
#define TOK             0x01 /*R-transmit OK*/
#define CLRTOK          0x01 /*W-clear transmit OK interrupt*/
#define TER             0x02 /*R-transmit error*/
#define CLRTER          0x02 /*W-clear transmit error interrupt*/
#define ROK             0x04 /*R-receive OK*/
#define CLRROK          0x04 /*W-clear receive OK interrupt*/
#define RER             0x08 /*R-receive error*/
#define CLRRER          0x08 /*W-clear receive error interrupt*/
#define RBER            0x10 /*R-receive buffer error (buffer full...)*/
#define CLRRBER         0x10 /*W-clear receive buffer error interrupt*/

/* IMR bits */
#define TOKM            0x01 /*transmit ok mask*/
#define TERM            0x02 /*transmit error mask*/
#define ROKM            0x04 /*receive ok mask*/
#define RERM            0x08 /*receive error mask*/
#define RBERM           0x10 /*receive buffer error mask*/

/* CMR1 bits
 * read and write have different sense!!! */
#define BUFE            0x01 /*R-buffer empty*/
#define RDPAC           0x01 /*W-read packet acknowledge*/
#define IRQ             0x02 /*R-interrupt request*/
#define WRPAC           0x02 /*W-write packet acknowledge*/
#define TRA             0x04 /*R/W-transmit start*/
#define RETX            0x08 /*W-retransmit*/
#define TE              0x10 /*R/W-transmitter enable*/
#define RE              0x20 /*R/W-receiver enable*/
#define RST             0x40 /*R/W-reset*/
#define MUX             0x80 /*W-enable printer multiplexer*/

/* CMR2 bits */
#define IRQOUT          0x01 /*interrupt signal output enable*/
#define RAMTST          0x02 /*ram test mode*/
#define PAGE            0x04 /*register page select*/
#define IRQINV          0x08 /*interrupt signal active low*/
#define AM0             0x10 /*addressing mode flags 0, 1*/
#define AM1             0x20
#define LBK             0x40 /*loopback function*/
#define SER             0x80 /*save packet with error*/

/* receive addressing modes -- a combination of AM bits */
#define AM_NOACCEPT     0 /*no accept mode*/
#define AM_PHYSICAL     AM0 /*only physical address match*/
#define AM_NORMAL       AM1 /*physical, broadcast and multicast addr. match*/
#define AM_PROMISCUOUS  (AM1|AM0) /*accept all packets*/

/* MODSEL bits */
#define DIR0            0x01 /*direction mode flags 0, 1*/
#define DIR1            0x02
#define EPPWAIT         0x04 /*enable wait signal for IEEE 1284 EPP standard*/
#define DMAMOD          0x10 /*switch data port to remote read/write op.*/
#define DMAWRB          0x20 /*determines data port write/read operation*/

/* PCMR bits */
#define EEDI            0x10 /*serial data input, set means  "one"*/
#define EECS            0x20 /*chip select*/
#define EESKB           0x40 /*inverse clock signal*/

/* PDR bits */
#define EEDO            0x01 /*R-serial data out*/


/* own structures and data types */

/* information that need to be kept for each board */
struct net_local {
	/* ethernet statistic at the beginning
	 * of the private data area */
	struct net_device_stats stats;
	
	/* pointers to functions for writing/reading data
	 * to/from ethernet controller. functions depend
	 * on available parallel port mode. */
	void (*write_data)( struct net_device *dev,
			const unsigned char *buff, int len );
	int (*read_data)( struct net_device *dev,
			unsigned char *buff, int len );

	/* receive addressing mode --
	 * one of AM_* defined values */
	unsigned char rx_mode;

	/* parallel port transfer mode:
	 * 0=SPP, 1=PS/2 (bi-SPP), 2=EPP */
	char parallel_port_mode;
	
	/* state of the device
	 * 0 = device and/or parallel port not found
	 * 1 = device not attached, parallel port present
	 * 2 = device detected at least once
	 * 3 = device detached (temporary out of order) */
	char state;
	
	/* values used for manual packet transmit.
	 * number of packets in 2-pages Tx buffer (0, 1, 2) */
	int packets_in_tx_queue;
	
	/* for packet transmit, its size must be written
	 * into the controller, however it can't be written while
	 * another packet is transmited */
	int save_packet_size;
	
	/* receive buffer. max size of one ethernet frame
	 * which is defined by ETH_FRAME_LEN (1514 bytes) */
	unsigned char *buff;

	/* pointer to parport structure */
	pardevice *parport;
};

/* each data read from controller is preceded by this header */
struct rx_header {
	/* unused 3 bytes */
	unsigned char unused[3];
	
	/* length of received packet including CRC
	 * byte3=LSB, byte4=MSB */
	unsigned char length_lsb;
	unsigned char length_msb;
	
	/* receive status, the same as RSR? */
	unsigned char status;
	
	/* next packet pointer in receive buffer,
	 * range 4kB-32kB = pointer 0x0200-0x0fff */
	unsigned char next_lsb;
	unsigned char next_msb;
};


/* global variables */

/* the name of the driver. used for kernel
 * messages, region and irq requests */
static const char *cardname= "rtl8012";

// X /* a zero-terminated list of I/O addresses to be probed */
// X static unsigned int rtl8012_portlist[]=
// X		{ 0x378, 0x278, 0x3bc, 0 };

/* use 0 for production, 1 for verification, >2 for debug */
static unsigned int net_debug= NET_DEBUG;

/* pattern for switching off the printer multiplexer */
static unsigned char muxoff[]=
		{ 0xff, 0xf7, 0xff, 0xfb, 0xf3, 0xfb, 0xff, 0xf7 };


/* function prototypes */

/* standard driver functions */
extern int rtl8012_probe( struct net_device *dev );

static int rtl8012_probe1( struct net_device *dev, int ioaddr );
static int net_open( struct net_device *dev );
static int net_send_packet( struct sk_buff *skb, struct net_device *dev );
static void net_interrupt( int irq, void *dev_id, struct pt_regs *regs );
static int net_rx( struct net_device *dev );
static int net_close( struct net_device *dev );
static struct net_device_stats *net_get_stats( struct net_device *dev );
static void set_multicast_list( struct net_device *dev );
static unsigned int ether_crc( unsigned char *data, int len );
static void net_send_timeout (struct net_device *dev);


/* device specific functions */
static int chipset_init( struct net_device *dev );
static void chipset_deinit( struct net_device *dev );
static void write_reg( struct net_device *dev, int reg, int val );
static int read_reg( struct net_device *dev, int reg );
static void write_data_spp( struct net_device *dev,
		const unsigned char *buff, int len );
static int read_data_spp( struct net_device *dev,
		unsigned char *buff, int len );
static void write_data_bispp( struct net_device *dev,
		const unsigned char *buff, int len );
static int read_data_bispp( struct net_device *dev,
		unsigned char *buff, int len );
static void write_data_epp( struct net_device *dev,
		const unsigned char *buff, int len );
static int read_data_epp( struct net_device *dev,
		unsigned char *buff, int len );
static int eeprom_operation( struct net_device *dev, int cmd );
static void getnodeid( struct net_device *dev );

/* ############################################### standard driver functions */

#ifdef HAVE_DEVLIST
/* support for an alternate probe manager,
 * which will eliminate the boilerplate below */
struct netdev_entry rtl8012_drv= {
	cardname,
	rtl8012_probe1,
	8, /*iosize*/
	rtl8012_portlist
};
#else
/* check for a network adapter with rtl8012, and return 0
 * if one exists. accept these input values of dev->base_addr:
 *  0 = probe all likely locations
 *  1 = always return failure
 *  2 = allocate space for the (detachable) device and return success */
int rtl8012_probe( struct net_device *dev )
{
	int i, ioaddr= 0;
	struct parport *par;
	
	if (dev!=NULL)
		ioaddr= dev->base_addr;

	/* check for single specified location */
	if (ioaddr>2)
		return( rtl8012_probe1( dev, ioaddr ));
	/* don't probe -- return failure */
	if (ioaddr==1)
		return( -ENXIO ); /*no such device or address*/
	
	/* probe for the ethernet adapter. probe routine should
	 * accept value ioaddr=2, however, we dont know which parallel
	 * port to reserve, so values ioaddr=0 and ioaddr=2 have the
	 * same meaning */
// X	for( i=0; rtl8012_portlist[i]; i++ ) {
// X		ioaddr= rtl8012_portlist[i];
// X		if (check_region(ioaddr,IOSIZE(ioaddr)))
// X			continue; /*port already used*/
// X		if (rtl8012_probe1(dev,ioaddr)==0)
// X			return( 0 ); /*success*/
// X	}
/* insert parport stuff here :) */
	par = parport_enumerate();
	while (!par) {
		/* XXXX support for only one adapter */
//		dev->parport = parport_register_device(	par, cardname, NULL,
// HERE									
		par = par->next;
	}
	return( -ENODEV ); /*no such device*/
}
#endif

/* this is the real probe routine.
 *  1) test presence of parallel port
 *  2) reset and test for ethernet adapter
 *  3) detect available enhanced parallel port modes
 *  4) create new ethernet network device
 * returns: 0=success, negative value=error */
static int rtl8012_probe1( struct net_device *dev, int ioaddr )
{
	static int version_printed= 0; /*print version info just once*/
	int i, tmp, mode, state;
	int dataport, statport, ctrlport;
	struct net_local *lp;
	unsigned char *buff;

	/* reset parallel port mode */
	dataport= DATA( ioaddr );
	statport= STAT( ioaddr );
	ctrlport= CTRL( ioaddr );
	state= 0;
	mode= 0;
	
	/* test parallel port (SPP mode) */
	tmp= inb_p( ctrlport ); /*remember value of control register*/
	outb_p( 0x04, ctrlport );
	outb_p( 0xaa, dataport );
	if (inb_p(dataport)!=0xaa) {
		outb_p( tmp, ctrlport );
		return( -ENXIO ); /*no parallel port*/
	}
	mode |= SPPMODE;
	outb( 0x04, ctrlport ); /*reset control port*/

	/* determine explicitly specified device */
	state= (dev!=NULL && dev->base_addr>2) ? 1 : 0;
	
	/* set control port and output "switch off
	 * built-in printer multiplexer" pattern */
	for( i=0; i<8; i++ )
		outb( muxoff[i], dataport );
	
	/* reset adapter and check CMR1 and CMR2 registers */
	{
		/* just temporary device struct
		 * for carrying base address */
		struct net_device tmpdev;
// X		tmpdev.name= (char*)cardname;
		tmpdev.base_addr= ioaddr;
		
		write_reg( &tmpdev, CMR1, RST );
		udelay( 450 ); /*give 450 usec to complete the reset*/
		if (read_reg(&tmpdev,CMR1)!=0x01
				|| read_reg(&tmpdev,CMR2)!=0x20) {
			/* controller not detected. if base address
			 * was specified explicitly allocate for later use */
			if (state==0) {
				outb( 0x04, ctrlport );
				return( -ENODEV ); /*no rtl8012 controller detected*/
			}
		}
		else state= 2; /*controller found*/

		/* allocate a new 'dev' if needed */
		if (dev==NULL) {
			/* don't allocate the private data here, it is done later.
			 * this makes it easier to free the memory when this driver
			 * is used as a module */
			dev= init_etherdev( 0, 0 );
			if (dev==NULL) {
				chipset_deinit( &tmpdev );
				return( -ENOMEM );
			}
		}
	}
	/* fill in the device structure (base address) */
	dev->base_addr= ioaddr;

	/* print info */
	if (!(version_printed++))
		printk( KERN_INFO "%s", version );
	if (state==2) {
		printk( KERN_INFO "%s: pocket adapter %s found " \
				"at %#3x,", dev->name, cardname, ioaddr );
		/* print the ethernet address */
		getnodeid( dev );
		for( i=0; i<6; i++ )
			printk( "%c%02X", i ? ':' : ' ', dev->dev_addr[i] );
		printk( ", " );
	}
	else printk( KERN_INFO "%s: pocket adapter %s not found " \
				"at %#3x (forced as detached), ",
				dev->name, cardname, ioaddr );

	/* if this board has jumpered interrupts, allocate the interrupt
	 * vector now. There is no point in waiting since no other device
	 * can use the interrupt, and this marks the irq as busy. jumpered
	 * interrupts are typically not reported by the boards, and we must
	 * used autoIRQ to find them */
	if (dev->irq<2 && state<2) {
		/* should be auto-IRQ routine, but because of device
		 * is not attached, there is impossible to trigger
		 * an intrerrupt, so we must guess ;-) */
		dev->irq= (dev->base_addr==0x378) ? 7 : 5;
		printk( "guess-" );			
	} else if (dev->irq<2) {
		/* auto IRQ routine --
		 * uff! hard work, there is almost impossible explicitly
		 * to trigger an interrupt. we must use some bad trick,
		 * which is based on multiplexed input line for data (RD0)
		 * and interrupt request (IRQ). interrupt should be raised
		 * when changing from low to high nibble data when reading
		 * CMR2 register, maybe. */
		int cmr2= read_reg( dev, CMR2 );
		write_reg( dev, CMR2, cmr2 | 0x80 );
		autoirq_setup( 0 );
		
		outb( 0x14, ctrlport ); /*enable parallel port irq*/
		read_reg( dev, CMR2 ); /*trigger an interrupt*/
		outb( 0x04, ctrlport ); /*disable parallel port irq*/
		
		dev->irq= autoirq_report( 0 );
		write_reg( dev, CMR2, cmr2 ); /*restore CMR2*/
		printk( "auto-" );
	} else if (dev->irq==2)
		/* fixup for users that don't know that IRQ 2 is really
		 * IRQ9, or don't know which one to set */
		dev->irq= 9;
	/* print (auto) detected IRQ line */
	printk( "IRQ %d.\n", dev->irq );

	tmp= request_irq( dev->irq, &net_interrupt, 0, dev->name, NULL );
	if (tmp) { /*irq not allocated*/
		printk( KERN_WARNING "%s: unable to get IRQ %d (rc=%d)\n",
				dev->name, dev->irq, tmp );
		chipset_deinit( dev );
		return( -EAGAIN );
	}

	/* initialize the device structure */
	if (dev->priv==NULL) {
		dev->priv= kmalloc( sizeof(struct net_local), GFP_KERNEL );
		if (dev->priv==NULL) {
			free_irq( dev->irq, NULL ); /*free irq*/
			chipset_deinit( dev );
			return( -ENOMEM );
		}
	}
	/* clear private data memory, and allocate receive buffer */
	lp= (struct net_local*)dev->priv;
	memset( lp, 0, sizeof(struct net_local) );
	lp->buff= kmalloc( ETH_FRAME_LEN, GFP_KERNEL );
	if (lp->buff==NULL) {
		free_irq( dev->irq, NULL ); /*free irq*/
		chipset_deinit( dev );
		return( -ENOMEM );
	}
	
	/* test bidirectional SPP capability */
	outb_p( 0x24, ctrlport );
	outb_p( 0xaa, dataport );
	if (inb_p(dataport)!=0xaa)
		mode |= BISPPMODE;
	
	/* test epp mode, except with 0x3bc port */
	if ((dev->base_addr & 0x07)==0) {
		tmp= inb_p( statport );
		outb_p( tmp, statport );
		outb_p( tmp & 0xfe, statport ); /*try to clear EPP timeout bit*/
		if ((inb_p(statport)&0x01)==0) {
			outb_p( 0x24, ctrlport ); /*input direction*/
			inb_p( EPPDATA(ioaddr) ); /*generate timeout*/
			tmp= inb_p( statport );
			outb_p( tmp, statport );
			outb_p( tmp & 0xfe, statport ); /*clear timeout*/
			if (tmp & 0x01)
				mode |= EPPMODE;
		}
	}
	outb( 0x04, ctrlport ); /*reset control port*/
	
	/* set write_data and read_data functions */
	if (mode & EPPMODE) {
		lp->write_data= write_data_epp;
		lp->read_data= read_data_epp;
		lp->parallel_port_mode= 2;
	} else if (mode & BISPPMODE) {
		lp->write_data= write_data_bispp;
		lp->read_data= read_data_bispp;
		lp->parallel_port_mode= 1;
	} else {
		lp->write_data= write_data_spp;
		lp->read_data= read_data_spp;
		lp->parallel_port_mode= 0;
	}
	printk( KERN_INFO "%s: using %s parallel port), ramtest ", dev->name,
			(mode & EPPMODE) ? "EPP (enhanced" : (
			(mode & BISPPMODE) ? "PS/2 (bi-directional" : (
			"SPP (standard" )));
	
	/* remember device state */
	lp->state= state;
	
	/* perform ramtest */
	buff= (state==2) ? (unsigned char*)kmalloc(32768,GFP_KERNEL) : NULL;
	if (buff==NULL)
		printk( "skipped.\n" );
	else {
		/* switch to ramtest mode */
		int cmr2= read_reg( dev, CMR2 );
		write_reg( dev, CMR2, cmr2 | RAMTST ); /*enter ramtest mode*/
		write_reg( dev, CMR1, 0 );
		write_reg( dev,CMR1, RE | TE ); /*disable and enable Rx & Tx*/
		
		/* write test pattern */
		for( i=0; i<32768; i++ )
			buff[i]= i % 51;
		lp->write_data( dev, buff, 32768 );
		
		/* disable and enable Rx & Tx */
		write_reg( dev, CMR1, 0 );
		write_reg( dev, CMR1, RE | TE );
		
		/* readf nad test data */
		memset( buff, 0, 32768 );
		tmp= lp->read_data( dev, buff, 32768 );
		if (tmp!=32768) {
			printk( "read error " );
			for( i=0; i<32768; i++ )
				if (buff[i]!=i%51)
					break;
		} else {
			for( i=0; i<32768; i++ )
				if (buff[i]!=i%51) {
					printk( "memory error " );
					break;
				}
		}
		if (i==32768)
			printk( "%d bytes OK.\n", i );
		else printk( "at %d byte.\n", i );
				
		/* terminate ramtest */
		write_reg( dev, CMR1, 0 );
		write_reg( dev, CMR2, cmr2 );	
		kfree( buff );
	}

	/* grab the region so that no one else tries to probe our ioports */
	request_region( ioaddr, IOSIZE(ioaddr), dev->name );

	/* put adapter into "transparent"
	 * mode -- switch multiplexer on */
	chipset_deinit( dev );
	
	dev->open= net_open;
	dev->stop= net_close;
	dev->hard_start_xmit= net_send_packet;
	dev->tx_timeout = net_send_timeout;
	dev->get_stats= net_get_stats;
	dev->set_multicast_list= set_multicast_list;

	/* fill in the fields of the device structure with ethernet values */
	ether_setup( dev );
	return( 0 );
}

/* open/initialize the board. this is called (in the current kernel)
 * sometime after booting when the 'ifconfig' program is run.
 *
 * 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 non-reboot way to recover if something goes wrong */
static int net_open( struct net_device *dev )
{
	int rc;
	
	/* IRQ handler setup??? */
// X	irq2dev_map[dev->irq]= dev;
	if (request_irq(dev->irq, &net_interrupt, 0, dev->name, dev)) {
		printk(KERN_WARNING "%s: couldn't get interrupt\n", dev->name);
		return -EAGAIN;
	}
	 
	/* reset hardware and enable interrupts
	 * generated by the device */
	rc= chipset_init( dev );
	if (rc)
		return( rc );
	
// X	dev->tbusy= 0; /*transmitter busy flag*/
// X	dev->interrupt= 0; /*interrupt arrived flag*/
// X	dev->start= 1; /*start operation*/
	netif_start_queue (dev);

	MOD_INC_USE_COUNT;
	return( 0 );
}

/* this function is called whenever we got a timeout */
static void net_send_timeout (struct net_device *dev) {
	struct net_local *lp = (struct net_local *)dev->priv;
	
	printk( KERN_WARNING "%s: transmit timed out\n", dev->name );
	lp->stats.tx_errors++;
		
	/* try to restart the adapter */
	if (chipset_init(dev)) {
		lp->state= 3; /*hw error, set out of order*/
		printk( KERN_WARNING "%s: adapter put out " \
				"of order\n", dev->name );
		netif_stop_queue(dev);
	}
	/* continue, packet will be transmited once more */
}

/* this function transmits supplied packet.
 * returns: 0=packet accepted, 1=packet cannot be accepted */
static int net_send_packet( struct sk_buff *skb, struct net_device *dev )
{
	struct net_local *lp= (struct net_local*)dev->priv;
	unsigned char *buff;
	int cmr2, len;

	if (net_debug>=1) /*### DEBUG ###*/
		printk( KERN_DEBUG "%s: Tx packet skb=%p\n",
				dev ? dev->name : cardname, skb );
	
// X	if (dev->tbusy) {
// X		/* if we get here, some higher level has decided we are broken.
// X		 * there should really be a "kick me" function call instead */
// X		if (jiffies-dev->trans_start<TX_TIMEOUT) {
// X			return( 1 ); /*not timed out yet*/
// X		}
// X		printk( KERN_WARNING "%s: transmit timed out\n", dev->name );
// X		lp->stats.tx_errors++;
// X		
// X		/* try to restart the adapter */
// X		if (chipset_init(dev)) {
// X			lp->state= 3; /*hw error, set out of order*/
// X			printk( KERN_WARNING "%s: adapter put out " \
// X					"of order\n", dev->name );
// X		}
// X		dev->tbusy= 0;
// X		/* continue, packet will be transmited once more */
// X	}	
	/* if adapter is not working, drop the frame */
	if (lp->state!=2) {
		dev_kfree_skb( skb );
		lp->stats.tx_dropped++;
		return( 0 );
	}
// X	
// X	/* block a timer-based transmit from overlapping. this could better be
// X	 * done with atomic_swap(1, dev->tbusy), but set_bit() works as well */
// X	if (set_bit(0,(void*)&dev->tbusy)!=0) {
// X		printk( KERN_WARNING "%s: transmitter access conflict\n", dev->name );
// X		lp->stats.tx_dropped++;
// X	} else {
// X		unsigned char *buff;
// X		int cmr2, len;
		
	/* turn off interrupts and IRQOUT signal */
	disable_irq( dev->irq ); /*mask IRQ for sure*/
	/* interrupts cannot be masked out using IRQEN bit on
	 * control port, because the interrupts raised during 
	 * the data write wouldn't be noticed nor processed */
	cmr2= read_reg( dev, CMR2 );
	cmr2 &= 0x77;
	write_reg( dev, CMR2, cmr2 & ~IRQOUT ); /*switch IRQ line to RD3*/
	
	/*hardware_send_packet( ioaddr, buf, length );*/
	len= (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
	buff= skb->data;
	
	if (lp->packets_in_tx_queue<0 || lp->packets_in_tx_queue>1)
		printk( KERN_WARNING "%s: huh? number of packets in Tx queue " \
				"is out of range, packets_in_tx_queue=%d\n", dev->name,
				lp->packets_in_tx_queue );
		
	lp->write_data( dev, buff, len ); /*write packet data*/
	write_reg( dev, CMR1, RE | TE | WRPAC ); /*confirm packet write*/
	/*udelay( 2 );*/ /*wait at least 2usec after WRPAC bit is set*/
	lp->packets_in_tx_queue++;
	if (lp->packets_in_tx_queue==1) {
		if (net_debug>3) /*### DEBUG ###*/
			printk( KERN_DEBUG "%s: transmit start, data=%p " \
					"len=%d\n", dev->name, buff, len );
		/* start packet transmition */
		write_reg( dev, TBCR0, len & 0xff ); /*packet length*/
		write_reg( dev, TBCR1, (len>>8) & 0x07 );
		write_reg( dev, CMR1, RE | TE | TRA ); /*transmit start*/
		dev->trans_start= jiffies;
	} else {
		if (net_debug>3) /*### DEBUG ###*/
			printk( KERN_DEBUG "%s: transmit delayed, data=%p " \
				"len=%d\n", dev->name, buff, len );
	
		lp->save_packet_size= len; /*delay packet transmit*/
	}
	/* enable interrupts and IRQOUT line */
	write_reg( dev, CMR2, cmr2 | IRQOUT ); /*switch RD3 to IRQ line*/
	enable_irq( dev->irq ); /*unmask IRQ*/

	dev_kfree_skb( skb );
	return( 0 );
}

/* the typical workload of the driver:
 * handle the network interface interrupts.
 * assume, that this function is uninterruptible */
static void net_interrupt( int irq, void *dev_id, struct pt_regs *regs )
{
	struct net_device *dev= (struct net_device*)dev_id;
	struct net_local *lp;
	int cmr2, status, count;

	/* check params */
	if (dev==NULL) {
		printk( KERN_WARNING "%s: irq %d for unknown device\n",
				cardname, irq );
		return;
	}
	/* set interrupt flag */
	/*if (set_bit(0,(void*)&dev->interrupt)!=0) {
		if (net_debug>=2)
			printk( KERN_DEBUG "%s: interrupt irrived when in interrupt " \
					"handling routine\n", dev->name );
		return;
	}*/
// X	dev->interrupt= 1;
	
	/* turn off interrupts and IRQOUT signal */
	disable_irq( irq ); /*mask IRQ*/
	cmr2= read_reg( dev, CMR2 );
	cmr2 &= 0x77;
	write_reg( dev, CMR2, cmr2 & ~IRQOUT );
	
	/* read interrupt status */
	count= 20;
	lp= (struct net_local*)dev->priv;
	while (count-->0
			&& lp->state==2 
			&& (status=read_reg(dev,ISR))!=0) {
		if (net_debug>=2) /*### DEBUG ###*/
			printk( KERN_DEBUG "%s: in interrupt, status=0x%02x " \
					"CMR1=0x%02x CMR2=0x%02x PNR=0x%02x\n", dev->name,
					status, read_reg(dev,CMR1), cmr2, read_reg(dev,PNR) );
		
		/* check always zero-bits */
		if (status & 0xe0) {
			/* adapter probably detached */
			printk( KERN_WARNING "%s: huh? always zero-bits of interrupt " \
					"status register are non-zero, status=0x%02x\n",
					dev->name, status );
			if (chipset_init(dev)) { /*reset it and check it*/
				lp->state= 3; /*hw error, set out of order*/
				printk( KERN_WARNING "%s: adapter put " \
						"out of order\n", dev->name );
				netif_stop_queue(dev);
			}
			continue;
		}
		
		if (status & (RBER | RER)) { /*receive error*/
			int rsr= read_reg( dev, RSR );
			lp->stats.rx_errors++;
			if (rsr & FA)
				lp->stats.rx_frame_errors++;
			if (rsr & CRC)
				lp->stats.rx_crc_errors++;
		
			if (net_debug>=1) /*### DEBUG ###*/
				printk( KERN_DEBUG "%s: Rx error interrupt, RSR=0x%02x\n",
						dev->name, rsr );
		
			if (status & RBER) {
				if (net_debug>2)
					printk( KERN_DEBUG "%s: receive buffer error\n",
							dev->name );
				/* manage buffer errors */
				if (rsr & (POV | BUFO)) {
					/* this should never occur, so reseting
					 * the board is good recovery. maybe. */
					lp->stats.rx_over_errors++;
					if (chipset_init(dev)) {
						lp->state= 3; /*hw error, set out of order*/
						printk( KERN_WARNING "%s: adapter put " \
								"out of order\n", dev->name );
					}
					continue;
				}
				if (rsr & PUN) {
					/* disable receiver (reset RE in CMR1, receiver
					 * will reset) and then enable receiver (set RE bit,
					 * receiver will function normally) */
					write_reg( dev, CMR1, TE );
					write_reg( dev, CMR1, RE | TE );
				}
				write_reg( dev, ISR, CLRRBER ); /*clear interrupt*/
			}
			if (status & RER) {
				if (net_debug>2)
					printk( KERN_DEBUG "%s: receive error\n", dev->name );
				write_reg( dev, ISR, CLRRER ); /*clear interrupt*/
			}
		}

		if (status & ROK) { /*packet received OK*/
			int len= 0;
			if (net_debug>=1) /*### DEBUG ###*/
				printk( KERN_DEBUG "%s: Rx interrupt\n", dev->name );
	
			/* read packets from Rx buffer while PNR>0 */
			while (len>=0 && read_reg(dev,PNR)>0)
				len= net_rx( dev );
			write_reg( dev, ISR, CLRROK ); /*clear interrupt*/
		}
		
		if (status & (TER | TOK)) { /*transmit error or OK*/
			int tsr= read_reg( dev, TSR );
			lp->stats.collisions += read_reg( dev, TBCR1 ) & 0x0f;
			if (tsr & TABT)
				lp->stats.tx_dropped++;
			if (tsr & TXOK)
				lp->stats.tx_packets++;
			
			if (net_debug>=1) /*### DEBUG ###*/
				printk( KERN_DEBUG "%s: Tx interrupt, TSR=0x%02x\n",
						dev->name, tsr );
			
			/* clear interrupts */
			if (status & TER)
				write_reg( dev, ISR, CLRTER );
			if (status & TOK)
				write_reg( dev, ISR, CLRTOK );
			
			if (net_debug>=2) /*### DEBUG ###*/
				if (read_reg(dev,CMR1) & TRA)
					printk( KERN_WARNING "%s: huh? Tx interrupt when "
							"transmitter is active\n", dev->name );
			
			/* if last packet transmition is over, transmit next */
			if (tsr & (TABT | TXOK)) {
				lp->packets_in_tx_queue--;
				if (lp->packets_in_tx_queue>0) {
					if (net_debug>3) /*### DEBUG ###*/
						printk( KERN_DEBUG "%s: delayed transmit start\n",
								dev->name );
					/* start delayed transmition */
					write_reg( dev, TBCR0, lp->save_packet_size & 0xff );
					write_reg( dev, TBCR1, (lp->save_packet_size>>8) & 0x07 );
					write_reg( dev, CMR1, RE | TE | TRA ); /*transmit start*/
					dev->trans_start= jiffies;
				} else {
					if (net_debug>3) /*### DEBUG ###*/
						printk( KERN_DEBUG "%s: all transmitions done\n",
								dev->name );
				}
				lp->save_packet_size= 0;
// X				mark_bh( NET_BH ); /*inform upper layers*/
				netif_wake_queue(dev);
			}
		}
		if (net_debug>=2) /*### DEBUG ###*/
			printk( KERN_DEBUG "%s: interrupt done, status=0x%02x " \
					"CMR1=0x%02x CMR2=0x%02x PNR=0x%02x\n", dev->name,
					read_reg(dev,ISR), read_reg(dev,CMR1), read_reg(dev,CMR2),
					read_reg(dev,PNR) );
	}
	/* enable interrupts and IRQOUT line */
	write_reg( dev, CMR2, cmr2 ); /*switch RD3 to IRQ line*/
	enable_irq( irq ); /*unmask IRQ*/
	
	/* clear interrupt flag */
	/*clear_bit( 0, (void*)&dev->interrupt );*/
// X	dev->interrupt = 0;
}

/* we have a good packet(s), get it/them out of the buffers
 * returns: length of received packet, -1 in case of read error */
static int net_rx( struct net_device *dev )
{
	struct net_local *lp= (struct net_local*)dev->priv;
	int len;
	
	/* issue read packet command */
	write_reg( dev, CMR1, RE | TE | RDPAC );
	len= lp->read_data( dev, lp->buff, -1/*autodetect*/ );
	
	if (net_debug>=1) /*### DEBUG ###*/
		printk( KERN_DEBUG "%s: Rx packet, len=%d\n", dev->name, len );
	
	if (len>0) {
		struct sk_buff *skb;
		skb= dev_alloc_skb( len + 2 );
		if (skb==NULL) {
			/* error, insufficient memory for packet */
			printk( KERN_NOTICE "%s: memory squeeze, dropping packet\n",
				   dev->name );
			lp->stats.rx_dropped++;
			len= 0;
		} else {
			/* copy packet from receive buffer */
			skb->dev = dev;
			skb_reserve( skb, 2 );
			memcpy( skb_put(skb,len), lp->buff, len );
			skb->protocol= eth_type_trans( skb, dev );
			netif_rx( skb );
			lp->stats.rx_packets++;
		}
	}
	return( len );
}

/* close the adapter.
 * the inverse routine to net_open() */
static int net_close( struct net_device *dev )
{
	/* set flags */
// X	dev->tbusy= 1;
// X	dev->start= 0;
	netif_stop_queue(dev);

	/* put adapter in "transparent" mode */
	chipset_deinit( dev );

	/* de-setup interrupt */
// X	irq2dev_map[dev->irq]= 0;
	free_irq(dev->irq, dev);

	MOD_DEC_USE_COUNT;
	return( 0 );
}

/* get the current interface statistics.
 * this may be called with the card open or closed */
static struct net_device_stats* net_get_stats( struct net_device *dev )
{
	struct net_local *lp= (struct net_local*)dev->priv;
	return( &lp->stats );
}

/* set or clear the multicast filter for rtl8012 adapter. */
static void set_multicast_list( struct net_device *dev )
{
	struct net_local *lp= (struct net_local*)dev->priv;
	unsigned char mc_filter[8];
	int cmr2, i;
	
	if (net_debug>2) /*### DEBUG ###*/
		printk( KERN_DEBUG "%s: set_multicast_list(): mc_count=%d\n",
				dev->name, dev->mc_count );
	
	if (dev->flags & IFF_PROMISC) { /*set promiscuous mode*/
		lp->rx_mode= AM_PROMISCUOUS;
		memset( mc_filter, 0x00, sizeof(mc_filter) ); /*clear hash filter*/
		printk( KERN_INFO "%s: promiscuous Rx mode\n", dev->name );
	} else if ((dev->flags&IFF_ALLMULTI) || dev->mc_count>1000) {
		/* too many physical addresses to filter perfectly --
		 * accept all multicast packets. or set ALLMULTI mode */
		lp->rx_mode= AM_NORMAL;
		memset( mc_filter, 0xff, sizeof(mc_filter) );
		if (net_debug>2) /*### DEBUG ###*/
			printk( KERN_DEBUG "%s: all-multicasts Rx mode\n", dev->name );
	} else {
		/* set individual hash filter bits.
		 * something is wrong:
		 * recommended process */
		struct dev_mc_list *mc_list= dev->mc_list;
		unsigned char bc_addr[ETH_ALEN]= /*ethernet broadcast address*/
				{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
		lp->rx_mode= AM_NORMAL;
		memset( mc_filter, 0x00, sizeof(mc_filter) ); /*clear hash filter*/
		set_bit( ether_crc(bc_addr,ETH_ALEN) & 0x3f, (void*)mc_filter );
		for( i=0; mc_list && i<dev->mc_count; i++ ) { /*take 6 MSB bits*/
			set_bit( ether_crc(mc_list->dmi_addr,ETH_ALEN) & 0x3f,
					(void*)mc_filter ); /*set n-th bit of mc_filter*/
			mc_list= mc_list->next;
		}
		if (net_debug>2) /*### DEBUG ###*/
			printk( KERN_DEBUG "%s: normal Rx mode\n", dev->name );
	}

	/* turn off interrupts and IRQOUT signal */
	disable_irq( dev->irq ); /*mask IRQ*/
	cmr2= read_reg( dev, CMR2 );
	cmr2 &= 0x77 & ~IRQOUT; /*switch IRQ line back to RD3 data*/
	write_reg( dev, CMR2, cmr2 | PAGE); /*set also page #1 registers*/
	
	/* write multicast filter into MAR0-7 registers */
	for( i=0; i<8; i++ )
		write_reg( dev, MAR0+i, mc_filter[i] );
	cmr2 &= ~(AM1 | AM0); /*mask out rx address mode bits*/
	cmr2 |= lp->rx_mode;
	
	/* enable interrupts and IRQOUT line.
	 * write into CMR2 also sets the proper rx address mode */
	write_reg( dev, CMR2, cmr2 | IRQOUT ); /*switch RD3 back to IRQ line*/
	enable_irq( dev->irq ); /*unmask IRQ*/
}

/* this code is common little-endian autodin32 ethernet CRC
 * calculation. CRC is used in creation of multicast hash filter */
static const unsigned int ether_polynomial= 0xedb88320;
static unsigned int ether_crc( unsigned char *data, int len )
{
	unsigned int byte, crc= 0xffffffff; /*initial value*/
	int i, j;
	for( i=0; i<len; i++ ) {
		byte= data[i];
		for( j=0; j<8; j++ ) {
			if ((crc^byte) & 0x01) {
				crc >>= 1;
				crc ^= ether_polynomial;
			} else
				crc >>= 1;
			byte >>= 1;
		}
	}
	return( crc );
}

#ifdef MODULE
/* ############################################### module related functions */

/* device structure */
static char devicename[9]= "";
static struct net_device this_device= {
	devicename, /*will be inserted by linux/drivers/net/net_init.c*/
	0, 0, 0, 0, /*unused--shared memory spec.*/
	0, 0, /*base_addr, irq*/
	NULL, /*next device struct*/
	rtl8012_probe, /*device init (called only once)*/
	/*...structure continues...*/
};

/* variables for insmod parameters */
static int io= 0;
static int irq= 0;

/* module initialization */
int init_module( void )
{
	if (io==0)
		printk( KERN_WARNING "%s: you should not use auto-probing " \
				"with insmod\n", cardname );

	/* copy the parameters from insmod into the device structure */
	this_device.base_addr= io;
	this_device.irq= irq;

	/* register_netdev() return codes are not that we want */
	if (register_netdev(&this_device))
		return( -ENODEV );
	return( 0 ); /*ok*/
}

/* deinitialize module */
int cleanup_module( void )
{
	struct net_local *lp= (struct net_local*)this_device.priv;
	
	/* no need to check MOD_IN_USE, as sys_delete_module() checks */
	unregister_netdev( &this_device );
	
	/* if we don't do this, we can't re-insmod it later.
	 * release irq/dma here, when you have jumpered versions and
	 * allocate them in net_probe1() */
	free_irq( this_device.irq, NULL );
	release_region( this_device.base_addr, IOSIZE(this_device.base_addr) );

	/* release private data memory */
	if (lp->buff!=NULL)
		kfree( lp->buff );
	if (this_device.priv!=NULL)
		kfree( this_device.priv );
	
	return( 0 );
}
#endif /*MODULE*/


/* ############################################ hardware dependent functions */

/* function turns off printer multiplexer and reset hardware */
static int chipset_init( struct net_device *dev )
{
	struct net_local *lp= (struct net_local*)dev->priv;
	int i, ctrlport;

	/* ### DEBUG ### */
	if (net_debug>4)
		printk( KERN_DEBUG "%s: chipset_init(): ctrl=0x%02x stat=0x%02x\n",
				dev->name, inb(CTRL(dev->base_addr)),
				inb(STAT(dev->base_addr)) );
	
	/* reset control port state */
	ctrlport= CTRL( dev->base_addr );
	outb( 0x04, ctrlport );

	/* turn off printer multiplexer --
	 * rtl8012 will accept and respond to commands */
	for( i=0; i<8; i++ )
		outb( muxoff[i], DATA(dev->base_addr) );
	
	/* reset adapter and check CMR1 and CMR2 registers */
	write_reg( dev, CMR1, RST );
	udelay( 450 ); /*give 450 usec to complete the reset*/
	if (read_reg(dev,CMR1)!=0x01 || read_reg(dev,CMR2)!=0x20) {
		printk( KERN_WARNING "%s: cannot initialize controller, pocket " \
				"adapter %stached?\n", dev->name,
				(lp->state<2) ? "not at" : "de" );
		if (lp->state==2)
			lp->state= 3; /*mark as detached*/
		return( -ENODEV );
	}
	
	/* get node id if empty */
	if (dev->dev_addr[0]==0
			&& dev->dev_addr[1]==0
			&& dev->dev_addr[2]==0
			&& dev->dev_addr[3]==0
			&& dev->dev_addr[4]==0
			&& dev->dev_addr[5]==0)
		getnodeid( dev );
	
	/* if adapter was detached at boot time */
	if (lp->state==1) {
		printk( KERN_INFO "%s: MAC address", dev->name );
		for( i=0; i<6; i++ )
			printk( "%c%02X", i ? ':' : ' ', dev->dev_addr[i] );
		printk( ".\n" );
	} else if (lp->state==3)
		printk( KERN_INFO "%s: pocket adapter reinitialized\n", dev->name );
	
	/* change values */
	lp->rx_mode= AM_NORMAL;
	lp->packets_in_tx_queue= 0;
	lp->save_packet_size= 0;
	lp->state= 2; /*set "attached" state*/
	
	/* set ethernet controller's node id */
	for( i=0; i<6; i++ )
		write_reg( dev, IDR0+i, dev->dev_addr[i] );
		
	/* enable transmitter and receiver,
	 * set address mode and IRQOUT */
	write_reg( dev, CMR1, RE | TE );
	write_reg( dev, CMR2, lp->rx_mode | IRQOUT );

	/* write MODSEL register */
	write_reg( dev, MODSEL, (lp->parallel_port_mode==0) ? 0 :
			((lp->parallel_port_mode==1) ? DIR0 : (EPPWAIT | DIR1)) );

	/* enable interrupts */
	write_reg( dev, IMR, TOKM | TERM | ROKM | RERM | RBERM ); /*rtl8012*/
	outb( 0x14, ctrlport ); /*parallel port IRQ*/
	return( 0 );
}

/* function turns the printer multiplexer on.
 * member dev->priv may be NULL!!! */
static void chipset_deinit( struct net_device *dev )
{
	/* set idle state of control port */
	outb( 0x04, CTRL(dev->base_addr) );
	
	/* turn on printer multiplexer --
	 * rtl8012 will be "transparent" */
	write_reg( dev, IMR, 0 ); /*disable interrupts*/
	write_reg( dev, CMR2, 0 ); /*no acception mode*/
	write_reg( dev, CMR1, MUX );
}

/* function writes value into specified register */
static void write_reg( struct net_device *dev, int reg, int val )
{
	int dataport, value;
	dataport= DATA( dev->base_addr );
	
	value= 0xf0 | (reg & 0x0f); /*idle signals + register number*/
	outb( value, dataport );
	value &= ~0x10; /*clear hnib*/
	outb( value, dataport );
	value &= ~0x20; /*clear csb*/
	outb_p( value, dataport );
	outb_p( value, dataport ); /*delay 400ns*/
	
	/* low nibble */
	value= (value & 0xf0) | (val & 0x0f);
	/*outb( value, dataport );*/
	value &= ~0x40; /*clear a/db*/
	outb_p( value, dataport );
	outb_p( value, dataport ); /*delay 500ns*/
	
	/* high nibble */
	value= (value & 0xf0) | ((val >> 4) & 0x0f);
	/*outb( value, dataport );*/
	value |= 0x10; /*set hnib*/
	outb_p( value, dataport );
	outb_p( value, dataport ); /*delay 500ns*/
		
	value |= 0x60; /*set csb,a/db*/
	outb_p( value, dataport ); /*delay 300ns*/
}

/* reads actual value from specified register */
static int read_reg( struct net_device *dev, int reg )
{
	int dataport, statport, value, retval;
	dataport= DATA( dev->base_addr );
	statport= STAT( dev->base_addr );

	value= 0xf0 | (reg & 0x0f); /*idle signals  + register number*/
	outb( value, dataport );
	value &= ~0x90; /*clear hnib,w/rb*/
	outb( value, dataport );
	value &= ~0x20; /*clear csb*/
	outb_p( value, dataport );
	outb_p( value, dataport ); /*delay 500ns*/
	
	/* low nibble */
	retval= (inb(statport) >> 3) & 0x0f;
	value |= 0x10; /*set hnib*/
	outb_p( value, dataport );
	outb_p( value, dataport ); /*delay 300ns*/
	
	/* high nibble */
	retval |= (inb_p(statport) << 1) & 0xf0;
	inb_p( statport ); /*delay 500ns*/
	
	value |= 0xc0; /*set csb,w/rb*/
	outb_p( value, dataport ); /*delay 300ns*/
	return( retval );
}

/* write data into the controller using SPP mode */
static void write_data_spp( struct net_device *dev,
		const unsigned char *buff, int len )
{
	int i, dmaclk, ctrl;
	int dataport, ctrlport;
	dataport= DATA( dev->base_addr );
	ctrlport= CTRL( dev->base_addr );
	
	ctrl= inb( ctrlport );
	ctrl |= 0x04; /*set DMACSB*/
	ctrl &= ~0x02; /*reset DMACLK (inv)*/
	outb( ctrl, ctrlport );
	write_reg( dev, MODSEL, DMAWRB | DMAMOD ); /*set mode C*/
	ctrl &= ~0x04; /*reset DMACSB*/
	outb_p( ctrl, ctrlport ); /*delay 100ns*/
		
	/* write data */
	dmaclk= 0;
	for( i=0; i<len; i++ ) {
		outb_p( buff[i], dataport );
		if (dmaclk) {
			dmaclk= 0;
			ctrl &= ~0x02; /*reset DMACLK*/
		} else {
			dmaclk= 1;
			ctrl |= 0x02; /*set DMACLK*/
		}
		outb_p( ctrl, ctrlport );
		outb_p( ctrl, ctrlport ); /*delay 500ns*/
	}
	
	ctrl |= 0x04; /*set DMACSB*/
	outb_p( ctrl, ctrlport ); /*delay 100ns*/
	ctrl &= ~0x02; /*reset DMACLK*/
	outb( ctrl, ctrlport );
}

/* read data from controller using SPP (nibble) mode.
 * if len<0, then length of the data is determined from data header.
 * returns length of read data */
static int read_data_spp( struct net_device *dev,
		unsigned char *buff, int len )
{
	int i, ctrl;
	int statport, ctrlport;
	struct rx_header header;
	unsigned char *ptr;
	statport= STAT( dev->base_addr );
	ctrlport= CTRL( dev->base_addr );
	
	ctrl= inb( ctrlport );
	ctrl |= 0x04; /*set DMACSB*/
	ctrl &= ~0x02; /*reset DMACLK (inv)*/
	outb( ctrl, ctrlport ); /*reset DMACLK and DMACSB*/
	write_reg( dev, MODSEL, DMAMOD ); /*set mode B*/
	ctrl &= ~0x04; /*reset DMACSB*/
	outb_p( ctrl, ctrlport ); /*delay 100ns*/
	
	/* process header (8 bytes) */
	ptr= (unsigned char*)&header;
	for( i=0; i<8; i++ ) {
		inb_p( statport ); /*delay 500ns*/
		ptr[i]= (unsigned char)((inb_p(statport) >> 3) & 0x0f);
		ctrl |= 0x02; /*set DMACLK*/
		outb_p( ctrl, ctrlport );
		inb_p( statport ); /*delay 500ns*/
		ptr[i] |= (unsigned char)((inb_p(statport) << 1) & 0xf0);
		ctrl &= ~0x02; /*reset DMACLK*/
		outb_p( ctrl, ctrlport );
	}
	header.next_msb &= 0x0f;
	if (net_debug>4) /*### DEBUG ###*/
		printk( KERN_DEBUG "%s: rx_header: len=%d " \
				"stat=0x%02x next=0x%04x\n", dev->name,
				((int)header.length_msb << 8) | header.length_lsb,
				header.status, 
				((int)header.next_msb << 8) | header.next_lsb );
				
	if (len<0) { /*automatic data length*/
		len= (((int)header.length_msb << 8) | header.length_lsb) - 4/*crc*/;
		if (len>ETH_FRAME_LEN) {
			/* limited buffer size (lp->buff). all in all,
			 * lengths over 1500+14 bytes are very stange ;-) */
			printk( KERN_WARNING "%s: huh? ethernet frame longer than " \
					"1514 bytes, len=%d\n", dev->name, len );
			len= ETH_FRAME_LEN;
		}
	}
	/* read data */
	for( i=0; i<len; i++ ) {
		inb_p( statport ); /*delay 500ns*/
		buff[i]= (unsigned char)((inb_p(statport) >> 3) & 0x0f);
		ctrl |= 0x02; /*set DMACLK*/
		outb_p( ctrl, ctrlport );
		inb_p( statport ); /*delay 500ns*/
		buff[i] |= (unsigned char)((inb_p(statport) << 1) & 0xf0);
		ctrl &= ~0x02; /*reset DMACLK*/
		outb_p( ctrl, ctrlport );
	}
	
	ctrl |= 0x04; /*set DMACSB*/
	outb_p( ctrl, ctrlport ); /*delay 100ns*/
	ctrl &= ~0x02; /*reset DMACLK*/
	outb( ctrl, ctrlport );
	return( len );
}

/* write data into the controller using bidirectional SPP mode */
static void write_data_bispp( struct net_device *dev,
		const unsigned char *buff, int len )
{
	int i, dmaclk, ctrl;
	int dataport, ctrlport;
	dataport= DATA( dev->base_addr );
	ctrlport= CTRL( dev->base_addr );
	
	ctrl= inb( ctrlport );
	ctrl |= 0x04; /*set DMACSB*/
	ctrl &= ~0x02; /*reset DMACLK (inv)*/
	outb( ctrl, ctrlport );
	write_reg( dev, MODSEL, DMAWRB | DMAMOD | DIR0 ); /*set mode F*/
	ctrl &= ~0x04; /*reset DMACSB*/
	outb_p( ctrl, ctrlport ); /*delay 100ns*/
		
	/* write data */
	dmaclk= 0;
	for( i=0; i<len; i++ ) {
		outb_p( buff[i], dataport );
		outb( buff[i], dataport );
		if (dmaclk) {
			dmaclk= 0;
			ctrl &= ~0x02; /*reset DMACLK*/
		} else {
			dmaclk= 1;
			ctrl |= 0x02; /*set DMACLK*/
		}
		outb_p( ctrl, ctrlport );
		outb_p( ctrl, ctrlport ); /*delay 500ns*/
	}
	
	ctrl |= 0x04; /*set DMACSB*/
	outb_p( ctrl, ctrlport ); /*delay 100ns*/
	ctrl &= ~0x02; /*reset DMACLK*/
	outb( ctrl, ctrlport );
}

/* read data from controller using bidirectional SPP mode.
 * if len<0, then length of the data is determined from data header.
 * returns length of read data */
static int read_data_bispp( struct net_device *dev,
		unsigned char *buff, int len )
{
	int i, dmaclk, ctrl;
	int dataport, ctrlport;
	struct rx_header header;
	unsigned char *ptr;
	dataport= DATA( dev->base_addr );
	ctrlport= CTRL( dev->base_addr );
	
	ctrl= inb( ctrlport );
	ctrl |= 0x04; /*set DMACSB*/
	ctrl &= ~0x02; /*reset DMACLK (inv)*/
	outb( ctrl, ctrlport ); /*reset DMACLK and DMACSB*/
	write_reg( dev, MODSEL, DMAMOD | DIR0 ); /*set mode E*/
	ctrl |= 0x20; /*set INPUT direction*/
	ctrl &= ~0x04; /*reset DMACSB*/
	outb_p( ctrl, ctrlport );
	
	/* proces header (8 bytes) */
	ptr= (unsigned char*)&header;
	dmaclk= 0;
	for( i=0; i<8; i++ ) {
		inb_p( dataport ); /*delay 500ns*/
		ptr[i]= inb_p( dataport );
		if (dmaclk) {
			dmaclk= 0;
			ctrl &= ~0x02; /*reset DMACLK*/
		} else {
			dmaclk= 1;
			ctrl |= 0x02; /*set DMACLK*/
		}
		outb_p( ctrl, ctrlport );
	}
	header.next_msb &= 0x0f;
	if (net_debug>4) /*### DEBUG ###*/
		printk( KERN_DEBUG "%s: rx_header: len=%d " \
				"stat=0x%02x next=0x%04x\n", dev->name,
				((int)header.length_msb << 8) | header.length_lsb,
				header.status, 
				((int)header.next_msb << 8) | header.next_lsb );
	
	if (len<0) { /*automatic data length*/
		len= (((int)header.length_msb << 8) | header.length_lsb) - 4/*crc*/;
		if (len>ETH_FRAME_LEN) {
			/* limited buffer size (lp->buff). all in all,
			 * lengths over 150014+ bytes are very stange ;-) */
			printk( KERN_WARNING "%s: huh? ethernet frame longer than " \
					"1514 bytes, len=%d\n", dev->name, len );
			len= ETH_FRAME_LEN;
		}
	}
	/* read data */
	for( i=0; i<len; i++ ) {
		inb_p( dataport );
		buff[i]= inb_p( dataport ); /*delay 500ns*/
		if (dmaclk) {
			dmaclk= 0;
			ctrl &= ~0x02; /*reset DMACLK*/
		} else {
			dmaclk= 1;
			ctrl |= 0x02; /*set DMACLK*/
		}
		outb_p( ctrl, ctrlport );
	}
	
	ctrl |= 0x04; /*set DMACSB*/
	ctrl &= ~0x20; /*set OUTPUT direction*/
	outb_p( ctrl, ctrlport ); /*delay 100ns*/
	ctrl &= ~0x02; /*reset DMACLK*/
	outb( ctrl, ctrlport );
	return( len );
}

/* write data into the controller using EPP mode */
static void write_data_epp( struct net_device *dev,
		const unsigned char *buff, int len )
{
	int i, ctrl, stat;
	unsigned int timeout;
	int eppdataport, statport, ctrlport;
	
	/* timeout when transfer is slower than 32kB/sec */
	timeout= jiffies + (len*HZ)/32768 + 2/*for sure*/;
	eppdataport= EPPDATA( dev->base_addr );
	statport= STAT( dev->base_addr );
	ctrlport= CTRL( dev->base_addr );
	
	ctrl= inb( ctrlport );
	ctrl |= 0x04; /*set DMACSB*/
	ctrl &= ~0x02; /*reset DMACLK (inv)*/
	outb( ctrl, ctrlport );
	write_reg( dev, MODSEL, DMAWRB | DMAMOD | EPPWAIT | DIR1 ); /*set mode I*/
	ctrl &= ~0x04; /*reset DMACSB*/
	outb( ctrl, ctrlport ); /*delay 100ns*/

	/* check EPP timeout bit */
	stat= inb( statport );
	if (stat & 0x01) {
		outb_p( stat, statport );
		outb_p( stat & 0xfe, statport ); /*clear timeout bit*/
		printk( KERN_NOTICE "%s: EPP timeout bit was set before write " \
				"operation begin\n", dev->name );
	}
	
	/* write data */
	i= 0;
	while (i<len && jiffies<timeout) {
		outb( buff[i], eppdataport ); /*write a byte*/
		stat= inb( statport );
		if (stat & 0x01) { /*clear EPP timeout*/
			outb_p( stat, statport );
			outb_p( stat & 0xfe, statport );
			udelay( 10 );
			continue;
		}
		i++;
	}
	if (i<len) /*ughh, transfer error*/
		printk( KERN_WARNING "%s: ughh, EPP write timed out\n", dev->name );
	
	ctrl |= 0x04; /*set DMACSB*/
	outb_p( ctrl, ctrlport ); /*delay 100ns*/
	ctrl &= ~0x02; /*reset DMACLK*/
	outb( ctrl, ctrlport );
}

/* read data from controller using EPP mode.
 * if len<0, then length of the data is determined from data header.
 * returns length of read data or -1 in case of read error */
static int read_data_epp( struct net_device *dev,
		unsigned char *buff, int len )
{
	int i, ctrl, stat;
	unsigned int timeout;
	int eppdataport, statport, ctrlport;
	struct rx_header header;
	unsigned char *ptr;
	
	/* timeout when transfer is slower than 32kB/sec */
	timeout= jiffies + (len*HZ)/32768 + 2/*for sure*/;
	eppdataport= EPPDATA( dev->base_addr );
	statport= STAT( dev->base_addr );
	ctrlport= CTRL( dev->base_addr );
	
	ctrl= inb( ctrlport );
	ctrl |= 0x04; /*set DMACSB*/
	ctrl &= ~0x02; /*reset DMACLK (inv)*/
	outb( ctrl, ctrlport ); /*reset DMACLK and DMACSB*/
	write_reg( dev, MODSEL, DMAMOD | EPPWAIT | DIR1 ); /*set mode E*/
	ctrl |= 0x20; /*set INPUT direction*/
	ctrl &= ~0x04; /*reset DMACSB*/
	outb_p( ctrl, ctrlport ); /*delay 100ns*/
	
	/* check EPP timeout bit */
	stat= inb( statport );
	if (stat & 0x01) {
		outb_p( stat, statport );
		outb_p( stat & 0xfe, statport ); /*clear timeout bit*/
		printk( KERN_NOTICE "%s: EPP timeout bit was set before read " \
				"operation begin\n", dev->name );
	}
	
	/* read and proces header (8 bytes) */
	i= 0;
	ptr= (unsigned char*)&header;
	while (i<8 && jiffies<timeout) {
		ptr[i]= inb( eppdataport ); /*read a byte*/
		stat= inb( statport );
		if (stat & 0x01) { /*clear EPP timeout*/
			outb_p( stat, statport );
			outb_p( stat & 0xfe, statport );
			udelay( 10 );
			continue;
		}
		i++;
	}
	header.next_msb &= 0x0f;
	if (i<8) { /*ughh, transfer error*/
		printk( KERN_WARNING "%s: ughh, EPP read timed out\n", dev->name );
		len= -1; /*do not continue with reading*/
		goto read_error;
	}
	if (net_debug>4) /*### DEBUG ###*/
		printk( KERN_DEBUG "%s: rx_header: len=%d " \
				"stat=0x%02x next=0x%04x\n", dev->name,
				((int)header.length_msb << 8) | header.length_lsb,
				header.status, 
				((int)header.next_msb << 8) | header.next_lsb );
				
	if (len<0) { /*automatic data length*/
		len= (((int)header.length_msb << 8) | header.length_lsb) - 4/*crc*/;
		if (len>ETH_FRAME_LEN) {
			/* limited buffer size (lp->buff). all in all,
			 * lengths over 150014+ bytes are very stange ;-) */
			printk( KERN_WARNING "%s: huh? ethernet frame longer than " \
					"1514 bytes, len=%d\n", dev->name, len );
			len= ETH_FRAME_LEN;
		}
	}
	/* read data */
	i= 0;
	while (i<len && jiffies<timeout) {
		buff[i]= inb( eppdataport ); /*read a byte*/
		stat= inb( statport );
		if (stat & 0x01) { /*clear EPP timeout*/
			outb_p( stat, statport );
			outb_p( stat & 0xfe, statport );
			udelay( 10 );
			continue;
		}
		i++;
	}
	if (i<len) { /*ughh, transfer error*/
		printk( KERN_WARNING "%s: ughh, EPP read timed out\n", dev->name );
		len= i; /*say how data much we read*/
	}

read_error:
	ctrl |= 0x04; /*set DMACSB*/
	ctrl &= ~0x20; /*set OUTPUT direction*/
	outb_p( ctrl, ctrlport ); /*delay 100ns*/
	ctrl &= ~0x02; /*reset DMACLK*/
	outb( ctrl, ctrlport );
	return( len );
}

/* perform 9346 eeprom operation. this chip is 1024-bit serial
 * eeprom organized in 16-bit words (total 64 words). each input
 * command has 27 bits. see datasheet NM93C46 for details. function
 * returns latched eeprom output (low 16 bits, msb to lsb) */
static int eeprom_operation( struct net_device *dev, int cmd )
{
	int i, value, retval, cmr2;
	
	/* select page #1 registers */
	cmr2= read_reg( dev, CMR2 );
	write_reg( dev, CMR2, cmr2 | PAGE );
	
	/* feed 27 input bits and simultaneously catch
	 * 27 output bits. only lowest 16 bits are valid. */
	write_reg( dev, PCMR, EESKB );
	retval= 0;
	i= 27;
	while (i-->0)
	{
		value= (cmd & (1 << i)) ? EEDI : 0;
		value |= EECS | EESKB;
		write_reg( dev, PCMR, value );
		udelay( 1 );
		value &= ~EESKB;
		write_reg( dev, PCMR, value );
		retval <<=1;
		if (read_reg(dev,PDR)&EEDO)
			retval |= 1;
		udelay( 1 );
	}
	write_reg( dev, PCMR, EESKB );
	retval &= 0xffff;
	
	/* restore CMR2: page #0 regs */
	write_reg( dev, CMR2, cmr2 );
	return( retval );
}

/* functions gets node id. node id must
 * be shifted out from serial eeprom */
static void getnodeid( struct net_device *dev )
{
	int i, j;
	for( i=0; i<3; i++ )
	{
		j= eeprom_operation( dev, EEPROM_READ(i) );
		dev->dev_addr[2*i]= j & 0xff;
		dev->dev_addr[2*i+1]= (j >> 8) & 0xff;
	}
}
