/* * rtl8012.c * * Copyright (c)1999 S O L A M Y L W A R E , Stepan Skrob. * Author may be reached at . * * 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). */ #define __KERNEL__ /* We're part of the kernel */ #define MODULE /* Not a permanent part, though. */ static const char *version= "rtl8012.c: v1.02 16/10/1999 Stepan Skrob \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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* 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 */ struct 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) { printk( KERN_WARNING "%s: unable initialize the device structure\n",dev->name); 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) { printk( KERN_WARNING "%s: unable allocate receive buffer\n",dev->name); 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 ); free_irq( dev->irq, NULL ); /*free irq*/ 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 (rc=request_irq(dev->irq, &net_interrupt, 0, dev->name, dev)) { printk(KERN_WARNING "%s: couldn't get interrupt %d rc=%d\n", dev->name,dev->irq,rc); // Z 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_startname ); // 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 && imc_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>= 1; crc ^= ether_polynomial; } else crc >>= 1; byte >>= 1; } } return( crc ); } #ifdef MODULE /* ############################################### module related functions */ /* variables for insmod parameters */ static int io= 0x378; static int irq= 7; /* device structure */ static char devicename[9]= ""; static struct net_device this_device= { " ", /*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*/ NULL, /*device init (called only once)*/ /*...structure continues...*/ }; MODULE_LICENSE ("GPL"); MODULE_PARM (io, "i"); MODULE_PARM (irq, "i"); /* 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; this_device.init= &rtl8012_probe; /* 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; ibase_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> 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; ibase_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; ibase_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 (iname ); 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 && jiffiesname ); 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 (iname ); 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; } }