2005-04-17 02:20:36 +04:00
/*
* net - 3 - driver for the NI5210 card ( i82586 Ethernet chip )
*
* This is an extension to the Linux operating system , and is covered by the
* same GNU General Public License that covers that work .
*
* Alphacode 0.82 ( 96 / 09 / 29 ) for Linux 2.0 .0 ( or later )
* Copyrights ( c ) 1994 , 1995 , 1996 by M . Hipp ( hippm @ informatik . uni - tuebingen . de )
* [ feel free to mail . . . . ]
*
* when using as module : ( no autoprobing ! )
* run with e . g :
* insmod ni52 . o io = 0x360 irq = 9 memstart = 0xd0000 memend = 0xd4000
*
* CAN YOU PLEASE REPORT ME YOUR PERFORMANCE EXPERIENCES ! ! .
*
* If you find a bug , please report me :
* The kernel panic output and any kmsg from the ni52 driver
* the ni5210 - driver - version and the linux - kernel version
* how many shared memory ( memsize ) on the netcard ,
* bootprom : yes / no , base_addr , mem_start
* maybe the ni5210 - card revision and the i82586 version
*
* autoprobe for : base_addr : 0x300 , 0x280 , 0x360 , 0x320 , 0x340
* mem_start : 0xd0000 , 0xd2000 , 0xc8000 , 0xca000 , 0xd4000 , 0xd6000 ,
* 0xd8000 , 0xcc000 , 0xce000 , 0xda000 , 0xdc000
*
* sources :
* skeleton . c from Donald Becker
*
* I have also done a look in the following sources : ( mail me if you need them )
* crynwr - packet - driver by Russ Nelson
* Garret A . Wollman ' s ( fourth ) i82586 - driver for BSD
2008-02-08 18:27:38 +03:00
* ( before getting an i82596 ( yes 596 not 586 ) manual , the existing drivers
* helped me a lot to understand this tricky chip . )
2005-04-17 02:20:36 +04:00
*
* Known Problems :
* The internal sysbus seems to be slow . So we often lose packets because of
* overruns while receiving from a fast remote host .
2008-02-08 18:27:38 +03:00
* This can slow down TCP connections . Maybe the newer ni5210 cards are
* better . My experience is , that if a machine sends with more than about
* 500 - 600 K / s the fifo / sysbus overflows .
2005-04-17 02:20:36 +04:00
*
* IMPORTANT NOTE :
* On fast networks , it ' s a ( very ) good idea to have 16 K shared memory . With
2008-02-08 18:27:38 +03:00
* 8 K , we can store only 4 receive frames , so it can ( easily ) happen that a
* remote machine ' overruns ' our system .
2005-04-17 02:20:36 +04:00
*
* Known i82586 / card problems ( I ' m sure , there are many more ! ) :
* Running the NOP - mode , the i82586 sometimes seems to forget to report
* every xmit - interrupt until we restart the CU .
* Another MAJOR bug is , that the RU sometimes seems to ignore the EL - Bit
* in the RBD - Struct which indicates an end of the RBD queue .
* Instead , the RU fetches another ( randomly selected and
* usually used ) RBD and begins to fill it . ( Maybe , this happens only if
* the last buffer from the previous RFD fits exact into the queue and
* the next RFD can ' t fetch an initial RBD . Anyone knows more ? )
*
* results from ftp performance tests with Linux 1.2 .5
* send and receive about 350 - 400 KByte / s ( peak up to 460 kbytes / s )
2008-02-08 18:27:38 +03:00
* sending in NOP - mode : peak performance up to 530 K / s ( but better don ' t
* run this mode )
2005-04-17 02:20:36 +04:00
*/
/*
* 29. Sept .96 : virt_to_bus changes for new memory scheme
* 19.F eb .96 : more Mcast changes , module support ( MH )
*
* 18. Nov .95 : Mcast changes ( AC ) .
*
* 23. April .95 : fixed ( ? ) receiving problems by configuring a RFD more
* than the number of RBD ' s . Can maybe cause other problems .
* 18. April .95 : Added MODULE support ( MH )
* 17. April .95 : MC related changes in init586 ( ) and set_multicast_list ( ) .
* removed use of ' jiffies ' in init586 ( ) ( MH )
*
* 19. Sep .94 : Added Multicast support ( not tested yet ) ( MH )
*
* 18. Sep .94 : Workaround for ' EL - Bug ' . Removed flexible RBD - handling .
* Now , every RFD has exact one RBD . ( MH )
*
* 14. Sep .94 : added promiscuous mode , a few cleanups ( MH )
*
* 19. Aug .94 : changed request_irq ( ) parameter ( MH )
*
* 20. July .94 : removed cleanup bugs , removed a 16 K - mem - probe - bug ( MH )
*
* 19. July .94 : lotsa cleanups . . ( MH )
*
* 17. July .94 : some patches . . . verified to run with 1.1 .29 ( MH )
*
* 4. July .94 : patches for Linux 1.1 .24 ( MH )
*
* 26. March .94 : patches for Linux 1.0 and iomem - auto - probe ( MH )
*
2008-02-08 18:27:38 +03:00
* 30. Sep .93 : Added nop - chain . . driver now runs with only one Xmit - Buff ,
* too ( MH )
2005-04-17 02:20:36 +04:00
*
* < 30. Sep .93 : first versions
*/
static int debuglevel ; /* debug-printk 0: off 1: a few 2: more */
static int automatic_resume ; /* experimental .. better should be zero */
static int rfdadd ; /* rfdadd=1 may be better for 8K MEM cards */
2008-02-08 18:27:38 +03:00
static int fifo = 0x8 ; /* don't change */
2005-04-17 02:20:36 +04:00
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/string.h>
# include <linux/errno.h>
# include <linux/ioport.h>
# include <linux/interrupt.h>
# include <linux/delay.h>
# include <linux/init.h>
# include <linux/bitops.h>
# include <asm/io.h>
# include <linux/netdevice.h>
# include <linux/etherdevice.h>
# include <linux/skbuff.h>
# include "ni52.h"
# define DRV_NAME "ni52"
# define DEBUG /* debug on */
# define SYSBUSVAL 1 /* 8 Bit */
2008-02-08 18:27:38 +03:00
# define ni_attn586() { outb(0, dev->base_addr + NI52_ATTENTION); }
# define ni_reset586() { outb(0, dev->base_addr + NI52_RESET); }
# define ni_disint() { outb(0, dev->base_addr + NI52_INTDIS); }
# define ni_enaint() { outb(0, dev->base_addr + NI52_INTENA); }
2005-04-17 02:20:36 +04:00
2008-03-19 12:44:39 +03:00
# define make32(ptr16) ((void __iomem *)(p->memtop + (short) (ptr16)))
2008-03-19 12:43:59 +03:00
# define make24(ptr32) ((char __iomem *)(ptr32)) - p->base
# define make16(ptr32) ((unsigned short) ((char __iomem *)(ptr32)\
- p - > memtop ) )
2005-04-17 02:20:36 +04:00
/******************* how to calculate the buffers *****************************
* IMPORTANT NOTE : if you configure only one NUM_XMIT_BUFFS , the driver works
* - - - - - - - - - - - - - - - in a different ( more stable ? ) mode . Only in this mode it ' s
* possible to configure the driver with ' NO_NOPCOMMANDS '
sizeof ( scp ) = 12 ; sizeof ( scb ) = 16 ; sizeof ( iscp ) = 8 ;
sizeof ( scp ) + sizeof ( iscp ) + sizeof ( scb ) = 36 = INIT
sizeof ( rfd ) = 24 ; sizeof ( rbd ) = 12 ;
sizeof ( tbd ) = 8 ; sizeof ( transmit_cmd ) = 16 ;
sizeof ( nop_cmd ) = 8 ;
* if you don ' t know the driver , better do not change these values : */
# define RECV_BUFF_SIZE 1524 /* slightly oversized */
# define XMIT_BUFF_SIZE 1524 /* slightly oversized */
# define NUM_XMIT_BUFFS 1 /* config for both, 8K and 16K shmem */
# define NUM_RECV_BUFFS_8 4 /* config for 8K shared mem */
# define NUM_RECV_BUFFS_16 9 /* config for 16K shared mem */
# define NO_NOPCOMMANDS /* only possible with NUM_XMIT_BUFFS=1 */
/**************************************************************************/
# define NI52_TOTAL_SIZE 16
# define NI52_ADDR0 0x02
# define NI52_ADDR1 0x07
# define NI52_ADDR2 0x01
2008-02-08 18:27:38 +03:00
static int ni52_probe1 ( struct net_device * dev , int ioaddr ) ;
static irqreturn_t ni52_interrupt ( int irq , void * dev_id ) ;
2005-04-17 02:20:36 +04:00
static int ni52_open ( struct net_device * dev ) ;
static int ni52_close ( struct net_device * dev ) ;
2009-08-31 23:50:58 +04:00
static netdev_tx_t ni52_send_packet ( struct sk_buff * , struct net_device * ) ;
2005-04-17 02:20:36 +04:00
static struct net_device_stats * ni52_get_stats ( struct net_device * dev ) ;
static void set_multicast_list ( struct net_device * dev ) ;
static void ni52_timeout ( struct net_device * dev ) ;
/* helper-functions */
static int init586 ( struct net_device * dev ) ;
2008-03-19 12:43:49 +03:00
static int check586 ( struct net_device * dev , unsigned size ) ;
2005-04-17 02:20:36 +04:00
static void alloc586 ( struct net_device * dev ) ;
static void startrecv586 ( struct net_device * dev ) ;
2008-03-19 12:43:29 +03:00
static void __iomem * alloc_rfa ( struct net_device * dev , void __iomem * ptr ) ;
2005-04-17 02:20:36 +04:00
static void ni52_rcv_int ( struct net_device * dev ) ;
static void ni52_xmt_int ( struct net_device * dev ) ;
static void ni52_rnr_int ( struct net_device * dev ) ;
2008-02-08 18:27:38 +03:00
struct priv {
2008-03-19 12:43:59 +03:00
char __iomem * base ;
char __iomem * mapped ;
2008-03-19 12:43:29 +03:00
char __iomem * memtop ;
2008-02-08 18:27:38 +03:00
spinlock_t spinlock ;
int reset ;
2008-03-19 12:43:29 +03:00
struct rfd_struct __iomem * rfd_last , * rfd_top , * rfd_first ;
struct scp_struct __iomem * scp ;
struct iscp_struct __iomem * iscp ;
struct scb_struct __iomem * scb ;
struct tbd_struct __iomem * xmit_buffs [ NUM_XMIT_BUFFS ] ;
2005-04-17 02:20:36 +04:00
# if (NUM_XMIT_BUFFS == 1)
2008-03-19 12:43:29 +03:00
struct transmit_cmd_struct __iomem * xmit_cmds [ 2 ] ;
struct nop_cmd_struct __iomem * nop_cmds [ 2 ] ;
2005-04-17 02:20:36 +04:00
# else
2008-03-19 12:43:29 +03:00
struct transmit_cmd_struct __iomem * xmit_cmds [ NUM_XMIT_BUFFS ] ;
struct nop_cmd_struct __iomem * nop_cmds [ NUM_XMIT_BUFFS ] ;
2005-04-17 02:20:36 +04:00
# endif
2008-02-08 18:27:38 +03:00
int nop_point , num_recv_buffs ;
2008-03-19 12:43:29 +03:00
char __iomem * xmit_cbuffs [ NUM_XMIT_BUFFS ] ;
2008-02-08 18:27:38 +03:00
int xmit_count , xmit_last ;
2005-04-17 02:20:36 +04:00
} ;
2008-02-08 18:27:38 +03:00
/* wait for command with timeout: */
static void wait_for_scb_cmd ( struct net_device * dev )
{
2008-11-13 10:38:14 +03:00
struct priv * p = netdev_priv ( dev ) ;
2008-02-08 18:27:38 +03:00
int i ;
for ( i = 0 ; i < 16384 ; i + + ) {
if ( readb ( & p - > scb - > cmd_cuc ) = = 0 )
break ;
udelay ( 4 ) ;
if ( i = = 16383 ) {
printk ( KERN_ERR " %s: scb_cmd timed out: %04x,%04x .. disabling i82586!! \n " ,
dev - > name , readb ( & p - > scb - > cmd_cuc ) , readb ( & p - > scb - > cus ) ) ;
if ( ! p - > reset ) {
p - > reset = 1 ;
ni_reset586 ( ) ;
}
}
}
}
static void wait_for_scb_cmd_ruc ( struct net_device * dev )
{
2008-11-13 10:38:14 +03:00
struct priv * p = netdev_priv ( dev ) ;
2008-02-08 18:27:38 +03:00
int i ;
for ( i = 0 ; i < 16384 ; i + + ) {
if ( readb ( & p - > scb - > cmd_ruc ) = = 0 )
break ;
udelay ( 4 ) ;
if ( i = = 16383 ) {
printk ( KERN_ERR " %s: scb_cmd (ruc) timed out: %04x,%04x .. disabling i82586!! \n " ,
2008-03-19 12:44:39 +03:00
dev - > name , readb ( & p - > scb - > cmd_ruc ) ,
readb ( & p - > scb - > rus ) ) ;
2008-02-08 18:27:38 +03:00
if ( ! p - > reset ) {
p - > reset = 1 ;
ni_reset586 ( ) ;
}
}
}
}
2008-03-19 12:43:29 +03:00
static void wait_for_stat_compl ( void __iomem * p )
2008-02-08 18:27:38 +03:00
{
2008-03-19 12:43:29 +03:00
struct nop_cmd_struct __iomem * addr = p ;
2008-02-08 18:27:38 +03:00
int i ;
for ( i = 0 ; i < 32767 ; i + + ) {
if ( readw ( & ( ( addr ) - > cmd_status ) ) & STAT_COMPL )
break ;
udelay ( 32 ) ;
}
}
2005-04-17 02:20:36 +04:00
/**********************************************
* close device
*/
static int ni52_close ( struct net_device * dev )
{
free_irq ( dev - > irq , dev ) ;
ni_reset586 ( ) ; /* the hard way to stop the receiver */
netif_stop_queue ( dev ) ;
return 0 ;
}
/**********************************************
* open device
*/
static int ni52_open ( struct net_device * dev )
{
int ret ;
ni_disint ( ) ;
alloc586 ( dev ) ;
init586 ( dev ) ;
startrecv586 ( dev ) ;
ni_enaint ( ) ;
2009-11-19 10:29:17 +03:00
ret = request_irq ( dev - > irq , ni52_interrupt , 0 , dev - > name , dev ) ;
2008-02-08 18:27:38 +03:00
if ( ret ) {
2005-04-17 02:20:36 +04:00
ni_reset586 ( ) ;
return ret ;
}
netif_start_queue ( dev ) ;
return 0 ; /* most done by init */
}
2008-03-19 12:44:19 +03:00
static int check_iscp ( struct net_device * dev , void __iomem * addr )
{
struct iscp_struct __iomem * iscp = addr ;
2008-11-13 10:38:14 +03:00
struct priv * p = netdev_priv ( dev ) ;
2008-03-19 12:44:19 +03:00
memset_io ( iscp , 0 , sizeof ( struct iscp_struct ) ) ;
writel ( make24 ( iscp ) , & p - > scp - > iscp ) ;
writeb ( 1 , & iscp - > busy ) ;
ni_reset586 ( ) ;
ni_attn586 ( ) ;
mdelay ( 32 ) ; /* wait a while... */
/* i82586 clears 'busy' after successful init */
if ( readb ( & iscp - > busy ) )
return 0 ;
return 1 ;
}
2005-04-17 02:20:36 +04:00
/**********************************************
* Check to see if there ' s an 82586 out there .
*/
2008-03-19 12:43:49 +03:00
static int check586 ( struct net_device * dev , unsigned size )
2005-04-17 02:20:36 +04:00
{
2008-11-13 10:38:14 +03:00
struct priv * p = netdev_priv ( dev ) ;
2005-04-17 02:20:36 +04:00
int i ;
2008-03-19 12:44:29 +03:00
p - > mapped = ioremap ( dev - > mem_start , size ) ;
if ( ! p - > mapped )
return 0 ;
2008-03-19 12:43:59 +03:00
p - > base = p - > mapped + size - 0x01000000 ;
p - > memtop = p - > mapped + size ;
2008-03-19 12:43:29 +03:00
p - > scp = ( struct scp_struct __iomem * ) ( p - > base + SCP_DEFAULT_ADDRESS ) ;
2008-03-19 12:44:09 +03:00
p - > scb = ( struct scb_struct __iomem * ) p - > mapped ;
2008-03-19 12:44:19 +03:00
p - > iscp = ( struct iscp_struct __iomem * ) p - > scp - 1 ;
2008-03-19 12:43:29 +03:00
memset_io ( p - > scp , 0 , sizeof ( struct scp_struct ) ) ;
2008-02-08 18:27:38 +03:00
for ( i = 0 ; i < sizeof ( struct scp_struct ) ; i + + )
/* memory was writeable? */
2008-03-19 12:43:29 +03:00
if ( readb ( ( char __iomem * ) p - > scp + i ) )
2008-03-19 12:44:29 +03:00
goto Enodev ;
2008-02-08 18:27:38 +03:00
writeb ( SYSBUSVAL , & p - > scp - > sysbus ) ; /* 1 = 8Bit-Bus, 0 = 16 Bit */
if ( readb ( & p - > scp - > sysbus ) ! = SYSBUSVAL )
2008-03-19 12:44:29 +03:00
goto Enodev ;
2005-04-17 02:20:36 +04:00
2008-03-19 12:44:19 +03:00
if ( ! check_iscp ( dev , p - > mapped ) )
2008-03-19 12:44:29 +03:00
goto Enodev ;
2008-03-19 12:44:19 +03:00
if ( ! check_iscp ( dev , p - > iscp ) )
2008-03-19 12:44:29 +03:00
goto Enodev ;
2005-04-17 02:20:36 +04:00
return 1 ;
2008-03-19 12:44:29 +03:00
Enodev :
iounmap ( p - > mapped ) ;
return 0 ;
2005-04-17 02:20:36 +04:00
}
/******************************************************************
* set iscp at the right place , called by ni52_probe1 and open586 .
*/
static void alloc586 ( struct net_device * dev )
{
2008-11-13 10:38:14 +03:00
struct priv * p = netdev_priv ( dev ) ;
2005-04-17 02:20:36 +04:00
ni_reset586 ( ) ;
2008-02-08 18:27:38 +03:00
mdelay ( 32 ) ;
memset_io ( p - > iscp , 0 , sizeof ( struct iscp_struct ) ) ;
memset_io ( p - > scp , 0 , sizeof ( struct scp_struct ) ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
writel ( make24 ( p - > iscp ) , & p - > scp - > iscp ) ;
writeb ( SYSBUSVAL , & p - > scp - > sysbus ) ;
writew ( make16 ( p - > scb ) , & p - > iscp - > scb_offset ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
writeb ( 1 , & p - > iscp - > busy ) ;
2005-04-17 02:20:36 +04:00
ni_reset586 ( ) ;
ni_attn586 ( ) ;
2008-02-08 18:27:38 +03:00
mdelay ( 32 ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
if ( readb ( & p - > iscp - > busy ) )
printk ( KERN_ERR " %s: Init-Problems (alloc). \n " , dev - > name ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
p - > reset = 0 ;
2005-04-17 02:20:36 +04:00
2008-03-19 12:43:29 +03:00
memset_io ( p - > scb , 0 , sizeof ( struct scb_struct ) ) ;
2005-04-17 02:20:36 +04:00
}
/* set: io,irq,memstart,memend or set it when calling insmod */
2008-02-08 18:27:38 +03:00
static int irq = 9 ;
static int io = 0x300 ;
2005-04-17 02:20:36 +04:00
static long memstart ; /* e.g 0xd0000 */
static long memend ; /* e.g 0xd4000 */
/**********************************************
* probe the ni5210 - card
*/
struct net_device * __init ni52_probe ( int unit )
{
struct net_device * dev = alloc_etherdev ( sizeof ( struct priv ) ) ;
2010-12-21 13:16:08 +03:00
static const int ports [ ] = { 0x300 , 0x280 , 0x360 , 0x320 , 0x340 , 0 } ;
const int * port ;
2008-03-19 12:44:29 +03:00
struct priv * p ;
2005-04-17 02:20:36 +04:00
int err = 0 ;
if ( ! dev )
return ERR_PTR ( - ENOMEM ) ;
2008-11-13 10:38:14 +03:00
p = netdev_priv ( dev ) ;
2008-03-19 12:44:29 +03:00
2005-04-17 02:20:36 +04:00
if ( unit > = 0 ) {
sprintf ( dev - > name , " eth%d " , unit ) ;
netdev_boot_setup_check ( dev ) ;
io = dev - > base_addr ;
irq = dev - > irq ;
memstart = dev - > mem_start ;
memend = dev - > mem_end ;
}
if ( io > 0x1ff ) { /* Check a single specified location. */
err = ni52_probe1 ( dev , io ) ;
} else if ( io > 0 ) { /* Don't probe at all. */
err = - ENXIO ;
} else {
for ( port = ports ; * port & & ni52_probe1 ( dev , * port ) ; port + + )
;
if ( * port )
goto got_it ;
# ifdef FULL_IO_PROBE
for ( io = 0x200 ; io < 0x400 & & ni52_probe1 ( dev , io ) ; io + = 8 )
;
if ( io < 0x400 )
goto got_it ;
# endif
err = - ENODEV ;
}
if ( err )
goto out ;
got_it :
err = register_netdev ( dev ) ;
if ( err )
goto out1 ;
return dev ;
out1 :
2008-03-19 12:44:29 +03:00
iounmap ( p - > mapped ) ;
2005-04-17 02:20:36 +04:00
release_region ( dev - > base_addr , NI52_TOTAL_SIZE ) ;
out :
free_netdev ( dev ) ;
return ERR_PTR ( err ) ;
}
2009-03-26 18:11:39 +03:00
static const struct net_device_ops ni52_netdev_ops = {
. ndo_open = ni52_open ,
. ndo_stop = ni52_close ,
. ndo_get_stats = ni52_get_stats ,
. ndo_tx_timeout = ni52_timeout ,
. ndo_start_xmit = ni52_send_packet ,
. ndo_set_multicast_list = set_multicast_list ,
. ndo_change_mtu = eth_change_mtu ,
. ndo_set_mac_address = eth_mac_addr ,
. ndo_validate_addr = eth_validate_addr ,
} ;
2008-02-08 18:27:38 +03:00
static int __init ni52_probe1 ( struct net_device * dev , int ioaddr )
2005-04-17 02:20:36 +04:00
{
int i , size , retval ;
2008-11-13 10:38:14 +03:00
struct priv * priv = netdev_priv ( dev ) ;
2005-04-17 02:20:36 +04:00
dev - > base_addr = ioaddr ;
dev - > irq = irq ;
dev - > mem_start = memstart ;
dev - > mem_end = memend ;
2008-03-19 12:44:09 +03:00
spin_lock_init ( & priv - > spinlock ) ;
2005-04-17 02:20:36 +04:00
if ( ! request_region ( ioaddr , NI52_TOTAL_SIZE , DRV_NAME ) )
return - EBUSY ;
2008-02-08 18:27:38 +03:00
if ( ! ( inb ( ioaddr + NI52_MAGIC1 ) = = NI52_MAGICVAL1 ) | |
2005-04-17 02:20:36 +04:00
! ( inb ( ioaddr + NI52_MAGIC2 ) = = NI52_MAGICVAL2 ) ) {
retval = - ENODEV ;
goto out ;
}
2008-02-08 18:27:38 +03:00
for ( i = 0 ; i < ETH_ALEN ; i + + )
2005-04-17 02:20:36 +04:00
dev - > dev_addr [ i ] = inb ( dev - > base_addr + i ) ;
2009-12-03 10:58:21 +03:00
if ( dev - > dev_addr [ 0 ] ! = NI52_ADDR0 | | dev - > dev_addr [ 1 ] ! = NI52_ADDR1 | |
dev - > dev_addr [ 2 ] ! = NI52_ADDR2 ) {
2005-04-17 02:20:36 +04:00
retval = - ENODEV ;
goto out ;
}
2008-02-08 18:27:38 +03:00
printk ( KERN_INFO " %s: NI5210 found at %#3lx, " ,
dev - > name , dev - > base_addr ) ;
2005-04-17 02:20:36 +04:00
/*
* check ( or search ) IO - Memory , 8 K and 16 K
*/
# ifdef MODULE
size = dev - > mem_end - dev - > mem_start ;
2008-02-08 18:27:38 +03:00
if ( size ! = 0x2000 & & size ! = 0x4000 ) {
printk ( " \n " ) ;
printk ( KERN_ERR " %s: Invalid memory size %d. Allowed is 0x2000 or 0x4000 bytes. \n " , dev - > name , size ) ;
2005-04-17 02:20:36 +04:00
retval = - ENODEV ;
goto out ;
}
2008-03-19 12:43:49 +03:00
if ( ! check586 ( dev , size ) ) {
2008-02-08 18:27:38 +03:00
printk ( KERN_ERR " ?memcheck, Can't find memory at 0x%lx with size %d! \n " , dev - > mem_start , size ) ;
2005-04-17 02:20:36 +04:00
retval = - ENODEV ;
goto out ;
}
# else
2008-02-08 18:27:38 +03:00
if ( dev - > mem_start ! = 0 ) {
/* no auto-mem-probe */
2005-04-17 02:20:36 +04:00
size = 0x4000 ; /* check for 16K mem */
2008-03-19 12:43:49 +03:00
if ( ! check586 ( dev , size ) ) {
2005-04-17 02:20:36 +04:00
size = 0x2000 ; /* check for 8K mem */
2008-03-19 12:43:49 +03:00
if ( ! check586 ( dev , size ) ) {
2008-02-08 18:27:38 +03:00
printk ( KERN_ERR " ?memprobe, Can't find memory at 0x%lx! \n " , dev - > mem_start ) ;
2005-04-17 02:20:36 +04:00
retval = - ENODEV ;
goto out ;
}
}
2008-02-08 18:27:38 +03:00
} else {
static const unsigned long memaddrs [ ] = {
0xc8000 , 0xca000 , 0xcc000 , 0xce000 , 0xd0000 , 0xd2000 ,
0xd4000 , 0xd6000 , 0xd8000 , 0xda000 , 0xdc000 , 0
} ;
for ( i = 0 ; ; i + + ) {
if ( ! memaddrs [ i ] ) {
printk ( KERN_ERR " ?memprobe, Can't find io-memory! \n " ) ;
2005-04-17 02:20:36 +04:00
retval = - ENODEV ;
goto out ;
}
dev - > mem_start = memaddrs [ i ] ;
size = 0x2000 ; /* check for 8K mem */
2008-03-19 12:43:49 +03:00
if ( check586 ( dev , size ) )
2008-02-08 18:27:38 +03:00
/* 8K-check */
2005-04-17 02:20:36 +04:00
break ;
size = 0x4000 ; /* check for 16K mem */
2008-03-19 12:43:49 +03:00
if ( check586 ( dev , size ) )
2008-02-08 18:27:38 +03:00
/* 16K-check */
2005-04-17 02:20:36 +04:00
break ;
}
}
2008-02-08 18:27:38 +03:00
/* set mem_end showed by 'ifconfig' */
dev - > mem_end = dev - > mem_start + size ;
2005-04-17 02:20:36 +04:00
# endif
alloc586 ( dev ) ;
/* set number of receive-buffs according to memsize */
2008-02-08 18:27:38 +03:00
if ( size = = 0x2000 )
2008-03-19 12:43:59 +03:00
priv - > num_recv_buffs = NUM_RECV_BUFFS_8 ;
2005-04-17 02:20:36 +04:00
else
2008-03-19 12:43:59 +03:00
priv - > num_recv_buffs = NUM_RECV_BUFFS_16 ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
printk ( KERN_DEBUG " Memaddr: 0x%lx, Memsize: %d, " ,
dev - > mem_start , size ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
if ( dev - > irq < 2 ) {
2005-04-17 02:20:36 +04:00
unsigned long irq_mask ;
irq_mask = probe_irq_on ( ) ;
ni_reset586 ( ) ;
ni_attn586 ( ) ;
mdelay ( 20 ) ;
dev - > irq = probe_irq_off ( irq_mask ) ;
2008-02-08 18:27:38 +03:00
if ( ! dev - > irq ) {
2005-04-17 02:20:36 +04:00
printk ( " ?autoirq, Failed to detect IRQ line! \n " ) ;
retval = - EAGAIN ;
2008-03-19 12:44:29 +03:00
iounmap ( priv - > mapped ) ;
2005-04-17 02:20:36 +04:00
goto out ;
}
2008-02-08 18:27:38 +03:00
printk ( " IRQ %d (autodetected). \n " , dev - > irq ) ;
} else {
if ( dev - > irq = = 2 )
2005-04-17 02:20:36 +04:00
dev - > irq = 9 ;
2008-02-08 18:27:38 +03:00
printk ( " IRQ %d (assigned and not checked!). \n " , dev - > irq ) ;
2005-04-17 02:20:36 +04:00
}
2009-03-26 18:11:39 +03:00
dev - > netdev_ops = & ni52_netdev_ops ;
2005-04-17 02:20:36 +04:00
dev - > watchdog_timeo = HZ / 20 ;
return 0 ;
out :
release_region ( ioaddr , NI52_TOTAL_SIZE ) ;
return retval ;
}
/**********************************************
* init the chip ( ni52 - interrupt should be disabled ? ! )
* needs a correct ' allocated ' memory
*/
static int init586 ( struct net_device * dev )
{
2008-03-19 12:43:29 +03:00
void __iomem * ptr ;
2008-02-08 18:27:38 +03:00
int i , result = 0 ;
2008-11-13 10:38:14 +03:00
struct priv * p = netdev_priv ( dev ) ;
2008-03-19 12:43:29 +03:00
struct configure_cmd_struct __iomem * cfg_cmd ;
struct iasetup_cmd_struct __iomem * ias_cmd ;
struct tdr_cmd_struct __iomem * tdr_cmd ;
struct mcsetup_cmd_struct __iomem * mc_cmd ;
2010-04-02 01:22:57 +04:00
struct netdev_hw_addr * ha ;
2010-02-08 07:30:35 +03:00
int num_addrs = netdev_mc_count ( dev ) ;
2005-04-17 02:20:36 +04:00
2008-03-19 12:43:29 +03:00
ptr = p - > scb + 1 ;
2005-04-17 02:20:36 +04:00
2008-03-19 12:43:29 +03:00
cfg_cmd = ptr ; /* configure-command */
2008-02-08 18:27:38 +03:00
writew ( 0 , & cfg_cmd - > cmd_status ) ;
writew ( CMD_CONFIGURE | CMD_LAST , & cfg_cmd - > cmd_cmd ) ;
writew ( 0xFFFF , & cfg_cmd - > cmd_link ) ;
/* number of cfg bytes */
writeb ( 0x0a , & cfg_cmd - > byte_cnt ) ;
/* fifo-limit (8=tx:32/rx:64) */
writeb ( fifo , & cfg_cmd - > fifo ) ;
/* hold or discard bad recv frames (bit 7) */
writeb ( 0x40 , & cfg_cmd - > sav_bf ) ;
/* addr_len |!src_insert |pre-len |loopback */
writeb ( 0x2e , & cfg_cmd - > adr_len ) ;
writeb ( 0x00 , & cfg_cmd - > priority ) ;
2009-08-18 22:18:35 +04:00
writeb ( 0x60 , & cfg_cmd - > ifs ) ;
2008-02-08 18:27:38 +03:00
writeb ( 0x00 , & cfg_cmd - > time_low ) ;
writeb ( 0xf2 , & cfg_cmd - > time_high ) ;
2009-08-18 22:18:35 +04:00
writeb ( 0x00 , & cfg_cmd - > promisc ) ;
2008-02-08 18:27:38 +03:00
if ( dev - > flags & IFF_ALLMULTI ) {
2008-03-19 12:43:29 +03:00
int len = ( ( char __iomem * ) p - > iscp - ( char __iomem * ) ptr - 8 ) / 6 ;
2008-02-08 18:27:38 +03:00
if ( num_addrs > len ) {
printk ( KERN_ERR " %s: switching to promisc. mode \n " ,
dev - > name ) ;
2008-07-22 09:13:12 +04:00
writeb ( 0x01 , & cfg_cmd - > promisc ) ;
2005-04-17 02:20:36 +04:00
}
}
2008-02-08 18:27:38 +03:00
if ( dev - > flags & IFF_PROMISC )
writeb ( 0x01 , & cfg_cmd - > promisc ) ;
writeb ( 0x00 , & cfg_cmd - > carr_coll ) ;
writew ( make16 ( cfg_cmd ) , & p - > scb - > cbl_offset ) ;
2008-03-19 12:44:39 +03:00
writeb ( 0 , & p - > scb - > cmd_ruc ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
writeb ( CUC_START , & p - > scb - > cmd_cuc ) ; /* cmd.-unit start */
2005-04-17 02:20:36 +04:00
ni_attn586 ( ) ;
2008-02-08 18:27:38 +03:00
wait_for_stat_compl ( cfg_cmd ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
if ( ( readw ( & cfg_cmd - > cmd_status ) & ( STAT_OK | STAT_COMPL ) ) ! =
( STAT_COMPL | STAT_OK ) ) {
printk ( KERN_ERR " %s: configure command failed: %x \n " ,
dev - > name , readw ( & cfg_cmd - > cmd_status ) ) ;
2005-04-17 02:20:36 +04:00
return 1 ;
}
/*
* individual address setup
*/
2008-03-19 12:43:29 +03:00
ias_cmd = ptr ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
writew ( 0 , & ias_cmd - > cmd_status ) ;
writew ( CMD_IASETUP | CMD_LAST , & ias_cmd - > cmd_cmd ) ;
writew ( 0xffff , & ias_cmd - > cmd_link ) ;
2005-04-17 02:20:36 +04:00
2008-03-19 12:43:29 +03:00
memcpy_toio ( & ias_cmd - > iaddr , ( char * ) dev - > dev_addr , ETH_ALEN ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
writew ( make16 ( ias_cmd ) , & p - > scb - > cbl_offset ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
writeb ( CUC_START , & p - > scb - > cmd_cuc ) ; /* cmd.-unit start */
2005-04-17 02:20:36 +04:00
ni_attn586 ( ) ;
2008-02-08 18:27:38 +03:00
wait_for_stat_compl ( ias_cmd ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
if ( ( readw ( & ias_cmd - > cmd_status ) & ( STAT_OK | STAT_COMPL ) ) ! =
( STAT_OK | STAT_COMPL ) ) {
printk ( KERN_ERR " %s (ni52): individual address setup command failed: %04x \n " , dev - > name , readw ( & ias_cmd - > cmd_status ) ) ;
2005-04-17 02:20:36 +04:00
return 1 ;
}
/*
* TDR , wire check . . e . g . no resistor e . t . c
*/
2006-09-13 21:24:59 +04:00
2008-03-19 12:43:29 +03:00
tdr_cmd = ptr ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
writew ( 0 , & tdr_cmd - > cmd_status ) ;
writew ( CMD_TDR | CMD_LAST , & tdr_cmd - > cmd_cmd ) ;
writew ( 0xffff , & tdr_cmd - > cmd_link ) ;
writew ( 0 , & tdr_cmd - > status ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
writew ( make16 ( tdr_cmd ) , & p - > scb - > cbl_offset ) ;
writeb ( CUC_START , & p - > scb - > cmd_cuc ) ; /* cmd.-unit start */
2005-04-17 02:20:36 +04:00
ni_attn586 ( ) ;
2008-02-08 18:27:38 +03:00
wait_for_stat_compl ( tdr_cmd ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
if ( ! ( readw ( & tdr_cmd - > cmd_status ) & STAT_COMPL ) )
printk ( KERN_ERR " %s: Problems while running the TDR. \n " ,
dev - > name ) ;
else {
udelay ( 16 ) ;
result = readw ( & tdr_cmd - > status ) ;
writeb ( readb ( & p - > scb - > cus ) & STAT_MASK , & p - > scb - > cmd_cuc ) ;
2005-04-17 02:20:36 +04:00
ni_attn586 ( ) ; /* ack the interrupts */
2008-02-08 18:27:38 +03:00
if ( result & TDR_LNK_OK )
2005-04-17 02:20:36 +04:00
;
2008-02-08 18:27:38 +03:00
else if ( result & TDR_XCVR_PRB )
printk ( KERN_ERR " %s: TDR: Transceiver problem. Check the cable(s)! \n " ,
dev - > name ) ;
else if ( result & TDR_ET_OPN )
printk ( KERN_ERR " %s: TDR: No correct termination %d clocks away. \n " ,
dev - > name , result & TDR_TIMEMASK ) ;
else if ( result & TDR_ET_SRT ) {
/* time == 0 -> strange :-) */
if ( result & TDR_TIMEMASK )
printk ( KERN_ERR " %s: TDR: Detected a short circuit %d clocks away. \n " ,
dev - > name , result & TDR_TIMEMASK ) ;
} else
printk ( KERN_ERR " %s: TDR: Unknown status %04x \n " ,
dev - > name , result ) ;
2005-04-17 02:20:36 +04:00
}
/*
* Multicast setup
*/
2008-02-08 18:27:38 +03:00
if ( num_addrs & & ! ( dev - > flags & IFF_PROMISC ) ) {
2008-03-19 12:43:29 +03:00
mc_cmd = ptr ;
2008-02-08 18:27:38 +03:00
writew ( 0 , & mc_cmd - > cmd_status ) ;
writew ( CMD_MCSETUP | CMD_LAST , & mc_cmd - > cmd_cmd ) ;
writew ( 0xffff , & mc_cmd - > cmd_link ) ;
writew ( num_addrs * 6 , & mc_cmd - > mc_cnt ) ;
2005-04-17 02:20:36 +04:00
2010-02-23 12:19:49 +03:00
i = 0 ;
2010-04-02 01:22:57 +04:00
netdev_for_each_mc_addr ( ha , dev )
memcpy_toio ( mc_cmd - > mc_list [ i + + ] , ha - > addr , 6 ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
writew ( make16 ( mc_cmd ) , & p - > scb - > cbl_offset ) ;
writeb ( CUC_START , & p - > scb - > cmd_cuc ) ;
2005-04-17 02:20:36 +04:00
ni_attn586 ( ) ;
2008-02-08 18:27:38 +03:00
wait_for_stat_compl ( mc_cmd ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
if ( ( readw ( & mc_cmd - > cmd_status ) & ( STAT_COMPL | STAT_OK ) )
! = ( STAT_COMPL | STAT_OK ) )
printk ( KERN_ERR " %s: Can't apply multicast-address-list. \n " , dev - > name ) ;
2005-04-17 02:20:36 +04:00
}
/*
* alloc nop / xmit - cmds
*/
# if (NUM_XMIT_BUFFS == 1)
2008-02-08 18:27:38 +03:00
for ( i = 0 ; i < 2 ; i + + ) {
2008-03-19 12:43:29 +03:00
p - > nop_cmds [ i ] = ptr ;
2008-02-08 18:27:38 +03:00
writew ( CMD_NOP , & p - > nop_cmds [ i ] - > cmd_cmd ) ;
writew ( 0 , & p - > nop_cmds [ i ] - > cmd_status ) ;
writew ( make16 ( p - > nop_cmds [ i ] ) , & p - > nop_cmds [ i ] - > cmd_link ) ;
2008-03-19 12:43:29 +03:00
ptr = ptr + sizeof ( struct nop_cmd_struct ) ;
2005-04-17 02:20:36 +04:00
}
# else
2008-02-08 18:27:38 +03:00
for ( i = 0 ; i < NUM_XMIT_BUFFS ; i + + ) {
2008-03-19 12:43:29 +03:00
p - > nop_cmds [ i ] = ptr ;
2008-02-08 18:27:38 +03:00
writew ( CMD_NOP , & p - > nop_cmds [ i ] - > cmd_cmd ) ;
writew ( 0 , & p - > nop_cmds [ i ] - > cmd_status ) ;
writew ( make16 ( p - > nop_cmds [ i ] ) , & p - > nop_cmds [ i ] - > cmd_link ) ;
2008-03-19 12:43:29 +03:00
ptr = ptr + sizeof ( struct nop_cmd_struct ) ;
2005-04-17 02:20:36 +04:00
}
# endif
2008-03-19 12:43:29 +03:00
ptr = alloc_rfa ( dev , ptr ) ; /* init receive-frame-area */
2005-04-17 02:20:36 +04:00
/*
* alloc xmit - buffs / init xmit_cmds
*/
2008-02-08 18:27:38 +03:00
for ( i = 0 ; i < NUM_XMIT_BUFFS ; i + + ) {
/* Transmit cmd/buff 0 */
2008-03-19 12:43:29 +03:00
p - > xmit_cmds [ i ] = ptr ;
ptr = ptr + sizeof ( struct transmit_cmd_struct ) ;
p - > xmit_cbuffs [ i ] = ptr ; /* char-buffs */
ptr = ptr + XMIT_BUFF_SIZE ;
p - > xmit_buffs [ i ] = ptr ; /* TBD */
ptr = ptr + sizeof ( struct tbd_struct ) ;
if ( ( void __iomem * ) ptr > ( void __iomem * ) p - > iscp ) {
2008-02-08 18:27:38 +03:00
printk ( KERN_ERR " %s: not enough shared-mem for your configuration! \n " ,
dev - > name ) ;
2005-04-17 02:20:36 +04:00
return 1 ;
}
2008-03-19 12:43:29 +03:00
memset_io ( p - > xmit_cmds [ i ] , 0 ,
2008-02-08 18:27:38 +03:00
sizeof ( struct transmit_cmd_struct ) ) ;
2008-03-19 12:43:29 +03:00
memset_io ( p - > xmit_buffs [ i ] , 0 ,
2008-02-08 18:27:38 +03:00
sizeof ( struct tbd_struct ) ) ;
writew ( make16 ( p - > nop_cmds [ ( i + 1 ) % NUM_XMIT_BUFFS ] ) ,
& p - > xmit_cmds [ i ] - > cmd_link ) ;
writew ( STAT_COMPL , & p - > xmit_cmds [ i ] - > cmd_status ) ;
writew ( CMD_XMIT | CMD_INT , & p - > xmit_cmds [ i ] - > cmd_cmd ) ;
writew ( make16 ( p - > xmit_buffs [ i ] ) , & p - > xmit_cmds [ i ] - > tbd_offset ) ;
writew ( 0xffff , & p - > xmit_buffs [ i ] - > next ) ;
writel ( make24 ( p - > xmit_cbuffs [ i ] ) , & p - > xmit_buffs [ i ] - > buffer ) ;
2005-04-17 02:20:36 +04:00
}
p - > xmit_count = 0 ;
p - > xmit_last = 0 ;
# ifndef NO_NOPCOMMANDS
p - > nop_point = 0 ;
# endif
/*
* ' start transmitter '
*/
# ifndef NO_NOPCOMMANDS
2008-02-08 18:27:38 +03:00
writew ( make16 ( p - > nop_cmds [ 0 ] ) , & p - > scb - > cbl_offset ) ;
writeb ( CUC_START , & p - > scb - > cmd_cuc ) ;
2005-04-17 02:20:36 +04:00
ni_attn586 ( ) ;
2008-02-08 18:27:38 +03:00
wait_for_scb_cmd ( dev ) ;
2005-04-17 02:20:36 +04:00
# else
2008-02-08 18:27:38 +03:00
writew ( make16 ( p - > xmit_cmds [ 0 ] ) , & p - > xmit_cmds [ 0 ] - > cmd_link ) ;
writew ( CMD_XMIT | CMD_SUSPEND | CMD_INT , & p - > xmit_cmds [ 0 ] - > cmd_cmd ) ;
2005-04-17 02:20:36 +04:00
# endif
/*
* ack . interrupts
*/
2008-02-08 18:27:38 +03:00
writeb ( readb ( & p - > scb - > cus ) & STAT_MASK , & p - > scb - > cmd_cuc ) ;
2005-04-17 02:20:36 +04:00
ni_attn586 ( ) ;
2008-02-08 18:27:38 +03:00
udelay ( 16 ) ;
2005-04-17 02:20:36 +04:00
ni_enaint ( ) ;
return 0 ;
}
/******************************************************
* This is a helper routine for ni52_rnr_int ( ) and init586 ( ) .
* It sets up the Receive Frame Area ( RFA ) .
*/
2008-03-19 12:43:29 +03:00
static void __iomem * alloc_rfa ( struct net_device * dev , void __iomem * ptr )
2005-04-17 02:20:36 +04:00
{
2008-03-19 12:43:29 +03:00
struct rfd_struct __iomem * rfd = ptr ;
struct rbd_struct __iomem * rbd ;
2005-04-17 02:20:36 +04:00
int i ;
2008-11-13 10:38:14 +03:00
struct priv * p = netdev_priv ( dev ) ;
2005-04-17 02:20:36 +04:00
2008-03-19 12:43:29 +03:00
memset_io ( rfd , 0 ,
2008-02-08 18:27:38 +03:00
sizeof ( struct rfd_struct ) * ( p - > num_recv_buffs + rfdadd ) ) ;
2005-04-17 02:20:36 +04:00
p - > rfd_first = rfd ;
2008-02-08 18:27:38 +03:00
for ( i = 0 ; i < ( p - > num_recv_buffs + rfdadd ) ; i + + ) {
writew ( make16 ( rfd + ( i + 1 ) % ( p - > num_recv_buffs + rfdadd ) ) ,
& rfd [ i ] . next ) ;
writew ( 0xffff , & rfd [ i ] . rbd_offset ) ;
2005-04-17 02:20:36 +04:00
}
2008-02-08 18:27:38 +03:00
/* RU suspend */
writeb ( RFD_SUSP , & rfd [ p - > num_recv_buffs - 1 + rfdadd ] . last ) ;
2005-04-17 02:20:36 +04:00
2008-03-19 12:43:29 +03:00
ptr = rfd + ( p - > num_recv_buffs + rfdadd ) ;
2005-04-17 02:20:36 +04:00
2008-03-19 12:43:29 +03:00
rbd = ptr ;
ptr = rbd + p - > num_recv_buffs ;
2005-04-17 02:20:36 +04:00
/* clr descriptors */
2008-03-19 12:43:29 +03:00
memset_io ( rbd , 0 , sizeof ( struct rbd_struct ) * ( p - > num_recv_buffs ) ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
for ( i = 0 ; i < p - > num_recv_buffs ; i + + ) {
writew ( make16 ( rbd + ( i + 1 ) % p - > num_recv_buffs ) , & rbd [ i ] . next ) ;
writew ( RECV_BUFF_SIZE , & rbd [ i ] . size ) ;
writel ( make24 ( ptr ) , & rbd [ i ] . buffer ) ;
2008-03-19 12:43:29 +03:00
ptr = ptr + RECV_BUFF_SIZE ;
2005-04-17 02:20:36 +04:00
}
p - > rfd_top = p - > rfd_first ;
p - > rfd_last = p - > rfd_first + ( p - > num_recv_buffs - 1 + rfdadd ) ;
2008-02-08 18:27:38 +03:00
writew ( make16 ( p - > rfd_first ) , & p - > scb - > rfa_offset ) ;
writew ( make16 ( rbd ) , & p - > rfd_first - > rbd_offset ) ;
2005-04-17 02:20:36 +04:00
return ptr ;
}
/**************************************************
* Interrupt Handler . . .
*/
2008-02-08 18:27:38 +03:00
static irqreturn_t ni52_interrupt ( int irq , void * dev_id )
2005-04-17 02:20:36 +04:00
{
struct net_device * dev = dev_id ;
2008-02-08 18:27:38 +03:00
unsigned int stat ;
int cnt = 0 ;
2005-04-17 02:20:36 +04:00
struct priv * p ;
2008-11-13 10:38:14 +03:00
p = netdev_priv ( dev ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
if ( debuglevel > 1 )
2005-04-17 02:20:36 +04:00
printk ( " I " ) ;
2008-02-08 18:27:38 +03:00
spin_lock ( & p - > spinlock ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
wait_for_scb_cmd ( dev ) ; /* wait for last command */
while ( ( stat = readb ( & p - > scb - > cus ) & STAT_MASK ) ) {
writeb ( stat , & p - > scb - > cmd_cuc ) ;
2005-04-17 02:20:36 +04:00
ni_attn586 ( ) ;
2008-02-08 18:27:38 +03:00
if ( stat & STAT_FR ) /* received a frame */
2005-04-17 02:20:36 +04:00
ni52_rcv_int ( dev ) ;
2008-02-08 18:27:38 +03:00
if ( stat & STAT_RNR ) { /* RU went 'not ready' */
2005-04-17 02:20:36 +04:00
printk ( " (R) " ) ;
2008-02-08 18:27:38 +03:00
if ( readb ( & p - > scb - > rus ) & RU_SUSPEND ) {
/* special case: RU_SUSPEND */
wait_for_scb_cmd ( dev ) ;
2008-03-19 12:44:39 +03:00
writeb ( RUC_RESUME , & p - > scb - > cmd_ruc ) ;
2005-04-17 02:20:36 +04:00
ni_attn586 ( ) ;
2008-02-08 18:27:38 +03:00
wait_for_scb_cmd_ruc ( dev ) ;
} else {
printk ( KERN_ERR " %s: Receiver-Unit went 'NOT READY': %04x/%02x. \n " ,
dev - > name , stat , readb ( & p - > scb - > rus ) ) ;
2005-04-17 02:20:36 +04:00
ni52_rnr_int ( dev ) ;
}
}
2008-02-08 18:27:38 +03:00
/* Command with I-bit set complete */
if ( stat & STAT_CX )
2005-04-17 02:20:36 +04:00
ni52_xmt_int ( dev ) ;
# ifndef NO_NOPCOMMANDS
2008-02-08 18:27:38 +03:00
if ( stat & STAT_CNA ) { /* CU went 'not ready' */
if ( netif_running ( dev ) )
printk ( KERN_ERR " %s: oops! CU has left active state. stat: %04x/%02x. \n " ,
dev - > name , stat , readb ( & p - > scb - > cus ) ) ;
2005-04-17 02:20:36 +04:00
}
# endif
2008-02-08 18:27:38 +03:00
if ( debuglevel > 1 )
printk ( " %d " , cnt + + ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
/* Wait for ack. (ni52_xmt_int can be faster than ack!!) */
wait_for_scb_cmd ( dev ) ;
2008-03-19 12:44:39 +03:00
if ( readb ( & p - > scb - > cmd_cuc ) ) { /* timed out? */
2008-02-08 18:27:38 +03:00
printk ( KERN_ERR " %s: Acknowledge timed out. \n " ,
dev - > name ) ;
2005-04-17 02:20:36 +04:00
ni_disint ( ) ;
break ;
}
}
2008-02-08 18:27:38 +03:00
spin_unlock ( & p - > spinlock ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
if ( debuglevel > 1 )
2005-04-17 02:20:36 +04:00
printk ( " i " ) ;
return IRQ_HANDLED ;
}
/*******************************************************
* receive - interrupt
*/
static void ni52_rcv_int ( struct net_device * dev )
{
2008-02-08 18:27:38 +03:00
int status , cnt = 0 ;
2005-04-17 02:20:36 +04:00
unsigned short totlen ;
struct sk_buff * skb ;
2008-03-19 12:43:29 +03:00
struct rbd_struct __iomem * rbd ;
2008-11-13 10:38:14 +03:00
struct priv * p = netdev_priv ( dev ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
if ( debuglevel > 0 )
2005-04-17 02:20:36 +04:00
printk ( " R " ) ;
2008-02-08 18:27:38 +03:00
for ( ; ( status = readb ( & p - > rfd_top - > stat_high ) ) & RFD_COMPL ; ) {
2008-03-19 12:44:39 +03:00
rbd = make32 ( readw ( & p - > rfd_top - > rbd_offset ) ) ;
2008-02-08 18:27:38 +03:00
if ( status & RFD_OK ) { /* frame received without error? */
totlen = readw ( & rbd - > status ) ;
if ( totlen & RBD_LAST ) {
/* the first and the last buffer? */
totlen & = RBD_MASK ; /* length of this frame */
writew ( 0x00 , & rbd - > status ) ;
skb = ( struct sk_buff * ) dev_alloc_skb ( totlen + 2 ) ;
if ( skb ! = NULL ) {
skb_reserve ( skb , 2 ) ;
skb_put ( skb , totlen ) ;
2008-03-19 12:44:39 +03:00
memcpy_fromio ( skb - > data , p - > base + readl ( & rbd - > buffer ) , totlen ) ;
2008-02-08 18:27:38 +03:00
skb - > protocol = eth_type_trans ( skb , dev ) ;
netif_rx ( skb ) ;
2010-07-05 06:14:23 +04:00
dev - > stats . rx_packets + + ;
dev - > stats . rx_bytes + = totlen ;
2008-02-08 18:27:38 +03:00
} else
2010-07-05 06:14:23 +04:00
dev - > stats . rx_dropped + + ;
2008-02-08 18:27:38 +03:00
} else {
int rstat ;
/* free all RBD's until RBD_LAST is set */
totlen = 0 ;
while ( ! ( ( rstat = readw ( & rbd - > status ) ) & RBD_LAST ) ) {
totlen + = rstat & RBD_MASK ;
if ( ! rstat ) {
printk ( KERN_ERR " %s: Whoops .. no end mark in RBD list \n " , dev - > name ) ;
break ;
2005-04-17 02:20:36 +04:00
}
2008-02-08 18:27:38 +03:00
writew ( 0 , & rbd - > status ) ;
2008-03-19 12:44:39 +03:00
rbd = make32 ( readw ( & rbd - > next ) ) ;
2005-04-17 02:20:36 +04:00
}
2008-02-08 18:27:38 +03:00
totlen + = rstat & RBD_MASK ;
writew ( 0 , & rbd - > status ) ;
printk ( KERN_ERR " %s: received oversized frame! length: %d \n " ,
dev - > name , totlen ) ;
2010-07-05 06:14:23 +04:00
dev - > stats . rx_dropped + + ;
2005-04-17 02:20:36 +04:00
}
2008-02-08 18:27:38 +03:00
} else { /* frame !(ok), only with 'save-bad-frames' */
printk ( KERN_ERR " %s: oops! rfd-error-status: %04x \n " ,
dev - > name , status ) ;
2010-07-05 06:14:23 +04:00
dev - > stats . rx_errors + + ;
2005-04-17 02:20:36 +04:00
}
2008-02-08 18:27:38 +03:00
writeb ( 0 , & p - > rfd_top - > stat_high ) ;
writeb ( RFD_SUSP , & p - > rfd_top - > last ) ; /* maybe exchange by RFD_LAST */
writew ( 0xffff , & p - > rfd_top - > rbd_offset ) ;
writeb ( 0 , & p - > rfd_last - > last ) ; /* delete RFD_SUSP */
2005-04-17 02:20:36 +04:00
p - > rfd_last = p - > rfd_top ;
2008-03-19 12:44:39 +03:00
p - > rfd_top = make32 ( readw ( & p - > rfd_top - > next ) ) ; /* step to next RFD */
2008-02-08 18:27:38 +03:00
writew ( make16 ( p - > rfd_top ) , & p - > scb - > rfa_offset ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
if ( debuglevel > 0 )
printk ( " %d " , cnt + + ) ;
2005-04-17 02:20:36 +04:00
}
2008-02-08 18:27:38 +03:00
if ( automatic_resume ) {
wait_for_scb_cmd ( dev ) ;
writeb ( RUC_RESUME , & p - > scb - > cmd_ruc ) ;
2005-04-17 02:20:36 +04:00
ni_attn586 ( ) ;
2008-02-08 18:27:38 +03:00
wait_for_scb_cmd_ruc ( dev ) ;
2005-04-17 02:20:36 +04:00
}
# ifdef WAIT_4_BUSY
{
int i ;
2008-02-08 18:27:38 +03:00
for ( i = 0 ; i < 1024 ; i + + ) {
if ( p - > rfd_top - > status )
2005-04-17 02:20:36 +04:00
break ;
2008-02-08 18:27:38 +03:00
udelay ( 16 ) ;
if ( i = = 1023 )
printk ( KERN_ERR " %s: RU hasn't fetched next RFD (not busy/complete) \n " , dev - > name ) ;
2005-04-17 02:20:36 +04:00
}
}
# endif
2008-02-08 18:27:38 +03:00
if ( debuglevel > 0 )
2005-04-17 02:20:36 +04:00
printk ( " r " ) ;
}
/**********************************************************
* handle ' Receiver went not ready ' .
*/
static void ni52_rnr_int ( struct net_device * dev )
{
2008-11-13 10:38:14 +03:00
struct priv * p = netdev_priv ( dev ) ;
2005-04-17 02:20:36 +04:00
2010-07-05 06:14:23 +04:00
dev - > stats . rx_errors + + ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
wait_for_scb_cmd ( dev ) ; /* wait for the last cmd, WAIT_4_FULLSTAT?? */
writeb ( RUC_ABORT , & p - > scb - > cmd_ruc ) ; /* usually the RU is in the 'no resource'-state .. abort it now. */
2005-04-17 02:20:36 +04:00
ni_attn586 ( ) ;
2008-02-08 18:27:38 +03:00
wait_for_scb_cmd_ruc ( dev ) ; /* wait for accept cmd. */
2005-04-17 02:20:36 +04:00
2008-03-19 12:43:29 +03:00
alloc_rfa ( dev , p - > rfd_first ) ;
2008-02-08 18:27:38 +03:00
/* maybe add a check here, before restarting the RU */
2005-04-17 02:20:36 +04:00
startrecv586 ( dev ) ; /* restart RU */
2008-03-19 12:44:39 +03:00
printk ( KERN_ERR " %s: Receive-Unit restarted. Status: %04x \n " ,
dev - > name , readb ( & p - > scb - > rus ) ) ;
2005-04-17 02:20:36 +04:00
}
/**********************************************************
* handle xmit - interrupt
*/
static void ni52_xmt_int ( struct net_device * dev )
{
int status ;
2008-11-13 10:38:14 +03:00
struct priv * p = netdev_priv ( dev ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
if ( debuglevel > 0 )
2005-04-17 02:20:36 +04:00
printk ( " X " ) ;
2008-02-08 18:27:38 +03:00
status = readw ( & p - > xmit_cmds [ p - > xmit_last ] - > cmd_status ) ;
if ( ! ( status & STAT_COMPL ) )
printk ( KERN_ERR " %s: strange .. xmit-int without a 'COMPLETE' \n " , dev - > name ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
if ( status & STAT_OK ) {
2010-07-05 06:14:23 +04:00
dev - > stats . tx_packets + + ;
dev - > stats . collisions + = ( status & TCMD_MAXCOLLMASK ) ;
2008-02-08 18:27:38 +03:00
} else {
2010-07-05 06:14:23 +04:00
dev - > stats . tx_errors + + ;
2008-02-08 18:27:38 +03:00
if ( status & TCMD_LATECOLL ) {
printk ( KERN_ERR " %s: late collision detected. \n " ,
dev - > name ) ;
2010-07-05 06:14:23 +04:00
dev - > stats . collisions + + ;
2008-02-08 18:27:38 +03:00
} else if ( status & TCMD_NOCARRIER ) {
2010-07-05 06:14:23 +04:00
dev - > stats . tx_carrier_errors + + ;
2008-02-08 18:27:38 +03:00
printk ( KERN_ERR " %s: no carrier detected. \n " ,
dev - > name ) ;
} else if ( status & TCMD_LOSTCTS )
printk ( KERN_ERR " %s: loss of CTS detected. \n " ,
dev - > name ) ;
else if ( status & TCMD_UNDERRUN ) {
2010-07-05 06:14:23 +04:00
dev - > stats . tx_fifo_errors + + ;
2008-02-08 18:27:38 +03:00
printk ( KERN_ERR " %s: DMA underrun detected. \n " ,
dev - > name ) ;
} else if ( status & TCMD_MAXCOLL ) {
printk ( KERN_ERR " %s: Max. collisions exceeded. \n " ,
dev - > name ) ;
2010-07-05 06:14:23 +04:00
dev - > stats . collisions + = 16 ;
2005-04-17 02:20:36 +04:00
}
}
# if (NUM_XMIT_BUFFS > 1)
2008-02-08 18:27:38 +03:00
if ( ( + + p - > xmit_last ) = = NUM_XMIT_BUFFS )
2005-04-17 02:20:36 +04:00
p - > xmit_last = 0 ;
# endif
netif_wake_queue ( dev ) ;
}
/***********************************************************
* ( re ) start the receiver
*/
static void startrecv586 ( struct net_device * dev )
{
2008-11-13 10:38:14 +03:00
struct priv * p = netdev_priv ( dev ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
wait_for_scb_cmd ( dev ) ;
wait_for_scb_cmd_ruc ( dev ) ;
writew ( make16 ( p - > rfd_first ) , & p - > scb - > rfa_offset ) ;
writeb ( RUC_START , & p - > scb - > cmd_ruc ) ;
2005-04-17 02:20:36 +04:00
ni_attn586 ( ) ; /* start cmd. */
2008-02-08 18:27:38 +03:00
wait_for_scb_cmd_ruc ( dev ) ;
/* wait for accept cmd. (no timeout!!) */
2005-04-17 02:20:36 +04:00
}
static void ni52_timeout ( struct net_device * dev )
{
2008-11-13 10:38:14 +03:00
struct priv * p = netdev_priv ( dev ) ;
2005-04-17 02:20:36 +04:00
# ifndef NO_NOPCOMMANDS
2008-02-08 18:27:38 +03:00
if ( readb ( & p - > scb - > cus ) & CU_ACTIVE ) { /* COMMAND-UNIT active? */
2005-04-17 02:20:36 +04:00
netif_wake_queue ( dev ) ;
# ifdef DEBUG
2008-02-08 18:27:38 +03:00
printk ( KERN_ERR " %s: strange ... timeout with CU active?!? \n " ,
dev - > name ) ;
printk ( KERN_ERR " %s: X0: %04x N0: %04x N1: %04x %d \n " ,
dev - > name , ( int ) p - > xmit_cmds [ 0 ] - > cmd_status ,
readw ( & p - > nop_cmds [ 0 ] - > cmd_status ) ,
readw ( & p - > nop_cmds [ 1 ] - > cmd_status ) ,
p - > nop_point ) ;
2005-04-17 02:20:36 +04:00
# endif
2008-02-08 18:27:38 +03:00
writeb ( CUC_ABORT , & p - > scb - > cmd_cuc ) ;
2005-04-17 02:20:36 +04:00
ni_attn586 ( ) ;
2008-02-08 18:27:38 +03:00
wait_for_scb_cmd ( dev ) ;
writew ( make16 ( p - > nop_cmds [ p - > nop_point ] ) , & p - > scb - > cbl_offset ) ;
writeb ( CUC_START , & p - > scb - > cmd_cuc ) ;
2005-04-17 02:20:36 +04:00
ni_attn586 ( ) ;
2008-02-08 18:27:38 +03:00
wait_for_scb_cmd ( dev ) ;
2010-05-10 16:01:31 +04:00
dev - > trans_start = jiffies ; /* prevent tx timeout */
2005-04-17 02:20:36 +04:00
return 0 ;
}
# endif
{
# ifdef DEBUG
2008-02-08 18:27:38 +03:00
printk ( KERN_ERR " %s: xmitter timed out, try to restart! stat: %02x \n " ,
dev - > name , readb ( & p - > scb - > cus ) ) ;
printk ( KERN_ERR " %s: command-stats: %04x %04x \n " ,
dev - > name ,
readw ( & p - > xmit_cmds [ 0 ] - > cmd_status ) ,
readw ( & p - > xmit_cmds [ 1 ] - > cmd_status ) ) ;
printk ( KERN_ERR " %s: check, whether you set the right interrupt number! \n " ,
dev - > name ) ;
2005-04-17 02:20:36 +04:00
# endif
ni52_close ( dev ) ;
ni52_open ( dev ) ;
}
2010-05-10 16:01:31 +04:00
dev - > trans_start = jiffies ; /* prevent tx timeout */
2005-04-17 02:20:36 +04:00
}
/******************************************************
* send frame
*/
2009-08-31 23:50:58 +04:00
static netdev_tx_t ni52_send_packet ( struct sk_buff * skb ,
struct net_device * dev )
2005-04-17 02:20:36 +04:00
{
2008-02-08 18:27:38 +03:00
int len , i ;
2005-04-17 02:20:36 +04:00
# ifndef NO_NOPCOMMANDS
int next_nop ;
# endif
2008-11-13 10:38:14 +03:00
struct priv * p = netdev_priv ( dev ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 18:27:38 +03:00
if ( skb - > len > XMIT_BUFF_SIZE ) {
printk ( KERN_ERR " %s: Sorry, max. framelength is %d bytes. The length of your frame is %d bytes. \n " , dev - > name , XMIT_BUFF_SIZE , skb - > len ) ;
2009-07-06 06:23:38 +04:00
return NETDEV_TX_OK ;
2005-04-17 02:20:36 +04:00
}
netif_stop_queue ( dev ) ;
2008-03-19 12:44:39 +03:00
memcpy_toio ( p - > xmit_cbuffs [ p - > xmit_count ] , skb - > data , skb - > len ) ;
2008-02-08 18:27:38 +03:00
len = skb - > len ;
if ( len < ETH_ZLEN ) {
len = ETH_ZLEN ;
2008-03-19 12:44:39 +03:00
memset_io ( p - > xmit_cbuffs [ p - > xmit_count ] + skb - > len , 0 ,
2008-02-08 18:27:38 +03:00
len - skb - > len ) ;
2005-04-17 02:20:36 +04:00
}
# if (NUM_XMIT_BUFFS == 1)
# ifdef NO_NOPCOMMANDS
# ifdef DEBUG
2008-03-19 12:44:39 +03:00
if ( readb ( & p - > scb - > cus ) & CU_ACTIVE ) {
2008-02-08 18:27:38 +03:00
printk ( KERN_ERR " %s: Hmmm .. CU is still running and we wanna send a new packet. \n " , dev - > name ) ;
printk ( KERN_ERR " %s: stat: %04x %04x \n " ,
dev - > name , readb ( & p - > scb - > cus ) ,
readw ( & p - > xmit_cmds [ 0 ] - > cmd_status ) ) ;
}
2005-04-17 02:20:36 +04:00
# endif
2008-03-19 12:44:39 +03:00
writew ( TBD_LAST | len , & p - > xmit_buffs [ 0 ] - > size ) ;
2008-02-08 18:27:38 +03:00
for ( i = 0 ; i < 16 ; i + + ) {
writew ( 0 , & p - > xmit_cmds [ 0 ] - > cmd_status ) ;
wait_for_scb_cmd ( dev ) ;
if ( ( readb ( & p - > scb - > cus ) & CU_STATUS ) = = CU_SUSPEND )
writeb ( CUC_RESUME , & p - > scb - > cmd_cuc ) ;
else {
writew ( make16 ( p - > xmit_cmds [ 0 ] ) , & p - > scb - > cbl_offset ) ;
writeb ( CUC_START , & p - > scb - > cmd_cuc ) ;
2005-04-17 02:20:36 +04:00
}
2008-02-08 18:27:38 +03:00
ni_attn586 ( ) ;
if ( ! i )
dev_kfree_skb ( skb ) ;
wait_for_scb_cmd ( dev ) ;
/* test it, because CU sometimes doesn't start immediately */
if ( readb ( & p - > scb - > cus ) & CU_ACTIVE )
break ;
if ( readw ( & p - > xmit_cmds [ 0 ] - > cmd_status ) )
break ;
if ( i = = 15 )
printk ( KERN_WARNING " %s: Can't start transmit-command. \n " , dev - > name ) ;
}
# else
next_nop = ( p - > nop_point + 1 ) & 0x1 ;
writew ( TBD_LAST | len , & p - > xmit_buffs [ 0 ] - > size ) ;
writew ( make16 ( p - > nop_cmds [ next_nop ] ) , & p - > xmit_cmds [ 0 ] - > cmd_link ) ;
writew ( make16 ( p - > nop_cmds [ next_nop ] ) ,
& p - > nop_cmds [ next_nop ] - > cmd_link ) ;
writew ( 0 , & p - > xmit_cmds [ 0 ] - > cmd_status ) ;
writew ( 0 , & p - > nop_cmds [ next_nop ] - > cmd_status ) ;
writew ( make16 ( p - > xmit_cmds [ 0 ] ) , & p - > nop_cmds [ p - > nop_point ] - > cmd_link ) ;
p - > nop_point = next_nop ;
dev_kfree_skb ( skb ) ;
2005-04-17 02:20:36 +04:00
# endif
# else
2008-02-08 18:27:38 +03:00
writew ( TBD_LAST | len , & p - > xmit_buffs [ p - > xmit_count ] - > size ) ;
next_nop = p - > xmit_count + 1
if ( next_nop = = NUM_XMIT_BUFFS )
next_nop = 0 ;
writew ( 0 , & p - > xmit_cmds [ p - > xmit_count ] - > cmd_status ) ;
/* linkpointer of xmit-command already points to next nop cmd */
writew ( make16 ( p - > nop_cmds [ next_nop ] ) ,
& p - > nop_cmds [ next_nop ] - > cmd_link ) ;
writew ( 0 , & p - > nop_cmds [ next_nop ] - > cmd_status ) ;
writew ( make16 ( p - > xmit_cmds [ p - > xmit_count ] ) ,
& p - > nop_cmds [ p - > xmit_count ] - > cmd_link ) ;
p - > xmit_count = next_nop ;
{
unsigned long flags ;
spin_lock_irqsave ( & p - > spinlock ) ;
if ( p - > xmit_count ! = p - > xmit_last )
netif_wake_queue ( dev ) ;
spin_unlock_irqrestore ( & p - > spinlock ) ;
2005-04-17 02:20:36 +04:00
}
2008-02-08 18:27:38 +03:00
dev_kfree_skb ( skb ) ;
# endif
2009-07-06 06:23:38 +04:00
return NETDEV_TX_OK ;
2005-04-17 02:20:36 +04:00
}
/*******************************************
* Someone wanna have the statistics
*/
static struct net_device_stats * ni52_get_stats ( struct net_device * dev )
{
2008-11-13 10:38:14 +03:00
struct priv * p = netdev_priv ( dev ) ;
2008-02-08 18:27:38 +03:00
unsigned short crc , aln , rsc , ovrn ;
/* Get error-statistics from the ni82586 */
crc = readw ( & p - > scb - > crc_errs ) ;
writew ( 0 , & p - > scb - > crc_errs ) ;
aln = readw ( & p - > scb - > aln_errs ) ;
writew ( 0 , & p - > scb - > aln_errs ) ;
rsc = readw ( & p - > scb - > rsc_errs ) ;
writew ( 0 , & p - > scb - > rsc_errs ) ;
ovrn = readw ( & p - > scb - > ovrn_errs ) ;
writew ( 0 , & p - > scb - > ovrn_errs ) ;
2005-04-17 02:20:36 +04:00
2010-07-05 06:14:23 +04:00
dev - > stats . rx_crc_errors + = crc ;
dev - > stats . rx_fifo_errors + = ovrn ;
dev - > stats . rx_frame_errors + = aln ;
dev - > stats . rx_dropped + = rsc ;
2005-04-17 02:20:36 +04:00
2010-07-05 06:14:23 +04:00
return & dev - > stats ;
2005-04-17 02:20:36 +04:00
}
/********************************************************
* Set MC list . .
*/
static void set_multicast_list ( struct net_device * dev )
{
netif_stop_queue ( dev ) ;
ni_disint ( ) ;
alloc586 ( dev ) ;
init586 ( dev ) ;
startrecv586 ( dev ) ;
ni_enaint ( ) ;
netif_wake_queue ( dev ) ;
}
# ifdef MODULE
static struct net_device * dev_ni52 ;
module_param ( io , int , 0 ) ;
module_param ( irq , int , 0 ) ;
module_param ( memstart , long , 0 ) ;
module_param ( memend , long , 0 ) ;
MODULE_PARM_DESC ( io , " NI5210 I/O base address,required " ) ;
MODULE_PARM_DESC ( irq , " NI5210 IRQ number,required " ) ;
MODULE_PARM_DESC ( memstart , " NI5210 memory base address,required " ) ;
MODULE_PARM_DESC ( memend , " NI5210 memory end address,required " ) ;
2006-08-15 10:00:05 +04:00
int __init init_module ( void )
2005-04-17 02:20:36 +04:00
{
2008-02-08 18:27:38 +03:00
if ( io < = 0x0 | | ! memend | | ! memstart | | irq < 2 ) {
printk ( KERN_ERR " ni52: Autoprobing not allowed for modules. \n " ) ;
printk ( KERN_ERR " ni52: Set symbols 'io' 'irq' 'memstart' and 'memend' \n " ) ;
2005-04-17 02:20:36 +04:00
return - ENODEV ;
}
dev_ni52 = ni52_probe ( - 1 ) ;
if ( IS_ERR ( dev_ni52 ) )
return PTR_ERR ( dev_ni52 ) ;
return 0 ;
}
2006-06-15 02:50:53 +04:00
void __exit cleanup_module ( void )
2005-04-17 02:20:36 +04:00
{
2008-11-13 10:38:14 +03:00
struct priv * p = netdev_priv ( dev_ni52 ) ;
2005-04-17 02:20:36 +04:00
unregister_netdev ( dev_ni52 ) ;
2008-03-19 12:44:29 +03:00
iounmap ( p - > mapped ) ;
2005-04-17 02:20:36 +04:00
release_region ( dev_ni52 - > base_addr , NI52_TOTAL_SIZE ) ;
free_netdev ( dev_ni52 ) ;
}
# endif /* MODULE */
MODULE_LICENSE ( " GPL " ) ;