2005-04-17 02:20:36 +04:00
/*
* Linux ARCnet driver - COM20020 chipset support
2015-05-05 20:05:47 +03:00
*
2005-04-17 02:20:36 +04:00
* Written 1997 by David Woodhouse .
* Written 1994 - 1999 by Avery Pennarun .
* Written 1999 - 2000 by Martin Mares < mj @ ucw . cz > .
* Derived from skeleton . c by Donald Becker .
*
* Special thanks to Contemporary Controls , Inc . ( www . ccontrols . com )
* for sponsoring the further development of this driver .
*
* * * * * * * * * * * * * * * * * * * * * * *
*
* The original copyright of skeleton . c was as follows :
*
* skeleton . c Written 1993 by Donald Becker .
* Copyright 1993 United States Government as represented by the
* Director , National Security Agency . This software may only be used
* and distributed according to the terms of the GNU General Public License as
* modified by SRC , incorporated herein by reference .
*
* * * * * * * * * * * * * * * * * * * * * * *
*
* For more details , see drivers / net / arcnet . c
*
* * * * * * * * * * * * * * * * * * * * * * *
*/
2015-05-05 20:05:56 +03:00
# define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
2005-04-17 02:20:36 +04:00
# include <linux/module.h>
# include <linux/moduleparam.h>
# include <linux/kernel.h>
# include <linux/types.h>
# include <linux/ioport.h>
# include <linux/errno.h>
# include <linux/delay.h>
# include <linux/netdevice.h>
# include <linux/init.h>
2011-06-06 14:43:46 +04:00
# include <linux/interrupt.h>
2018-10-31 01:09:49 +03:00
# include <linux/memblock.h>
2015-05-05 20:05:51 +03:00
# include <linux/io.h>
2005-04-17 02:20:36 +04:00
2015-05-05 20:06:03 +03:00
# include "arcdevice.h"
# include "com20020.h"
2015-05-05 20:05:52 +03:00
/* We cannot (yet) probe for an IO mapped card, although we can check that
2005-04-17 02:20:36 +04:00
* it ' s where we were told it was , and even do autoirq .
*/
static int __init com20020isa_probe ( struct net_device * dev )
{
int ioaddr ;
unsigned long airqmask ;
2008-11-13 10:37:49 +03:00
struct arcnet_local * lp = netdev_priv ( dev ) ;
2005-04-17 02:20:36 +04:00
int err ;
2015-05-05 20:05:54 +03:00
if ( BUGLVL ( D_NORMAL ) )
2015-05-05 20:05:56 +03:00
pr_info ( " %s \n " , " COM20020 ISA support (by David Woodhouse et al.) " ) ;
2005-04-17 02:20:36 +04:00
ioaddr = dev - > base_addr ;
if ( ! ioaddr ) {
2015-05-05 20:05:55 +03:00
arc_printk ( D_NORMAL , dev , " No autoprobe (yet) for IO mapped cards; you must specify the base address! \n " ) ;
2005-04-17 02:20:36 +04:00
return - ENODEV ;
}
if ( ! request_region ( ioaddr , ARCNET_TOTAL_SIZE , " arcnet (COM20020) " ) ) {
2015-05-05 20:05:55 +03:00
arc_printk ( D_NORMAL , dev , " IO region %xh-%xh already allocated. \n " ,
ioaddr , ioaddr + ARCNET_TOTAL_SIZE - 1 ) ;
2005-04-17 02:20:36 +04:00
return - ENXIO ;
}
2015-05-05 20:06:06 +03:00
if ( arcnet_inb ( ioaddr , COM20020_REG_R_STATUS ) = = 0xFF ) {
2015-05-05 20:05:55 +03:00
arc_printk ( D_NORMAL , dev , " IO address %x empty \n " , ioaddr ) ;
2005-04-17 02:20:36 +04:00
err = - ENODEV ;
goto out ;
}
if ( com20020_check ( dev ) ) {
err = - ENODEV ;
goto out ;
}
if ( ! dev - > irq ) {
/* if we do this, we're sure to get an IRQ since the
* card has just reset and the NORXflag is on until
* we tell it to start receiving .
*/
2015-05-05 20:05:55 +03:00
arc_printk ( D_INIT_REASONS , dev , " intmask was %02Xh \n " ,
2015-05-05 20:06:06 +03:00
arcnet_inb ( ioaddr , COM20020_REG_R_STATUS ) ) ;
arcnet_outb ( 0 , ioaddr , COM20020_REG_W_INTMASK ) ;
2005-04-17 02:20:36 +04:00
airqmask = probe_irq_on ( ) ;
2015-05-05 20:06:06 +03:00
arcnet_outb ( NORXflag , ioaddr , COM20020_REG_W_INTMASK ) ;
2005-04-17 02:20:36 +04:00
udelay ( 1 ) ;
2015-05-05 20:06:06 +03:00
arcnet_outb ( 0 , ioaddr , COM20020_REG_W_INTMASK ) ;
2005-04-17 02:20:36 +04:00
dev - > irq = probe_irq_off ( airqmask ) ;
2010-07-17 11:21:28 +04:00
if ( ( int ) dev - > irq < = 0 ) {
2015-05-05 20:05:55 +03:00
arc_printk ( D_INIT_REASONS , dev , " Autoprobe IRQ failed first time \n " ) ;
2005-04-17 02:20:36 +04:00
airqmask = probe_irq_on ( ) ;
2015-05-05 20:06:06 +03:00
arcnet_outb ( NORXflag , ioaddr , COM20020_REG_W_INTMASK ) ;
2005-04-17 02:20:36 +04:00
udelay ( 5 ) ;
2015-05-05 20:06:06 +03:00
arcnet_outb ( 0 , ioaddr , COM20020_REG_W_INTMASK ) ;
2005-04-17 02:20:36 +04:00
dev - > irq = probe_irq_off ( airqmask ) ;
2010-07-17 11:21:28 +04:00
if ( ( int ) dev - > irq < = 0 ) {
2015-05-05 20:05:55 +03:00
arc_printk ( D_NORMAL , dev , " Autoprobe IRQ failed. \n " ) ;
2005-04-17 02:20:36 +04:00
err = - ENODEV ;
goto out ;
}
}
}
lp - > card_name = " ISA COM20020 " ;
2015-05-05 20:05:59 +03:00
err = com20020_found ( dev , 0 ) ;
if ( err ! = 0 )
2005-04-17 02:20:36 +04:00
goto out ;
return 0 ;
out :
release_region ( ioaddr , ARCNET_TOTAL_SIZE ) ;
return err ;
}
static int node = 0 ;
static int io = 0x0 ; /* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */
static int irq = 0 ; /* or use the insmod io= irq= shmem= options */
static char device [ 9 ] ; /* use eg. device="arc1" to change name */
static int timeout = 3 ;
static int backplane = 0 ;
static int clockp = 0 ;
static int clockm = 0 ;
module_param ( node , int , 0 ) ;
2017-04-04 18:54:25 +03:00
module_param_hw ( io , int , ioport , 0 ) ;
module_param_hw ( irq , int , irq , 0 ) ;
2005-04-17 02:20:36 +04:00
module_param_string ( device , device , sizeof ( device ) , 0 ) ;
module_param ( timeout , int , 0 ) ;
module_param ( backplane , int , 0 ) ;
module_param ( clockp , int , 0 ) ;
module_param ( clockm , int , 0 ) ;
MODULE_LICENSE ( " GPL " ) ;
static struct net_device * my_dev ;
static int __init com20020_init ( void )
{
struct net_device * dev ;
struct arcnet_local * lp ;
dev = alloc_arcdev ( device ) ;
if ( ! dev )
return - ENOMEM ;
if ( node & & node ! = 0xff )
dev - > dev_addr [ 0 ] = node ;
2009-01-09 16:01:10 +03:00
dev - > netdev_ops = & com20020_netdev_ops ;
2008-11-13 10:37:49 +03:00
lp = netdev_priv ( dev ) ;
2005-04-17 02:20:36 +04:00
lp - > backplane = backplane ;
lp - > clockp = clockp & 7 ;
lp - > clockm = clockm & 3 ;
lp - > timeout = timeout & 3 ;
lp - > hw . owner = THIS_MODULE ;
dev - > base_addr = io ;
dev - > irq = irq ;
if ( dev - > irq = = 2 )
dev - > irq = 9 ;
if ( com20020isa_probe ( dev ) ) {
free_netdev ( dev ) ;
return - EIO ;
}
my_dev = dev ;
return 0 ;
}
static void __exit com20020_exit ( void )
{
unregister_netdev ( my_dev ) ;
free_irq ( my_dev - > irq , my_dev ) ;
release_region ( my_dev - > base_addr , ARCNET_TOTAL_SIZE ) ;
free_netdev ( my_dev ) ;
}
# ifndef MODULE
static int __init com20020isa_setup ( char * s )
{
int ints [ 8 ] ;
s = get_options ( s , 8 , ints ) ;
if ( ! ints [ 0 ] )
return 1 ;
switch ( ints [ 0 ] ) {
default : /* ERROR */
2015-05-05 20:05:56 +03:00
pr_info ( " Too many arguments \n " ) ;
2019-07-29 17:25:03 +03:00
/* Fall through */
2005-04-17 02:20:36 +04:00
case 6 : /* Timeout */
timeout = ints [ 6 ] ;
2019-07-29 17:25:03 +03:00
/* Fall through */
2005-04-17 02:20:36 +04:00
case 5 : /* CKP value */
clockp = ints [ 5 ] ;
2019-07-29 17:25:03 +03:00
/* Fall through */
2005-04-17 02:20:36 +04:00
case 4 : /* Backplane flag */
backplane = ints [ 4 ] ;
2019-07-29 17:25:03 +03:00
/* Fall through */
2005-04-17 02:20:36 +04:00
case 3 : /* Node ID */
node = ints [ 3 ] ;
2019-07-29 17:25:03 +03:00
/* Fall through */
2005-04-17 02:20:36 +04:00
case 2 : /* IRQ */
irq = ints [ 2 ] ;
2019-07-29 17:25:03 +03:00
/* Fall through */
2005-04-17 02:20:36 +04:00
case 1 : /* IO address */
io = ints [ 1 ] ;
}
if ( * s )
snprintf ( device , sizeof ( device ) , " %s " , s ) ;
return 1 ;
}
__setup ( " com20020= " , com20020isa_setup ) ;
# endif /* MODULE */
module_init ( com20020_init )
module_exit ( com20020_exit )