2005-04-16 15:20:36 -07:00
/*
* PCMCIA client driver for AVM A1 / Fritz ! PCMCIA
*
* Author Carsten Paeth
* Copyright 1998 - 2001 by Carsten Paeth < calle @ calle . in - berlin . de >
*
* This software may be used and distributed according to the terms
* of the GNU General Public License , incorporated herein by reference .
*
*/
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/ptrace.h>
# include <linux/slab.h>
# include <linux/string.h>
# include <asm/io.h>
# include <asm/system.h>
# include <pcmcia/cistpl.h>
# include <pcmcia/ds.h>
# include "hisax_cfg.h"
MODULE_DESCRIPTION ( " ISDN4Linux: PCMCIA client driver for AVM A1/Fritz!PCMCIA cards " ) ;
MODULE_AUTHOR ( " Carsten Paeth " ) ;
MODULE_LICENSE ( " GPL " ) ;
/*====================================================================*/
/* Parameters that can be set with 'insmod' */
static int isdnprot = 2 ;
module_param ( isdnprot , int , 0 ) ;
/*====================================================================*/
2010-03-25 12:05:31 +00:00
static int avma1cs_config ( struct pcmcia_device * link ) __devinit ;
2006-03-31 17:21:06 +02:00
static void avma1cs_release ( struct pcmcia_device * link ) ;
2010-03-25 12:05:31 +00:00
static void avma1cs_detach ( struct pcmcia_device * p_dev ) __devexit ;
2005-04-16 15:20:36 -07:00
2010-03-25 12:05:31 +00:00
static int __devinit avma1cs_probe ( struct pcmcia_device * p_dev )
2005-04-16 15:20:36 -07:00
{
2009-10-24 15:50:13 +02:00
dev_dbg ( & p_dev - > dev , " avma1cs_attach() \n " ) ;
2005-04-16 15:20:36 -07:00
/* General socket configuration */
2010-07-30 13:13:46 +02:00
p_dev - > config_flags | = CONF_ENABLE_IRQ | CONF_AUTO_SET_IO ;
2010-07-29 18:35:47 +02:00
p_dev - > config_index = 1 ;
p_dev - > config_regs = PRESENT_OPTION ;
2005-11-14 21:25:51 +01:00
2006-03-31 17:26:06 +02:00
return avma1cs_config ( p_dev ) ;
2005-04-16 15:20:36 -07:00
} /* avma1cs_attach */
2010-03-25 12:05:31 +00:00
static void __devexit avma1cs_detach ( struct pcmcia_device * link )
2005-04-16 15:20:36 -07:00
{
2009-10-24 15:50:13 +02:00
dev_dbg ( & link - > dev , " avma1cs_detach(0x%p) \n " , link ) ;
2006-03-02 00:09:29 +01:00
avma1cs_release ( link ) ;
kfree ( link - > priv ) ;
2005-04-16 15:20:36 -07:00
} /* avma1cs_detach */
2010-07-30 13:13:46 +02:00
static int avma1cs_configcheck ( struct pcmcia_device * p_dev , void * priv_data )
2005-04-16 15:20:36 -07:00
{
2010-07-30 13:13:46 +02:00
p_dev - > resource [ 0 ] - > end = 16 ;
p_dev - > resource [ 0 ] - > flags & = ~ IO_DATA_PATH_WIDTH ;
p_dev - > resource [ 0 ] - > flags | = IO_DATA_PATH_WIDTH_8 ;
2010-07-24 17:23:51 +02:00
p_dev - > io_lines = 5 ;
2010-07-30 13:13:46 +02:00
2010-07-24 17:23:51 +02:00
return pcmcia_request_io ( p_dev ) ;
2005-04-16 15:20:36 -07:00
}
2010-03-25 12:05:31 +00:00
static int __devinit avma1cs_config ( struct pcmcia_device * link )
2005-04-16 15:20:36 -07:00
{
2010-03-07 12:21:16 +01:00
int i = - 1 ;
2005-04-16 15:20:36 -07:00
char devname [ 128 ] ;
IsdnCard_t icard ;
int busy = 0 ;
2006-03-31 17:21:06 +02:00
2009-10-24 15:50:13 +02:00
dev_dbg ( & link - > dev , " avma1cs_config(0x%p) \n " , link ) ;
2005-04-16 15:20:36 -07:00
2008-07-29 08:38:55 +02:00
devname [ 0 ] = 0 ;
if ( link - > prod_id [ 1 ] )
strlcpy ( devname , link - > prod_id [ 1 ] , sizeof ( devname ) ) ;
2006-06-04 18:06:13 +02:00
2008-07-29 08:38:55 +02:00
if ( pcmcia_loop_config ( link , avma1cs_configcheck , NULL ) )
return - ENODEV ;
2005-04-16 15:20:36 -07:00
2008-07-29 08:38:55 +02:00
do {
2005-04-16 15:20:36 -07:00
/*
* allocate an interrupt line
*/
2010-03-07 12:21:16 +01:00
if ( ! link - > irq ) {
2006-01-15 10:05:19 +01:00
/* undo */
2006-03-31 17:21:06 +02:00
pcmcia_disable_device ( link ) ;
2005-04-16 15:20:36 -07:00
break ;
}
2006-01-15 10:05:19 +01:00
2005-04-16 15:20:36 -07:00
/*
* configure the PCMCIA socket
*/
2010-07-29 19:27:09 +02:00
i = pcmcia_enable_device ( link ) ;
2008-08-03 10:07:45 +02:00
if ( i ! = 0 ) {
2006-03-31 17:21:06 +02:00
pcmcia_disable_device ( link ) ;
2005-04-16 15:20:36 -07:00
break ;
}
} while ( 0 ) ;
/* If any step failed, release any partially configured state */
if ( i ! = 0 ) {
avma1cs_release ( link ) ;
2006-03-31 17:26:06 +02:00
return - ENODEV ;
2005-04-16 15:20:36 -07:00
}
2010-03-07 12:21:16 +01:00
icard . para [ 0 ] = link - > irq ;
2010-07-24 15:58:54 +02:00
icard . para [ 1 ] = link - > resource [ 0 ] - > start ;
2005-04-16 15:20:36 -07:00
icard . protocol = isdnprot ;
icard . typ = ISDN_CTYPE_A1_PCMCIA ;
i = hisax_init_pcmcia ( link , & busy , & icard ) ;
if ( i < 0 ) {
2010-07-24 15:58:54 +02:00
printk ( KERN_ERR " avma1_cs: failed to initialize AVM A1 "
" PCMCIA %d at i/o %#x \n " , i ,
( unsigned int ) link - > resource [ 0 ] - > start ) ;
2005-04-16 15:20:36 -07:00
avma1cs_release ( link ) ;
2006-03-31 17:26:06 +02:00
return - ENODEV ;
2005-04-16 15:20:36 -07:00
}
2010-03-20 19:43:26 +01:00
link - > priv = ( void * ) ( unsigned long ) i ;
2005-04-16 15:20:36 -07:00
2006-03-31 17:26:06 +02:00
return 0 ;
2005-04-16 15:20:36 -07:00
} /* avma1cs_config */
2006-03-31 17:21:06 +02:00
static void avma1cs_release ( struct pcmcia_device * link )
2005-04-16 15:20:36 -07:00
{
2010-03-20 19:43:26 +01:00
unsigned long minor = ( unsigned long ) link - > priv ;
2005-04-16 15:20:36 -07:00
2009-10-24 15:50:13 +02:00
dev_dbg ( & link - > dev , " avma1cs_release(0x%p) \n " , link ) ;
2005-04-16 15:20:36 -07:00
2006-01-15 09:32:39 +01:00
/* now unregister function with hisax */
2010-03-20 19:43:26 +01:00
HiSax_closecard ( minor ) ;
2005-04-16 15:20:36 -07:00
2006-03-31 17:21:06 +02:00
pcmcia_disable_device ( link ) ;
2005-04-16 15:20:36 -07:00
} /* avma1cs_release */
2011-05-03 19:29:01 -07:00
static const struct pcmcia_device_id avma1cs_ids [ ] = {
2005-06-27 16:28:34 -07:00
PCMCIA_DEVICE_PROD_ID12 ( " AVM " , " ISDN A " , 0x95d42008 , 0xadc9d4bb ) ,
PCMCIA_DEVICE_PROD_ID12 ( " ISDN " , " CARD " , 0x8d9761c8 , 0x01c5aa7b ) ,
PCMCIA_DEVICE_NULL
} ;
MODULE_DEVICE_TABLE ( pcmcia , avma1cs_ids ) ;
2005-04-16 15:20:36 -07:00
static struct pcmcia_driver avma1cs_driver = {
. owner = THIS_MODULE ,
2010-08-08 11:36:26 +02:00
. name = " avma1_cs " ,
2006-03-31 17:26:06 +02:00
. probe = avma1cs_probe ,
2010-03-25 12:05:31 +00:00
. remove = __devexit_p ( avma1cs_detach ) ,
2005-06-27 16:28:34 -07:00
. id_table = avma1cs_ids ,
2005-04-16 15:20:36 -07:00
} ;
2006-03-02 00:02:33 +01:00
2005-04-16 15:20:36 -07:00
static int __init init_avma1_cs ( void )
{
2010-08-08 12:27:40 +02:00
return pcmcia_register_driver ( & avma1cs_driver ) ;
2005-04-16 15:20:36 -07:00
}
static void __exit exit_avma1_cs ( void )
{
pcmcia_unregister_driver ( & avma1cs_driver ) ;
}
module_init ( init_avma1_cs ) ;
module_exit ( exit_avma1_cs ) ;