11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * PCBIT-D interface with isdn4linux 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1996 Universidade de Lisboa 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Written by Pedro Roque Marques (roque@di.fc.ul.pt) 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This software may be used and distributed according to the terms of 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the GNU General Public License, incorporated herein by reference. 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Fixes: 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Nuno Grilo <l38486@alfa.ist.utl.pt> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * fixed msn_list NULL pointer dereference. 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 26d43c36dc6b357fa1806800f18aa30123c747a6d1Alexey Dobriyan#include <linux/sched.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/skbuff.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/isdnif.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/string.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "pcbit.h" 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "edss1.h" 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "layer2.h" 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "capi.h" 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern ushort last_ref_num; 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pcbit_ioctl(isdn_ctrl* ctl); 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char* pcbit_devname[MAX_PCBIT_CARDS] = { 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "pcbit0", 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "pcbit1", 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "pcbit2", 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "pcbit3" 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * prototypes 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 59886cca3a0fda659e17c730c20929134014ebe1f2Adrian Bunkstatic int pcbit_command(isdn_ctrl* ctl); 60886cca3a0fda659e17c730c20929134014ebe1f2Adrian Bunkstatic int pcbit_stat(u_char __user * buf, int len, int, int); 61886cca3a0fda659e17c730c20929134014ebe1f2Adrian Bunkstatic int pcbit_xmit(int driver, int chan, int ack, struct sk_buff *skb); 62886cca3a0fda659e17c730c20929134014ebe1f2Adrian Bunkstatic int pcbit_writecmd(const u_char __user *, int, int, int); 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int set_protocol_running(struct pcbit_dev * dev); 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pcbit_clear_msn(struct pcbit_dev *dev); 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pcbit_set_msn(struct pcbit_dev *dev, char *list); 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pcbit_check_msn(struct pcbit_dev *dev, char *msn); 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint pcbit_init_dev(int board, int mem_base, int irq) 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcbit_dev *dev; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds isdn_if *dev_if; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7641f96935b4c41daea2c4dbbf137960375cf764c1Burman Yan if ((dev=kzalloc(sizeof(struct pcbit_dev), GFP_KERNEL)) == NULL) 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("pcbit_init: couldn't malloc pcbit_dev struct\n"); 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_pcbit[board] = dev; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_waitqueue_head(&dev->set_running_wq); 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_init(&dev->lock); 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mem_base >= 0xA0000 && mem_base <= 0xFFFFF ) { 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->ph_mem = mem_base; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!request_mem_region(dev->ph_mem, 4096, "PCBIT mem")) { 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "PCBIT: memory region %lx-%lx already in use\n", 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->ph_mem, dev->ph_mem + 4096); 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(dev); 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_pcbit[board] = NULL; 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EACCES; 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->sh_mem = ioremap(dev->ph_mem, 4096); 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("memory address invalid"); 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(dev); 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_pcbit[board] = NULL; 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EACCES; 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10641f96935b4c41daea2c4dbbf137960375cf764c1Burman Yan dev->b1 = kzalloc(sizeof(struct pcbit_chan), GFP_KERNEL); 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev->b1) { 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("pcbit_init: couldn't malloc pcbit_chan struct\n"); 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iounmap(dev->sh_mem); 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_mem_region(dev->ph_mem, 4096); 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(dev); 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11541f96935b4c41daea2c4dbbf137960375cf764c1Burman Yan dev->b2 = kzalloc(sizeof(struct pcbit_chan), GFP_KERNEL); 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev->b2) { 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("pcbit_init: couldn't malloc pcbit_chan struct\n"); 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(dev->b1); 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iounmap(dev->sh_mem); 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_mem_region(dev->ph_mem, 4096); 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(dev); 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->b2->id = 1; 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 127c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells INIT_WORK(&dev->qdelivery, pcbit_deliver); 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * interrupts 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (request_irq(irq, &pcbit_irq_handler, 0, pcbit_devname[board], dev) != 0) 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(dev->b1); 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(dev->b2); 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iounmap(dev->sh_mem); 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_mem_region(dev->ph_mem, 4096); 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(dev); 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_pcbit[board] = NULL; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->irq = irq; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* next frame to be received */ 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->rcv_seq = 0; 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->send_seq = 0; 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->unack_seq = 0; 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->hl_hdrlen = 16; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_if = kmalloc(sizeof(isdn_if), GFP_KERNEL); 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev_if) { 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_irq(irq, dev); 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(dev->b1); 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(dev->b2); 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iounmap(dev->sh_mem); 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_mem_region(dev->ph_mem, 4096); 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(dev); 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_pcbit[board] = NULL; 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev_if = dev_if; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_if->owner = THIS_MODULE; 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_if->channels = 2; 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_if->features = (ISDN_FEATURE_P_EURO | ISDN_FEATURE_L3_TRANS | 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ISDN_FEATURE_L2_HDLC | ISDN_FEATURE_L2_TRANS ); 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_if->writebuf_skb = pcbit_xmit; 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_if->hl_hdrlen = 16; 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_if->maxbufsize = MAXBUFSIZE; 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_if->command = pcbit_command; 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_if->writecmd = pcbit_writecmd; 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_if->readstat = pcbit_stat; 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(dev_if->id, pcbit_devname[board]); 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!register_isdn(dev_if)) { 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_irq(irq, dev); 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(dev->b1); 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(dev->b2); 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iounmap(dev->sh_mem); 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_mem_region(dev->ph_mem, 4096); 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(dev); 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_pcbit[board] = NULL; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->id = dev_if->channels; 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->l2_state = L2_DOWN; 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->free = 511; 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * set_protocol_running(dev); 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef MODULE 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid pcbit_terminate(int board) 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcbit_dev * dev; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev = dev_pcbit[board]; 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev) { 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* unregister_isdn(dev->dev_if); */ 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_irq(dev->irq, dev); 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcbit_clear_msn(dev); 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(dev->dev_if); 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->b1->fsm_timer.function) 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer(&dev->b1->fsm_timer); 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->b2->fsm_timer.function) 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer(&dev->b2->fsm_timer); 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(dev->b1); 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(dev->b2); 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iounmap(dev->sh_mem); 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_mem_region(dev->ph_mem, 4096); 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(dev); 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 236886cca3a0fda659e17c730c20929134014ebe1f2Adrian Bunkstatic int pcbit_command(isdn_ctrl* ctl) 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcbit_dev *dev; 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcbit_chan *chan; 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct callb_data info; 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev = finddev(ctl->driver); 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev) 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("pcbit_command: unknown device\n"); 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chan = (ctl->arg & 0x0F) ? dev->b2 : dev->b1; 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch(ctl->command) { 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ISDN_CMD_IOCTL: 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return pcbit_ioctl(ctl); 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ISDN_CMD_DIAL: 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.type = EV_USR_SETUP_REQ; 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.data.setup.CalledPN = (char *) &ctl->parm.setup.phone; 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcbit_fsm_event(dev, chan, EV_USR_SETUP_REQ, &info); 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ISDN_CMD_ACCEPTD: 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcbit_fsm_event(dev, chan, EV_USR_SETUP_RESP, NULL); 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ISDN_CMD_ACCEPTB: 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("ISDN_CMD_ACCEPTB - not really needed\n"); 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ISDN_CMD_HANGUP: 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcbit_fsm_event(dev, chan, EV_USR_RELEASE_REQ, NULL); 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ISDN_CMD_SETL2: 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chan->proto = (ctl->arg >> 8); 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ISDN_CMD_CLREAZ: 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcbit_clear_msn(dev); 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ISDN_CMD_SETEAZ: 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcbit_set_msn(dev, ctl->parm.num); 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ISDN_CMD_SETL3: 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((ctl->arg >> 8) != ISDN_PROTO_L3_TRANS) 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "L3 protocol unknown\n"); 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "pcbit_command: unknown command\n"); 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }; 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Another Hack :-( 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * on some conditions the board stops sending TDATA_CONFs 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * let's see if we can turn around the problem 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef BLOCK_TIMER 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pcbit_block_timer(unsigned long data) 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcbit_chan *chan; 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcbit_dev * dev; 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds isdn_ctrl ictl; 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chan = (struct pcbit_chan *) data; 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev = chan2dev(chan); 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev == NULL) { 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "pcbit: chan2dev failed\n"); 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer(&chan->block_timer); 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chan->block_timer.function = NULL; 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "pcbit_block_timer\n"); 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chan->queued = 0; 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ictl.driver = dev->id; 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ictl.command = ISDN_STAT_BSENT; 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ictl.arg = chan->id; 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev_if->statcallb(&ictl); 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 328886cca3a0fda659e17c730c20929134014ebe1f2Adrian Bunkstatic int pcbit_xmit(int driver, int chnum, int ack, struct sk_buff *skb) 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ushort hdrlen; 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int refnum, len; 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcbit_chan * chan; 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcbit_dev *dev; 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev = finddev(driver); 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev == NULL) 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("finddev returned NULL"); 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chan = chnum ? dev->b2 : dev->b1; 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chan->fsm_state != ST_ACTIVE) 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chan->queued >= MAX_QUEUED ) 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_QUEUE 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "pcbit: %d packets already in queue - write fails\n", 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chan->queued); 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * packet stays on the head of the device queue 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * since dev_start_xmit will fail 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * see net/core/dev.c 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef BLOCK_TIMER 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chan->block_timer.function == NULL) { 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_timer(&chan->block_timer); 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chan->block_timer.function = &pcbit_block_timer; 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chan->block_timer.data = (long) chan; 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chan->block_timer.expires = jiffies + 1 * HZ; 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_timer(&chan->block_timer); 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chan->queued++; 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = skb->len; 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hdrlen = capi_tdata_req(chan, skb); 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds refnum = last_ref_num++ & 0x7fffU; 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chan->s_refnum = refnum; 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcbit_l2_write(dev, MSG_TDATA_REQ, refnum, skb, hdrlen); 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return len; 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 387886cca3a0fda659e17c730c20929134014ebe1f2Adrian Bunkstatic int pcbit_writecmd(const u_char __user *buf, int len, int driver, int channel) 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcbit_dev * dev; 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, j; 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const u_char * loadbuf; 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char * ptr = NULL; 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char *cbuf; 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int errstat; 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev = finddev(driver); 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev) 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("pcbit_writecmd: couldn't find device"); 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch(dev->l2_state) { 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case L2_LWMODE: 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check (size <= rdp_size); write buf into board */ 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (len < 0 || len > BANK4 + 1 || len > 1024) 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("pcbit_writecmd: invalid length %d\n", len); 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 414024cb8a67f3d3438322fac9d6f7b1cc578eca71cJulia Lawall cbuf = memdup_user(buf, len); 415024cb8a67f3d3438322fac9d6f7b1cc578eca71cJulia Lawall if (IS_ERR(cbuf)) 416024cb8a67f3d3438322fac9d6f7b1cc578eca71cJulia Lawall return PTR_ERR(cbuf); 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy_toio(dev->sh_mem, cbuf, len); 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(cbuf); 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return len; 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case L2_FWMODE: 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* this is the hard part */ 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* dumb board */ 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* get it into kernel space */ 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((ptr = kmalloc(len, GFP_KERNEL))==NULL) 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(ptr, buf, len)) { 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(ptr); 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds loadbuf = ptr; 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds errstat = 0; 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i=0; i < len; i++) 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for(j=0; j < LOAD_RETRY; j++) 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(readb(dev->sh_mem + dev->loadptr))) 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (j == LOAD_RETRY) 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds errstat = -ETIME; 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("TIMEOUT i=%d\n", i); 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writeb(loadbuf[i], dev->sh_mem + dev->loadptr + 1); 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writeb(0x01, dev->sh_mem + dev->loadptr); 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->loadptr += 2; 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->loadptr > LOAD_ZONE_END) 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->loadptr = LOAD_ZONE_START; 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(ptr); 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return errstat ? errstat : len; 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * demultiplexing of messages 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid pcbit_l3_receive(struct pcbit_dev * dev, ulong msg, 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff * skb, 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ushort hdr_len, ushort refnum) 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcbit_chan *chan; 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb2; 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short len; 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct callb_data cbdata; 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int complete, err; 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds isdn_ctrl ictl; 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch(msg) { 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MSG_TDATA_IND: 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(chan = capi_channel(dev, skb))) { 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CAPI header: unknown channel id\n"); 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chan->r_refnum = skb->data[7]; 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_pull(skb, 8); 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev_if->rcvcallb_skb(dev->id, chan->id, skb); 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (capi_tdata_resp(chan, &skb2) > 0) 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcbit_l2_write(dev, MSG_TDATA_RESP, refnum, 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb2, skb2->len); 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MSG_TDATA_CONF: 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(chan = capi_channel(dev, skb))) { 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CAPI header: unknown channel id\n"); 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ( (*((ushort *) (skb->data + 2) )) != 0) { 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "TDATA_CONF error\n"); 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef BLOCK_TIMER 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chan->queued == MAX_QUEUED) { 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer(&chan->block_timer); 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chan->block_timer.function = NULL; 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chan->queued--; 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ictl.driver = dev->id; 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ictl.command = ISDN_STAT_BSENT; 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ictl.arg = chan->id; 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev_if->statcallb(&ictl); 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MSG_CONN_IND: 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * channel: 1st not used will do 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * if both are used we're in trouble 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev->b1->fsm_state) 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chan = dev->b1; 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (!dev->b2->fsm_state) 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chan = dev->b2; 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Incoming connection: no channels available"); 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((len = capi_disc_req(*(ushort*)(skb->data), &skb2, CAUSE_NOCHAN)) > 0) 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcbit_l2_write(dev, MSG_DISC_REQ, refnum, skb2, len); 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cbdata.data.setup.CalledPN = NULL; 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cbdata.data.setup.CallingPN = NULL; 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds capi_decode_conn_ind(chan, skb, &cbdata); 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cbdata.type = EV_NET_SETUP; 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcbit_fsm_event(dev, chan, EV_NET_SETUP, NULL); 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pcbit_check_msn(dev, cbdata.data.setup.CallingPN)) 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcbit_fsm_event(dev, chan, EV_USR_PROCED_REQ, &cbdata); 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcbit_fsm_event(dev, chan, EV_USR_RELEASE_REQ, NULL); 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5553c7208f253571ee5f157b98f0e315b5172afe092Jesper Juhl kfree(cbdata.data.setup.CalledPN); 5563c7208f253571ee5f157b98f0e315b5172afe092Jesper Juhl kfree(cbdata.data.setup.CallingPN); 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MSG_CONN_CONF: 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We should be able to find the channel by the message 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * reference number. The current version of the firmware 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * doesn't sent the ref number correctly. 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "refnum=%04x b1=%04x b2=%04x\n", refnum, 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->b1->s_refnum, 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->b2->s_refnum); 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We just try to find a channel in the right state */ 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->b1->fsm_state == ST_CALL_INIT) 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chan = dev->b1; 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->b2->s_refnum == ST_CALL_INIT) 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chan = dev->b2; 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chan = NULL; 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "Connection Confirm - no channel in Call Init state\n"); 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (capi_decode_conn_conf(chan, skb, &complete)) { 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "conn_conf indicates error\n"); 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcbit_fsm_event(dev, chan, EV_ERROR, NULL); 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (complete) 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcbit_fsm_event(dev, chan, EV_NET_CALL_PROC, NULL); 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcbit_fsm_event(dev, chan, EV_NET_SETUP_ACK, NULL); 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MSG_CONN_ACTV_IND: 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(chan = capi_channel(dev, skb))) { 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CAPI header: unknown channel id\n"); 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (capi_decode_conn_actv_ind(chan, skb)) { 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("error in capi_decode_conn_actv_ind\n"); 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* pcbit_fsm_event(dev, chan, EV_ERROR, NULL); */ 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chan->r_refnum = refnum; 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcbit_fsm_event(dev, chan, EV_NET_CONN, NULL); 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MSG_CONN_ACTV_CONF: 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(chan = capi_channel(dev, skb))) { 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CAPI header: unknown channel id\n"); 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (capi_decode_conn_actv_conf(chan, skb) == 0) 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcbit_fsm_event(dev, chan, EV_NET_CONN_ACK, NULL); 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "decode_conn_actv_conf failed\n"); 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MSG_SELP_CONF: 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(chan = capi_channel(dev, skb))) { 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CAPI header: unknown channel id\n"); 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(err = capi_decode_sel_proto_conf(chan, skb))) 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcbit_fsm_event(dev, chan, EV_NET_SELP_RESP, NULL); 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Error */ 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("error %d - capi_decode_sel_proto_conf\n", err); 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MSG_ACT_TRANSP_CONF: 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(chan = capi_channel(dev, skb))) { 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CAPI header: unknown channel id\n"); 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!capi_decode_actv_trans_conf(chan, skb)) 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcbit_fsm_event(dev, chan, EV_NET_ACTV_RESP, NULL); 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MSG_DISC_IND: 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(chan = capi_channel(dev, skb))) { 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CAPI header: unknown channel id\n"); 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!capi_decode_disc_ind(chan, skb)) 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcbit_fsm_event(dev, chan, EV_NET_DISC, NULL); 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "capi_decode_disc_ind - error\n"); 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MSG_DISC_CONF: 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(chan = capi_channel(dev, skb))) { 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "CAPI header: unknown channel id\n"); 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!capi_decode_disc_ind(chan, skb)) 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcbit_fsm_event(dev, chan, EV_NET_RELEASE, NULL); 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "capi_decode_disc_conf - error\n"); 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MSG_INFO_IND: 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "received Info Indication - discarded\n"); 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MSG_DEBUG_188: 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds capi_decode_debug_188(skb->data, skb->len); 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "pcbit_l3_receive: unknown message %08lx\n", 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds msg); 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree_skb(skb); 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Single statbuf 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * should be a statbuf per device 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char statbuf[STATBUF_LEN]; 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int stat_st = 0; 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int stat_end = 0; 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 705886cca3a0fda659e17c730c20929134014ebe1f2Adrian Bunkstatic int pcbit_stat(u_char __user *buf, int len, int driver, int channel) 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int stat_count; 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stat_count = stat_end - stat_st; 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (stat_count < 0) 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stat_count = STATBUF_LEN - stat_st + stat_end; 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* FIXME: should we sleep and wait for more cookies ? */ 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (len > stat_count) 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = stat_count; 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (stat_st < stat_end) 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 7197786ce192fc4917fb9b789dd823476ff8fd6cf66Jeff Garzik if (copy_to_user(buf, statbuf + stat_st, len)) 7207786ce192fc4917fb9b789dd823476ff8fd6cf66Jeff Garzik return -EFAULT; 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stat_st += len; 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (len > STATBUF_LEN - stat_st) 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 7277786ce192fc4917fb9b789dd823476ff8fd6cf66Jeff Garzik if (copy_to_user(buf, statbuf + stat_st, 7287786ce192fc4917fb9b789dd823476ff8fd6cf66Jeff Garzik STATBUF_LEN - stat_st)) 7297786ce192fc4917fb9b789dd823476ff8fd6cf66Jeff Garzik return -EFAULT; 7307786ce192fc4917fb9b789dd823476ff8fd6cf66Jeff Garzik if (copy_to_user(buf, statbuf, 7317786ce192fc4917fb9b789dd823476ff8fd6cf66Jeff Garzik len - (STATBUF_LEN - stat_st))) 7327786ce192fc4917fb9b789dd823476ff8fd6cf66Jeff Garzik return -EFAULT; 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stat_st = len - (STATBUF_LEN - stat_st); 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 7387786ce192fc4917fb9b789dd823476ff8fd6cf66Jeff Garzik if (copy_to_user(buf, statbuf + stat_st, len)) 7397786ce192fc4917fb9b789dd823476ff8fd6cf66Jeff Garzik return -EFAULT; 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stat_st += len; 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (stat_st == STATBUF_LEN) 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stat_st = 0; 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (stat_st == stat_end) 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stat_st = stat_end = 0; 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return len; 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pcbit_logstat(struct pcbit_dev *dev, char *str) 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds isdn_ctrl ictl; 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i=stat_end; i<strlen(str); i++) 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds statbuf[i]=str[i]; 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stat_end = (stat_end + 1) % STATBUF_LEN; 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (stat_end == stat_st) 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stat_st = (stat_st + 1) % STATBUF_LEN; 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ictl.command=ISDN_STAT_STAVAIL; 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ictl.driver=dev->id; 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ictl.arg=strlen(str); 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev_if->statcallb(&ictl); 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid pcbit_state_change(struct pcbit_dev * dev, struct pcbit_chan * chan, 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short i, unsigned short ev, unsigned short f) 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char buf[256]; 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(buf, "change on device: %d channel:%d\n%s -> %s -> %s\n", 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->id, chan->id, 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds isdn_state_table[i], strisdnevent(ev), isdn_state_table[f] 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ); 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s", buf); 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcbit_logstat(dev, buf); 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void set_running_timeout(unsigned long ptr) 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcbit_dev * dev; 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "set_running_timeout\n"); 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev = (struct pcbit_dev *) ptr; 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wake_up_interruptible(&dev->set_running_wq); 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int set_protocol_running(struct pcbit_dev * dev) 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds isdn_ctrl ctl; 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_timer(&dev->set_running_timer); 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->set_running_timer.function = &set_running_timeout; 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->set_running_timer.data = (ulong) dev; 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->set_running_timer.expires = jiffies + SET_RUN_TIMEOUT; 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* kick it */ 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->l2_state = L2_STARTING; 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writeb((0x80U | ((dev->rcv_seq & 0x07) << 3) | (dev->send_seq & 0x07)), 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->sh_mem + BANK4); 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_timer(&dev->set_running_timer); 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds interruptible_sleep_on(&dev->set_running_wq); 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer(&dev->set_running_timer); 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->l2_state == L2_RUNNING) 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "pcbit: running\n"); 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->unack_seq = dev->send_seq; 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->writeptr = dev->sh_mem; 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->readptr = dev->sh_mem + BANK2; 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* tell the good news to the upper layer */ 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ctl.driver = dev->id; 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ctl.command = ISDN_STAT_RUN; 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev_if->statcallb(&ctl); 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "pcbit: initialization failed\n"); 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "pcbit: firmware not loaded\n"); 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->l2_state = L2_DOWN; 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "Bank3 = %02x\n", 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds readb(dev->sh_mem + BANK3)); 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writeb(0x40, dev->sh_mem + BANK4); 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* warn the upper layer */ 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ctl.driver = dev->id; 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ctl.command = ISDN_STAT_STOP; 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev_if->statcallb(&ctl); 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EL2HLT; /* Level 2 halted */ 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pcbit_ioctl(isdn_ctrl* ctl) 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcbit_dev * dev; 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pcbit_ioctl *cmd; 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev = finddev(ctl->driver); 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev) 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "pcbit_ioctl: unknown device\n"); 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cmd = (struct pcbit_ioctl *) ctl->parm.num; 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch(ctl->arg) { 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PCBIT_IOCTL_GETSTAT: 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cmd->info.l2_status = dev->l2_state; 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PCBIT_IOCTL_STRLOAD: 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->l2_state == L2_RUNNING) 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->unack_seq = dev->send_seq = dev->rcv_seq = 0; 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->writeptr = dev->sh_mem; 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->readptr = dev->sh_mem + BANK2; 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->l2_state = L2_LOADING; 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PCBIT_IOCTL_LWMODE: 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->l2_state != L2_LOADING) 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->l2_state = L2_LWMODE; 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PCBIT_IOCTL_FWMODE: 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->l2_state == L2_RUNNING) 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->loadptr = LOAD_ZONE_START; 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->l2_state = L2_FWMODE; 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PCBIT_IOCTL_ENDLOAD: 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->l2_state == L2_RUNNING) 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->l2_state = L2_DOWN; 9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PCBIT_IOCTL_SETBYTE: 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->l2_state == L2_RUNNING) 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check addr */ 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cmd->info.rdp_byte.addr > BANK4) 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writeb(cmd->info.rdp_byte.value, dev->sh_mem + cmd->info.rdp_byte.addr); 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PCBIT_IOCTL_GETBYTE: 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->l2_state == L2_RUNNING) 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check addr */ 9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cmd->info.rdp_byte.addr > BANK4) 9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("getbyte: invalid addr %04x\n", cmd->info.rdp_byte.addr); 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cmd->info.rdp_byte.value = readb(dev->sh_mem + cmd->info.rdp_byte.addr); 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PCBIT_IOCTL_RUNNING: 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->l2_state == L2_RUNNING) 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return set_protocol_running(dev); 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PCBIT_IOCTL_WATCH188: 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->l2_state != L2_LOADING) 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcbit_l2_write(dev, MSG_WATCH188, 0x0001, NULL, 0); 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PCBIT_IOCTL_PING188: 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->l2_state != L2_LOADING) 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcbit_l2_write(dev, MSG_PING188_REQ, 0x0001, NULL, 0); 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PCBIT_IOCTL_APION: 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->l2_state != L2_LOADING) 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcbit_l2_write(dev, MSG_API_ON, 0x0001, NULL, 0); 9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PCBIT_IOCTL_STOP: 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->l2_state = L2_DOWN; 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writeb(0x40, dev->sh_mem + BANK4); 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->rcv_seq = 0; 9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->send_seq = 0; 9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->unack_seq = 0; 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("error: unknown ioctl\n"); 9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }; 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MSN list handling 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * if null reject all calls 9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * if first entry has null MSN accept all calls 9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pcbit_clear_msn(struct pcbit_dev *dev) 9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct msn_entry *ptr, *back; 9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (ptr=dev->msn_list; ptr; ) 9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds back = ptr->next; 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(ptr); 9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr = back; 9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->msn_list = NULL; 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pcbit_set_msn(struct pcbit_dev *dev, char *list) 9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct msn_entry *ptr; 9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct msn_entry *back = NULL; 10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *cp, *sp; 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len; 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (strlen(list) == 0) { 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr = kmalloc(sizeof(struct msn_entry), GFP_ATOMIC); 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ptr) { 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "kmalloc failed\n"); 10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr->msn = NULL; 10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr->next = dev->msn_list; 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->msn_list = ptr; 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->msn_list) 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (back=dev->msn_list; back->next; back=back->next); 10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sp = list; 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cp=strchr(sp, ','); 10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cp) 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = cp - sp; 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = strlen(sp); 10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr = kmalloc(sizeof(struct msn_entry), GFP_ATOMIC); 10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ptr) { 10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "kmalloc failed\n"); 10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr->next = NULL; 10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr->msn = kmalloc(len, GFP_ATOMIC); 10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ptr->msn) { 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "kmalloc failed\n"); 10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(ptr); 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(ptr->msn, sp, len - 1); 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr->msn[len] = 0; 10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG 10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "msn: %s\n", ptr->msn); 10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->msn_list == NULL) 10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->msn_list = ptr; 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds back->next = ptr; 10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds back = ptr; 10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sp += len; 10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while(cp); 10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * check if we do signal or reject an incoming call 10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pcbit_check_msn(struct pcbit_dev *dev, char *msn) 10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct msn_entry *ptr; 10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (ptr=dev->msn_list; ptr; ptr=ptr->next) { 10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ptr->msn == NULL) 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (strcmp(ptr->msn, msn) == 0) 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1078