1/* $Id: b1isa.c,v 1.1.1.1 2008/10/15 03:26:33 james26_jang Exp $ 2 * 3 * Module for AVM B1 ISA-card. 4 * 5 * Copyright 1999 by Carsten Paeth <calle@calle.de> 6 * 7 * This software may be used and distributed according to the terms 8 * of the GNU General Public License, incorporated herein by reference. 9 * 10 */ 11 12#include <linux/module.h> 13#include <linux/kernel.h> 14#include <linux/skbuff.h> 15#include <linux/delay.h> 16#include <linux/mm.h> 17#include <linux/interrupt.h> 18#include <linux/ioport.h> 19#include <linux/capi.h> 20#include <linux/init.h> 21#include <asm/io.h> 22#include "capicmd.h" 23#include "capiutil.h" 24#include "capilli.h" 25#include "avmcard.h" 26 27static char *revision = "$Revision: 1.1.1.1 $"; 28 29/* ------------------------------------------------------------- */ 30 31MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM B1 ISA card"); 32MODULE_AUTHOR("Carsten Paeth"); 33MODULE_LICENSE("GPL"); 34 35/* ------------------------------------------------------------- */ 36 37static void b1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs) 38{ 39 avmcard *card; 40 41 card = (avmcard *) devptr; 42 43 if (!card) { 44 printk(KERN_WARNING "b1_interrupt: wrong device\n"); 45 return; 46 } 47 if (card->interrupt) { 48 printk(KERN_ERR "b1_interrupt: reentering interrupt hander (%s)\n", card->name); 49 return; 50 } 51 52 card->interrupt = 1; 53 54 b1_handle_interrupt(card); 55 56 card->interrupt = 0; 57} 58/* ------------------------------------------------------------- */ 59 60static struct capi_driver_interface *di; 61 62/* ------------------------------------------------------------- */ 63 64static void b1isa_remove_ctr(struct capi_ctr *ctrl) 65{ 66 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); 67 avmcard *card = cinfo->card; 68 unsigned int port = card->port; 69 70 b1_reset(port); 71 b1_reset(port); 72 73 di->detach_ctr(ctrl); 74 free_irq(card->irq, card); 75 release_region(card->port, AVMB1_PORTLEN); 76 kfree(card->ctrlinfo); 77 kfree(card); 78 79 MOD_DEC_USE_COUNT; 80} 81 82/* ------------------------------------------------------------- */ 83 84static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p) 85{ 86 avmctrl_info *cinfo; 87 avmcard *card; 88 int retval; 89 90 MOD_INC_USE_COUNT; 91 92 card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC); 93 94 if (!card) { 95 printk(KERN_WARNING "b1isa: no memory.\n"); 96 MOD_DEC_USE_COUNT; 97 return -ENOMEM; 98 } 99 memset(card, 0, sizeof(avmcard)); 100 cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC); 101 if (!cinfo) { 102 printk(KERN_WARNING "b1isa: no memory.\n"); 103 kfree(card); 104 MOD_DEC_USE_COUNT; 105 return -ENOMEM; 106 } 107 memset(cinfo, 0, sizeof(avmctrl_info)); 108 card->ctrlinfo = cinfo; 109 cinfo->card = card; 110 sprintf(card->name, "b1isa-%x", p->port); 111 card->port = p->port; 112 card->irq = p->irq; 113 card->cardtype = avm_b1isa; 114 115 if (check_region(card->port, AVMB1_PORTLEN)) { 116 printk(KERN_WARNING 117 "b1isa: ports 0x%03x-0x%03x in use.\n", 118 card->port, card->port + AVMB1_PORTLEN); 119 kfree(card->ctrlinfo); 120 kfree(card); 121 MOD_DEC_USE_COUNT; 122 return -EBUSY; 123 } 124 if (b1_irq_table[card->irq & 0xf] == 0) { 125 printk(KERN_WARNING "b1isa: irq %d not valid.\n", card->irq); 126 kfree(card->ctrlinfo); 127 kfree(card); 128 MOD_DEC_USE_COUNT; 129 return -EINVAL; 130 } 131 if ( card->port != 0x150 && card->port != 0x250 132 && card->port != 0x300 && card->port != 0x340) { 133 printk(KERN_WARNING "b1isa: illegal port 0x%x.\n", card->port); 134 kfree(card->ctrlinfo); 135 kfree(card); 136 MOD_DEC_USE_COUNT; 137 return -EINVAL; 138 } 139 b1_reset(card->port); 140 if ((retval = b1_detect(card->port, card->cardtype)) != 0) { 141 printk(KERN_NOTICE "b1isa: NO card at 0x%x (%d)\n", 142 card->port, retval); 143 kfree(card->ctrlinfo); 144 kfree(card); 145 MOD_DEC_USE_COUNT; 146 return -EIO; 147 } 148 b1_reset(card->port); 149 b1_getrevision(card); 150 151 request_region(p->port, AVMB1_PORTLEN, card->name); 152 153 retval = request_irq(card->irq, b1isa_interrupt, 0, card->name, card); 154 if (retval) { 155 printk(KERN_ERR "b1isa: unable to get IRQ %d.\n", card->irq); 156 release_region(card->port, AVMB1_PORTLEN); 157 kfree(card->ctrlinfo); 158 kfree(card); 159 MOD_DEC_USE_COUNT; 160 return -EBUSY; 161 } 162 163 cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo); 164 if (!cinfo->capi_ctrl) { 165 printk(KERN_ERR "b1isa: attach controller failed.\n"); 166 free_irq(card->irq, card); 167 release_region(card->port, AVMB1_PORTLEN); 168 kfree(card->ctrlinfo); 169 kfree(card); 170 MOD_DEC_USE_COUNT; 171 return -EBUSY; 172 } 173 174 printk(KERN_INFO 175 "%s: AVM B1 ISA at i/o %#x, irq %d, revision %d\n", 176 driver->name, card->port, card->irq, card->revision); 177 178 return 0; 179} 180 181static char *b1isa_procinfo(struct capi_ctr *ctrl) 182{ 183 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); 184 185 if (!cinfo) 186 return ""; 187 sprintf(cinfo->infobuf, "%s %s 0x%x %d r%d", 188 cinfo->cardname[0] ? cinfo->cardname : "-", 189 cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", 190 cinfo->card ? cinfo->card->port : 0x0, 191 cinfo->card ? cinfo->card->irq : 0, 192 cinfo->card ? cinfo->card->revision : 0 193 ); 194 return cinfo->infobuf; 195} 196 197/* ------------------------------------------------------------- */ 198 199static struct capi_driver b1isa_driver = { 200 name: "b1isa", 201 revision: "0.0", 202 load_firmware: b1_load_firmware, 203 reset_ctr: b1_reset_ctr, 204 remove_ctr: b1isa_remove_ctr, 205 register_appl: b1_register_appl, 206 release_appl: b1_release_appl, 207 send_message: b1_send_message, 208 209 procinfo: b1isa_procinfo, 210 ctr_read_proc: b1ctl_read_proc, 211 driver_read_proc: 0, /* use standard driver_read_proc */ 212 213 add_card: b1isa_add_card, 214}; 215 216static int __init b1isa_init(void) 217{ 218 struct capi_driver *driver = &b1isa_driver; 219 char *p; 220 int retval = 0; 221 222 MOD_INC_USE_COUNT; 223 224 if ((p = strchr(revision, ':')) != 0 && p[1]) { 225 strncpy(driver->revision, p + 2, sizeof(driver->revision)); 226 driver->revision[sizeof(driver->revision)-1] = 0; 227 if ((p = strchr(driver->revision, '$')) != 0 && p > driver->revision) 228 *(p-1) = 0; 229 } 230 231 printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision); 232 233 di = attach_capi_driver(driver); 234 235 if (!di) { 236 printk(KERN_ERR "%s: failed to attach capi_driver\n", 237 driver->name); 238 retval = -EIO; 239 } 240 MOD_DEC_USE_COUNT; 241 return retval; 242} 243 244static void __exit b1isa_exit(void) 245{ 246 detach_capi_driver(&b1isa_driver); 247} 248 249module_init(b1isa_init); 250module_exit(b1isa_exit); 251