diff options
Diffstat (limited to 'drivers/isdn/pcbit/drv.c')
-rw-r--r-- | drivers/isdn/pcbit/drv.c | 1088 |
1 files changed, 1088 insertions, 0 deletions
diff --git a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c new file mode 100644 index 000000000000..e98f9c48c184 --- /dev/null +++ b/drivers/isdn/pcbit/drv.c | |||
@@ -0,0 +1,1088 @@ | |||
1 | /* | ||
2 | * PCBIT-D interface with isdn4linux | ||
3 | * | ||
4 | * Copyright (C) 1996 Universidade de Lisboa | ||
5 | * | ||
6 | * Written by Pedro Roque Marques (roque@di.fc.ul.pt) | ||
7 | * | ||
8 | * This software may be used and distributed according to the terms of | ||
9 | * the GNU General Public License, incorporated herein by reference. | ||
10 | */ | ||
11 | |||
12 | /* | ||
13 | * Fixes: | ||
14 | * | ||
15 | * Nuno Grilo <l38486@alfa.ist.utl.pt> | ||
16 | * fixed msn_list NULL pointer dereference. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | |||
22 | #include <linux/sched.h> | ||
23 | |||
24 | #include <linux/kernel.h> | ||
25 | |||
26 | #include <linux/types.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/mm.h> | ||
29 | #include <linux/interrupt.h> | ||
30 | #include <linux/string.h> | ||
31 | #include <linux/skbuff.h> | ||
32 | |||
33 | #include <linux/isdnif.h> | ||
34 | #include <asm/string.h> | ||
35 | #include <asm/io.h> | ||
36 | #include <linux/ioport.h> | ||
37 | |||
38 | #include "pcbit.h" | ||
39 | #include "edss1.h" | ||
40 | #include "layer2.h" | ||
41 | #include "capi.h" | ||
42 | |||
43 | |||
44 | extern ushort last_ref_num; | ||
45 | |||
46 | static int pcbit_ioctl(isdn_ctrl* ctl); | ||
47 | |||
48 | static char* pcbit_devname[MAX_PCBIT_CARDS] = { | ||
49 | "pcbit0", | ||
50 | "pcbit1", | ||
51 | "pcbit2", | ||
52 | "pcbit3" | ||
53 | }; | ||
54 | |||
55 | /* | ||
56 | * prototypes | ||
57 | */ | ||
58 | |||
59 | int pcbit_command(isdn_ctrl* ctl); | ||
60 | int pcbit_stat(u_char __user * buf, int len, int, int); | ||
61 | int pcbit_xmit(int driver, int chan, int ack, struct sk_buff *skb); | ||
62 | int pcbit_writecmd(const u_char __user *, int, int, int); | ||
63 | |||
64 | static int set_protocol_running(struct pcbit_dev * dev); | ||
65 | |||
66 | static void pcbit_clear_msn(struct pcbit_dev *dev); | ||
67 | static void pcbit_set_msn(struct pcbit_dev *dev, char *list); | ||
68 | static int pcbit_check_msn(struct pcbit_dev *dev, char *msn); | ||
69 | |||
70 | |||
71 | extern void pcbit_deliver(void * data); | ||
72 | |||
73 | int pcbit_init_dev(int board, int mem_base, int irq) | ||
74 | { | ||
75 | struct pcbit_dev *dev; | ||
76 | isdn_if *dev_if; | ||
77 | |||
78 | if ((dev=kmalloc(sizeof(struct pcbit_dev), GFP_KERNEL)) == NULL) | ||
79 | { | ||
80 | printk("pcbit_init: couldn't malloc pcbit_dev struct\n"); | ||
81 | return -ENOMEM; | ||
82 | } | ||
83 | |||
84 | dev_pcbit[board] = dev; | ||
85 | memset(dev, 0, sizeof(struct pcbit_dev)); | ||
86 | init_waitqueue_head(&dev->set_running_wq); | ||
87 | spin_lock_init(&dev->lock); | ||
88 | |||
89 | if (mem_base >= 0xA0000 && mem_base <= 0xFFFFF ) { | ||
90 | dev->ph_mem = mem_base; | ||
91 | if (!request_mem_region(dev->ph_mem, 4096, "PCBIT mem")) { | ||
92 | printk(KERN_WARNING | ||
93 | "PCBIT: memory region %lx-%lx already in use\n", | ||
94 | dev->ph_mem, dev->ph_mem + 4096); | ||
95 | kfree(dev); | ||
96 | dev_pcbit[board] = NULL; | ||
97 | return -EACCES; | ||
98 | } | ||
99 | dev->sh_mem = ioremap(dev->ph_mem, 4096); | ||
100 | } | ||
101 | else | ||
102 | { | ||
103 | printk("memory address invalid"); | ||
104 | kfree(dev); | ||
105 | dev_pcbit[board] = NULL; | ||
106 | return -EACCES; | ||
107 | } | ||
108 | |||
109 | dev->b1 = kmalloc(sizeof(struct pcbit_chan), GFP_KERNEL); | ||
110 | if (!dev->b1) { | ||
111 | printk("pcbit_init: couldn't malloc pcbit_chan struct\n"); | ||
112 | iounmap(dev->sh_mem); | ||
113 | release_mem_region(dev->ph_mem, 4096); | ||
114 | kfree(dev); | ||
115 | return -ENOMEM; | ||
116 | } | ||
117 | |||
118 | dev->b2 = kmalloc(sizeof(struct pcbit_chan), GFP_KERNEL); | ||
119 | if (!dev->b2) { | ||
120 | printk("pcbit_init: couldn't malloc pcbit_chan struct\n"); | ||
121 | kfree(dev->b1); | ||
122 | iounmap(dev->sh_mem); | ||
123 | release_mem_region(dev->ph_mem, 4096); | ||
124 | kfree(dev); | ||
125 | return -ENOMEM; | ||
126 | } | ||
127 | |||
128 | memset(dev->b1, 0, sizeof(struct pcbit_chan)); | ||
129 | memset(dev->b2, 0, sizeof(struct pcbit_chan)); | ||
130 | dev->b2->id = 1; | ||
131 | |||
132 | INIT_WORK(&dev->qdelivery, pcbit_deliver, dev); | ||
133 | |||
134 | /* | ||
135 | * interrupts | ||
136 | */ | ||
137 | |||
138 | if (request_irq(irq, &pcbit_irq_handler, 0, pcbit_devname[board], dev) != 0) | ||
139 | { | ||
140 | kfree(dev->b1); | ||
141 | kfree(dev->b2); | ||
142 | iounmap(dev->sh_mem); | ||
143 | release_mem_region(dev->ph_mem, 4096); | ||
144 | kfree(dev); | ||
145 | dev_pcbit[board] = NULL; | ||
146 | return -EIO; | ||
147 | } | ||
148 | |||
149 | dev->irq = irq; | ||
150 | |||
151 | /* next frame to be received */ | ||
152 | dev->rcv_seq = 0; | ||
153 | dev->send_seq = 0; | ||
154 | dev->unack_seq = 0; | ||
155 | |||
156 | dev->hl_hdrlen = 16; | ||
157 | |||
158 | dev_if = kmalloc(sizeof(isdn_if), GFP_KERNEL); | ||
159 | |||
160 | if (!dev_if) { | ||
161 | free_irq(irq, dev); | ||
162 | kfree(dev->b1); | ||
163 | kfree(dev->b2); | ||
164 | iounmap(dev->sh_mem); | ||
165 | release_mem_region(dev->ph_mem, 4096); | ||
166 | kfree(dev); | ||
167 | dev_pcbit[board] = NULL; | ||
168 | return -EIO; | ||
169 | } | ||
170 | |||
171 | dev->dev_if = dev_if; | ||
172 | |||
173 | dev_if->owner = THIS_MODULE; | ||
174 | |||
175 | dev_if->channels = 2; | ||
176 | |||
177 | dev_if->features = (ISDN_FEATURE_P_EURO | ISDN_FEATURE_L3_TRANS | | ||
178 | ISDN_FEATURE_L2_HDLC | ISDN_FEATURE_L2_TRANS ); | ||
179 | |||
180 | dev_if->writebuf_skb = pcbit_xmit; | ||
181 | dev_if->hl_hdrlen = 16; | ||
182 | |||
183 | dev_if->maxbufsize = MAXBUFSIZE; | ||
184 | dev_if->command = pcbit_command; | ||
185 | |||
186 | dev_if->writecmd = pcbit_writecmd; | ||
187 | dev_if->readstat = pcbit_stat; | ||
188 | |||
189 | |||
190 | strcpy(dev_if->id, pcbit_devname[board]); | ||
191 | |||
192 | if (!register_isdn(dev_if)) { | ||
193 | free_irq(irq, dev); | ||
194 | kfree(dev->b1); | ||
195 | kfree(dev->b2); | ||
196 | iounmap(dev->sh_mem); | ||
197 | release_mem_region(dev->ph_mem, 4096); | ||
198 | kfree(dev); | ||
199 | dev_pcbit[board] = NULL; | ||
200 | return -EIO; | ||
201 | } | ||
202 | |||
203 | dev->id = dev_if->channels; | ||
204 | |||
205 | |||
206 | dev->l2_state = L2_DOWN; | ||
207 | dev->free = 511; | ||
208 | |||
209 | /* | ||
210 | * set_protocol_running(dev); | ||
211 | */ | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | #ifdef MODULE | ||
217 | void pcbit_terminate(int board) | ||
218 | { | ||
219 | struct pcbit_dev * dev; | ||
220 | |||
221 | dev = dev_pcbit[board]; | ||
222 | |||
223 | if (dev) { | ||
224 | /* unregister_isdn(dev->dev_if); */ | ||
225 | free_irq(dev->irq, dev); | ||
226 | pcbit_clear_msn(dev); | ||
227 | kfree(dev->dev_if); | ||
228 | if (dev->b1->fsm_timer.function) | ||
229 | del_timer(&dev->b1->fsm_timer); | ||
230 | if (dev->b2->fsm_timer.function) | ||
231 | del_timer(&dev->b2->fsm_timer); | ||
232 | kfree(dev->b1); | ||
233 | kfree(dev->b2); | ||
234 | iounmap(dev->sh_mem); | ||
235 | release_mem_region(dev->ph_mem, 4096); | ||
236 | kfree(dev); | ||
237 | } | ||
238 | } | ||
239 | #endif | ||
240 | |||
241 | int pcbit_command(isdn_ctrl* ctl) | ||
242 | { | ||
243 | struct pcbit_dev *dev; | ||
244 | struct pcbit_chan *chan; | ||
245 | struct callb_data info; | ||
246 | |||
247 | dev = finddev(ctl->driver); | ||
248 | |||
249 | if (!dev) | ||
250 | { | ||
251 | printk("pcbit_command: unknown device\n"); | ||
252 | return -1; | ||
253 | } | ||
254 | |||
255 | chan = (ctl->arg & 0x0F) ? dev->b2 : dev->b1; | ||
256 | |||
257 | |||
258 | switch(ctl->command) { | ||
259 | case ISDN_CMD_IOCTL: | ||
260 | return pcbit_ioctl(ctl); | ||
261 | break; | ||
262 | case ISDN_CMD_DIAL: | ||
263 | info.type = EV_USR_SETUP_REQ; | ||
264 | info.data.setup.CalledPN = (char *) &ctl->parm.setup.phone; | ||
265 | pcbit_fsm_event(dev, chan, EV_USR_SETUP_REQ, &info); | ||
266 | break; | ||
267 | case ISDN_CMD_ACCEPTD: | ||
268 | pcbit_fsm_event(dev, chan, EV_USR_SETUP_RESP, NULL); | ||
269 | break; | ||
270 | case ISDN_CMD_ACCEPTB: | ||
271 | printk("ISDN_CMD_ACCEPTB - not really needed\n"); | ||
272 | break; | ||
273 | case ISDN_CMD_HANGUP: | ||
274 | pcbit_fsm_event(dev, chan, EV_USR_RELEASE_REQ, NULL); | ||
275 | break; | ||
276 | case ISDN_CMD_SETL2: | ||
277 | chan->proto = (ctl->arg >> 8); | ||
278 | break; | ||
279 | case ISDN_CMD_CLREAZ: | ||
280 | pcbit_clear_msn(dev); | ||
281 | break; | ||
282 | case ISDN_CMD_SETEAZ: | ||
283 | pcbit_set_msn(dev, ctl->parm.num); | ||
284 | break; | ||
285 | case ISDN_CMD_SETL3: | ||
286 | if ((ctl->arg >> 8) != ISDN_PROTO_L3_TRANS) | ||
287 | printk(KERN_DEBUG "L3 protocol unknown\n"); | ||
288 | break; | ||
289 | default: | ||
290 | printk(KERN_DEBUG "pcbit_command: unknown command\n"); | ||
291 | break; | ||
292 | }; | ||
293 | |||
294 | return 0; | ||
295 | } | ||
296 | |||
297 | /* | ||
298 | * Another Hack :-( | ||
299 | * on some conditions the board stops sending TDATA_CONFs | ||
300 | * let's see if we can turn around the problem | ||
301 | */ | ||
302 | |||
303 | #ifdef BLOCK_TIMER | ||
304 | static void pcbit_block_timer(unsigned long data) | ||
305 | { | ||
306 | struct pcbit_chan *chan; | ||
307 | struct pcbit_dev * dev; | ||
308 | isdn_ctrl ictl; | ||
309 | |||
310 | chan = (struct pcbit_chan *) data; | ||
311 | |||
312 | dev = chan2dev(chan); | ||
313 | |||
314 | if (dev == NULL) { | ||
315 | printk(KERN_DEBUG "pcbit: chan2dev failed\n"); | ||
316 | return; | ||
317 | } | ||
318 | |||
319 | del_timer(&chan->block_timer); | ||
320 | chan->block_timer.function = NULL; | ||
321 | |||
322 | #ifdef DEBUG | ||
323 | printk(KERN_DEBUG "pcbit_block_timer\n"); | ||
324 | #endif | ||
325 | chan->queued = 0; | ||
326 | ictl.driver = dev->id; | ||
327 | ictl.command = ISDN_STAT_BSENT; | ||
328 | ictl.arg = chan->id; | ||
329 | dev->dev_if->statcallb(&ictl); | ||
330 | } | ||
331 | #endif | ||
332 | |||
333 | int pcbit_xmit(int driver, int chnum, int ack, struct sk_buff *skb) | ||
334 | { | ||
335 | ushort hdrlen; | ||
336 | int refnum, len; | ||
337 | struct pcbit_chan * chan; | ||
338 | struct pcbit_dev *dev; | ||
339 | |||
340 | dev = finddev(driver); | ||
341 | if (dev == NULL) | ||
342 | { | ||
343 | printk("finddev returned NULL"); | ||
344 | return -1; | ||
345 | } | ||
346 | |||
347 | chan = chnum ? dev->b2 : dev->b1; | ||
348 | |||
349 | |||
350 | if (chan->fsm_state != ST_ACTIVE) | ||
351 | return -1; | ||
352 | |||
353 | if (chan->queued >= MAX_QUEUED ) | ||
354 | { | ||
355 | #ifdef DEBUG_QUEUE | ||
356 | printk(KERN_DEBUG | ||
357 | "pcbit: %d packets already in queue - write fails\n", | ||
358 | chan->queued); | ||
359 | #endif | ||
360 | /* | ||
361 | * packet stays on the head of the device queue | ||
362 | * since dev_start_xmit will fail | ||
363 | * see net/core/dev.c | ||
364 | */ | ||
365 | #ifdef BLOCK_TIMER | ||
366 | if (chan->block_timer.function == NULL) { | ||
367 | init_timer(&chan->block_timer); | ||
368 | chan->block_timer.function = &pcbit_block_timer; | ||
369 | chan->block_timer.data = (long) chan; | ||
370 | chan->block_timer.expires = jiffies + 1 * HZ; | ||
371 | add_timer(&chan->block_timer); | ||
372 | } | ||
373 | #endif | ||
374 | return 0; | ||
375 | } | ||
376 | |||
377 | |||
378 | chan->queued++; | ||
379 | |||
380 | len = skb->len; | ||
381 | |||
382 | hdrlen = capi_tdata_req(chan, skb); | ||
383 | |||
384 | refnum = last_ref_num++ & 0x7fffU; | ||
385 | chan->s_refnum = refnum; | ||
386 | |||
387 | pcbit_l2_write(dev, MSG_TDATA_REQ, refnum, skb, hdrlen); | ||
388 | |||
389 | return len; | ||
390 | } | ||
391 | |||
392 | int pcbit_writecmd(const u_char __user *buf, int len, int driver, int channel) | ||
393 | { | ||
394 | struct pcbit_dev * dev; | ||
395 | int i, j; | ||
396 | const u_char * loadbuf; | ||
397 | u_char * ptr = NULL; | ||
398 | u_char *cbuf; | ||
399 | |||
400 | int errstat; | ||
401 | |||
402 | dev = finddev(driver); | ||
403 | |||
404 | if (!dev) | ||
405 | { | ||
406 | printk("pcbit_writecmd: couldn't find device"); | ||
407 | return -ENODEV; | ||
408 | } | ||
409 | |||
410 | switch(dev->l2_state) { | ||
411 | case L2_LWMODE: | ||
412 | /* check (size <= rdp_size); write buf into board */ | ||
413 | if (len < 0 || len > BANK4 + 1 || len > 1024) | ||
414 | { | ||
415 | printk("pcbit_writecmd: invalid length %d\n", len); | ||
416 | return -EINVAL; | ||
417 | } | ||
418 | |||
419 | cbuf = kmalloc(len, GFP_KERNEL); | ||
420 | if (!cbuf) | ||
421 | return -ENOMEM; | ||
422 | |||
423 | if (copy_from_user(cbuf, buf, len)) { | ||
424 | kfree(cbuf); | ||
425 | return -EFAULT; | ||
426 | } | ||
427 | memcpy_toio(dev->sh_mem, cbuf, len); | ||
428 | kfree(cbuf); | ||
429 | return len; | ||
430 | case L2_FWMODE: | ||
431 | /* this is the hard part */ | ||
432 | /* dumb board */ | ||
433 | /* get it into kernel space */ | ||
434 | if ((ptr = kmalloc(len, GFP_KERNEL))==NULL) | ||
435 | return -ENOMEM; | ||
436 | if (copy_from_user(ptr, buf, len)) { | ||
437 | kfree(ptr); | ||
438 | return -EFAULT; | ||
439 | } | ||
440 | loadbuf = ptr; | ||
441 | |||
442 | errstat = 0; | ||
443 | |||
444 | for (i=0; i < len; i++) | ||
445 | { | ||
446 | for(j=0; j < LOAD_RETRY; j++) | ||
447 | if (!(readb(dev->sh_mem + dev->loadptr))) | ||
448 | break; | ||
449 | |||
450 | if (j == LOAD_RETRY) | ||
451 | { | ||
452 | errstat = -ETIME; | ||
453 | printk("TIMEOUT i=%d\n", i); | ||
454 | break; | ||
455 | } | ||
456 | writeb(loadbuf[i], dev->sh_mem + dev->loadptr + 1); | ||
457 | writeb(0x01, dev->sh_mem + dev->loadptr); | ||
458 | |||
459 | dev->loadptr += 2; | ||
460 | if (dev->loadptr > LOAD_ZONE_END) | ||
461 | dev->loadptr = LOAD_ZONE_START; | ||
462 | } | ||
463 | kfree(ptr); | ||
464 | |||
465 | return errstat ? errstat : len; | ||
466 | default: | ||
467 | return -EBUSY; | ||
468 | } | ||
469 | } | ||
470 | |||
471 | /* | ||
472 | * demultiplexing of messages | ||
473 | * | ||
474 | */ | ||
475 | |||
476 | void pcbit_l3_receive(struct pcbit_dev * dev, ulong msg, | ||
477 | struct sk_buff * skb, | ||
478 | ushort hdr_len, ushort refnum) | ||
479 | { | ||
480 | struct pcbit_chan *chan; | ||
481 | struct sk_buff *skb2; | ||
482 | unsigned short len; | ||
483 | struct callb_data cbdata; | ||
484 | int complete, err; | ||
485 | isdn_ctrl ictl; | ||
486 | |||
487 | switch(msg) { | ||
488 | |||
489 | case MSG_TDATA_IND: | ||
490 | if (!(chan = capi_channel(dev, skb))) { | ||
491 | printk(KERN_WARNING | ||
492 | "CAPI header: unknown channel id\n"); | ||
493 | break; | ||
494 | } | ||
495 | chan->r_refnum = skb->data[7]; | ||
496 | skb_pull(skb, 8); | ||
497 | |||
498 | dev->dev_if->rcvcallb_skb(dev->id, chan->id, skb); | ||
499 | |||
500 | if (capi_tdata_resp(chan, &skb2) > 0) | ||
501 | pcbit_l2_write(dev, MSG_TDATA_RESP, refnum, | ||
502 | skb2, skb2->len); | ||
503 | return; | ||
504 | break; | ||
505 | case MSG_TDATA_CONF: | ||
506 | if (!(chan = capi_channel(dev, skb))) { | ||
507 | printk(KERN_WARNING | ||
508 | "CAPI header: unknown channel id\n"); | ||
509 | break; | ||
510 | } | ||
511 | |||
512 | #ifdef DEBUG | ||
513 | if ( (*((ushort *) (skb->data + 2) )) != 0) { | ||
514 | printk(KERN_DEBUG "TDATA_CONF error\n"); | ||
515 | } | ||
516 | #endif | ||
517 | #ifdef BLOCK_TIMER | ||
518 | if (chan->queued == MAX_QUEUED) { | ||
519 | del_timer(&chan->block_timer); | ||
520 | chan->block_timer.function = NULL; | ||
521 | } | ||
522 | |||
523 | #endif | ||
524 | chan->queued--; | ||
525 | |||
526 | ictl.driver = dev->id; | ||
527 | ictl.command = ISDN_STAT_BSENT; | ||
528 | ictl.arg = chan->id; | ||
529 | dev->dev_if->statcallb(&ictl); | ||
530 | break; | ||
531 | |||
532 | case MSG_CONN_IND: | ||
533 | /* | ||
534 | * channel: 1st not used will do | ||
535 | * if both are used we're in trouble | ||
536 | */ | ||
537 | |||
538 | if (!dev->b1->fsm_state) | ||
539 | chan = dev->b1; | ||
540 | else if (!dev->b2->fsm_state) | ||
541 | chan = dev->b2; | ||
542 | else { | ||
543 | printk(KERN_INFO | ||
544 | "Incoming connection: no channels available"); | ||
545 | |||
546 | if ((len = capi_disc_req(*(ushort*)(skb->data), &skb2, CAUSE_NOCHAN)) > 0) | ||
547 | pcbit_l2_write(dev, MSG_DISC_REQ, refnum, skb2, len); | ||
548 | break; | ||
549 | } | ||
550 | |||
551 | cbdata.data.setup.CalledPN = NULL; | ||
552 | cbdata.data.setup.CallingPN = NULL; | ||
553 | |||
554 | capi_decode_conn_ind(chan, skb, &cbdata); | ||
555 | cbdata.type = EV_NET_SETUP; | ||
556 | |||
557 | pcbit_fsm_event(dev, chan, EV_NET_SETUP, NULL); | ||
558 | |||
559 | if (pcbit_check_msn(dev, cbdata.data.setup.CallingPN)) | ||
560 | pcbit_fsm_event(dev, chan, EV_USR_PROCED_REQ, &cbdata); | ||
561 | else | ||
562 | pcbit_fsm_event(dev, chan, EV_USR_RELEASE_REQ, NULL); | ||
563 | |||
564 | if (cbdata.data.setup.CalledPN) | ||
565 | kfree(cbdata.data.setup.CalledPN); | ||
566 | if (cbdata.data.setup.CallingPN) | ||
567 | kfree(cbdata.data.setup.CallingPN); | ||
568 | break; | ||
569 | |||
570 | case MSG_CONN_CONF: | ||
571 | /* | ||
572 | * We should be able to find the channel by the message | ||
573 | * reference number. The current version of the firmware | ||
574 | * doesn't sent the ref number correctly. | ||
575 | */ | ||
576 | #ifdef DEBUG | ||
577 | printk(KERN_DEBUG "refnum=%04x b1=%04x b2=%04x\n", refnum, | ||
578 | dev->b1->s_refnum, | ||
579 | dev->b2->s_refnum); | ||
580 | #endif | ||
581 | /* We just try to find a channel in the right state */ | ||
582 | |||
583 | if (dev->b1->fsm_state == ST_CALL_INIT) | ||
584 | chan = dev->b1; | ||
585 | else { | ||
586 | if (dev->b2->s_refnum == ST_CALL_INIT) | ||
587 | chan = dev->b2; | ||
588 | else { | ||
589 | chan = NULL; | ||
590 | printk(KERN_WARNING "Connection Confirm - no channel in Call Init state\n"); | ||
591 | break; | ||
592 | } | ||
593 | } | ||
594 | if (capi_decode_conn_conf(chan, skb, &complete)) { | ||
595 | printk(KERN_DEBUG "conn_conf indicates error\n"); | ||
596 | pcbit_fsm_event(dev, chan, EV_ERROR, NULL); | ||
597 | } | ||
598 | else | ||
599 | if (complete) | ||
600 | pcbit_fsm_event(dev, chan, EV_NET_CALL_PROC, NULL); | ||
601 | else | ||
602 | pcbit_fsm_event(dev, chan, EV_NET_SETUP_ACK, NULL); | ||
603 | break; | ||
604 | case MSG_CONN_ACTV_IND: | ||
605 | |||
606 | if (!(chan = capi_channel(dev, skb))) { | ||
607 | printk(KERN_WARNING | ||
608 | "CAPI header: unknown channel id\n"); | ||
609 | break; | ||
610 | } | ||
611 | |||
612 | if (capi_decode_conn_actv_ind(chan, skb)) { | ||
613 | printk("error in capi_decode_conn_actv_ind\n"); | ||
614 | /* pcbit_fsm_event(dev, chan, EV_ERROR, NULL); */ | ||
615 | break; | ||
616 | } | ||
617 | chan->r_refnum = refnum; | ||
618 | pcbit_fsm_event(dev, chan, EV_NET_CONN, NULL); | ||
619 | break; | ||
620 | case MSG_CONN_ACTV_CONF: | ||
621 | |||
622 | if (!(chan = capi_channel(dev, skb))) { | ||
623 | printk(KERN_WARNING | ||
624 | "CAPI header: unknown channel id\n"); | ||
625 | break; | ||
626 | } | ||
627 | |||
628 | if (capi_decode_conn_actv_conf(chan, skb) == 0) | ||
629 | pcbit_fsm_event(dev, chan, EV_NET_CONN_ACK, NULL); | ||
630 | |||
631 | else | ||
632 | printk(KERN_DEBUG "decode_conn_actv_conf failed\n"); | ||
633 | break; | ||
634 | |||
635 | case MSG_SELP_CONF: | ||
636 | |||
637 | if (!(chan = capi_channel(dev, skb))) { | ||
638 | printk(KERN_WARNING | ||
639 | "CAPI header: unknown channel id\n"); | ||
640 | break; | ||
641 | } | ||
642 | |||
643 | if (!(err = capi_decode_sel_proto_conf(chan, skb))) | ||
644 | pcbit_fsm_event(dev, chan, EV_NET_SELP_RESP, NULL); | ||
645 | else { | ||
646 | /* Error */ | ||
647 | printk("error %d - capi_decode_sel_proto_conf\n", err); | ||
648 | } | ||
649 | break; | ||
650 | case MSG_ACT_TRANSP_CONF: | ||
651 | if (!(chan = capi_channel(dev, skb))) { | ||
652 | printk(KERN_WARNING | ||
653 | "CAPI header: unknown channel id\n"); | ||
654 | break; | ||
655 | } | ||
656 | |||
657 | if (!capi_decode_actv_trans_conf(chan, skb)) | ||
658 | pcbit_fsm_event(dev, chan, EV_NET_ACTV_RESP, NULL); | ||
659 | break; | ||
660 | |||
661 | case MSG_DISC_IND: | ||
662 | |||
663 | if (!(chan = capi_channel(dev, skb))) { | ||
664 | printk(KERN_WARNING | ||
665 | "CAPI header: unknown channel id\n"); | ||
666 | break; | ||
667 | } | ||
668 | |||
669 | if (!capi_decode_disc_ind(chan, skb)) | ||
670 | pcbit_fsm_event(dev, chan, EV_NET_DISC, NULL); | ||
671 | else | ||
672 | printk(KERN_WARNING "capi_decode_disc_ind - error\n"); | ||
673 | break; | ||
674 | case MSG_DISC_CONF: | ||
675 | if (!(chan = capi_channel(dev, skb))) { | ||
676 | printk(KERN_WARNING | ||
677 | "CAPI header: unknown channel id\n"); | ||
678 | break; | ||
679 | } | ||
680 | |||
681 | if (!capi_decode_disc_ind(chan, skb)) | ||
682 | pcbit_fsm_event(dev, chan, EV_NET_RELEASE, NULL); | ||
683 | else | ||
684 | printk(KERN_WARNING "capi_decode_disc_conf - error\n"); | ||
685 | break; | ||
686 | case MSG_INFO_IND: | ||
687 | #ifdef DEBUG | ||
688 | printk(KERN_DEBUG "received Info Indication - discarded\n"); | ||
689 | #endif | ||
690 | break; | ||
691 | #ifdef DEBUG | ||
692 | case MSG_DEBUG_188: | ||
693 | capi_decode_debug_188(skb->data, skb->len); | ||
694 | break; | ||
695 | |||
696 | default: | ||
697 | printk(KERN_DEBUG "pcbit_l3_receive: unknown message %08lx\n", | ||
698 | msg); | ||
699 | break; | ||
700 | #endif | ||
701 | } | ||
702 | |||
703 | kfree_skb(skb); | ||
704 | |||
705 | } | ||
706 | |||
707 | /* | ||
708 | * Single statbuf | ||
709 | * should be a statbuf per device | ||
710 | */ | ||
711 | |||
712 | static char statbuf[STATBUF_LEN]; | ||
713 | static int stat_st = 0; | ||
714 | static int stat_end = 0; | ||
715 | |||
716 | int pcbit_stat(u_char __user *buf, int len, int driver, int channel) | ||
717 | { | ||
718 | int stat_count; | ||
719 | stat_count = stat_end - stat_st; | ||
720 | |||
721 | if (stat_count < 0) | ||
722 | stat_count = STATBUF_LEN - stat_st + stat_end; | ||
723 | |||
724 | /* FIXME: should we sleep and wait for more cookies ? */ | ||
725 | if (len > stat_count) | ||
726 | len = stat_count; | ||
727 | |||
728 | if (stat_st < stat_end) | ||
729 | { | ||
730 | copy_to_user(buf, statbuf + stat_st, len); | ||
731 | stat_st += len; | ||
732 | } | ||
733 | else | ||
734 | { | ||
735 | if (len > STATBUF_LEN - stat_st) | ||
736 | { | ||
737 | copy_to_user(buf, statbuf + stat_st, | ||
738 | STATBUF_LEN - stat_st); | ||
739 | copy_to_user(buf, statbuf, | ||
740 | len - (STATBUF_LEN - stat_st)); | ||
741 | |||
742 | stat_st = len - (STATBUF_LEN - stat_st); | ||
743 | } | ||
744 | else | ||
745 | { | ||
746 | copy_to_user(buf, statbuf + stat_st, len); | ||
747 | |||
748 | stat_st += len; | ||
749 | |||
750 | if (stat_st == STATBUF_LEN) | ||
751 | stat_st = 0; | ||
752 | } | ||
753 | } | ||
754 | |||
755 | if (stat_st == stat_end) | ||
756 | stat_st = stat_end = 0; | ||
757 | |||
758 | return len; | ||
759 | } | ||
760 | |||
761 | static void pcbit_logstat(struct pcbit_dev *dev, char *str) | ||
762 | { | ||
763 | int i; | ||
764 | isdn_ctrl ictl; | ||
765 | |||
766 | for (i=stat_end; i<strlen(str); i++) | ||
767 | { | ||
768 | statbuf[i]=str[i]; | ||
769 | stat_end = (stat_end + 1) % STATBUF_LEN; | ||
770 | if (stat_end == stat_st) | ||
771 | stat_st = (stat_st + 1) % STATBUF_LEN; | ||
772 | } | ||
773 | |||
774 | ictl.command=ISDN_STAT_STAVAIL; | ||
775 | ictl.driver=dev->id; | ||
776 | ictl.arg=strlen(str); | ||
777 | dev->dev_if->statcallb(&ictl); | ||
778 | } | ||
779 | |||
780 | extern char * isdn_state_table[]; | ||
781 | extern char * strisdnevent(unsigned short); | ||
782 | |||
783 | |||
784 | void pcbit_state_change(struct pcbit_dev * dev, struct pcbit_chan * chan, | ||
785 | unsigned short i, unsigned short ev, unsigned short f) | ||
786 | { | ||
787 | char buf[256]; | ||
788 | |||
789 | sprintf(buf, "change on device: %d channel:%d\n%s -> %s -> %s\n", | ||
790 | dev->id, chan->id, | ||
791 | isdn_state_table[i], strisdnevent(ev), isdn_state_table[f] | ||
792 | ); | ||
793 | |||
794 | #ifdef DEBUG | ||
795 | printk("%s", buf); | ||
796 | #endif | ||
797 | |||
798 | pcbit_logstat(dev, buf); | ||
799 | } | ||
800 | |||
801 | static void set_running_timeout(unsigned long ptr) | ||
802 | { | ||
803 | struct pcbit_dev * dev; | ||
804 | |||
805 | #ifdef DEBUG | ||
806 | printk(KERN_DEBUG "set_running_timeout\n"); | ||
807 | #endif | ||
808 | dev = (struct pcbit_dev *) ptr; | ||
809 | |||
810 | wake_up_interruptible(&dev->set_running_wq); | ||
811 | } | ||
812 | |||
813 | static int set_protocol_running(struct pcbit_dev * dev) | ||
814 | { | ||
815 | isdn_ctrl ctl; | ||
816 | |||
817 | init_timer(&dev->set_running_timer); | ||
818 | |||
819 | dev->set_running_timer.function = &set_running_timeout; | ||
820 | dev->set_running_timer.data = (ulong) dev; | ||
821 | dev->set_running_timer.expires = jiffies + SET_RUN_TIMEOUT; | ||
822 | |||
823 | /* kick it */ | ||
824 | |||
825 | dev->l2_state = L2_STARTING; | ||
826 | |||
827 | writeb((0x80U | ((dev->rcv_seq & 0x07) << 3) | (dev->send_seq & 0x07)), | ||
828 | dev->sh_mem + BANK4); | ||
829 | |||
830 | add_timer(&dev->set_running_timer); | ||
831 | |||
832 | interruptible_sleep_on(&dev->set_running_wq); | ||
833 | |||
834 | del_timer(&dev->set_running_timer); | ||
835 | |||
836 | if (dev->l2_state == L2_RUNNING) | ||
837 | { | ||
838 | printk(KERN_DEBUG "pcbit: running\n"); | ||
839 | |||
840 | dev->unack_seq = dev->send_seq; | ||
841 | |||
842 | dev->writeptr = dev->sh_mem; | ||
843 | dev->readptr = dev->sh_mem + BANK2; | ||
844 | |||
845 | /* tell the good news to the upper layer */ | ||
846 | ctl.driver = dev->id; | ||
847 | ctl.command = ISDN_STAT_RUN; | ||
848 | |||
849 | dev->dev_if->statcallb(&ctl); | ||
850 | } | ||
851 | else | ||
852 | { | ||
853 | printk(KERN_DEBUG "pcbit: initialization failed\n"); | ||
854 | printk(KERN_DEBUG "pcbit: firmware not loaded\n"); | ||
855 | |||
856 | dev->l2_state = L2_DOWN; | ||
857 | |||
858 | #ifdef DEBUG | ||
859 | printk(KERN_DEBUG "Bank3 = %02x\n", | ||
860 | readb(dev->sh_mem + BANK3)); | ||
861 | #endif | ||
862 | writeb(0x40, dev->sh_mem + BANK4); | ||
863 | |||
864 | /* warn the upper layer */ | ||
865 | ctl.driver = dev->id; | ||
866 | ctl.command = ISDN_STAT_STOP; | ||
867 | |||
868 | dev->dev_if->statcallb(&ctl); | ||
869 | |||
870 | return -EL2HLT; /* Level 2 halted */ | ||
871 | } | ||
872 | |||
873 | return 0; | ||
874 | } | ||
875 | |||
876 | static int pcbit_ioctl(isdn_ctrl* ctl) | ||
877 | { | ||
878 | struct pcbit_dev * dev; | ||
879 | struct pcbit_ioctl *cmd; | ||
880 | |||
881 | dev = finddev(ctl->driver); | ||
882 | |||
883 | if (!dev) | ||
884 | { | ||
885 | printk(KERN_DEBUG "pcbit_ioctl: unknown device\n"); | ||
886 | return -ENODEV; | ||
887 | } | ||
888 | |||
889 | cmd = (struct pcbit_ioctl *) ctl->parm.num; | ||
890 | |||
891 | switch(ctl->arg) { | ||
892 | case PCBIT_IOCTL_GETSTAT: | ||
893 | cmd->info.l2_status = dev->l2_state; | ||
894 | break; | ||
895 | |||
896 | case PCBIT_IOCTL_STRLOAD: | ||
897 | if (dev->l2_state == L2_RUNNING) | ||
898 | return -EBUSY; | ||
899 | |||
900 | dev->unack_seq = dev->send_seq = dev->rcv_seq = 0; | ||
901 | |||
902 | dev->writeptr = dev->sh_mem; | ||
903 | dev->readptr = dev->sh_mem + BANK2; | ||
904 | |||
905 | dev->l2_state = L2_LOADING; | ||
906 | break; | ||
907 | |||
908 | case PCBIT_IOCTL_LWMODE: | ||
909 | if (dev->l2_state != L2_LOADING) | ||
910 | return -EINVAL; | ||
911 | |||
912 | dev->l2_state = L2_LWMODE; | ||
913 | break; | ||
914 | |||
915 | case PCBIT_IOCTL_FWMODE: | ||
916 | if (dev->l2_state == L2_RUNNING) | ||
917 | return -EBUSY; | ||
918 | dev->loadptr = LOAD_ZONE_START; | ||
919 | dev->l2_state = L2_FWMODE; | ||
920 | |||
921 | break; | ||
922 | case PCBIT_IOCTL_ENDLOAD: | ||
923 | if (dev->l2_state == L2_RUNNING) | ||
924 | return -EBUSY; | ||
925 | dev->l2_state = L2_DOWN; | ||
926 | break; | ||
927 | |||
928 | case PCBIT_IOCTL_SETBYTE: | ||
929 | if (dev->l2_state == L2_RUNNING) | ||
930 | return -EBUSY; | ||
931 | |||
932 | /* check addr */ | ||
933 | if (cmd->info.rdp_byte.addr > BANK4) | ||
934 | return -EFAULT; | ||
935 | |||
936 | writeb(cmd->info.rdp_byte.value, dev->sh_mem + cmd->info.rdp_byte.addr); | ||
937 | break; | ||
938 | case PCBIT_IOCTL_GETBYTE: | ||
939 | if (dev->l2_state == L2_RUNNING) | ||
940 | return -EBUSY; | ||
941 | |||
942 | /* check addr */ | ||
943 | |||
944 | if (cmd->info.rdp_byte.addr > BANK4) | ||
945 | { | ||
946 | printk("getbyte: invalid addr %04x\n", cmd->info.rdp_byte.addr); | ||
947 | return -EFAULT; | ||
948 | } | ||
949 | |||
950 | cmd->info.rdp_byte.value = readb(dev->sh_mem + cmd->info.rdp_byte.addr); | ||
951 | break; | ||
952 | case PCBIT_IOCTL_RUNNING: | ||
953 | if (dev->l2_state == L2_RUNNING) | ||
954 | return -EBUSY; | ||
955 | return set_protocol_running(dev); | ||
956 | break; | ||
957 | case PCBIT_IOCTL_WATCH188: | ||
958 | if (dev->l2_state != L2_LOADING) | ||
959 | return -EINVAL; | ||
960 | pcbit_l2_write(dev, MSG_WATCH188, 0x0001, NULL, 0); | ||
961 | break; | ||
962 | case PCBIT_IOCTL_PING188: | ||
963 | if (dev->l2_state != L2_LOADING) | ||
964 | return -EINVAL; | ||
965 | pcbit_l2_write(dev, MSG_PING188_REQ, 0x0001, NULL, 0); | ||
966 | break; | ||
967 | case PCBIT_IOCTL_APION: | ||
968 | if (dev->l2_state != L2_LOADING) | ||
969 | return -EINVAL; | ||
970 | pcbit_l2_write(dev, MSG_API_ON, 0x0001, NULL, 0); | ||
971 | break; | ||
972 | case PCBIT_IOCTL_STOP: | ||
973 | dev->l2_state = L2_DOWN; | ||
974 | writeb(0x40, dev->sh_mem + BANK4); | ||
975 | dev->rcv_seq = 0; | ||
976 | dev->send_seq = 0; | ||
977 | dev->unack_seq = 0; | ||
978 | break; | ||
979 | default: | ||
980 | printk("error: unknown ioctl\n"); | ||
981 | break; | ||
982 | }; | ||
983 | return 0; | ||
984 | } | ||
985 | |||
986 | /* | ||
987 | * MSN list handling | ||
988 | * | ||
989 | * if null reject all calls | ||
990 | * if first entry has null MSN accept all calls | ||
991 | */ | ||
992 | |||
993 | static void pcbit_clear_msn(struct pcbit_dev *dev) | ||
994 | { | ||
995 | struct msn_entry *ptr, *back; | ||
996 | |||
997 | for (ptr=dev->msn_list; ptr; ) | ||
998 | { | ||
999 | back = ptr->next; | ||
1000 | kfree(ptr); | ||
1001 | ptr = back; | ||
1002 | } | ||
1003 | |||
1004 | dev->msn_list = NULL; | ||
1005 | } | ||
1006 | |||
1007 | static void pcbit_set_msn(struct pcbit_dev *dev, char *list) | ||
1008 | { | ||
1009 | struct msn_entry *ptr; | ||
1010 | struct msn_entry *back = NULL; | ||
1011 | char *cp, *sp; | ||
1012 | int len; | ||
1013 | |||
1014 | if (strlen(list) == 0) { | ||
1015 | ptr = kmalloc(sizeof(struct msn_entry), GFP_ATOMIC); | ||
1016 | if (!ptr) { | ||
1017 | printk(KERN_WARNING "kmalloc failed\n"); | ||
1018 | return; | ||
1019 | } | ||
1020 | |||
1021 | ptr->msn = NULL; | ||
1022 | |||
1023 | ptr->next = dev->msn_list; | ||
1024 | dev->msn_list = ptr; | ||
1025 | |||
1026 | return; | ||
1027 | } | ||
1028 | |||
1029 | if (dev->msn_list) | ||
1030 | for (back=dev->msn_list; back->next; back=back->next); | ||
1031 | |||
1032 | sp = list; | ||
1033 | |||
1034 | do { | ||
1035 | cp=strchr(sp, ','); | ||
1036 | if (cp) | ||
1037 | len = cp - sp; | ||
1038 | else | ||
1039 | len = strlen(sp); | ||
1040 | |||
1041 | ptr = kmalloc(sizeof(struct msn_entry), GFP_ATOMIC); | ||
1042 | |||
1043 | if (!ptr) { | ||
1044 | printk(KERN_WARNING "kmalloc failed\n"); | ||
1045 | return; | ||
1046 | } | ||
1047 | ptr->next = NULL; | ||
1048 | |||
1049 | ptr->msn = kmalloc(len, GFP_ATOMIC); | ||
1050 | if (!ptr->msn) { | ||
1051 | printk(KERN_WARNING "kmalloc failed\n"); | ||
1052 | kfree(ptr); | ||
1053 | return; | ||
1054 | } | ||
1055 | |||
1056 | memcpy(ptr->msn, sp, len - 1); | ||
1057 | ptr->msn[len] = 0; | ||
1058 | |||
1059 | #ifdef DEBUG | ||
1060 | printk(KERN_DEBUG "msn: %s\n", ptr->msn); | ||
1061 | #endif | ||
1062 | if (dev->msn_list == NULL) | ||
1063 | dev->msn_list = ptr; | ||
1064 | else | ||
1065 | back->next = ptr; | ||
1066 | back = ptr; | ||
1067 | sp += len; | ||
1068 | } while(cp); | ||
1069 | } | ||
1070 | |||
1071 | /* | ||
1072 | * check if we do signal or reject an incoming call | ||
1073 | */ | ||
1074 | static int pcbit_check_msn(struct pcbit_dev *dev, char *msn) | ||
1075 | { | ||
1076 | struct msn_entry *ptr; | ||
1077 | |||
1078 | for (ptr=dev->msn_list; ptr; ptr=ptr->next) { | ||
1079 | |||
1080 | if (ptr->msn == NULL) | ||
1081 | return 1; | ||
1082 | |||
1083 | if (strcmp(ptr->msn, msn) == 0) | ||
1084 | return 1; | ||
1085 | } | ||
1086 | |||
1087 | return 0; | ||
1088 | } | ||