Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.18-rc4 351 lines 9.6 kB view raw
1/* 2* cycx_main.c Cyclades Cyclom 2X WAN Link Driver. Main module. 3* 4* Author: Arnaldo Carvalho de Melo <acme@conectiva.com.br> 5* 6* Copyright: (c) 1998-2003 Arnaldo Carvalho de Melo 7* 8* Based on sdlamain.c by Gene Kozin <genek@compuserve.com> & 9* Jaspreet Singh <jaspreet@sangoma.com> 10* 11* This program is free software; you can redistribute it and/or 12* modify it under the terms of the GNU General Public License 13* as published by the Free Software Foundation; either version 14* 2 of the License, or (at your option) any later version. 15* ============================================================================ 16* Please look at the bitkeeper changelog (or any other scm tool that ends up 17* importing bitkeeper changelog or that replaces bitkeeper in the future as 18* main tool for linux development). 19* 20* 2001/05/09 acme Fix MODULE_DESC for debug, .bss nitpicks, 21* some cleanups 22* 2000/07/13 acme remove useless #ifdef MODULE and crap 23* #if KERNEL_VERSION > blah 24* 2000/07/06 acme __exit at cyclomx_cleanup 25* 2000/04/02 acme dprintk and cycx_debug 26* module_init/module_exit 27* 2000/01/21 acme rename cyclomx_open to cyclomx_mod_inc_use_count 28* and cyclomx_close to cyclomx_mod_dec_use_count 29* 2000/01/08 acme cleanup 30* 1999/11/06 acme cycx_down back to life (it needs to be 31* called to iounmap the dpmbase) 32* 1999/08/09 acme removed references to enable_tx_int 33* use spinlocks instead of cli/sti in 34* cyclomx_set_state 35* 1999/05/19 acme works directly linked into the kernel 36* init_waitqueue_head for 2.3.* kernel 37* 1999/05/18 acme major cleanup (polling not needed), etc 38* 1998/08/28 acme minor cleanup (ioctls for firmware deleted) 39* queue_task activated 40* 1998/08/08 acme Initial version. 41*/ 42 43#include <linux/config.h> /* OS configuration options */ 44#include <linux/stddef.h> /* offsetof(), etc. */ 45#include <linux/errno.h> /* return codes */ 46#include <linux/string.h> /* inline memset(), etc. */ 47#include <linux/slab.h> /* kmalloc(), kfree() */ 48#include <linux/kernel.h> /* printk(), and other useful stuff */ 49#include <linux/module.h> /* support for loadable modules */ 50#include <linux/ioport.h> /* request_region(), release_region() */ 51#include <linux/wanrouter.h> /* WAN router definitions */ 52#include <linux/cyclomx.h> /* cyclomx common user API definitions */ 53#include <linux/init.h> /* __init (when not using as a module) */ 54 55unsigned int cycx_debug; 56 57MODULE_AUTHOR("Arnaldo Carvalho de Melo"); 58MODULE_DESCRIPTION("Cyclom 2X Sync Card Driver."); 59MODULE_LICENSE("GPL"); 60module_param(cycx_debug, int, 0); 61MODULE_PARM_DESC(cycx_debug, "cyclomx debug level"); 62 63/* Defines & Macros */ 64 65#define CYCX_DRV_VERSION 0 /* version number */ 66#define CYCX_DRV_RELEASE 11 /* release (minor version) number */ 67#define CYCX_MAX_CARDS 1 /* max number of adapters */ 68 69#define CONFIG_CYCX_CARDS 1 70 71/* Function Prototypes */ 72 73/* WAN link driver entry points */ 74static int cycx_wan_setup(struct wan_device *wandev, wandev_conf_t *conf); 75static int cycx_wan_shutdown(struct wan_device *wandev); 76 77/* Miscellaneous functions */ 78static irqreturn_t cycx_isr(int irq, void *dev_id, struct pt_regs *regs); 79 80/* Global Data 81 * Note: All data must be explicitly initialized!!! 82 */ 83 84/* private data */ 85static char cycx_drvname[] = "cyclomx"; 86static char cycx_fullname[] = "CYCLOM 2X(tm) Sync Card Driver"; 87static char cycx_copyright[] = "(c) 1998-2003 Arnaldo Carvalho de Melo " 88 "<acme@conectiva.com.br>"; 89static int cycx_ncards = CONFIG_CYCX_CARDS; 90static struct cycx_device *cycx_card_array; /* adapter data space */ 91 92/* Kernel Loadable Module Entry Points */ 93 94/* 95 * Module 'insert' entry point. 96 * o print announcement 97 * o allocate adapter data space 98 * o initialize static data 99 * o register all cards with WAN router 100 * o calibrate Cyclom 2X shared memory access delay. 101 * 102 * Return: 0 Ok 103 * < 0 error. 104 * Context: process 105 */ 106static int __init cycx_init(void) 107{ 108 int cnt, err = -ENOMEM; 109 110 printk(KERN_INFO "%s v%u.%u %s\n", 111 cycx_fullname, CYCX_DRV_VERSION, CYCX_DRV_RELEASE, 112 cycx_copyright); 113 114 /* Verify number of cards and allocate adapter data space */ 115 cycx_ncards = min_t(int, cycx_ncards, CYCX_MAX_CARDS); 116 cycx_ncards = max_t(int, cycx_ncards, 1); 117 cycx_card_array = kmalloc(sizeof(struct cycx_device) * cycx_ncards, 118 GFP_KERNEL); 119 if (!cycx_card_array) 120 goto out; 121 122 memset(cycx_card_array, 0, sizeof(struct cycx_device) * cycx_ncards); 123 124 /* Register adapters with WAN router */ 125 for (cnt = 0; cnt < cycx_ncards; ++cnt) { 126 struct cycx_device *card = &cycx_card_array[cnt]; 127 struct wan_device *wandev = &card->wandev; 128 129 sprintf(card->devname, "%s%d", cycx_drvname, cnt + 1); 130 wandev->magic = ROUTER_MAGIC; 131 wandev->name = card->devname; 132 wandev->private = card; 133 wandev->setup = cycx_wan_setup; 134 wandev->shutdown = cycx_wan_shutdown; 135 err = register_wan_device(wandev); 136 137 if (err) { 138 printk(KERN_ERR "%s: %s registration failed with " 139 "error %d!\n", 140 cycx_drvname, card->devname, err); 141 break; 142 } 143 } 144 145 err = -ENODEV; 146 if (!cnt) { 147 kfree(cycx_card_array); 148 goto out; 149 } 150 err = 0; 151 cycx_ncards = cnt; /* adjust actual number of cards */ 152out: return err; 153} 154 155/* 156 * Module 'remove' entry point. 157 * o unregister all adapters from the WAN router 158 * o release all remaining system resources 159 */ 160static void __exit cycx_exit(void) 161{ 162 int i = 0; 163 164 for (; i < cycx_ncards; ++i) { 165 struct cycx_device *card = &cycx_card_array[i]; 166 unregister_wan_device(card->devname); 167 } 168 169 kfree(cycx_card_array); 170} 171 172/* WAN Device Driver Entry Points */ 173/* 174 * Setup/configure WAN link driver. 175 * o check adapter state 176 * o make sure firmware is present in configuration 177 * o allocate interrupt vector 178 * o setup Cyclom 2X hardware 179 * o call appropriate routine to perform protocol-specific initialization 180 * 181 * This function is called when router handles ROUTER_SETUP IOCTL. The 182 * configuration structure is in kernel memory (including extended data, if 183 * any). 184 */ 185static int cycx_wan_setup(struct wan_device *wandev, wandev_conf_t *conf) 186{ 187 int rc = -EFAULT; 188 struct cycx_device *card; 189 int irq; 190 191 /* Sanity checks */ 192 193 if (!wandev || !wandev->private || !conf) 194 goto out; 195 196 card = wandev->private; 197 rc = -EBUSY; 198 if (wandev->state != WAN_UNCONFIGURED) 199 goto out; 200 201 rc = -EINVAL; 202 if (!conf->data_size || !conf->data) { 203 printk(KERN_ERR "%s: firmware not found in configuration " 204 "data!\n", wandev->name); 205 goto out; 206 } 207 208 if (conf->irq <= 0) { 209 printk(KERN_ERR "%s: can't configure without IRQ!\n", 210 wandev->name); 211 goto out; 212 } 213 214 /* Allocate IRQ */ 215 irq = conf->irq == 2 ? 9 : conf->irq; /* IRQ2 -> IRQ9 */ 216 217 if (request_irq(irq, cycx_isr, 0, wandev->name, card)) { 218 printk(KERN_ERR "%s: can't reserve IRQ %d!\n", 219 wandev->name, irq); 220 goto out; 221 } 222 223 /* Configure hardware, load firmware, etc. */ 224 memset(&card->hw, 0, sizeof(card->hw)); 225 card->hw.irq = irq; 226 card->hw.dpmsize = CYCX_WINDOWSIZE; 227 card->hw.fwid = CFID_X25_2X; 228 spin_lock_init(&card->lock); 229 init_waitqueue_head(&card->wait_stats); 230 231 rc = cycx_setup(&card->hw, conf->data, conf->data_size, conf->maddr); 232 if (rc) 233 goto out_irq; 234 235 /* Initialize WAN device data space */ 236 wandev->irq = irq; 237 wandev->dma = wandev->ioport = 0; 238 wandev->maddr = (unsigned long)card->hw.dpmbase; 239 wandev->msize = card->hw.dpmsize; 240 wandev->hw_opt[2] = 0; 241 wandev->hw_opt[3] = card->hw.fwid; 242 243 /* Protocol-specific initialization */ 244 switch (card->hw.fwid) { 245#ifdef CONFIG_CYCLOMX_X25 246 case CFID_X25_2X: 247 rc = cycx_x25_wan_init(card, conf); 248 break; 249#endif 250 default: 251 printk(KERN_ERR "%s: this firmware is not supported!\n", 252 wandev->name); 253 rc = -EINVAL; 254 } 255 256 if (rc) { 257 cycx_down(&card->hw); 258 goto out_irq; 259 } 260 261 rc = 0; 262out: 263 return rc; 264out_irq: 265 free_irq(irq, card); 266 goto out; 267} 268 269/* 270 * Shut down WAN link driver. 271 * o shut down adapter hardware 272 * o release system resources. 273 * 274 * This function is called by the router when device is being unregistered or 275 * when it handles ROUTER_DOWN IOCTL. 276 */ 277static int cycx_wan_shutdown(struct wan_device *wandev) 278{ 279 int ret = -EFAULT; 280 struct cycx_device *card; 281 282 /* sanity checks */ 283 if (!wandev || !wandev->private) 284 goto out; 285 286 ret = 0; 287 if (wandev->state == WAN_UNCONFIGURED) 288 goto out; 289 290 card = wandev->private; 291 wandev->state = WAN_UNCONFIGURED; 292 cycx_down(&card->hw); 293 printk(KERN_INFO "%s: irq %d being freed!\n", wandev->name, 294 wandev->irq); 295 free_irq(wandev->irq, card); 296out: return ret; 297} 298 299/* Miscellaneous */ 300/* 301 * Cyclom 2X Interrupt Service Routine. 302 * o acknowledge Cyclom 2X hardware interrupt. 303 * o call protocol-specific interrupt service routine, if any. 304 */ 305static irqreturn_t cycx_isr(int irq, void *dev_id, struct pt_regs *regs) 306{ 307 struct cycx_device *card = (struct cycx_device *)dev_id; 308 309 if (!card || card->wandev.state == WAN_UNCONFIGURED) 310 goto out; 311 312 if (card->in_isr) { 313 printk(KERN_WARNING "%s: interrupt re-entrancy on IRQ %d!\n", 314 card->devname, card->wandev.irq); 315 goto out; 316 } 317 318 if (card->isr) 319 card->isr(card); 320 return IRQ_HANDLED; 321out: 322 return IRQ_NONE; 323} 324 325/* Set WAN device state. */ 326void cycx_set_state(struct cycx_device *card, int state) 327{ 328 unsigned long flags; 329 char *string_state = NULL; 330 331 spin_lock_irqsave(&card->lock, flags); 332 333 if (card->wandev.state != state) { 334 switch (state) { 335 case WAN_CONNECTED: 336 string_state = "connected!"; 337 break; 338 case WAN_DISCONNECTED: 339 string_state = "disconnected!"; 340 break; 341 } 342 printk(KERN_INFO "%s: link %s\n", card->devname, string_state); 343 card->wandev.state = state; 344 } 345 346 card->state_tick = jiffies; 347 spin_unlock_irqrestore(&card->lock, flags); 348} 349 350module_init(cycx_init); 351module_exit(cycx_exit);