1 /*****************************************************************************
2 * sdlamain.c WANPIPE(tm) Multiprotocol WAN Link Driver. Main module.
4 * Author: Gene Kozin <genek@compuserve.com>
6 * Copyright: (c) 1995-1997 Sangoma Technologies Inc.
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 * ============================================================================
13 * Jan 02, 1997 Gene Kozin Initial version.
14 *****************************************************************************/
16 #if !defined(__KERNEL__) || !defined(MODULE)
17 #error This code MUST be compiled as a kernel module!
20 #include <linux/config.h> /* OS configuration options */
21 #include <linux/stddef.h> /* offsetof(), etc. */
22 #include <linux/errno.h> /* return codes */
23 #include <linux/string.h> /* inline memset(), etc. */
24 #include <linux/malloc.h> /* kmalloc(), kfree() */
25 #include <linux/kernel.h> /* printk(), and other useful stuff */
26 #include <linux/module.h> /* support for loadable modules */
27 #include <linux/ioport.h> /* request_region(), release_region() */
28 #include <linux/tqueue.h> /* for kernel task queues */
29 #include <linux/router.h> /* WAN router definitions */
30 #include <linux/wanpipe.h> /* WANPIPE common user API definitions */
31 #include <asm/segment.h> /* kernel <-> user copy */
33 /****** Defines & Macros ****************************************************/
41 #define DRV_VERSION 3 /* version number */
42 #define DRV_RELEASE 0 /* release (minor version) number */
43 #define MAX_CARDS 8 /* max number of adapters */
45 #ifndef CONFIG_WANPIPE_CARDS /* configurable option */
46 #define CONFIG_WANPIPE_CARDS 1
49 #define CMD_OK 0 /* normal firmware return code */
50 #define CMD_TIMEOUT 0xFF /* firmware command timed out */
51 #define MAX_CMD_RETRY 10 /* max number of firmware retries */
53 /****** Function Prototypes *************************************************/
55 /* Module entry points */
56 int init_module (void);
57 void cleanup_module (void);
59 /* WAN link driver entry points */
60 static int setup (wan_device_t
* wandev
, wandev_conf_t
* conf
);
61 static int shutdown (wan_device_t
* wandev
);
62 static int ioctl (wan_device_t
* wandev
, unsigned cmd
, unsigned long arg
);
65 static int ioctl_dump (sdla_t
* card
, sdla_dump_t
* u_dump
);
66 static int ioctl_exec (sdla_t
* card
, sdla_exec_t
* u_exec
);
68 /* Miscellaneous functions */
69 STATIC
void sdla_isr (int irq
, void* dev_id
, struct pt_regs
*regs
);
70 STATIC
void sdla_poll (void* data
);
72 /****** Global Data **********************************************************
73 * Note: All data must be explicitly initialized!!!
77 static char drvname
[] = "wanpipe";
78 static char fullname
[] = "WANPIPE(tm) Multiprotocol Driver";
79 static char copyright
[] = "(c) 1995-1996 Sangoma Technologies Inc.";
80 static int ncards
= CONFIG_WANPIPE_CARDS
;
81 static int active
= 0; /* number of active cards */
82 static sdla_t
* card_array
= NULL
; /* adapter data space */
84 /* Task queue element for creating a 'thread' */
85 static struct tq_struct sdla_tq
=
89 &sdla_poll
, /* .routine */
93 /******* Kernel Loadable Module Entry Points ********************************/
95 /*============================================================================
96 * Module 'insert' entry point.
97 * o print announcement
98 * o allocate adapter data space
99 * o initialize static data
100 * o register all cards with WAN router
101 * o calibrate SDLA shared memory access delay.
107 int init_module (void)
111 printk(KERN_INFO
"%s v%u.%u %s\n",
112 fullname
, DRV_VERSION
, DRV_RELEASE
, copyright
)
115 /* Verify number of cards and allocate adapter data space */
116 ncards
= min(ncards
, MAX_CARDS
);
117 ncards
= max(ncards
, 1);
118 card_array
= kmalloc(sizeof(sdla_t
) * ncards
, GFP_KERNEL
);
119 if (card_array
== NULL
)
122 memset(card_array
, 0, sizeof(sdla_t
) * ncards
);
124 /* Register adapters with WAN router */
125 for (cnt
= 0; cnt
< ncards
; ++cnt
)
127 sdla_t
* card
= &card_array
[cnt
];
128 wan_device_t
* wandev
= &card
->wandev
;
130 sprintf(card
->devname
, "%s%d", drvname
, cnt
+ 1);
131 wandev
->magic
= ROUTER_MAGIC
;
132 wandev
->name
= card
->devname
;
133 wandev
->private = card
;
134 wandev
->setup
= &setup
;
135 wandev
->shutdown
= &shutdown
;
136 wandev
->ioctl
= &ioctl
;
137 err
= register_wandev(wandev
);
141 "%s: %s registration failed with error %d!\n",
142 drvname
, card
->devname
, err
)
147 if (cnt
) ncards
= cnt
; /* adjust actual number of cards */
148 else kfree(card_array
);
152 /*============================================================================
153 * Module 'remove' entry point.
154 * o unregister all adapters from the WAN router
155 * o release all remaining system resources
157 void cleanup_module (void)
161 for (i
= 0; i
< ncards
; ++i
)
163 sdla_t
* card
= &card_array
[i
];
164 unregister_wandev(card
->devname
);
169 /******* WAN Device Driver Entry Points *************************************/
171 /*============================================================================
172 * Setup/confugure WAN link driver.
173 * o check adapter state
174 * o make sure firmware is present in configuration
175 * o make sure I/O port and IRQ are specified
176 * o make sure I/O region is available
177 * o allocate interrupt vector
178 * o setup SDLA hardware
179 * o call appropriate routine to perform protocol-specific initialization
180 * o mark I/O region as used
181 * o if this is the first active card, then schedule background task
183 * This function is called when router handles ROUTER_SETUP IOCTL. The
184 * configuration structure is in kernel memory (including extended data, if
187 static int setup (wan_device_t
* wandev
, wandev_conf_t
* conf
)
194 if ((wandev
== NULL
) || (wandev
->private == NULL
) || (conf
== NULL
))
197 card
= wandev
->private;
198 if (wandev
->state
!= WAN_UNCONFIGURED
)
199 return -EBUSY
/* already configured */
201 if (!conf
->data_size
|| (conf
->data
== NULL
))
204 "%s: firmware not found in configuration data!\n",
209 if (conf
->ioport
<= 0)
212 "%s: can't configure without I/O port address!\n",
219 printk(KERN_ERR
"%s: can't configure without IRQ!\n",
225 /* Make sure I/O port region is available */
226 if (check_region(conf
->ioport
, SDLA_MAXIORANGE
))
228 printk(KERN_ERR
"%s: I/O region 0x%X - 0x%X is in use!\n",
229 wandev
->name
, conf
->ioport
,
230 conf
->ioport
+ SDLA_MAXIORANGE
)
236 irq
= (conf
->irq
== 2) ? 9 : conf
->irq
; /* IRQ2 -> IRQ9 */
237 if (request_irq(irq
, sdla_isr
, 0, wandev
->name
, card
))
239 printk(KERN_ERR
"%s: can't reserve IRQ %d!\n",
245 /* Configure hardware, load firmware, etc. */
246 memset(&card
->hw
, 0, sizeof(sdlahw_t
));
247 card
->hw
.port
= conf
->ioport
;
248 card
->hw
.irq
= (conf
->irq
== 9) ? 2 : conf
->irq
;
249 card
->hw
.dpmbase
= conf
->maddr
;
250 card
->hw
.dpmsize
= SDLA_WINDOWSIZE
;
251 card
->hw
.type
= conf
->hw_opt
[0];
252 card
->hw
.pclk
= conf
->hw_opt
[1];
253 err
= sdla_setup(&card
->hw
, conf
->data
, conf
->data_size
);
260 /* Intialize WAN device data space */
263 wandev
->ioport
= card
->hw
.port
;
264 wandev
->maddr
= card
->hw
.dpmbase
;
265 wandev
->msize
= card
->hw
.dpmsize
;
266 wandev
->hw_opt
[0] = card
->hw
.type
;
267 wandev
->hw_opt
[1] = card
->hw
.pclk
;
268 wandev
->hw_opt
[2] = card
->hw
.memory
;
269 wandev
->hw_opt
[3] = card
->hw
.fwid
;
271 /* Protocol-specific initialization */
272 switch (card
->hw
.fwid
)
274 #ifdef CONFIG_WANPIPE_X25
277 err
= wpx_init(card
, conf
);
281 #ifdef CONFIG_WANPIPE_FR
284 err
= wpf_init(card
, conf
);
288 #ifdef CONFIG_WANPIPE_PPP
291 err
= wpp_init(card
, conf
);
296 printk(KERN_ERR
"%s: this firmware is not supported!\n",
303 sdla_down(&card
->hw
);
307 /* Reserve I/O region and schedule background task */
308 request_region(card
->hw
.port
, card
->hw
.io_range
, wandev
->name
);
310 queue_task(&sdla_tq
, &tq_scheduler
)
312 wandev
->critical
= 0;
316 /*============================================================================
317 * Shut down WAN link driver.
318 * o shut down adapter hardware
319 * o release system resources.
321 * This function is called by the router when device is being unregistered or
322 * when it handles ROUTER_DOWN IOCTL.
324 static int shutdown (wan_device_t
* wandev
)
329 if ((wandev
== NULL
) || (wandev
->private == NULL
))
332 if (wandev
->state
== WAN_UNCONFIGURED
)
335 if (test_and_set_bit(0, (void*)&wandev
->critical
))
338 card
= wandev
->private;
339 wandev
->state
= WAN_UNCONFIGURED
;
340 if (--active
== 0) schedule(); /* stop background thread */
341 sdla_down(&card
->hw
);
342 free_irq(wandev
->irq
, card
);
343 release_region(card
->hw
.port
, card
->hw
.io_range
);
344 wandev
->critical
= 0;
348 /*============================================================================
349 * Driver I/O control.
351 * o perform requested action
353 * This function is called when router handles one of the reserved user
354 * IOCTLs. Note that 'arg' stil points to user address space.
356 static int ioctl (wan_device_t
* wandev
, unsigned cmd
, unsigned long arg
)
361 if ((wandev
== NULL
) || (wandev
->private == NULL
))
364 if (wandev
->state
== WAN_UNCONFIGURED
)
367 if (test_and_set_bit(0, (void*)&wandev
->critical
))
373 err
= ioctl_dump(wandev
->private, (void*)arg
);
377 err
= ioctl_exec(wandev
->private, (void*)arg
);
383 wandev
->critical
= 0;
387 /****** Driver IOCTL Hanlers ************************************************/
389 /*============================================================================
390 * Dump adpater memory to user buffer.
391 * o verify request structure
392 * o copy request structure to kernel data space
393 * o verify length/offset
394 * o verify user buffer
395 * o copy adapter memory image to user buffer
397 * Note: when dumping memory, this routine switches curent dual-port memory
398 * vector, so care must be taken to avoid racing conditions.
400 static int ioctl_dump (sdla_t
* card
, sdla_dump_t
* u_dump
)
404 unsigned long oldvec
; /* DPM window vector */
407 if ((u_dump
== NULL
) ||
408 verify_area(VERIFY_READ
, u_dump
, sizeof(sdla_dump_t
)))
411 memcpy_fromfs((void*)&dump
, (void*)u_dump
, sizeof(sdla_dump_t
));
412 if ((dump
.magic
!= WANPIPE_MAGIC
) ||
413 (dump
.offset
+ dump
.length
> card
->hw
.memory
))
416 if ((dump
.ptr
== NULL
) ||
417 verify_area(VERIFY_WRITE
, dump
.ptr
, dump
.length
))
421 winsize
= card
->hw
.dpmsize
;
422 cli(); /* >>> critical section start <<< */
423 oldvec
= card
->hw
.vector
;
426 unsigned pos
= dump
.offset
% winsize
; /* current offset */
427 unsigned long vec
= dump
.offset
- pos
; /* current vector */
428 unsigned len
= (dump
.length
> (winsize
- pos
)) ?
429 (winsize
- pos
) : dump
.length
431 if (sdla_mapmem(&card
->hw
, vec
) != 0) /* relocate window */
436 memcpy_tofs((void*)(dump
.ptr
),
437 (void*)(card
->hw
.dpmbase
+ pos
), len
)
441 (char*)dump
.ptr
+= len
;
443 sdla_mapmem(&card
->hw
, oldvec
); /* restore DPM window position */
444 sti(); /* >>> critical section end <<< */
448 /*============================================================================
449 * Execute adapter firmware command.
450 * o verify request structure
451 * o copy request structure to kernel data space
452 * o call protocol-specific 'exec' function
454 static int ioctl_exec (sdla_t
* card
, sdla_exec_t
* u_exec
)
458 if (card
->exec
== NULL
)
461 if ((u_exec
== NULL
) ||
462 verify_area(VERIFY_READ
, u_exec
, sizeof(sdla_exec_t
)))
465 memcpy_fromfs((void*)&exec
, (void*)u_exec
, sizeof(sdla_exec_t
));
466 if ((exec
.magic
!= WANPIPE_MAGIC
) || (exec
.cmd
== NULL
))
469 return card
->exec(card
, exec
.cmd
, exec
.data
);
472 /******* Miscellaneous ******************************************************/
474 /*============================================================================
475 * SDLA Interrupt Service Routine.
476 * o acknowledge SDLA hardware interrupt.
477 * o call protocol-specific interrupt service routine, if any.
479 STATIC
void sdla_isr (int irq
, void* dev_id
, struct pt_regs
*regs
)
481 #define card ((sdla_t*)dev_id)
483 if (!card
|| (card
->wandev
.state
== WAN_UNCONFIGURED
))
488 printk(KERN_WARNING
"%s: interrupt re-entrancy on IRQ %d!\n",
489 card
->devname
, card
->wandev
.irq
)
494 sdla_intack(&card
->hw
);
495 if (card
->isr
) card
->isr(card
);
501 /*============================================================================
502 * SDLA polling routine.
503 * This routine simulates kernel thread to perform various housekeeping job.
505 * o for each configured device call its poll() routine
506 * o if there is at least one active card, then reschedule itself once again
508 STATIC
void sdla_poll (void* data
)
512 for (i
= 0; i
< ncards
; ++i
)
514 sdla_t
* card
= &card_array
[i
];
516 if ((card
->wandev
.state
!= WAN_UNCONFIGURED
) && card
->poll
&&
517 !test_and_set_bit(0, (void*)&card
->wandev
.critical
))
520 card
->wandev
.critical
= 0;
523 if (active
) queue_task(&sdla_tq
, &tq_scheduler
);
526 /*============================================================================
527 * This routine is called by the protocol-specific modules when network
528 * interface is being open. The only reason we need this, is because we
529 * have to call MOD_INC_USE_COUNT, but cannot include 'module.h' where it's
530 * defined more than once into the same kernel module.
532 void wanpipe_open (sdla_t
* card
)
538 /*============================================================================
539 * This routine is called by the protocol-specific modules when network
540 * interface is being closed. The only reason we need this, is because we
541 * have to call MOD_DEC_USE_COUNT, but cannot include 'module.h' where it's
542 * defined more than once into the same kernel module.
544 void wanpipe_close (sdla_t
* card
)
550 /*============================================================================
551 * Set WAN device state.
553 void wanpipe_set_state (sdla_t
* card
, int state
)
559 if (card
->wandev
.state
!= state
)
564 printk (KERN_INFO
"%s: link connected!\n",
570 printk (KERN_INFO
"%s: link connecting...\n",
575 case WAN_DISCONNECTED
:
576 printk (KERN_INFO
"%s: link disconnected!\n",
581 card
->wandev
.state
= state
;
583 card
->state_tick
= jiffies
;
584 restore_flags(flags
);
587 /****** End *****************************************************************/