Commit 383a058c authored by Kai Germaschewski's avatar Kai Germaschewski

ISDN: Init ISA AVM CAPI drivers at module load time

Don't use a special CAPI solution to tell the drivers about 
ISA cards but use module parameters, just as other drivers do.

Internally use struct pci_dev to save that data - hopefully
one day the device tree will provide a nicer way to achieve this.
parent c1c5774f
......@@ -1135,54 +1135,13 @@ static struct capi_driver *find_driver(char *name)
static int old_capi_manufacturer(unsigned int cmd, void *data)
{
avmb1_loadandconfigdef ldef;
avmb1_extcarddef cdef;
avmb1_resetdef rdef;
avmb1_getdef gdef;
struct capi_driver *driver;
struct capi_ctr *card;
capicardparams cparams;
capiloaddata ldata;
int retval;
switch (cmd) {
case AVMB1_ADDCARD:
case AVMB1_ADDCARD_WITH_TYPE:
if (cmd == AVMB1_ADDCARD) {
if ((retval = copy_from_user((void *) &cdef, data,
sizeof(avmb1_carddef))))
return retval;
cdef.cardtype = AVM_CARDTYPE_B1;
} else {
if ((retval = copy_from_user((void *) &cdef, data,
sizeof(avmb1_extcarddef))))
return retval;
}
cparams.port = cdef.port;
cparams.irq = cdef.irq;
cparams.cardnr = cdef.cardnr;
switch (cdef.cardtype) {
case AVM_CARDTYPE_B1:
driver = find_driver("b1isa");
break;
case AVM_CARDTYPE_T1:
driver = find_driver("t1isa");
break;
default:
driver = 0;
break;
}
if (!driver) {
printk(KERN_ERR "kcapi: driver not loaded.\n");
return -EIO;
}
if (!driver->add_card) {
printk(KERN_ERR "kcapi: driver has no add card function.\n");
return -EIO;
}
return driver->add_card(driver, &cparams);
case AVMB1_LOAD:
case AVMB1_LOAD_AND_CONFIG:
......@@ -1327,8 +1286,6 @@ static int capi_manufacturer(unsigned int cmd, void *data)
switch (cmd) {
#ifdef CONFIG_AVMB1_COMPAT
case AVMB1_ADDCARD:
case AVMB1_ADDCARD_WITH_TYPE:
case AVMB1_LOAD:
case AVMB1_LOAD_AND_CONFIG:
case AVMB1_RESETCARD:
......@@ -1354,37 +1311,6 @@ static int capi_manufacturer(unsigned int cmd, void *data)
return 0;
}
case KCAPI_CMD_ADDCARD:
{
struct capi_driver *driver;
capicardparams cparams;
kcapi_carddef cdef;
if ((retval = copy_from_user((void *) &cdef, data,
sizeof(cdef))))
return retval;
cparams.port = cdef.port;
cparams.irq = cdef.irq;
cparams.membase = cdef.membase;
cparams.cardnr = cdef.cardnr;
cparams.cardtype = 0;
cdef.driver[sizeof(cdef.driver)-1] = 0;
if ((driver = find_driver(cdef.driver)) == 0) {
printk(KERN_ERR "kcapi: driver \"%s\" not loaded.\n",
cdef.driver);
return -ESRCH;
}
if (!driver->add_card) {
printk(KERN_ERR "kcapi: driver \"%s\" has no add card function.\n", cdef.driver);
return -EIO;
}
return driver->add_card(driver, &cparams);
}
default:
printk(KERN_ERR "kcapi: manufacturer command %d unknown.\n",
cmd);
......
......@@ -18,6 +18,7 @@
#include <linux/ioport.h>
#include <linux/capi.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <asm/io.h>
#include <linux/isdn/capicmd.h>
#include <linux/isdn/capiutil.h>
......@@ -34,16 +35,18 @@ MODULE_LICENSE("GPL");
/* ------------------------------------------------------------- */
static void b1isa_remove_ctr(struct capi_ctr *ctrl)
static struct capi_driver b1isa_driver;
static void b1isa_remove(struct pci_dev *pdev)
{
avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
avmctrl_info *cinfo = pci_get_drvdata(pdev);
avmcard *card = cinfo->card;
unsigned int port = card->port;
unsigned int port = cinfo->card->port;
b1_reset(port);
b1_reset(port);
detach_capi_ctr(ctrl);
detach_capi_ctr(cinfo->capi_ctrl);
free_irq(card->irq, card);
release_region(card->port, AVMB1_PORTLEN);
b1_free_card(card);
......@@ -51,7 +54,7 @@ static void b1isa_remove_ctr(struct capi_ctr *ctrl)
/* ------------------------------------------------------------- */
static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
static int __init b1isa_probe(struct pci_dev *pdev)
{
avmctrl_info *cinfo;
avmcard *card;
......@@ -66,10 +69,10 @@ static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
cinfo = card->ctrlinfo;
sprintf(card->name, "b1isa-%x", p->port);
card->port = p->port;
card->irq = p->irq;
card->port = pci_resource_start(pdev, 0);
card->irq = pdev->irq;
card->cardtype = avm_b1isa;
sprintf(card->name, "b1isa-%x", card->port);
if ( card->port != 0x150 && card->port != 0x250
&& card->port != 0x300 && card->port != 0x340) {
......@@ -103,7 +106,7 @@ static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
b1_reset(card->port);
b1_getrevision(card);
cinfo->capi_ctrl = attach_capi_ctr(driver, card->name, cinfo);
cinfo->capi_ctrl = attach_capi_ctr(&b1isa_driver, card->name, cinfo);
if (!cinfo->capi_ctrl) {
printk(KERN_ERR "b1isa: attach controller failed.\n");
retval = -EBUSY;
......@@ -112,8 +115,9 @@ static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
printk(KERN_INFO
"%s: AVM B1 ISA at i/o %#x, irq %d, revision %d\n",
driver->name, card->port, card->irq, card->revision);
b1isa_driver.name, card->port, card->irq, card->revision);
pci_set_drvdata(pdev, cinfo);
return 0;
err_free_irq:
......@@ -150,7 +154,6 @@ static struct capi_driver b1isa_driver = {
revision: "0.0",
load_firmware: b1_load_firmware,
reset_ctr: b1_reset_ctr,
remove_ctr: b1isa_remove_ctr,
register_appl: b1_register_appl,
release_appl: b1_release_appl,
send_message: b1_send_message,
......@@ -158,24 +161,63 @@ static struct capi_driver b1isa_driver = {
procinfo: b1isa_procinfo,
ctr_read_proc: b1ctl_read_proc,
driver_read_proc: 0, /* use standard driver_read_proc */
add_card: b1isa_add_card,
};
#define MAX_CARDS 4
static struct pci_dev isa_dev[MAX_CARDS];
static int io[MAX_CARDS];
static int irq[MAX_CARDS];
MODULE_PARM(io, "1-" __MODULE_STRING(MAX_CARDS) "i");
MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_CARDS) "i");
MODULE_PARM_DESC(io, "I/O base address(es)");
MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
static int __init b1isa_init(void)
{
int i, retval;
int found = 0;
MOD_INC_USE_COUNT;
b1_set_revision(&b1isa_driver, revision);
attach_capi_driver(&b1isa_driver);
for (i = 0; i < MAX_CARDS; i++) {
if (!io[i])
break;
isa_dev[i].resource[0].start = io[i];
isa_dev[i].irq_resource[0].start = irq[i];
if (b1isa_probe(&isa_dev[i]) == 0)
found++;
}
if (found == 0) {
retval = -ENODEV;
goto err;
}
retval = 0;
goto out;
err:
detach_capi_driver(&b1isa_driver);
out:
MOD_DEC_USE_COUNT;
return 0;
return retval;
}
static void __exit b1isa_exit(void)
{
detach_capi_driver(&b1isa_driver);
int i;
for (i = 0; i < MAX_CARDS; i++) {
if (!io[i])
break;
b1isa_remove(&isa_dev[i]);
}
detach_capi_driver(&b1isa_driver);
}
module_init(b1isa_init);
......
......@@ -20,6 +20,7 @@
#include <linux/netdevice.h>
#include <linux/kernelcapi.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <asm/io.h>
#include <linux/isdn/capicmd.h>
#include <linux/isdn/capiutil.h>
......@@ -36,6 +37,8 @@ MODULE_LICENSE("GPL");
/* ------------------------------------------------------------- */
static struct capi_driver t1isa_driver;
static int hema_irq_table[16] =
{0,
0,
......@@ -323,9 +326,9 @@ void t1isa_reset_ctr(struct capi_ctr *ctrl)
ctrl->reseted(ctrl);
}
static void t1isa_remove_ctr(struct capi_ctr *ctrl)
static void t1isa_remove(struct pci_dev *pdev)
{
avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
avmctrl_info *cinfo = pci_get_drvdata(pdev);
avmcard *card = cinfo->card;
unsigned int port = card->port;
......@@ -334,7 +337,7 @@ static void t1isa_remove_ctr(struct capi_ctr *ctrl)
b1_reset(port);
t1_reset(port);
detach_capi_ctr(ctrl);
detach_capi_ctr(cinfo->capi_ctrl);
free_irq(card->irq, card);
release_region(card->port, AVMB1_PORTLEN);
b1_free_card(card);
......@@ -342,87 +345,74 @@ static void t1isa_remove_ctr(struct capi_ctr *ctrl)
/* ------------------------------------------------------------- */
static int t1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
static int __init t1isa_probe(struct pci_dev *pdev)
{
struct capi_ctr *ctrl;
struct list_head *l;
avmctrl_info *cinfo;
avmcard *card;
int retval;
static int cardnr = 1;
card = b1_alloc_card(1);
if (!card) {
printk(KERN_WARNING "%s: no memory.\n", driver->name);
printk(KERN_WARNING "%s: no memory.\n", t1isa_driver.name);
retval = -ENOMEM;
goto err;
}
cinfo = card->ctrlinfo;
sprintf(card->name, "t1isa-%x", p->port);
card->port = p->port;
card->irq = p->irq;
card->port = pci_resource_start(pdev, 0);
card->irq = pdev->irq;
card->cardtype = avm_t1isa;
card->cardnr = p->cardnr;
card->cardnr = cardnr++;
sprintf(card->name, "t1isa-%x", card->port);
if (!(((card->port & 0x7) == 0) && ((card->port & 0x30) != 0x30))) {
printk(KERN_WARNING "%s: illegal port 0x%x.\n",
driver->name, card->port);
t1isa_driver.name, card->port);
retval = -EINVAL;
goto err_free;
}
if (hema_irq_table[card->irq & 0xf] == 0) {
printk(KERN_WARNING "%s: irq %d not valid.\n",
driver->name, card->irq);
t1isa_driver.name, card->irq);
retval = -EINVAL;
goto err_free;
}
list_for_each(l, &driver->contr_head) {
avmcard *cardp;
ctrl = list_entry(l, struct capi_ctr, driver_list);
cardp = ((avmctrl_info *)(ctrl->driverdata))->card;
if (cardp->cardnr == card->cardnr) {
printk(KERN_WARNING "%s: card with number %d already installed at 0x%x.\n",
driver->name, card->cardnr, cardp->port);
retval = -EINVAL;
goto err_free;
}
}
if (!request_region(card->port, AVMB1_PORTLEN, card->name)) {
printk(KERN_WARNING "%s: ports 0x%03x-0x%03x in use.\n",
driver->name, card->port, card->port + AVMB1_PORTLEN);
printk(KERN_INFO "%s: ports 0x%03x-0x%03x in use.\n",
t1isa_driver.name, card->port, card->port + AVMB1_PORTLEN);
retval = -EBUSY;
goto err_free;
}
retval = request_irq(card->irq, t1isa_interrupt, 0, card->name, card);
if (retval) {
printk(KERN_ERR "%s: unable to get IRQ %d.\n",
driver->name, card->irq);
printk(KERN_INFO "%s: unable to get IRQ %d.\n",
t1isa_driver.name, card->irq);
retval = -EBUSY;
goto err_release_region;
}
if ((retval = t1_detectandinit(card->port, card->irq, card->cardnr)) != 0) {
printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n",
driver->name, card->port, retval);
printk(KERN_INFO "%s: NO card at 0x%x (%d)\n",
t1isa_driver.name, card->port, retval);
retval = -ENODEV;
goto err_free_irq;
}
t1_disable_irq(card->port);
b1_reset(card->port);
cinfo->capi_ctrl = attach_capi_ctr(driver, card->name, cinfo);
cinfo->capi_ctrl = attach_capi_ctr(&t1isa_driver, card->name, cinfo);
if (!cinfo->capi_ctrl) {
printk(KERN_ERR "%s: attach controller failed.\n",
driver->name);
printk(KERN_INFO "%s: attach controller failed.\n",
t1isa_driver.name);
retval = -EBUSY;
goto err_free_irq;
}
printk(KERN_INFO
"%s: AVM T1 ISA at i/o %#x, irq %d, card %d\n",
driver->name, card->port, card->irq, card->cardnr);
printk(KERN_INFO "%s: AVM T1 ISA at i/o %#x, irq %d, card %d\n",
t1isa_driver.name, card->port, card->irq, card->cardnr);
pci_set_drvdata(pdev, cinfo);
return 0;
err_free_irq:
......@@ -502,7 +492,6 @@ static struct capi_driver t1isa_driver = {
revision: "0.0",
load_firmware: t1isa_load_firmware,
reset_ctr: t1isa_reset_ctr,
remove_ctr: t1isa_remove_ctr,
register_appl: b1_register_appl,
release_appl: b1_release_appl,
send_message: t1isa_send_message,
......@@ -510,23 +499,62 @@ static struct capi_driver t1isa_driver = {
procinfo: t1isa_procinfo,
ctr_read_proc: b1ctl_read_proc,
driver_read_proc: 0, /* use standard driver_read_proc */
add_card: t1isa_add_card,
};
#define MAX_CARDS 4
static struct pci_dev isa_dev[MAX_CARDS];
static int io[MAX_CARDS];
static int irq[MAX_CARDS];
MODULE_PARM(io, "1-" __MODULE_STRING(MAX_CARDS) "i");
MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_CARDS) "i");
MODULE_PARM_DESC(io, "I/O base address(es)");
MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
static int __init t1isa_init(void)
{
int i, retval;
int found = 0;
MOD_INC_USE_COUNT;
b1_set_revision(&t1isa_driver, revision);
attach_capi_driver(&t1isa_driver);
for (i = 0; i < MAX_CARDS; i++) {
if (!io[i])
break;
isa_dev[i].resource[0].start = io[i];
isa_dev[i].irq_resource[0].start = irq[i];
if (t1isa_probe(&isa_dev[i]) == 0)
found++;
}
if (found == 0) {
retval = -ENODEV;
goto err;
}
retval = 0;
goto out;
err:
detach_capi_driver(&t1isa_driver);
out:
MOD_DEC_USE_COUNT;
return 0;
return retval;
}
static void __exit t1isa_exit(void)
{
int i;
for (i = 0; i < MAX_CARDS; i++) {
if (!io[i])
break;
t1isa_remove(&isa_dev[i]);
}
detach_capi_driver(&t1isa_driver);
}
......
......@@ -701,8 +701,6 @@ static struct capi_driver hycapi_driver = {
procinfo: hycapi_procinfo,
ctr_read_proc: hycapi_read_proc,
driver_read_proc: 0, /* use standard driver_read_proc */
add_card: 0, /* no add_card function */
};
......
......@@ -61,7 +61,7 @@ typedef struct avmb1_extcarddef {
} avmb1_extcarddef;
#define AVMB1_LOAD 0 /* load image to card */
#define AVMB1_ADDCARD 1 /* add a new card */
#define AVMB1_ADDCARD 1 /* add a new card - OBSOLETE */
#define AVMB1_RESETCARD 2 /* reset a card */
#define AVMB1_LOAD_AND_CONFIG 3 /* load image and config to card */
#define AVMB1_ADDCARD_WITH_TYPE 4 /* add a new card, with cardtype */
......
......@@ -92,8 +92,6 @@ struct capi_driver {
int (*driver_read_proc)(char *page, char **start, off_t off,
int count, int *eof, struct capi_driver *driver);
int (*add_card)(struct capi_driver *driver, capicardparams *data);
/* intitialized by kcapi */
struct list_head contr_head; /* list of controllers */
struct list_head driver_list;
......
......@@ -32,7 +32,7 @@ typedef struct kcapi_carddef {
/* new ioctls >= 10 */
#define KCAPI_CMD_TRACE 10
#define KCAPI_CMD_ADDCARD 11 /* add card to named driver */
#define KCAPI_CMD_ADDCARD 11 /* OBSOLETE */
/*
* flag > 2 => trace also data
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment