forked from Minki/linux
2262054e74
What's worse than no comment? A wrong comment. Several PCMCIA device drivers contained the same comments, which were based on how the PCMCIA subsystem worked in the old days of 2.4., and which were originally part of a "dummy_cs" driver. These comments no longer matched at all what is happening now, and therefore should be removed. Tested-by: Wolfram Sang <w.sang@pengutronix.de> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
216 lines
5.2 KiB
C
216 lines
5.2 KiB
C
/* $Id: teles_cs.c,v 1.1.2.2 2004/01/25 15:07:06 keil Exp $ */
|
|
/*======================================================================
|
|
|
|
A teles S0 PCMCIA client driver
|
|
|
|
Based on skeleton by David Hinds, dhinds@allegro.stanford.edu
|
|
Written by Christof Petig, christof.petig@wtal.de
|
|
|
|
Also inspired by ELSA PCMCIA driver
|
|
by Klaus Lichtenwalder <Lichtenwalder@ACM.org>
|
|
|
|
Extentions to new hisax_pcmcia by Karsten Keil
|
|
|
|
minor changes to be compatible with kernel 2.4.x
|
|
by Jan.Schubert@GMX.li
|
|
|
|
======================================================================*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/init.h>
|
|
#include <linux/ptrace.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/string.h>
|
|
#include <linux/timer.h>
|
|
#include <linux/ioport.h>
|
|
#include <asm/io.h>
|
|
#include <asm/system.h>
|
|
|
|
#include <pcmcia/cistpl.h>
|
|
#include <pcmcia/cisreg.h>
|
|
#include <pcmcia/ds.h>
|
|
#include "hisax_cfg.h"
|
|
|
|
MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Teles PCMCIA cards");
|
|
MODULE_AUTHOR("Christof Petig, christof.petig@wtal.de, Karsten Keil, kkeil@suse.de");
|
|
MODULE_LICENSE("GPL");
|
|
|
|
|
|
/*====================================================================*/
|
|
|
|
/* Parameters that can be set with 'insmod' */
|
|
|
|
static int protocol = 2; /* EURO-ISDN Default */
|
|
module_param(protocol, int, 0);
|
|
|
|
static int teles_cs_config(struct pcmcia_device *link) __devinit ;
|
|
static void teles_cs_release(struct pcmcia_device *link);
|
|
static void teles_detach(struct pcmcia_device *p_dev) __devexit ;
|
|
|
|
typedef struct local_info_t {
|
|
struct pcmcia_device *p_dev;
|
|
int busy;
|
|
int cardnr;
|
|
} local_info_t;
|
|
|
|
static int __devinit teles_probe(struct pcmcia_device *link)
|
|
{
|
|
local_info_t *local;
|
|
|
|
dev_dbg(&link->dev, "teles_attach()\n");
|
|
|
|
/* Allocate space for private device-specific data */
|
|
local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
|
|
if (!local) return -ENOMEM;
|
|
local->cardnr = -1;
|
|
|
|
local->p_dev = link;
|
|
link->priv = local;
|
|
|
|
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
|
|
|
|
return teles_cs_config(link);
|
|
} /* teles_attach */
|
|
|
|
static void __devexit teles_detach(struct pcmcia_device *link)
|
|
{
|
|
local_info_t *info = link->priv;
|
|
|
|
dev_dbg(&link->dev, "teles_detach(0x%p)\n", link);
|
|
|
|
info->busy = 1;
|
|
teles_cs_release(link);
|
|
|
|
kfree(info);
|
|
} /* teles_detach */
|
|
|
|
static int teles_cs_configcheck(struct pcmcia_device *p_dev, void *priv_data)
|
|
{
|
|
int j;
|
|
|
|
p_dev->io_lines = 5;
|
|
p_dev->resource[0]->end = 96;
|
|
p_dev->resource[0]->flags &= IO_DATA_PATH_WIDTH;
|
|
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
|
|
|
|
if ((p_dev->resource[0]->end) && p_dev->resource[0]->start) {
|
|
printk(KERN_INFO "(teles_cs: looks like the 96 model)\n");
|
|
if (!pcmcia_request_io(p_dev))
|
|
return 0;
|
|
} else {
|
|
printk(KERN_INFO "(teles_cs: looks like the 97 model)\n");
|
|
for (j = 0x2f0; j > 0x100; j -= 0x10) {
|
|
p_dev->resource[0]->start = j;
|
|
if (!pcmcia_request_io(p_dev))
|
|
return 0;
|
|
}
|
|
}
|
|
return -ENODEV;
|
|
}
|
|
|
|
static int __devinit teles_cs_config(struct pcmcia_device *link)
|
|
{
|
|
local_info_t *dev;
|
|
int i;
|
|
IsdnCard_t icard;
|
|
|
|
dev_dbg(&link->dev, "teles_config(0x%p)\n", link);
|
|
dev = link->priv;
|
|
|
|
i = pcmcia_loop_config(link, teles_cs_configcheck, NULL);
|
|
if (i != 0)
|
|
goto cs_failed;
|
|
|
|
if (!link->irq)
|
|
goto cs_failed;
|
|
|
|
i = pcmcia_enable_device(link);
|
|
if (i != 0)
|
|
goto cs_failed;
|
|
|
|
icard.para[0] = link->irq;
|
|
icard.para[1] = link->resource[0]->start;
|
|
icard.protocol = protocol;
|
|
icard.typ = ISDN_CTYPE_TELESPCMCIA;
|
|
|
|
i = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->busy), &icard);
|
|
if (i < 0) {
|
|
printk(KERN_ERR "teles_cs: failed to initialize Teles PCMCIA %d at i/o %#x\n",
|
|
i, (unsigned int) link->resource[0]->start);
|
|
teles_cs_release(link);
|
|
return -ENODEV;
|
|
}
|
|
|
|
((local_info_t*)link->priv)->cardnr = i;
|
|
return 0;
|
|
|
|
cs_failed:
|
|
teles_cs_release(link);
|
|
return -ENODEV;
|
|
} /* teles_cs_config */
|
|
|
|
static void teles_cs_release(struct pcmcia_device *link)
|
|
{
|
|
local_info_t *local = link->priv;
|
|
|
|
dev_dbg(&link->dev, "teles_cs_release(0x%p)\n", link);
|
|
|
|
if (local) {
|
|
if (local->cardnr >= 0) {
|
|
/* no unregister function with hisax */
|
|
HiSax_closecard(local->cardnr);
|
|
}
|
|
}
|
|
|
|
pcmcia_disable_device(link);
|
|
} /* teles_cs_release */
|
|
|
|
static int teles_suspend(struct pcmcia_device *link)
|
|
{
|
|
local_info_t *dev = link->priv;
|
|
|
|
dev->busy = 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int teles_resume(struct pcmcia_device *link)
|
|
{
|
|
local_info_t *dev = link->priv;
|
|
|
|
dev->busy = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static struct pcmcia_device_id teles_ids[] = {
|
|
PCMCIA_DEVICE_PROD_ID12("TELES", "S0/PC", 0x67b50eae, 0xe9e70119),
|
|
PCMCIA_DEVICE_NULL,
|
|
};
|
|
MODULE_DEVICE_TABLE(pcmcia, teles_ids);
|
|
|
|
static struct pcmcia_driver teles_cs_driver = {
|
|
.owner = THIS_MODULE,
|
|
.name = "teles_cs",
|
|
.probe = teles_probe,
|
|
.remove = __devexit_p(teles_detach),
|
|
.id_table = teles_ids,
|
|
.suspend = teles_suspend,
|
|
.resume = teles_resume,
|
|
};
|
|
|
|
static int __init init_teles_cs(void)
|
|
{
|
|
return pcmcia_register_driver(&teles_cs_driver);
|
|
}
|
|
|
|
static void __exit exit_teles_cs(void)
|
|
{
|
|
pcmcia_unregister_driver(&teles_cs_driver);
|
|
}
|
|
|
|
module_init(init_teles_cs);
|
|
module_exit(exit_teles_cs);
|