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