diff options
Diffstat (limited to 'drivers/isdn')
28 files changed, 6 insertions, 9061 deletions
diff --git a/drivers/isdn/Makefile b/drivers/isdn/Makefile index 91c81965e7ca..c32e45826c2c 100644 --- a/drivers/isdn/Makefile +++ b/drivers/isdn/Makefile @@ -8,9 +8,6 @@ obj-$(CONFIG_MISDN) += mISDN/ obj-$(CONFIG_ISDN) += hardware/ obj-$(CONFIG_ISDN_DIVERSION) += divert/ obj-$(CONFIG_ISDN_DRV_HISAX) += hisax/ -obj-$(CONFIG_ISDN_DRV_ICN) += icn/ -obj-$(CONFIG_ISDN_DRV_PCBIT) += pcbit/ obj-$(CONFIG_ISDN_DRV_LOOP) += isdnloop/ -obj-$(CONFIG_ISDN_DRV_ACT2000) += act2000/ obj-$(CONFIG_HYSDN) += hysdn/ obj-$(CONFIG_ISDN_DRV_GIGASET) += gigaset/ diff --git a/drivers/isdn/act2000/Kconfig b/drivers/isdn/act2000/Kconfig deleted file mode 100644 index fa2673fc69c2..000000000000 --- a/drivers/isdn/act2000/Kconfig +++ /dev/null @@ -1,9 +0,0 @@ -config ISDN_DRV_ACT2000 - tristate "IBM Active 2000 support" - depends on ISA - help - Say Y here if you have an IBM Active 2000 ISDN card. In order to use - this card, additional firmware is necessary, which has to be loaded - into the card using a utility which is part of the latest - isdn4k-utils package. Please read the file - <file:Documentation/isdn/README.act2000> for more information. diff --git a/drivers/isdn/act2000/Makefile b/drivers/isdn/act2000/Makefile deleted file mode 100644 index 05e582fb5c00..000000000000 --- a/drivers/isdn/act2000/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# Makefile for the act2000 ISDN device driver - -# Each configuration option enables a list of files. - -obj-$(CONFIG_ISDN_DRV_ACT2000) += act2000.o - -# Multipart objects. - -act2000-y := module.o capi.o act2000_isa.o diff --git a/drivers/isdn/act2000/act2000.h b/drivers/isdn/act2000/act2000.h deleted file mode 100644 index 321d437f579e..000000000000 --- a/drivers/isdn/act2000/act2000.h +++ /dev/null @@ -1,202 +0,0 @@ -/* $Id: act2000.h,v 1.8.6.3 2001/09/23 22:24:32 kai Exp $ - * - * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000. - * - * Author Fritz Elfert - * Copyright by Fritz Elfert <fritz@isdn4linux.de> - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - * Thanks to Friedemann Baitinger and IBM Germany - * - */ - -#ifndef act2000_h -#define act2000_h - -#include <linux/compiler.h> - -#define ACT2000_IOCTL_SETPORT 1 -#define ACT2000_IOCTL_GETPORT 2 -#define ACT2000_IOCTL_SETIRQ 3 -#define ACT2000_IOCTL_GETIRQ 4 -#define ACT2000_IOCTL_SETBUS 5 -#define ACT2000_IOCTL_GETBUS 6 -#define ACT2000_IOCTL_SETPROTO 7 -#define ACT2000_IOCTL_GETPROTO 8 -#define ACT2000_IOCTL_SETMSN 9 -#define ACT2000_IOCTL_GETMSN 10 -#define ACT2000_IOCTL_LOADBOOT 11 -#define ACT2000_IOCTL_ADDCARD 12 - -#define ACT2000_IOCTL_TEST 98 -#define ACT2000_IOCTL_DEBUGVAR 99 - -#define ACT2000_BUS_ISA 1 -#define ACT2000_BUS_MCA 2 -#define ACT2000_BUS_PCMCIA 3 - -/* Struct for adding new cards */ -typedef struct act2000_cdef { - int bus; - int port; - int irq; - char id[10]; -} act2000_cdef; - -/* Struct for downloading firmware */ -typedef struct act2000_ddef { - int length; /* Length of code */ - char __user *buffer; /* Ptr. to code */ -} act2000_ddef; - -typedef struct act2000_fwid { - char isdn[4]; - char revlen[2]; - char revision[504]; -} act2000_fwid; - -#if defined(__KERNEL__) || defined(__DEBUGVAR__) - -#ifdef __KERNEL__ -/* Kernel includes */ - -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/workqueue.h> -#include <linux/interrupt.h> -#include <linux/skbuff.h> -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/major.h> -#include <asm/io.h> -#include <linux/kernel.h> -#include <linux/signal.h> -#include <linux/slab.h> -#include <linux/mm.h> -#include <linux/mman.h> -#include <linux/ioport.h> -#include <linux/timer.h> -#include <linux/wait.h> -#include <linux/delay.h> -#include <linux/ctype.h> -#include <linux/isdnif.h> - -#endif /* __KERNEL__ */ - -#define ACT2000_PORTLEN 8 - -#define ACT2000_FLAGS_RUNNING 1 /* Cards driver activated */ -#define ACT2000_FLAGS_PVALID 2 /* Cards port is valid */ -#define ACT2000_FLAGS_IVALID 4 /* Cards irq is valid */ -#define ACT2000_FLAGS_LOADED 8 /* Firmware loaded */ - -#define ACT2000_BCH 2 /* # of channels per card */ - -/* D-Channel states */ -#define ACT2000_STATE_NULL 0 -#define ACT2000_STATE_ICALL 1 -#define ACT2000_STATE_OCALL 2 -#define ACT2000_STATE_IWAIT 3 -#define ACT2000_STATE_OWAIT 4 -#define ACT2000_STATE_IBWAIT 5 -#define ACT2000_STATE_OBWAIT 6 -#define ACT2000_STATE_BWAIT 7 -#define ACT2000_STATE_BHWAIT 8 -#define ACT2000_STATE_BHWAIT2 9 -#define ACT2000_STATE_DHWAIT 10 -#define ACT2000_STATE_DHWAIT2 11 -#define ACT2000_STATE_BSETUP 12 -#define ACT2000_STATE_ACTIVE 13 - -#define ACT2000_MAX_QUEUED 8000 /* 2 * maxbuff */ - -#define ACT2000_LOCK_TX 0 -#define ACT2000_LOCK_RX 1 - -typedef struct act2000_chan { - unsigned short callref; /* Call Reference */ - unsigned short fsm_state; /* Current D-Channel state */ - unsigned short eazmask; /* EAZ-Mask for this Channel */ - short queued; /* User-Data Bytes in TX queue */ - unsigned short plci; - unsigned short ncci; - unsigned char l2prot; /* Layer 2 protocol */ - unsigned char l3prot; /* Layer 3 protocol */ -} act2000_chan; - -typedef struct msn_entry { - char eaz; - char msn[16]; - struct msn_entry *next; -} msn_entry; - -typedef struct irq_data_isa { - __u8 *rcvptr; - __u16 rcvidx; - __u16 rcvlen; - struct sk_buff *rcvskb; - __u8 rcvignore; - __u8 rcvhdr[8]; -} irq_data_isa; - -typedef union act2000_irq_data { - irq_data_isa isa; -} act2000_irq_data; - -/* - * Per card driver data - */ -typedef struct act2000_card { - unsigned short port; /* Base-port-address */ - unsigned short irq; /* Interrupt */ - u_char ptype; /* Protocol type (1TR6 or Euro) */ - u_char bus; /* Cardtype (ISA, MCA, PCMCIA) */ - struct act2000_card *next; /* Pointer to next device struct */ - spinlock_t lock; /* protect critical operations */ - int myid; /* Driver-Nr. assigned by linklevel */ - unsigned long flags; /* Statusflags */ - unsigned long ilock; /* Semaphores for IRQ-Routines */ - struct sk_buff_head rcvq; /* Receive-Message queue */ - struct sk_buff_head sndq; /* Send-Message queue */ - struct sk_buff_head ackq; /* Data-Ack-Message queue */ - u_char *ack_msg; /* Ptr to User Data in User skb */ - __u16 need_b3ack; /* Flag: Need ACK for current skb */ - struct sk_buff *sbuf; /* skb which is currently sent */ - struct timer_list ptimer; /* Poll timer */ - struct work_struct snd_tq; /* Task struct for xmit bh */ - struct work_struct rcv_tq; /* Task struct for rcv bh */ - struct work_struct poll_tq; /* Task struct for polled rcv bh */ - msn_entry *msn_list; - unsigned short msgnum; /* Message number for sending */ - spinlock_t mnlock; /* lock for msgnum */ - act2000_chan bch[ACT2000_BCH]; /* B-Channel status/control */ - char status_buf[256]; /* Buffer for status messages */ - char *status_buf_read; - char *status_buf_write; - char *status_buf_end; - act2000_irq_data idat; /* Data used for IRQ handler */ - isdn_if interface; /* Interface to upper layer */ - char regname[35]; /* Name used for request_region */ -} act2000_card; - -static inline void act2000_schedule_tx(act2000_card *card) -{ - schedule_work(&card->snd_tq); -} - -static inline void act2000_schedule_rx(act2000_card *card) -{ - schedule_work(&card->rcv_tq); -} - -static inline void act2000_schedule_poll(act2000_card *card) -{ - schedule_work(&card->poll_tq); -} - -extern char *act2000_find_eaz(act2000_card *, char); - -#endif /* defined(__KERNEL__) || defined(__DEBUGVAR__) */ -#endif /* act2000_h */ diff --git a/drivers/isdn/act2000/act2000_isa.c b/drivers/isdn/act2000/act2000_isa.c deleted file mode 100644 index b5fad29a9ba6..000000000000 --- a/drivers/isdn/act2000/act2000_isa.c +++ /dev/null @@ -1,443 +0,0 @@ -/* $Id: act2000_isa.c,v 1.11.6.3 2001/09/23 22:24:32 kai Exp $ - * - * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version). - * - * Author Fritz Elfert - * Copyright by Fritz Elfert <fritz@isdn4linux.de> - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - * Thanks to Friedemann Baitinger and IBM Germany - * - */ - -#include "act2000.h" -#include "act2000_isa.h" -#include "capi.h" - -/* - * Reset Controller, then try to read the Card's signature. - + Return: - * 1 = Signature found. - * 0 = Signature not found. - */ -static int -act2000_isa_reset(unsigned short portbase) -{ - unsigned char reg; - int i; - int found; - int serial = 0; - - found = 0; - if ((reg = inb(portbase + ISA_COR)) != 0xff) { - outb(reg | ISA_COR_RESET, portbase + ISA_COR); - mdelay(10); - outb(reg, portbase + ISA_COR); - mdelay(10); - - for (i = 0; i < 16; i++) { - if (inb(portbase + ISA_ISR) & ISA_ISR_SERIAL) - serial |= 0x10000; - serial >>= 1; - } - if (serial == ISA_SER_ID) - found++; - } - return found; -} - -int -act2000_isa_detect(unsigned short portbase) -{ - int ret = 0; - - if (request_region(portbase, ACT2000_PORTLEN, "act2000isa")) { - ret = act2000_isa_reset(portbase); - release_region(portbase, ISA_REGION); - } - return ret; -} - -static irqreturn_t -act2000_isa_interrupt(int dummy, void *dev_id) -{ - act2000_card *card = dev_id; - u_char istatus; - - istatus = (inb(ISA_PORT_ISR) & 0x07); - if (istatus & ISA_ISR_OUT) { - /* RX fifo has data */ - istatus &= ISA_ISR_OUT_MASK; - outb(0, ISA_PORT_SIS); - act2000_isa_receive(card); - outb(ISA_SIS_INT, ISA_PORT_SIS); - } - if (istatus & ISA_ISR_ERR) { - /* Error Interrupt */ - istatus &= ISA_ISR_ERR_MASK; - printk(KERN_WARNING "act2000: errIRQ\n"); - } - if (istatus) - printk(KERN_DEBUG "act2000: ?IRQ %d %02x\n", card->irq, istatus); - return IRQ_HANDLED; -} - -static void -act2000_isa_select_irq(act2000_card *card) -{ - unsigned char reg; - - reg = (inb(ISA_PORT_COR) & ~ISA_COR_IRQOFF) | ISA_COR_PERR; - switch (card->irq) { - case 3: - reg = ISA_COR_IRQ03; - break; - case 5: - reg = ISA_COR_IRQ05; - break; - case 7: - reg = ISA_COR_IRQ07; - break; - case 10: - reg = ISA_COR_IRQ10; - break; - case 11: - reg = ISA_COR_IRQ11; - break; - case 12: - reg = ISA_COR_IRQ12; - break; - case 15: - reg = ISA_COR_IRQ15; - break; - } - outb(reg, ISA_PORT_COR); -} - -static void -act2000_isa_enable_irq(act2000_card *card) -{ - act2000_isa_select_irq(card); - /* Enable READ irq */ - outb(ISA_SIS_INT, ISA_PORT_SIS); -} - -/* - * Install interrupt handler, enable irq on card. - * If irq is -1, choose next free irq, else irq is given explicitly. - */ -int -act2000_isa_config_irq(act2000_card *card, short irq) -{ - int old_irq; - - if (card->flags & ACT2000_FLAGS_IVALID) { - free_irq(card->irq, card); - } - card->flags &= ~ACT2000_FLAGS_IVALID; - outb(ISA_COR_IRQOFF, ISA_PORT_COR); - if (!irq) - return 0; - - old_irq = card->irq; - card->irq = irq; - if (request_irq(irq, &act2000_isa_interrupt, 0, card->regname, card)) { - card->irq = old_irq; - card->flags |= ACT2000_FLAGS_IVALID; - printk(KERN_WARNING - "act2000: Could not request irq %d\n", irq); - return -EBUSY; - } else { - act2000_isa_select_irq(card); - /* Disable READ and WRITE irq */ - outb(0, ISA_PORT_SIS); - outb(0, ISA_PORT_SOS); - } - return 0; -} - -int -act2000_isa_config_port(act2000_card *card, unsigned short portbase) -{ - if (card->flags & ACT2000_FLAGS_PVALID) { - release_region(card->port, ISA_REGION); - card->flags &= ~ACT2000_FLAGS_PVALID; - } - if (request_region(portbase, ACT2000_PORTLEN, card->regname) == NULL) - return -EBUSY; - else { - card->port = portbase; - card->flags |= ACT2000_FLAGS_PVALID; - return 0; - } -} - -/* - * Release ressources, used by an adaptor. - */ -void -act2000_isa_release(act2000_card *card) -{ - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); - if (card->flags & ACT2000_FLAGS_IVALID) - free_irq(card->irq, card); - - card->flags &= ~ACT2000_FLAGS_IVALID; - if (card->flags & ACT2000_FLAGS_PVALID) - release_region(card->port, ISA_REGION); - card->flags &= ~ACT2000_FLAGS_PVALID; - spin_unlock_irqrestore(&card->lock, flags); -} - -static int -act2000_isa_writeb(act2000_card *card, u_char data) -{ - u_char timeout = 40; - - while (timeout) { - if (inb(ISA_PORT_SOS) & ISA_SOS_READY) { - outb(data, ISA_PORT_SDO); - return 0; - } else { - timeout--; - udelay(10); - } - } - return 1; -} - -static int -act2000_isa_readb(act2000_card *card, u_char *data) -{ - u_char timeout = 40; - - while (timeout) { - if (inb(ISA_PORT_SIS) & ISA_SIS_READY) { - *data = inb(ISA_PORT_SDI); - return 0; - } else { - timeout--; - udelay(10); - } - } - return 1; -} - -void -act2000_isa_receive(act2000_card *card) -{ - u_char c; - - if (test_and_set_bit(ACT2000_LOCK_RX, (void *) &card->ilock) != 0) - return; - while (!act2000_isa_readb(card, &c)) { - if (card->idat.isa.rcvidx < 8) { - card->idat.isa.rcvhdr[card->idat.isa.rcvidx++] = c; - if (card->idat.isa.rcvidx == 8) { - int valid = actcapi_chkhdr(card, (actcapi_msghdr *)&card->idat.isa.rcvhdr); - - if (valid) { - card->idat.isa.rcvlen = ((actcapi_msghdr *)&card->idat.isa.rcvhdr)->len; - card->idat.isa.rcvskb = dev_alloc_skb(card->idat.isa.rcvlen); - if (card->idat.isa.rcvskb == NULL) { - card->idat.isa.rcvignore = 1; - printk(KERN_WARNING - "act2000_isa_receive: no memory\n"); - test_and_clear_bit(ACT2000_LOCK_RX, (void *) &card->ilock); - return; - } - memcpy(skb_put(card->idat.isa.rcvskb, 8), card->idat.isa.rcvhdr, 8); - card->idat.isa.rcvptr = skb_put(card->idat.isa.rcvskb, card->idat.isa.rcvlen - 8); - } else { - card->idat.isa.rcvidx = 0; - printk(KERN_WARNING - "act2000_isa_receive: Invalid CAPI msg\n"); - { - int i; __u8 *p; __u8 *t; __u8 tmp[30]; - for (i = 0, p = (__u8 *)&card->idat.isa.rcvhdr, t = tmp; i < 8; i++) - t += sprintf(t, "%02x ", *(p++)); - printk(KERN_WARNING "act2000_isa_receive: %s\n", tmp); - } - } - } - } else { - if (!card->idat.isa.rcvignore) - *card->idat.isa.rcvptr++ = c; - if (++card->idat.isa.rcvidx >= card->idat.isa.rcvlen) { - if (!card->idat.isa.rcvignore) { - skb_queue_tail(&card->rcvq, card->idat.isa.rcvskb); - act2000_schedule_rx(card); - } - card->idat.isa.rcvidx = 0; - card->idat.isa.rcvlen = 8; - card->idat.isa.rcvignore = 0; - card->idat.isa.rcvskb = NULL; - card->idat.isa.rcvptr = card->idat.isa.rcvhdr; - } - } - } - if (!(card->flags & ACT2000_FLAGS_IVALID)) { - /* In polling mode, schedule myself */ - if ((card->idat.isa.rcvidx) && - (card->idat.isa.rcvignore || - (card->idat.isa.rcvidx < card->idat.isa.rcvlen))) - act2000_schedule_poll(card); - } - test_and_clear_bit(ACT2000_LOCK_RX, (void *) &card->ilock); -} - -void -act2000_isa_send(act2000_card *card) -{ - unsigned long flags; - struct sk_buff *skb; - actcapi_msg *msg; - int l; - - if (test_and_set_bit(ACT2000_LOCK_TX, (void *) &card->ilock) != 0) - return; - while (1) { - spin_lock_irqsave(&card->lock, flags); - if (!(card->sbuf)) { - if ((card->sbuf = skb_dequeue(&card->sndq))) { - card->ack_msg = card->sbuf->data; - msg = (actcapi_msg *)card->sbuf->data; - if ((msg->hdr.cmd.cmd == 0x86) && - (msg->hdr.cmd.subcmd == 0)) { - /* Save flags in message */ - card->need_b3ack = msg->msg.data_b3_req.flags; - msg->msg.data_b3_req.flags = 0; - } - } - } - spin_unlock_irqrestore(&card->lock, flags); - if (!(card->sbuf)) { - /* No more data to send */ - test_and_clear_bit(ACT2000_LOCK_TX, (void *) &card->ilock); - return; - } - skb = card->sbuf; - l = 0; - while (skb->len) { - if (act2000_isa_writeb(card, *(skb->data))) { - /* Fifo is full, but more data to send */ - test_and_clear_bit(ACT2000_LOCK_TX, (void *) &card->ilock); - /* Schedule myself */ - act2000_schedule_tx(card); - return; - } - skb_pull(skb, 1); - l++; - } - msg = (actcapi_msg *)card->ack_msg; - if ((msg->hdr.cmd.cmd == 0x86) && - (msg->hdr.cmd.subcmd == 0)) { - /* - * If it's user data, reset data-ptr - * and put skb into ackq. - */ - skb->data = card->ack_msg; - /* Restore flags in message */ - msg->msg.data_b3_req.flags = card->need_b3ack; - skb_queue_tail(&card->ackq, skb); - } else - dev_kfree_skb(skb); - card->sbuf = NULL; - } -} - -/* - * Get firmware ID, check for 'ISDN' signature. - */ -static int -act2000_isa_getid(act2000_card *card) -{ - - act2000_fwid fid; - u_char *p = (u_char *)&fid; - int count = 0; - - while (1) { - if (count > 510) - return -EPROTO; - if (act2000_isa_readb(card, p++)) - break; - count++; - } - if (count <= 20) { - printk(KERN_WARNING "act2000: No Firmware-ID!\n"); - return -ETIME; - } - *p = '\0'; - fid.revlen[0] = '\0'; - if (strcmp(fid.isdn, "ISDN")) { - printk(KERN_WARNING "act2000: Wrong Firmware-ID!\n"); - return -EPROTO; - } - if ((p = strchr(fid.revision, '\n'))) - *p = '\0'; - printk(KERN_INFO "act2000: Firmware-ID: %s\n", fid.revision); - if (card->flags & ACT2000_FLAGS_IVALID) { - printk(KERN_DEBUG "Enabling Interrupts ...\n"); - act2000_isa_enable_irq(card); - } - return 0; -} - -/* - * Download microcode into card, check Firmware signature. - */ -int -act2000_isa_download(act2000_card *card, act2000_ddef __user *cb) -{ - unsigned int length; - int l; - int c; - long timeout; - u_char *b; - u_char __user *p; - u_char *buf; - act2000_ddef cblock; - - if (!act2000_isa_reset(card->port)) - return -ENXIO; - msleep_interruptible(500); - if (copy_from_user(&cblock, cb, sizeof(cblock))) - return -EFAULT; - length = cblock.length; - p = cblock.buffer; - if (!access_ok(VERIFY_READ, p, length)) - return -EFAULT; - buf = kmalloc(1024, GFP_KERNEL); - if (!buf) - return -ENOMEM; - timeout = 0; - while (length) { - l = (length > 1024) ? 1024 : length; - c = 0; - b = buf; - if (copy_from_user(buf, p, l)) { - kfree(buf); - return -EFAULT; - } - while (c < l) { - if (act2000_isa_writeb(card, *b++)) { - printk(KERN_WARNING - "act2000: loader timed out" - " len=%d c=%d\n", length, c); - kfree(buf); - return -ETIME; - } - c++; - } - length -= l; - p += l; - } - kfree(buf); - msleep_interruptible(500); - return (act2000_isa_getid(card)); -} diff --git a/drivers/isdn/act2000/act2000_isa.h b/drivers/isdn/act2000/act2000_isa.h deleted file mode 100644 index 1a728984ede1..000000000000 --- a/drivers/isdn/act2000/act2000_isa.h +++ /dev/null @@ -1,136 +0,0 @@ -/* $Id: act2000_isa.h,v 1.4.6.1 2001/09/23 22:24:32 kai Exp $ - * - * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version). - * - * Author Fritz Elfert - * Copyright by Fritz Elfert <fritz@isdn4linux.de> - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - * Thanks to Friedemann Baitinger and IBM Germany - * - */ - -#ifndef act2000_isa_h -#define act2000_isa_h - -#define ISA_POLL_LOOP 40 /* Try to read-write before give up */ - -typedef enum { - INT_NO_CHANGE = 0, /* Do not change the Mask */ - INT_ON = 1, /* Set to Enable */ - INT_OFF = 2, /* Set to Disable */ -} ISA_INT_T; - -/**************************************************************************/ -/* Configuration Register COR (RW) */ -/**************************************************************************/ -/* 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 */ -/* Soft Res| IRQM | IRQ Select | N/A | WAIT |Proc err */ -/**************************************************************************/ -#define ISA_COR 0 /* Offset for ISA config register */ -#define ISA_COR_PERR 0x01 /* Processor Error Enabled */ -#define ISA_COR_WS 0x02 /* Insert Wait State if 1 */ -#define ISA_COR_IRQOFF 0x38 /* No Interrupt */ -#define ISA_COR_IRQ07 0x30 /* IRQ 7 Enable */ -#define ISA_COR_IRQ05 0x28 /* IRQ 5 Enable */ -#define ISA_COR_IRQ03 0x20 /* IRQ 3 Enable */ -#define ISA_COR_IRQ10 0x18 /* IRQ 10 Enable */ -#define ISA_COR_IRQ11 0x10 /* IRQ 11 Enable */ -#define ISA_COR_IRQ12 0x08 /* IRQ 12 Enable */ -#define ISA_COR_IRQ15 0x00 /* IRQ 15 Enable */ -#define ISA_COR_IRQPULSE 0x40 /* 0 = Level 1 = Pulse Interrupt */ -#define ISA_COR_RESET 0x80 /* Soft Reset for Transputer */ - -/**************************************************************************/ -/* Interrupt Source Register ISR (RO) */ -/**************************************************************************/ -/* 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 */ -/* N/A | N/A | N/A |Err sig |Ser ID |IN Intr |Out Intr| Error */ -/**************************************************************************/ -#define ISA_ISR 1 /* Offset for Interrupt Register */ -#define ISA_ISR_ERR 0x01 /* Error Interrupt */ -#define ISA_ISR_OUT 0x02 /* Output Interrupt */ -#define ISA_ISR_INP 0x04 /* Input Interrupt */ -#define ISA_ISR_SERIAL 0x08 /* Read out Serial ID after Reset */ -#define ISA_ISR_ERRSIG 0x10 /* Error Signal Input */ -#define ISA_ISR_ERR_MASK 0xfe /* Mask Error Interrupt */ -#define ISA_ISR_OUT_MASK 0xfd /* Mask Output Interrupt */ -#define ISA_ISR_INP_MASK 0xfb /* Mask Input Interrupt */ - -/* Signature delivered after Reset at ISA_ISR_SERIAL (LSB first) */ -#define ISA_SER_ID 0x0201 /* ID for ISA Card */ - -/**************************************************************************/ -/* EEPROM Register EPR (RW) */ -/**************************************************************************/ -/* 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 */ -/* N/A | N/A | N/A |ROM Hold| ROM CS |ROM CLK | ROM IN |ROM Out */ -/**************************************************************************/ -#define ISA_EPR 2 /* Offset for this Register */ -#define ISA_EPR_OUT 0x01 /* Rome Register Out (RO) */ -#define ISA_EPR_IN 0x02 /* Rom Register In (WR) */ -#define ISA_EPR_CLK 0x04 /* Rom Clock (WR) */ -#define ISA_EPR_CS 0x08 /* Rom Cip Select (WR) */ -#define ISA_EPR_HOLD 0x10 /* Rom Hold Signal (WR) */ - -/**************************************************************************/ -/* EEPROM enable Register EER (unused) */ -/**************************************************************************/ -#define ISA_EER 3 /* Offset for this Register */ - -/**************************************************************************/ -/* SLC Data Input SDI (RO) */ -/**************************************************************************/ -#define ISA_SDI 4 /* Offset for this Register */ - -/**************************************************************************/ -/* SLC Data Output SDO (WO) */ -/**************************************************************************/ -#define ISA_SDO 5 /* Offset for this Register */ - -/**************************************************************************/ -/* IMS C011 Mode 2 Input Status Register for INMOS CPU SIS (RW) */ -/**************************************************************************/ -/* 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 */ -/* N/A | N/A | N/A | N/A | N/A | N/A |Int Ena |Data Pre */ -/**************************************************************************/ -#define ISA_SIS 6 /* Offset for this Register */ -#define ISA_SIS_READY 0x01 /* If 1 : data is available */ -#define ISA_SIS_INT 0x02 /* Enable Interrupt for READ */ - -/**************************************************************************/ -/* IMS C011 Mode 2 Output Status Register from INMOS CPU SOS (RW) */ -/**************************************************************************/ -/* 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 */ -/* N/A | N/A | N/A | N/A | N/A | N/A |Int Ena |Out Rdy */ -/**************************************************************************/ -#define ISA_SOS 7 /* Offset for this Register */ -#define ISA_SOS_READY 0x01 /* If 1 : we can write Data */ -#define ISA_SOS_INT 0x02 /* Enable Interrupt for WRITE */ - -#define ISA_REGION 8 /* Number of Registers */ - - -/* Macros for accessing ports */ -#define ISA_PORT_COR (card->port + ISA_COR) -#define ISA_PORT_ISR (card->port + ISA_ISR) -#define ISA_PORT_EPR (card->port + ISA_EPR) -#define ISA_PORT_EER (card->port + ISA_EER) -#define ISA_PORT_SDI (card->port + ISA_SDI) -#define ISA_PORT_SDO (card->port + ISA_SDO) -#define ISA_PORT_SIS (card->port + ISA_SIS) -#define ISA_PORT_SOS (card->port + ISA_SOS) - -/* Prototypes */ - -extern int act2000_isa_detect(unsigned short portbase); -extern int act2000_isa_config_irq(act2000_card *card, short irq); -extern int act2000_isa_config_port(act2000_card *card, unsigned short portbase); -extern int act2000_isa_download(act2000_card *card, act2000_ddef __user *cb); -extern void act2000_isa_release(act2000_card *card); -extern void act2000_isa_receive(act2000_card *card); -extern void act2000_isa_send(act2000_card *card); - -#endif /* act2000_isa_h */ diff --git a/drivers/isdn/act2000/capi.c b/drivers/isdn/act2000/capi.c deleted file mode 100644 index 3f66ca20b5e5..000000000000 --- a/drivers/isdn/act2000/capi.c +++ /dev/null @@ -1,1180 +0,0 @@ -/* $Id: capi.c,v 1.9.6.2 2001/09/23 22:24:32 kai Exp $ - * - * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000. - * CAPI encoder/decoder - * - * Author Fritz Elfert - * Copyright by Fritz Elfert <fritz@isdn4linux.de> - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - * Thanks to Friedemann Baitinger and IBM Germany - * - */ - -#include "act2000.h" -#include "capi.h" - -static actcapi_msgdsc valid_msg[] = { - {{ 0x86, 0x02}, "DATA_B3_IND"}, /* DATA_B3_IND/CONF must be first because of speed!!! */ - {{ 0x86, 0x01}, "DATA_B3_CONF"}, - {{ 0x02, 0x01}, "CONNECT_CONF"}, - {{ 0x02, 0x02}, "CONNECT_IND"}, - {{ 0x09, 0x01}, "CONNECT_INFO_CONF"}, - {{ 0x03, 0x02}, "CONNECT_ACTIVE_IND"}, - {{ 0x04, 0x01}, "DISCONNECT_CONF"}, - {{ 0x04, 0x02}, "DISCONNECT_IND"}, - {{ 0x05, 0x01}, "LISTEN_CONF"}, - {{ 0x06, 0x01}, "GET_PARAMS_CONF"}, - {{ 0x07, 0x01}, "INFO_CONF"}, - {{ 0x07, 0x02}, "INFO_IND"}, - {{ 0x08, 0x01}, "DATA_CONF"}, - {{ 0x08, 0x02}, "DATA_IND"}, - {{ 0x40, 0x01}, "SELECT_B2_PROTOCOL_CONF"}, - {{ 0x80, 0x01}, "SELECT_B3_PROTOCOL_CONF"}, - {{ 0x81, 0x01}, "LISTEN_B3_CONF"}, - {{ 0x82, 0x01}, "CONNECT_B3_CONF"}, - {{ 0x82, 0x02}, "CONNECT_B3_IND"}, - {{ 0x83, 0x02}, "CONNECT_B3_ACTIVE_IND"}, - {{ 0x84, 0x01}, "DISCONNECT_B3_CONF"}, - {{ 0x84, 0x02}, "DISCONNECT_B3_IND"}, - {{ 0x85, 0x01}, "GET_B3_PARAMS_CONF"}, - {{ 0x01, 0x01}, "RESET_B3_CONF"}, - {{ 0x01, 0x02}, "RESET_B3_IND"}, - /* {{ 0x87, 0x02, "HANDSET_IND"}, not implemented */ - {{ 0xff, 0x01}, "MANUFACTURER_CONF"}, - {{ 0xff, 0x02}, "MANUFACTURER_IND"}, -#ifdef DEBUG_MSG - /* Requests */ - {{ 0x01, 0x00}, "RESET_B3_REQ"}, - {{ 0x02, 0x00}, "CONNECT_REQ"}, - {{ 0x04, 0x00}, "DISCONNECT_REQ"}, - {{ 0x05, 0x00}, "LISTEN_REQ"}, - {{ 0x06, 0x00}, "GET_PARAMS_REQ"}, - {{ 0x07, 0x00}, "INFO_REQ"}, - {{ 0x08, 0x00}, "DATA_REQ"}, - {{ 0x09, 0x00}, "CONNECT_INFO_REQ"}, - {{ 0x40, 0x00}, "SELECT_B2_PROTOCOL_REQ"}, - {{ 0x80, 0x00}, "SELECT_B3_PROTOCOL_REQ"}, - {{ 0x81, 0x00}, "LISTEN_B3_REQ"}, - {{ 0x82, 0x00}, "CONNECT_B3_REQ"}, - {{ 0x84, 0x00}, "DISCONNECT_B3_REQ"}, - {{ 0x85, 0x00}, "GET_B3_PARAMS_REQ"}, - {{ 0x86, 0x00}, "DATA_B3_REQ"}, - {{ 0xff, 0x00}, "MANUFACTURER_REQ"}, - /* Responses */ - {{ 0x01, 0x03}, "RESET_B3_RESP"}, - {{ 0x02, 0x03}, "CONNECT_RESP"}, - {{ 0x03, 0x03}, "CONNECT_ACTIVE_RESP"}, - {{ 0x04, 0x03}, "DISCONNECT_RESP"}, - {{ 0x07, 0x03}, "INFO_RESP"}, - {{ 0x08, 0x03}, "DATA_RESP"}, - {{ 0x82, 0x03}, "CONNECT_B3_RESP"}, - {{ 0x83, 0x03}, "CONNECT_B3_ACTIVE_RESP"}, - {{ 0x84, 0x03}, "DISCONNECT_B3_RESP"}, - {{ 0x86, 0x03}, "DATA_B3_RESP"}, - {{ 0xff, 0x03}, "MANUFACTURER_RESP"}, -#endif - {{ 0x00, 0x00}, NULL}, -}; -#define num_valid_imsg 27 /* MANUFACTURER_IND */ - -/* - * Check for a valid incoming CAPI message. - * Return: - * 0 = Invalid message - * 1 = Valid message, no B-Channel-data - * 2 = Valid message, B-Channel-data - */ -int -actcapi_chkhdr(act2000_card *card, actcapi_msghdr *hdr) -{ - int i; - - if (hdr->applicationID != 1) - return 0; - if (hdr->len < 9) - return 0; - for (i = 0; i < num_valid_imsg; i++) - if ((hdr->cmd.cmd == valid_msg[i].cmd.cmd) && - (hdr->cmd.subcmd == valid_msg[i].cmd.subcmd)) { - return (i ? 1 : 2); - } - return 0; -} - -#define ACTCAPI_MKHDR(l, c, s) { \ - skb = alloc_skb(l + 8, GFP_ATOMIC); \ - if (skb) { \ - m = (actcapi_msg *)skb_put(skb, l + 8); \ - m->hdr.len = l + 8; \ - m->hdr.applicationID = 1; \ - m->hdr.cmd.cmd = c; \ - m->hdr.cmd.subcmd = s; \ - m->hdr.msgnum = actcapi_nextsmsg(card); \ - } else m = NULL; \ - } - -#define ACTCAPI_CHKSKB if (!skb) { \ - printk(KERN_WARNING "actcapi: alloc_skb failed\n"); \ - return; \ - } - -#define ACTCAPI_QUEUE_TX { \ - actcapi_debug_msg(skb, 1); \ - skb_queue_tail(&card->sndq, skb); \ - act2000_schedule_tx(card); \ - } - -int -actcapi_listen_req(act2000_card *card) -{ - __u16 eazmask = 0; - int i; - actcapi_msg *m; - struct sk_buff *skb; - - for (i = 0; i < ACT2000_BCH; i++) - eazmask |= card->bch[i].eazmask; - ACTCAPI_MKHDR(9, 0x05, 0x00); - if (!skb) { - printk(KERN_WARNING "actcapi: alloc_skb failed\n"); - return -ENOMEM; - } - m->msg.listen_req.controller = 0; - m->msg.listen_req.infomask = 0x3f; /* All information */ - m->msg.listen_req.eazmask = eazmask; - m->msg.listen_req.simask = (eazmask) ? 0x86 : 0; /* All SI's */ - ACTCAPI_QUEUE_TX; - return 0; -} - -int -actcapi_connect_req(act2000_card *card, act2000_chan *chan, char *phone, - char eaz, int si1, int si2) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR((11 + strlen(phone)), 0x02, 0x00); - if (!skb) { - printk(KERN_WARNING "actcapi: alloc_skb failed\n"); - chan->fsm_state = ACT2000_STATE_NULL; - return -ENOMEM; - } - m->msg.connect_req.controller = 0; - m->msg.connect_req.bchan = 0x83; - m->msg.connect_req.infomask = 0x3f; - m->msg.connect_req.si1 = si1; - m->msg.connect_req.si2 = si2; - m->msg.connect_req.eaz = eaz ? eaz : '0'; - m->msg.connect_req.addr.len = strlen(phone) + 1; - m->msg.connect_req.addr.tnp = 0x81; - memcpy(m->msg.connect_req.addr.num, phone, strlen(phone)); - chan->callref = m->hdr.msgnum; - ACTCAPI_QUEUE_TX; - return 0; -} - -static void -actcapi_connect_b3_req(act2000_card *card, act2000_chan *chan) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(17, 0x82, 0x00); - ACTCAPI_CHKSKB; - m->msg.connect_b3_req.plci = chan->plci; - memset(&m->msg.connect_b3_req.ncpi, 0, - sizeof(m->msg.connect_b3_req.ncpi)); - m->msg.connect_b3_req.ncpi.len = 13; - m->msg.connect_b3_req.ncpi.modulo = 8; - ACTCAPI_QUEUE_TX; -} - -/* - * Set net type (1TR6) or (EDSS1) - */ -int -actcapi_manufacturer_req_net(act2000_card *card) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(5, 0xff, 0x00); - if (!skb) { - printk(KERN_WARNING "actcapi: alloc_skb failed\n"); - return -ENOMEM; - } - m->msg.manufacturer_req_net.manuf_msg = 0x11; - m->msg.manufacturer_req_net.controller = 1; - m->msg.manufacturer_req_net.nettype = (card->ptype == ISDN_PTYPE_EURO) ? 1 : 0; - ACTCAPI_QUEUE_TX; - printk(KERN_INFO "act2000 %s: D-channel protocol now %s\n", - card->interface.id, (card->ptype == ISDN_PTYPE_EURO) ? "euro" : "1tr6"); - card->interface.features &= - ~(ISDN_FEATURE_P_UNKNOWN | ISDN_FEATURE_P_EURO | ISDN_FEATURE_P_1TR6); - card->interface.features |= - ((card->ptype == ISDN_PTYPE_EURO) ? ISDN_FEATURE_P_EURO : ISDN_FEATURE_P_1TR6); - return 0; -} - -/* - * Switch V.42 on or off - */ -#if 0 -int -actcapi_manufacturer_req_v42(act2000_card *card, ulong arg) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(8, 0xff, 0x00); - if (!skb) { - - printk(KERN_WARNING "actcapi: alloc_skb failed\n"); - return -ENOMEM; - } - m->msg.manufacturer_req_v42.manuf_msg = 0x10; - m->msg.manufacturer_req_v42.controller = 0; - m->msg.manufacturer_req_v42.v42control = (arg ? 1 : 0); - ACTCAPI_QUEUE_TX; - return 0; -} -#endif /* 0 */ - -/* - * Set error-handler - */ -int -actcapi_manufacturer_req_errh(act2000_card *card) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(4, 0xff, 0x00); - if (!skb) { - - printk(KERN_WARNING "actcapi: alloc_skb failed\n"); - return -ENOMEM; - } - m->msg.manufacturer_req_err.manuf_msg = 0x03; - m->msg.manufacturer_req_err.controller = 0; - ACTCAPI_QUEUE_TX; - return 0; -} - -/* - * Set MSN-Mapping. - */ -int -actcapi_manufacturer_req_msn(act2000_card *card) -{ - msn_entry *p = card->msn_list; - actcapi_msg *m; - struct sk_buff *skb; - int len; - - while (p) { - int i; - - len = strlen(p->msn); - for (i = 0; i < 2; i++) { - ACTCAPI_MKHDR(6 + len, 0xff, 0x00); - if (!skb) { - printk(KERN_WARNING "actcapi: alloc_skb failed\n"); - return -ENOMEM; - } - m->msg.manufacturer_req_msn.manuf_msg = 0x13 + i; - m->msg.manufacturer_req_msn.controller = 0; - m->msg.manufacturer_req_msn.msnmap.eaz = p->eaz; - m->msg.manufacturer_req_msn.msnmap.len = len; - memcpy(m->msg.manufacturer_req_msn.msnmap.msn, p->msn, len); - ACTCAPI_QUEUE_TX; - } - p = p->next; - } - return 0; -} - -void -actcapi_select_b2_protocol_req(act2000_card *card, act2000_chan *chan) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(10, 0x40, 0x00); - ACTCAPI_CHKSKB; - m->msg.select_b2_protocol_req.plci = chan->plci; - memset(&m->msg.select_b2_protocol_req.dlpd, 0, - sizeof(m->msg.select_b2_protocol_req.dlpd)); - m->msg.select_b2_protocol_req.dlpd.len = 6; - switch (chan->l2prot) { - case ISDN_PROTO_L2_TRANS: - m->msg.select_b2_protocol_req.protocol = 0x03; - m->msg.select_b2_protocol_req.dlpd.dlen = 4000; - break; - case ISDN_PROTO_L2_HDLC: - m->msg.select_b2_protocol_req.protocol = 0x02; - m->msg.select_b2_protocol_req.dlpd.dlen = 4000; - break; - case ISDN_PROTO_L2_X75I: - case ISDN_PROTO_L2_X75UI: - case ISDN_PROTO_L2_X75BUI: - m->msg.select_b2_protocol_req.protocol = 0x01; - m->msg.select_b2_protocol_req.dlpd.dlen = 4000; - m->msg.select_b2_protocol_req.dlpd.laa = 3; - m->msg.select_b2_protocol_req.dlpd.lab = 1; - m->msg.select_b2_protocol_req.dlpd.win = 7; - m->msg.select_b2_protocol_req.dlpd.modulo = 8; - break; - } - ACTCAPI_QUEUE_TX; -} - -static void -actcapi_select_b3_protocol_req(act2000_card *card, act2000_chan *chan) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(17, 0x80, 0x00); - ACTCAPI_CHKSKB; - m->msg.select_b3_protocol_req.plci = chan->plci; - memset(&m->msg.select_b3_protocol_req.ncpd, 0, - sizeof(m->msg.select_b3_protocol_req.ncpd)); - switch (chan->l3prot) { - case ISDN_PROTO_L3_TRANS: - m->msg.select_b3_protocol_req.protocol = 0x04; - m->msg.select_b3_protocol_req.ncpd.len = 13; - m->msg.select_b3_protocol_req.ncpd.modulo = 8; - break; - } - ACTCAPI_QUEUE_TX; -} - -static void -actcapi_listen_b3_req(act2000_card *card, act2000_chan *chan) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(2, 0x81, 0x00); - ACTCAPI_CHKSKB; - m->msg.listen_b3_req.plci = chan->plci; - ACTCAPI_QUEUE_TX; -} - -static void -actcapi_disconnect_req(act2000_card *card, act2000_chan *chan) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(3, 0x04, 0x00); - ACTCAPI_CHKSKB; - m->msg.disconnect_req.plci = chan->plci; - m->msg.disconnect_req.cause = 0; - ACTCAPI_QUEUE_TX; -} - -void -actcapi_disconnect_b3_req(act2000_card *card, act2000_chan *chan) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(17, 0x84, 0x00); - ACTCAPI_CHKSKB; - m->msg.disconnect_b3_req.ncci = chan->ncci; - memset(&m->msg.disconnect_b3_req.ncpi, 0, - sizeof(m->msg.disconnect_b3_req.ncpi)); - m->msg.disconnect_b3_req.ncpi.len = 13; - m->msg.disconnect_b3_req.ncpi.modulo = 8; - chan->fsm_state = ACT2000_STATE_BHWAIT; - ACTCAPI_QUEUE_TX; -} - -void -actcapi_connect_resp(act2000_card *card, act2000_chan *chan, __u8 cause) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(3, 0x02, 0x03); - ACTCAPI_CHKSKB; - m->msg.connect_resp.plci = chan->plci; - m->msg.connect_resp.rejectcause = cause; - if (cause) { - chan->fsm_state = ACT2000_STATE_NULL; - chan->plci = 0x8000; - } else - chan->fsm_state = ACT2000_STATE_IWAIT; - ACTCAPI_QUEUE_TX; -} - -static void -actcapi_connect_active_resp(act2000_card *card, act2000_chan *chan) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(2, 0x03, 0x03); - ACTCAPI_CHKSKB; - m->msg.connect_resp.plci = chan->plci; - if (chan->fsm_state == ACT2000_STATE_IWAIT) - chan->fsm_state = ACT2000_STATE_IBWAIT; - ACTCAPI_QUEUE_TX; -} - -static void -actcapi_connect_b3_resp(act2000_card *card, act2000_chan *chan, __u8 rejectcause) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR((rejectcause ? 3 : 17), 0x82, 0x03); - ACTCAPI_CHKSKB; - m->msg.connect_b3_resp.ncci = chan->ncci; - m->msg.connect_b3_resp.rejectcause = rejectcause; - if (!rejectcause) { - memset(&m->msg.connect_b3_resp.ncpi, 0, - sizeof(m->msg.connect_b3_resp.ncpi)); - m->msg.connect_b3_resp.ncpi.len = 13; - m->msg.connect_b3_resp.ncpi.modulo = 8; - chan->fsm_state = ACT2000_STATE_BWAIT; - } - ACTCAPI_QUEUE_TX; -} - -static void -actcapi_connect_b3_active_resp(act2000_card *card, act2000_chan *chan) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(2, 0x83, 0x03); - ACTCAPI_CHKSKB; - m->msg.connect_b3_active_resp.ncci = chan->ncci; - chan->fsm_state = ACT2000_STATE_ACTIVE; - ACTCAPI_QUEUE_TX; -} - -static void -actcapi_info_resp(act2000_card *card, act2000_chan *chan) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(2, 0x07, 0x03); - ACTCAPI_CHKSKB; - m->msg.info_resp.plci = chan->plci; - ACTCAPI_QUEUE_TX; -} - -static void -actcapi_disconnect_b3_resp(act2000_card *card, act2000_chan *chan) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(2, 0x84, 0x03); - ACTCAPI_CHKSKB; - m->msg.disconnect_b3_resp.ncci = chan->ncci; - chan->ncci = 0x8000; - chan->queued = 0; - ACTCAPI_QUEUE_TX; -} - -static void -actcapi_disconnect_resp(act2000_card *card, act2000_chan *chan) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(2, 0x04, 0x03); - ACTCAPI_CHKSKB; - m->msg.disconnect_resp.plci = chan->plci; - chan->plci = 0x8000; - ACTCAPI_QUEUE_TX; -} - -static int -new_plci(act2000_card *card, __u16 plci) -{ - int i; - for (i = 0; i < ACT2000_BCH; i++) - if (card->bch[i].plci == 0x8000) { - card->bch[i].plci = plci; - return i; - } - return -1; -} - -static int -find_plci(act2000_card *card, __u16 plci) -{ - int i; - for (i = 0; i < ACT2000_BCH; i++) - if (card->bch[i].plci == plci) - return i; - return -1; -} - -static int -find_ncci(act2000_card *card, __u16 ncci) -{ - int i; - for (i = 0; i < ACT2000_BCH; i++) - if (card->bch[i].ncci == ncci) - return i; - return -1; -} - -static int -find_dialing(act2000_card *card, __u16 callref) -{ - int i; - for (i = 0; i < ACT2000_BCH; i++) - if ((card->bch[i].callref == callref) && - (card->bch[i].fsm_state == ACT2000_STATE_OCALL)) - return i; - return -1; -} - -static int -actcapi_data_b3_ind(act2000_card *card, struct sk_buff *skb) { - __u16 plci; - __u16 ncci; - __u16 controller; - __u8 blocknr; - int chan; - actcapi_msg *msg = (actcapi_msg *)skb->data; - - EVAL_NCCI(msg->msg.data_b3_ind.fakencci, plci, controller, ncci); - chan = find_ncci(card, ncci); - if (chan < 0) - return 0; - if (card->bch[chan].fsm_state != ACT2000_STATE_ACTIVE) - return 0; - if (card->bch[chan].plci != plci) - return 0; - blocknr = msg->msg.data_b3_ind.blocknr; - skb_pull(skb, 19); - card->interface.rcvcallb_skb(card->myid, chan, skb); - if (!(skb = alloc_skb(11, GFP_ATOMIC))) { - printk(KERN_WARNING "actcapi: alloc_skb failed\n"); - return 1; - } - msg = (actcapi_msg *)skb_put(skb, 11); - msg->hdr.len = 11; - msg->hdr.applicationID = 1; - msg->hdr.cmd.cmd = 0x86; - msg->hdr.cmd.subcmd = 0x03; - msg->hdr.msgnum = actcapi_nextsmsg(card); - msg->msg.data_b3_resp.ncci = ncci; - msg->msg.data_b3_resp.blocknr = blocknr; - ACTCAPI_QUEUE_TX; - return 1; -} - -/* - * Walk over ackq, unlink DATA_B3_REQ from it, if - * ncci and blocknr are matching. - * Decrement queued-bytes counter. - */ -static int -handle_ack(act2000_card *card, act2000_chan *chan, __u8 blocknr) { - unsigned long flags; - struct sk_buff *skb; - struct sk_buff *tmp; - struct actcapi_msg *m; - int ret = 0; - - spin_lock_irqsave(&card->lock, flags); - skb = skb_peek(&card->ackq); - spin_unlock_irqrestore(&card->lock, flags); - if (!skb) { - printk(KERN_WARNING "act2000: handle_ack nothing found!\n"); - return 0; - } - tmp = skb; - while (1) { - m = (actcapi_msg *)tmp->data; - if ((((m->msg.data_b3_req.fakencci >> 8) & 0xff) == chan->ncci) && - (m->msg.data_b3_req.blocknr == blocknr)) { - /* found corresponding DATA_B3_REQ */ - skb_unlink(tmp, &card->ackq); - chan->queued -= m->msg.data_b3_req.datalen; - if (m->msg.data_b3_req.flags) - ret = m->msg.data_b3_req.datalen; - dev_kfree_skb(tmp); - if (chan->queued < 0) - chan->queued = 0; - return ret; - } - spin_lock_irqsave(&card->lock, flags); - tmp = skb_peek((struct sk_buff_head *)tmp); - spin_unlock_irqrestore(&card->lock, flags); - if ((tmp == skb) || (tmp == NULL)) { - /* reached end of queue */ - printk(KERN_WARNING "act2000: handle_ack nothing found!\n"); - return 0; - } - } -} - -void -actcapi_dispatch(struct work_struct *work) -{ - struct act2000_card *card = - container_of(work, struct act2000_card, rcv_tq); - struct sk_buff *skb; - actcapi_msg *msg; - __u16 ccmd; - int chan; - int len; - act2000_chan *ctmp; - isdn_ctrl cmd; - char tmp[170]; - - while ((skb = skb_dequeue(&card->rcvq))) { - actcapi_debug_msg(skb, 0); - msg = (actcapi_msg *)skb->data; - ccmd = ((msg->hdr.cmd.cmd << 8) | msg->hdr.cmd.subcmd); - switch (ccmd) { - case 0x8602: - /* DATA_B3_IND */ - if (actcapi_data_b3_ind(card, skb)) - return; - break; - case 0x8601: - /* DATA_B3_CONF */ - chan = find_ncci(card, msg->msg.data_b3_conf.ncci); - if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_ACTIVE)) { - if (msg->msg.data_b3_conf.info != 0) - printk(KERN_WARNING "act2000: DATA_B3_CONF: %04x\n", - msg->msg.data_b3_conf.info); - len = handle_ack(card, &card->bch[chan], - msg->msg.data_b3_conf.blocknr); - if (len) { - cmd.driver = card->myid; - cmd.command = ISDN_STAT_BSENT; - cmd.arg = chan; - cmd.parm.length = len; - card->interface.statcallb(&cmd); - } - } - break; - case 0x0201: - /* CONNECT_CONF */ - chan = find_dialing(card, msg->hdr.msgnum); - if (chan >= 0) { - if (msg->msg.connect_conf.info) { - card->bch[chan].fsm_state = ACT2000_STATE_NULL; - cmd.driver = card->myid; - cmd.command = ISDN_STAT_DHUP; - cmd.arg = chan; - card->interface.statcallb(&cmd); - } else { - card->bch[chan].fsm_state = ACT2000_STATE_OWAIT; - card->bch[chan].plci = msg->msg.connect_conf.plci; - } - } - break; - case 0x0202: - /* CONNECT_IND */ - chan = new_plci(card, msg->msg.connect_ind.plci); - if (chan < 0) { - ctmp = (act2000_chan *)tmp; - ctmp->plci = msg->msg.connect_ind.plci; - actcapi_connect_resp(card, ctmp, 0x11); /* All Card-Cannels busy */ - } else { - card->bch[chan].fsm_state = ACT2000_STATE_ICALL; - cmd.driver = card->myid; - cmd.command = ISDN_STAT_ICALL; - cmd.arg = chan; - cmd.parm.setup.si1 = msg->msg.connect_ind.si1; - cmd.parm.setup.si2 = msg->msg.connect_ind.si2; - if (card->ptype == ISDN_PTYPE_EURO) - strcpy(cmd.parm.setup.eazmsn, - act2000_find_eaz(card, msg->msg.connect_ind.eaz)); - else { - cmd.parm.setup.eazmsn[0] = msg->msg.connect_ind.eaz; - cmd.parm.setup.eazmsn[1] = 0; - } - memset(cmd.parm.setup.phone, 0, sizeof(cmd.parm.setup.phone)); - memcpy(cmd.parm.setup.phone, msg->msg.connect_ind.addr.num, - msg->msg.connect_ind.addr.len - 1); - cmd.parm.setup.plan = msg->msg.connect_ind.addr.tnp; - cmd.parm.setup.screen = 0; - if (card->interface.statcallb(&cmd) == 2) - actcapi_connect_resp(card, &card->bch[chan], 0x15); /* Reject Call */ - } - break; - case 0x0302: - /* CONNECT_ACTIVE_IND */ - chan = find_plci(card, msg->msg.connect_active_ind.plci); - if (chan >= 0) - switch (card->bch[chan].fsm_state) { - case ACT2000_STATE_IWAIT: - actcapi_connect_active_resp(card, &card->bch[chan]); - break; - case ACT2000_STATE_OWAIT: - actcapi_connect_active_resp(card, &card->bch[chan]); - actcapi_select_b2_protocol_req(card, &card->bch[chan]); - break; - } - break; - case 0x8202: - /* CONNECT_B3_IND */ - chan = find_plci(card, msg->msg.connect_b3_ind.plci); - if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_IBWAIT)) { - card->bch[chan].ncci = msg->msg.connect_b3_ind.ncci; - actcapi_connect_b3_resp(card, &card->bch[chan], 0); - } else { - ctmp = (act2000_chan *)tmp; - ctmp->ncci = msg->msg.connect_b3_ind.ncci; - actcapi_connect_b3_resp(card, ctmp, 0x11); /* All Card-Cannels busy */ - } - break; - case 0x8302: - /* CONNECT_B3_ACTIVE_IND */ - chan = find_ncci(card, msg->msg.connect_b3_active_ind.ncci); - if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_BWAIT)) { - actcapi_connect_b3_active_resp(card, &card->bch[chan]); - cmd.driver = card->myid; - cmd.command = ISDN_STAT_BCONN; - cmd.arg = chan; - card->interface.statcallb(&cmd); - } - break; - case 0x8402: - /* DISCONNECT_B3_IND */ - chan = find_ncci(card, msg->msg.disconnect_b3_ind.ncci); - if (chan >= 0) { - ctmp = &card->bch[chan]; - actcapi_disconnect_b3_resp(card, ctmp); - switch (ctmp->fsm_state) { - case ACT2000_STATE_ACTIVE: - ctmp->fsm_state = ACT2000_STATE_DHWAIT2; - cmd.driver = card->myid; - cmd.command = ISDN_STAT_BHUP; - cmd.arg = chan; - card->interface.statcallb(&cmd); - break; - case ACT2000_STATE_BHWAIT2: - actcapi_disconnect_req(card, ctmp); - ctmp->fsm_state = ACT2000_STATE_DHWAIT; - cmd.driver = card->myid; - cmd.command = ISDN_STAT_BHUP; - cmd.arg = chan; - card->interface.statcallb(&cmd); - break; - } - } - break; - case 0x0402: - /* DISCONNECT_IND */ - chan = find_plci(card, msg->msg.disconnect_ind.plci); - if (chan >= 0) { - ctmp = &card->bch[chan]; - actcapi_disconnect_resp(card, ctmp); - ctmp->fsm_state = ACT2000_STATE_NULL; - cmd.driver = card->myid; - cmd.command = ISDN_STAT_DHUP; - cmd.arg = chan; - card->interface.statcallb(&cmd); - } else { - ctmp = (act2000_chan *)tmp; - ctmp->plci = msg->msg.disconnect_ind.plci; - actcapi_disconnect_resp(card, ctmp); - } - break; - case 0x4001: - /* SELECT_B2_PROTOCOL_CONF */ - chan = find_plci(card, msg->msg.select_b2_protocol_conf.plci); - if (chan >= 0) - switch (card->bch[chan].fsm_state) { - case ACT2000_STATE_ICALL: - case ACT2000_STATE_OWAIT: - ctmp = &card->bch[chan]; - if (msg->msg.select_b2_protocol_conf.info == 0) - actcapi_select_b3_protocol_req(card, ctmp); - else { - ctmp->fsm_state = ACT2000_STATE_NULL; - cmd.driver = card->myid; - cmd.command = ISDN_STAT_DHUP; - cmd.arg = chan; - card->interface.statcallb(&cmd); - } - break; - } - break; - case 0x8001: - /* SELECT_B3_PROTOCOL_CONF */ - chan = find_plci(card, msg->msg.select_b3_protocol_conf.plci); - if (chan >= 0) - switch (card->bch[chan].fsm_state) { - case ACT2000_STATE_ICALL: - case ACT2000_STATE_OWAIT: - ctmp = &card->bch[chan]; - if (msg->msg.select_b3_protocol_conf.info == 0) - actcapi_listen_b3_req(card, ctmp); - else { - ctmp->fsm_state = ACT2000_STATE_NULL; - cmd.driver = card->myid; - cmd.command = ISDN_STAT_DHUP; - cmd.arg = chan; - card->interface.statcallb(&cmd); - } - } - break; - case 0x8101: - /* LISTEN_B3_CONF */ - chan = find_plci(card, msg->msg.listen_b3_conf.plci); - if (chan >= 0) - switch (card->bch[chan].fsm_state) { - case ACT2000_STATE_ICALL: - ctmp = &card->bch[chan]; - if (msg->msg.listen_b3_conf.info == 0) - actcapi_connect_resp(card, ctmp, 0); - else { - ctmp->fsm_state = ACT2000_STATE_NULL; - cmd.driver = card->myid; - cmd.command = ISDN_STAT_DHUP; - cmd.arg = chan; - card->interface.statcallb(&cmd); - } - break; - case ACT2000_STATE_OWAIT: - ctmp = &card->bch[chan]; - if (msg->msg.listen_b3_conf.info == 0) { - actcapi_connect_b3_req(card, ctmp); - ctmp->fsm_state = ACT2000_STATE_OBWAIT; - cmd.driver = card->myid; - cmd.command = ISDN_STAT_DCONN; - cmd.arg = chan; - card->interface.statcallb(&cmd); - } else { - ctmp->fsm_state = ACT2000_STATE_NULL; - cmd.driver = card->myid; - cmd.command = ISDN_STAT_DHUP; - cmd.arg = chan; - card->interface.statcallb(&cmd); - } - break; - } - break; - case 0x8201: - /* CONNECT_B3_CONF */ - chan = find_plci(card, msg->msg.connect_b3_conf.plci); - if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_OBWAIT)) { - ctmp = &card->bch[chan]; - if (msg->msg.connect_b3_conf.info) { - ctmp->fsm_state = ACT2000_STATE_NULL; - cmd.driver = card->myid; - cmd.command = ISDN_STAT_DHUP; - cmd.arg = chan; - card->interface.statcallb(&cmd); - } else { - ctmp->ncci = msg->msg.connect_b3_conf.ncci; - ctmp->fsm_state = ACT2000_STATE_BWAIT; - } - } - break; - case 0x8401: - /* DISCONNECT_B3_CONF */ - chan = find_ncci(card, msg->msg.disconnect_b3_conf.ncci); - if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_BHWAIT)) - card->bch[chan].fsm_state = ACT2000_STATE_BHWAIT2; - break; - case 0x0702: - /* INFO_IND */ - chan = find_plci(card, msg->msg.info_ind.plci); - if (chan >= 0) - /* TODO: Eval Charging info / cause */ - actcapi_info_resp(card, &card->bch[chan]); - break; - case 0x0401: - /* LISTEN_CONF */ - case 0x0501: - /* LISTEN_CONF */ - case 0xff01: - /* MANUFACTURER_CONF */ - break; - case 0xff02: - /* MANUFACTURER_IND */ - if (msg->msg.manuf_msg == 3) { - memset(tmp, 0, sizeof(tmp)); - strncpy(tmp, - &msg->msg.manufacturer_ind_err.errstring, - msg->hdr.len - 16); - if (msg->msg.manufacturer_ind_err.errcode) - printk(KERN_WARNING "act2000: %s\n", tmp); - else { - printk(KERN_DEBUG "act2000: %s\n", tmp); - if ((!strncmp(tmp, "INFO: Trace buffer con", 22)) || - (!strncmp(tmp, "INFO: Compile Date/Tim", 22))) { - card->flags |= ACT2000_FLAGS_RUNNING; - cmd.command = ISDN_STAT_RUN; - cmd.driver = card->myid; - cmd.arg = 0; - actcapi_manufacturer_req_net(card); - actcapi_manufacturer_req_msn(card); - actcapi_listen_req(card); - card->interface.statcallb(&cmd); - } - } - } - break; - default: - printk(KERN_WARNING "act2000: UNHANDLED Message %04x\n", ccmd); - break; - } - dev_kfree_skb(skb); - } -} - -#ifdef DEBUG_MSG -static void -actcapi_debug_caddr(actcapi_addr *addr) -{ - char tmp[30]; - - printk(KERN_DEBUG " Alen = %d\n", addr->len); - if (addr->len > 0) - printk(KERN_DEBUG " Atnp = 0x%02x\n", addr->tnp); - if (addr->len > 1) { - memset(tmp, 0, 30); - memcpy(tmp, addr->num, addr->len - 1); - printk(KERN_DEBUG " Anum = '%s'\n", tmp); - } -} - -static void -actcapi_debug_ncpi(actcapi_ncpi *ncpi) -{ - printk(KERN_DEBUG " ncpi.len = %d\n", ncpi->len); - if (ncpi->len >= 2) - printk(KERN_DEBUG " ncpi.lic = 0x%04x\n", ncpi->lic); - if (ncpi->len >= 4) - printk(KERN_DEBUG " ncpi.hic = 0x%04x\n", ncpi->hic); - if (ncpi->len >= 6) - printk(KERN_DEBUG " ncpi.ltc = 0x%04x\n", ncpi->ltc); - if (ncpi->len >= 8) - printk(KERN_DEBUG " ncpi.htc = 0x%04x\n", ncpi->htc); - if (ncpi->len >= 10) - printk(KERN_DEBUG " ncpi.loc = 0x%04x\n", ncpi->loc); - if (ncpi->len >= 12) - printk(KERN_DEBUG " ncpi.hoc = 0x%04x\n", ncpi->hoc); - if (ncpi->len >= 13) - printk(KERN_DEBUG " ncpi.mod = %d\n", ncpi->modulo); -} - -static void -actcapi_debug_dlpd(actcapi_dlpd *dlpd) -{ - printk(KERN_DEBUG " dlpd.len = %d\n", dlpd->len); - if (dlpd->len >= 2) - printk(KERN_DEBUG " dlpd.dlen = 0x%04x\n", dlpd->dlen); - if (dlpd->len >= 3) - printk(KERN_DEBUG " dlpd.laa = 0x%02x\n", dlpd->laa); - if (dlpd->len >= 4) - printk(KERN_DEBUG " dlpd.lab = 0x%02x\n", dlpd->lab); - if (dlpd->len >= 5) - printk(KERN_DEBUG " dlpd.modulo = %d\n", dlpd->modulo); - if (dlpd->len >= 6) - printk(KERN_DEBUG " dlpd.win = %d\n", dlpd->win); -} - -#ifdef DEBUG_DUMP_SKB -static void dump_skb(struct sk_buff *skb) { - char tmp[80]; - char *p = skb->data; - char *t = tmp; - int i; - - for (i = 0; i < skb->len; i++) { - t += sprintf(t, "%02x ", *p++ & 0xff); - if ((i & 0x0f) == 8) { - printk(KERN_DEBUG "dump: %s\n", tmp); - t = tmp; - } - } - if (i & 0x07) - printk(KERN_DEBUG "dump: %s\n", tmp); -} -#endif - -void -actcapi_debug_msg(struct sk_buff *skb, int direction) -{ - actcapi_msg *msg = (actcapi_msg *)skb->data; - char *descr; - int i; - char tmp[170]; - -#ifndef DEBUG_DATA_MSG - if (msg->hdr.cmd.cmd == 0x86) - return; -#endif - descr = "INVALID"; -#ifdef DEBUG_DUMP_SKB - dump_skb(skb); -#endif - for (i = 0; i < ARRAY_SIZE(valid_msg); i++) - if ((msg->hdr.cmd.cmd == valid_msg[i].cmd.cmd) && - (msg->hdr.cmd.subcmd == valid_msg[i].cmd.subcmd)) { - descr = valid_msg[i].description; - break; - } - printk(KERN_DEBUG "%s %s msg\n", direction ? "Outgoing" : "Incoming", descr); - printk(KERN_DEBUG " ApplID = %d\n", msg->hdr.applicationID); - printk(KERN_DEBUG " Len = %d\n", msg->hdr.len); - printk(KERN_DEBUG " MsgNum = 0x%04x\n", msg->hdr.msgnum); - printk(KERN_DEBUG " Cmd = 0x%02x\n", msg->hdr.cmd.cmd); - printk(KERN_DEBUG " SubCmd = 0x%02x\n", msg->hdr.cmd.subcmd); - switch (i) { - case 0: - /* DATA B3 IND */ - printk(KERN_DEBUG " BLOCK = 0x%02x\n", - msg->msg.data_b3_ind.blocknr); - break; - case 2: - /* CONNECT CONF */ - printk(KERN_DEBUG " PLCI = 0x%04x\n", - msg->msg.connect_conf.plci); - printk(KERN_DEBUG " Info = 0x%04x\n", - msg->msg.connect_conf.info); - break; - case 3: - /* CONNECT IND */ - printk(KERN_DEBUG " PLCI = 0x%04x\n", - msg->msg.connect_ind.plci); - printk(KERN_DEBUG " Contr = %d\n", - msg->msg.connect_ind.controller); - printk(KERN_DEBUG " SI1 = %d\n", - msg->msg.connect_ind.si1); - printk(KERN_DEBUG " SI2 = %d\n", - msg->msg.connect_ind.si2); - printk(KERN_DEBUG " EAZ = '%c'\n", - msg->msg.connect_ind.eaz); - actcapi_debug_caddr(&msg->msg.connect_ind.addr); - break; - case 5: - /* CONNECT ACTIVE IND */ - printk(KERN_DEBUG " PLCI = 0x%04x\n", - msg->msg.connect_active_ind.plci); - actcapi_debug_caddr(&msg->msg.connect_active_ind.addr); - break; - case 8: - /* LISTEN CONF */ - printk(KERN_DEBUG " Contr = %d\n", - msg->msg.listen_conf.controller); - printk(KERN_DEBUG " Info = 0x%04x\n", - msg->msg.listen_conf.info); - break; - case 11: - /* INFO IND */ - printk(KERN_DEBUG " PLCI = 0x%04x\n", - msg->msg.info_ind.plci); - printk(KERN_DEBUG " Imsk = 0x%04x\n", - msg->msg.info_ind.nr.mask); - if (msg->hdr.len > 12) { - int l = msg->hdr.len - 12; - int j; - char *p = tmp; - for (j = 0; j < l; j++) - p += sprintf(p, "%02x ", msg->msg.info_ind.el.display[j]); - printk(KERN_DEBUG " D = '%s'\n", tmp); - } - break; - case 14: - /* SELECT B2 PROTOCOL CONF */ - printk(KERN_DEBUG " PLCI = 0x%04x\n", - msg->msg.select_b2_protocol_conf.plci); - printk(KERN_DEBUG " Info = 0x%04x\n", - msg->msg.select_b2_protocol_conf.info); - break; - case 15: - /* SELECT B3 PROTOCOL CONF */ - printk(KERN_DEBUG " PLCI = 0x%04x\n", - msg->msg.select_b3_protocol_conf.plci); - printk(KERN_DEBUG " Info = 0x%04x\n", - msg->msg.select_b3_protocol_conf.info); - break; - case 16: - /* LISTEN B3 CONF */ - printk(KERN_DEBUG " PLCI = 0x%04x\n", - msg->msg.listen_b3_conf.plci); - printk(KERN_DEBUG " Info = 0x%04x\n", - msg->msg.listen_b3_conf.info); - break; - case 18: - /* CONNECT B3 IND */ - printk(KERN_DEBUG " NCCI = 0x%04x\n", - msg->msg.connect_b3_ind.ncci); - printk(KERN_DEBUG " PLCI = 0x%04x\n", - msg->msg.connect_b3_ind.plci); - actcapi_debug_ncpi(&msg->msg.connect_b3_ind.ncpi); - break; - case 19: - /* CONNECT B3 ACTIVE IND */ - printk(KERN_DEBUG " NCCI = 0x%04x\n", - msg->msg.connect_b3_active_ind.ncci); - actcapi_debug_ncpi(&msg->msg.connect_b3_active_ind.ncpi); - break; - case 26: - /* MANUFACTURER IND */ - printk(KERN_DEBUG " Mmsg = 0x%02x\n", - msg->msg.manufacturer_ind_err.manuf_msg); - switch (msg->msg.manufacturer_ind_err.manuf_msg) { - case 3: - printk(KERN_DEBUG " Contr = %d\n", - msg->msg.manufacturer_ind_err.controller); - printk(KERN_DEBUG " Code = 0x%08x\n", - msg->msg.manufacturer_ind_err.errcode); - memset(tmp, 0, sizeof(tmp)); - strncpy(tmp, &msg->msg.manufacturer_ind_err.errstring, - msg->hdr.len - 16); - printk(KERN_DEBUG " Emsg = '%s'\n", tmp); - break; - } - break; - case 30: - /* LISTEN REQ */ - printk(KERN_DEBUG " Imsk = 0x%08x\n", - msg->msg.listen_req.infomask); - printk(KERN_DEBUG " Emsk = 0x%04x\n", - msg->msg.listen_req.eazmask); - printk(KERN_DEBUG " Smsk = 0x%04x\n", - msg->msg.listen_req.simask); - break; - case 35: - /* SELECT_B2_PROTOCOL_REQ */ - printk(KERN_DEBUG " PLCI = 0x%04x\n", - msg->msg.select_b2_protocol_req.plci); - printk(KERN_DEBUG " prot = 0x%02x\n", - msg->msg.select_b2_protocol_req.protocol); - if (msg->hdr.len >= 11) - printk(KERN_DEBUG "No dlpd\n"); - else - actcapi_debug_dlpd(&msg->msg.select_b2_protocol_req.dlpd); - break; - case 44: - /* CONNECT RESP */ - printk(KERN_DEBUG " PLCI = 0x%04x\n", - msg->msg.connect_resp.plci); - printk(KERN_DEBUG " CAUSE = 0x%02x\n", - msg->msg.connect_resp.rejectcause); - break; - case 45: - /* CONNECT ACTIVE RESP */ - printk(KERN_DEBUG " PLCI = 0x%04x\n", - msg->msg.connect_active_resp.plci); - break; - } -} -#endif diff --git a/drivers/isdn/act2000/capi.h b/drivers/isdn/act2000/capi.h deleted file mode 100644 index 01ccdecd43f7..000000000000 --- a/drivers/isdn/act2000/capi.h +++ /dev/null @@ -1,365 +0,0 @@ -/* $Id: capi.h,v 1.6.6.2 2001/09/23 22:24:32 kai Exp $ - * - * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000. - * - * Author Fritz Elfert - * Copyright by Fritz Elfert <fritz@isdn4linux.de> - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - * Thanks to Friedemann Baitinger and IBM Germany - * - */ - -#ifndef CAPI_H -#define CAPI_H - -/* Command-part of a CAPI message */ -typedef struct actcapi_msgcmd { - __u8 cmd; - __u8 subcmd; -} actcapi_msgcmd; - -/* CAPI message header */ -typedef struct actcapi_msghdr { - __u16 len; - __u16 applicationID; - actcapi_msgcmd cmd; - __u16 msgnum; -} actcapi_msghdr; - -/* CAPI message description (for debugging) */ -typedef struct actcapi_msgdsc { - actcapi_msgcmd cmd; - char *description; -} actcapi_msgdsc; - -/* CAPI Address */ -typedef struct actcapi_addr { - __u8 len; /* Length of element */ - __u8 tnp; /* Type/Numbering Plan */ - __u8 num[20]; /* Caller ID */ -} actcapi_addr; - -/* CAPI INFO element mask */ -typedef union actcapi_infonr { /* info number */ - __u16 mask; /* info-mask field */ - struct bmask { /* bit definitions */ - unsigned codes:3; /* code set */ - unsigned rsvd:5; /* reserved */ - unsigned svind:1; /* single, variable length ind. */ - unsigned wtype:7; /* W-element type */ - } bmask; -} actcapi_infonr; - -/* CAPI INFO element */ -typedef union actcapi_infoel { /* info element */ - __u8 len; /* length of info element */ - __u8 display[40]; /* display contents */ - __u8 uuinfo[40]; /* User-user info field */ - struct cause { /* Cause information */ - unsigned ext2:1; /* extension */ - unsigned cod:2; /* coding standard */ - unsigned spare:1; /* spare */ - unsigned loc:4; /* location */ - unsigned ext1:1; /* extension */ - unsigned cval:7; /* Cause value */ - } cause; - struct charge { /* Charging information */ - __u8 toc; /* type of charging info */ - __u8 unit[10]; /* charging units */ - } charge; - __u8 date[20]; /* date fields */ - __u8 stat; /* state of remote party */ -} actcapi_infoel; - -/* Message for EAZ<->MSN Mapping */ -typedef struct actcapi_msn { - __u8 eaz; - __u8 len; /* Length of MSN */ - __u8 msn[15]; -} __attribute__((packed)) actcapi_msn; - -typedef struct actcapi_dlpd { - __u8 len; /* Length of structure */ - __u16 dlen; /* Data Length */ - __u8 laa; /* Link Address A */ - __u8 lab; /* Link Address B */ - __u8 modulo; /* Modulo Mode */ - __u8 win; /* Window size */ - __u8 xid[100]; /* XID Information */ -} __attribute__((packed)) actcapi_dlpd; - -typedef struct actcapi_ncpd { - __u8 len; /* Length of structure */ - __u16 lic; - __u16 hic; - __u16 ltc; - __u16 htc; - __u16 loc; - __u16 hoc; - __u8 modulo; -} __attribute__((packed)) actcapi_ncpd; -#define actcapi_ncpi actcapi_ncpd - -/* - * Layout of NCCI field in a B3 DATA CAPI message is different from - * standard at act2000: - * - * Bit 0-4 = PLCI - * Bit 5-7 = Controller - * Bit 8-15 = NCCI - */ -#define MAKE_NCCI(plci, contr, ncci) \ - ((plci & 0x1f) | ((contr & 0x7) << 5) | ((ncci & 0xff) << 8)) - -#define EVAL_NCCI(fakencci, plci, contr, ncci) { \ - plci = fakencci & 0x1f; \ - contr = (fakencci >> 5) & 0x7; \ - ncci = (fakencci >> 8) & 0xff; \ - } - -/* - * Layout of PLCI field in a B3 DATA CAPI message is different from - * standard at act2000: - * - * Bit 0-4 = PLCI - * Bit 5-7 = Controller - * Bit 8-15 = reserved (must be 0) - */ -#define MAKE_PLCI(plci, contr) \ - ((plci & 0x1f) | ((contr & 0x7) << 5)) - -#define EVAL_PLCI(fakeplci, plci, contr) { \ - plci = fakeplci & 0x1f; \ - contr = (fakeplci >> 5) & 0x7; \ - } - -typedef struct actcapi_msg { - actcapi_msghdr hdr; - union { - __u16 manuf_msg; - struct manufacturer_req_net { - __u16 manuf_msg; - __u16 controller; - __u8 nettype; - } manufacturer_req_net; - struct manufacturer_req_v42 { - __u16 manuf_msg; - __u16 controller; - __u32 v42control; - } manufacturer_req_v42; - struct manufacturer_conf_v42 { - __u16 manuf_msg; - __u16 controller; - } manufacturer_conf_v42; - struct manufacturer_req_err { - __u16 manuf_msg; - __u16 controller; - } manufacturer_req_err; - struct manufacturer_ind_err { - __u16 manuf_msg; - __u16 controller; - __u32 errcode; - __u8 errstring; /* actually up to 160 */ - } manufacturer_ind_err; - struct manufacturer_req_msn { - __u16 manuf_msg; - __u16 controller; - actcapi_msn msnmap; - } __attribute ((packed)) manufacturer_req_msn; - /* TODO: TraceInit-req/conf/ind/resp and - * TraceDump-req/conf/ind/resp - */ - struct connect_req { - __u8 controller; - __u8 bchan; - __u32 infomask; - __u8 si1; - __u8 si2; - __u8 eaz; - actcapi_addr addr; - } __attribute__ ((packed)) connect_req; - struct connect_conf { - __u16 plci; - __u16 info; - } connect_conf; - struct connect_ind { - __u16 plci; - __u8 controller; - __u8 si1; - __u8 si2; - __u8 eaz; - actcapi_addr addr; - } __attribute__ ((packed)) connect_ind; - struct connect_resp { - __u16 plci; - __u8 rejectcause; - } connect_resp; - struct connect_active_ind { - __u16 plci; - actcapi_addr addr; - } __attribute__ ((packed)) connect_active_ind; - struct connect_active_resp { - __u16 plci; - } connect_active_resp; - struct connect_b3_req { - __u16 plci; - actcapi_ncpi ncpi; - } __attribute__ ((packed)) connect_b3_req; - struct connect_b3_conf { - __u16 plci; - __u16 ncci; - __u16 info; - } connect_b3_conf; - struct connect_b3_ind { - __u16 ncci; - __u16 plci; - actcapi_ncpi ncpi; - } __attribute__ ((packed)) connect_b3_ind; - struct connect_b3_resp { - __u16 ncci; - __u8 rejectcause; - actcapi_ncpi ncpi; - } __attribute__ ((packed)) connect_b3_resp; - struct disconnect_req { - __u16 plci; - __u8 cause; - } disconnect_req; - struct disconnect_conf { - __u16 plci; - __u16 info; - } disconnect_conf; - struct disconnect_ind { - __u16 plci; - __u16 info; - } disconnect_ind; - struct disconnect_resp { - __u16 plci; - } disconnect_resp; - struct connect_b3_active_ind { - __u16 ncci; - actcapi_ncpi ncpi; - } __attribute__ ((packed)) connect_b3_active_ind; - struct connect_b3_active_resp { - __u16 ncci; - } connect_b3_active_resp; - struct disconnect_b3_req { - __u16 ncci; - actcapi_ncpi ncpi; - } __attribute__ ((packed)) disconnect_b3_req; - struct disconnect_b3_conf { - __u16 ncci; - __u16 info; - } disconnect_b3_conf; - struct disconnect_b3_ind { - __u16 ncci; - __u16 info; - actcapi_ncpi ncpi; - } __attribute__ ((packed)) disconnect_b3_ind; - struct disconnect_b3_resp { - __u16 ncci; - } disconnect_b3_resp; - struct info_ind { - __u16 plci; - actcapi_infonr nr; - actcapi_infoel el; - } __attribute__ ((packed)) info_ind; - struct info_resp { - __u16 plci; - } info_resp; - struct listen_b3_req { - __u16 plci; - } listen_b3_req; - struct listen_b3_conf { - __u16 plci; - __u16 info; - } listen_b3_conf; - struct select_b2_protocol_req { - __u16 plci; - __u8 protocol; - actcapi_dlpd dlpd; - } __attribute__ ((packed)) select_b2_protocol_req; - struct select_b2_protocol_conf { - __u16 plci; - __u16 info; - } select_b2_protocol_conf; - struct select_b3_protocol_req { - __u16 plci; - __u8 protocol; - actcapi_ncpd ncpd; - } __attribute__ ((packed)) select_b3_protocol_req; - struct select_b3_protocol_conf { - __u16 plci; - __u16 info; - } select_b3_protocol_conf; - struct listen_req { - __u8 controller; - __u32 infomask; - __u16 eazmask; - __u16 simask; - } __attribute__ ((packed)) listen_req; - struct listen_conf { - __u8 controller; - __u16 info; - } __attribute__ ((packed)) listen_conf; - struct data_b3_req { - __u16 fakencci; - __u16 datalen; - __u32 unused; - __u8 blocknr; - __u16 flags; - } __attribute ((packed)) data_b3_req; - struct data_b3_ind { - __u16 fakencci; - __u16 datalen; - __u32 unused; - __u8 blocknr; - __u16 flags; - } __attribute__ ((packed)) data_b3_ind; - struct data_b3_resp { - __u16 ncci; - __u8 blocknr; - } __attribute__ ((packed)) data_b3_resp; - struct data_b3_conf { - __u16 ncci; - __u8 blocknr; - __u16 info; - } __attribute__ ((packed)) data_b3_conf; - } msg; -} __attribute__ ((packed)) actcapi_msg; - -static inline unsigned short -actcapi_nextsmsg(act2000_card *card) -{ - unsigned long flags; - unsigned short n; - - spin_lock_irqsave(&card->mnlock, flags); - n = card->msgnum; - card->msgnum++; - card->msgnum &= 0x7fff; - spin_unlock_irqrestore(&card->mnlock, flags); - return n; -} -#define DEBUG_MSG -#undef DEBUG_DATA_MSG -#undef DEBUG_DUMP_SKB - -extern int actcapi_chkhdr(act2000_card *, actcapi_msghdr *); -extern int actcapi_listen_req(act2000_card *); -extern int actcapi_manufacturer_req_net(act2000_card *); -extern int actcapi_manufacturer_req_errh(act2000_card *); -extern int actcapi_manufacturer_req_msn(act2000_card *); -extern int actcapi_connect_req(act2000_card *, act2000_chan *, char *, char, int, int); -extern void actcapi_select_b2_protocol_req(act2000_card *, act2000_chan *); -extern void actcapi_disconnect_b3_req(act2000_card *, act2000_chan *); -extern void actcapi_connect_resp(act2000_card *, act2000_chan *, __u8); -extern void actcapi_dispatch(struct work_struct *); -#ifdef DEBUG_MSG -extern void actcapi_debug_msg(struct sk_buff *skb, int); -#else -#define actcapi_debug_msg(skb, len) -#endif -#endif diff --git a/drivers/isdn/act2000/module.c b/drivers/isdn/act2000/module.c deleted file mode 100644 index 68073d0da0e3..000000000000 --- a/drivers/isdn/act2000/module.c +++ /dev/null @@ -1,813 +0,0 @@ -/* $Id: module.c,v 1.14.6.4 2001/09/23 22:24:32 kai Exp $ - * - * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000. - * - * Author Fritz Elfert - * Copyright by Fritz Elfert <fritz@isdn4linux.de> - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - * Thanks to Friedemann Baitinger and IBM Germany - * - */ - -#include "act2000.h" -#include "act2000_isa.h" -#include "capi.h" -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/init.h> - -static unsigned short act2000_isa_ports[] = -{ - 0x0200, 0x0240, 0x0280, 0x02c0, 0x0300, 0x0340, 0x0380, - 0xcfe0, 0xcfa0, 0xcf60, 0xcf20, 0xcee0, 0xcea0, 0xce60, -}; - -static act2000_card *cards = (act2000_card *) NULL; - -/* Parameters to be set by insmod */ -static int act_bus = 0; -static int act_port = -1; /* -1 = Autoprobe */ -static int act_irq = -1; -static char *act_id = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; - -MODULE_DESCRIPTION("ISDN4Linux: Driver for IBM Active 2000 ISDN card"); -MODULE_AUTHOR("Fritz Elfert"); -MODULE_LICENSE("GPL"); -MODULE_PARM_DESC(act_bus, "BusType of first card, 1=ISA, 2=MCA, 3=PCMCIA, currently only ISA"); -MODULE_PARM_DESC(act_port, "Base port address of first card"); -MODULE_PARM_DESC(act_irq, "IRQ of first card"); -MODULE_PARM_DESC(act_id, "ID-String of first card"); -module_param(act_bus, int, 0); -module_param(act_port, int, 0); -module_param(act_irq, int, 0); -module_param(act_id, charp, 0); - -static int act2000_addcard(int, int, int, char *); - -static act2000_chan * -find_channel(act2000_card *card, int channel) -{ - if ((channel >= 0) && (channel < ACT2000_BCH)) - return &(card->bch[channel]); - printk(KERN_WARNING "act2000: Invalid channel %d\n", channel); - return NULL; -} - -/* - * Free MSN list - */ -static void -act2000_clear_msn(act2000_card *card) -{ - struct msn_entry *p = card->msn_list; - struct msn_entry *q; - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); - card->msn_list = NULL; - spin_unlock_irqrestore(&card->lock, flags); - while (p) { - q = p->next; - kfree(p); - p = q; - } -} - -/* - * Find an MSN entry in the list. - * If ia5 != 0, return IA5-encoded EAZ, else - * return a bitmask with corresponding bit set. - */ -static __u16 -act2000_find_msn(act2000_card *card, char *msn, int ia5) -{ - struct msn_entry *p = card->msn_list; - __u8 eaz = '0'; - - while (p) { - if (!strcmp(p->msn, msn)) { - eaz = p->eaz; - break; - } - p = p->next; - } - if (!ia5) - return (1 << (eaz - '0')); - else - return eaz; -} - -/* - * Find an EAZ entry in the list. - * return a string with corresponding msn. - */ -char * -act2000_find_eaz(act2000_card *card, char eaz) -{ - struct msn_entry *p = card->msn_list; - - while (p) { - if (p->eaz == eaz) - return (p->msn); - p = p->next; - } - return ("\0"); -} - -/* - * Add or delete an MSN to the MSN list - * - * First character of msneaz is EAZ, rest is MSN. - * If length of eazmsn is 1, delete that entry. - */ -static int -act2000_set_msn(act2000_card *card, char *eazmsn) -{ - struct msn_entry *p = card->msn_list; - struct msn_entry *q = NULL; - unsigned long flags; - int i; - - if (!strlen(eazmsn)) - return 0; - if (strlen(eazmsn) > 16) - return -EINVAL; - for (i = 0; i < strlen(eazmsn); i++) - if (!isdigit(eazmsn[i])) - return -EINVAL; - if (strlen(eazmsn) == 1) { - /* Delete a single MSN */ - while (p) { - if (p->eaz == eazmsn[0]) { - spin_lock_irqsave(&card->lock, flags); - if (q) - q->next = p->next; - else - card->msn_list = p->next; - spin_unlock_irqrestore(&card->lock, flags); - kfree(p); - printk(KERN_DEBUG - "Mapping for EAZ %c deleted\n", - eazmsn[0]); - return 0; - } - q = p; - p = p->next; - } - return 0; - } - /* Add a single MSN */ - while (p) { - /* Found in list, replace MSN */ - if (p->eaz == eazmsn[0]) { - spin_lock_irqsave(&card->lock, flags); - strcpy(p->msn, &eazmsn[1]); - spin_unlock_irqrestore(&card->lock, flags); - printk(KERN_DEBUG - "Mapping for EAZ %c changed to %s\n", - eazmsn[0], - &eazmsn[1]); - return 0; - } - p = p->next; - } - /* Not found in list, add new entry */ - p = kmalloc(sizeof(msn_entry), GFP_KERNEL); - if (!p) - return -ENOMEM; - p->eaz = eazmsn[0]; - strcpy(p->msn, &eazmsn[1]); - p->next = card->msn_list; - spin_lock_irqsave(&card->lock, flags); - card->msn_list = p; - spin_unlock_irqrestore(&card->lock, flags); - printk(KERN_DEBUG - "Mapping %c -> %s added\n", - eazmsn[0], - &eazmsn[1]); - return 0; -} - -static void -act2000_transmit(struct work_struct *work) -{ - struct act2000_card *card = - container_of(work, struct act2000_card, snd_tq); - - switch (card->bus) { - case ACT2000_BUS_ISA: - act2000_isa_send(card); - break; - case ACT2000_BUS_PCMCIA: - case ACT2000_BUS_MCA: - default: - printk(KERN_WARNING - "act2000_transmit: Illegal bustype %d\n", card->bus); - } -} - -static void -act2000_receive(struct work_struct *work) -{ - struct act2000_card *card = - container_of(work, struct act2000_card, poll_tq); - - switch (card->bus) { - case ACT2000_BUS_ISA: - act2000_isa_receive(card); - break; - case ACT2000_BUS_PCMCIA: - case ACT2000_BUS_MCA: - default: - printk(KERN_WARNING - "act2000_receive: Illegal bustype %d\n", card->bus); - } -} - -static void -act2000_poll(unsigned long data) -{ - act2000_card *card = (act2000_card *)data; - unsigned long flags; - - act2000_receive(&card->poll_tq); - spin_lock_irqsave(&card->lock, flags); - mod_timer(&card->ptimer, jiffies + 3); - spin_unlock_irqrestore(&card->lock, flags); -} - -static int -act2000_command(act2000_card *card, isdn_ctrl *c) -{ - ulong a; - act2000_chan *chan; - act2000_cdef cdef; - isdn_ctrl cmd; - char tmp[17]; - int ret; - unsigned long flags; - void __user *arg; - - switch (c->command) { - case ISDN_CMD_IOCTL: - memcpy(&a, c->parm.num, sizeof(ulong)); - arg = (void __user *)a; - switch (c->arg) { - case ACT2000_IOCTL_LOADBOOT: - switch (card->bus) { - case ACT2000_BUS_ISA: - ret = act2000_isa_download(card, - arg); - if (!ret) { - card->flags |= ACT2000_FLAGS_LOADED; - if (!(card->flags & ACT2000_FLAGS_IVALID)) { - card->ptimer.expires = jiffies + 3; - card->ptimer.function = act2000_poll; - card->ptimer.data = (unsigned long)card; - add_timer(&card->ptimer); - } - actcapi_manufacturer_req_errh(card); - } - break; - default: - printk(KERN_WARNING - "act2000: Illegal BUS type %d\n", - card->bus); - ret = -EIO; - } - return ret; - case ACT2000_IOCTL_SETPROTO: - card->ptype = a ? ISDN_PTYPE_EURO : ISDN_PTYPE_1TR6; - if (!(card->flags & ACT2000_FLAGS_RUNNING)) - return 0; - actcapi_manufacturer_req_net(card); - return 0; - case ACT2000_IOCTL_SETMSN: - if (copy_from_user(tmp, arg, - sizeof(tmp))) - return -EFAULT; - if ((ret = act2000_set_msn(card, tmp))) - return ret; - if (card->flags & ACT2000_FLAGS_RUNNING) - return (actcapi_manufacturer_req_msn(card)); - return 0; - case ACT2000_IOCTL_ADDCARD: - if (copy_from_user(&cdef, arg, - sizeof(cdef))) - return -EFAULT; - if (act2000_addcard(cdef.bus, cdef.port, cdef.irq, cdef.id)) - return -EIO; - return 0; - case ACT2000_IOCTL_TEST: - if (!(card->flags & ACT2000_FLAGS_RUNNING)) - return -ENODEV; - return 0; - default: - return -EINVAL; - } - break; - case ISDN_CMD_DIAL: - if (!(card->flags & ACT2000_FLAGS_RUNNING)) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x0f))) - break; - spin_lock_irqsave(&card->lock, flags); - if (chan->fsm_state != ACT2000_STATE_NULL) { - spin_unlock_irqrestore(&card->lock, flags); - printk(KERN_WARNING "Dial on channel with state %d\n", - chan->fsm_state); - return -EBUSY; - } - if (card->ptype == ISDN_PTYPE_EURO) - tmp[0] = act2000_find_msn(card, c->parm.setup.eazmsn, 1); - else - tmp[0] = c->parm.setup.eazmsn[0]; - chan->fsm_state = ACT2000_STATE_OCALL; - chan->callref = 0xffff; - spin_unlock_irqrestore(&card->lock, flags); - ret = actcapi_connect_req(card, chan, c->parm.setup.phone, - tmp[0], c->parm.setup.si1, - c->parm.setup.si2); - if (ret) { - cmd.driver = card->myid; - cmd.command = ISDN_STAT_DHUP; - cmd.arg &= 0x0f; - card->interface.statcallb(&cmd); - } - return ret; - case ISDN_CMD_ACCEPTD: - if (!(card->flags & ACT2000_FLAGS_RUNNING)) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x0f))) - break; - if (chan->fsm_state == ACT2000_STATE_ICALL) - actcapi_select_b2_protocol_req(card, chan); - return 0; - case ISDN_CMD_ACCEPTB: - if (!(card->flags & ACT2000_FLAGS_RUNNING)) - return -ENODEV; - return 0; - case ISDN_CMD_HANGUP: - if (!(card->flags & ACT2000_FLAGS_RUNNING)) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x0f))) - break; - switch (chan->fsm_state) { - case ACT2000_STATE_ICALL: - case ACT2000_STATE_BSETUP: - actcapi_connect_resp(card, chan, 0x15); - break; - case ACT2000_STATE_ACTIVE: - actcapi_disconnect_b3_req(card, chan); - break; - } - return 0; - case ISDN_CMD_SETEAZ: - if (!(card->flags & ACT2000_FLAGS_RUNNING)) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x0f))) - break; - if (strlen(c->parm.num)) { - if (card->ptype == ISDN_PTYPE_EURO) { - chan->eazmask = act2000_find_msn(card, c->parm.num, 0); - } - if (card->ptype == ISDN_PTYPE_1TR6) { - int i; - chan->eazmask = 0; - for (i = 0; i < strlen(c->parm.num); i++) - if (isdigit(c->parm.num[i])) - chan->eazmask |= (1 << (c->parm.num[i] - '0')); - } - } else - chan->eazmask = 0x3ff; - actcapi_listen_req(card); - return 0; - case ISDN_CMD_CLREAZ: - if (!(card->flags & ACT2000_FLAGS_RUNNING)) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x0f))) - break; - chan->eazmask = 0; - actcapi_listen_req(card); - return 0; - case ISDN_CMD_SETL2: - if (!(card->flags & ACT2000_FLAGS_RUNNING)) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x0f))) - break; - chan->l2prot = (c->arg >> 8); - return 0; - case ISDN_CMD_SETL3: - if (!(card->flags & ACT2000_FLAGS_RUNNING)) - return -ENODEV; - if ((c->arg >> 8) != ISDN_PROTO_L3_TRANS) { - printk(KERN_WARNING "L3 protocol unknown\n"); - return -1; - } - if (!(chan = find_channel(card, c->arg & 0x0f))) - break; - chan->l3prot = (c->arg >> 8); - return 0; - } - - return -EINVAL; -} - -static int -act2000_sendbuf(act2000_card *card, int channel, int ack, struct sk_buff *skb) -{ - struct sk_buff *xmit_skb; - int len; - act2000_chan *chan; - actcapi_msg *msg; - - if (!(chan = find_channel(card, channel))) - return -1; - if (chan->fsm_state != ACT2000_STATE_ACTIVE) - return -1; - len = skb->len; - if ((chan->queued + len) >= ACT2000_MAX_QUEUED) - return 0; - if (!len) - return 0; - if (skb_headroom(skb) < 19) { - printk(KERN_WARNING "act2000_sendbuf: Headroom only %d\n", - skb_headroom(skb)); - xmit_skb = alloc_skb(len + 19, GFP_ATOMIC); - if (!xmit_skb) { - printk(KERN_WARNING "act2000_sendbuf: Out of memory\n"); - return 0; - } - skb_reserve(xmit_skb, 19); - skb_copy_from_linear_data(skb, skb_put(xmit_skb, len), len); - } else { - xmit_skb = skb_clone(skb, GFP_ATOMIC); - if (!xmit_skb) { - printk(KERN_WARNING "act2000_sendbuf: Out of memory\n"); - return 0; - } - } - dev_kfree_skb(skb); - msg = (actcapi_msg *)skb_push(xmit_skb, 19); - msg->hdr.len = 19 + len; - msg->hdr.applicationID = 1; - msg->hdr.cmd.cmd = 0x86; - msg->hdr.cmd.subcmd = 0x00; - msg->hdr.msgnum = actcapi_nextsmsg(card); - msg->msg.data_b3_req.datalen = len; - msg->msg.data_b3_req.blocknr = (msg->hdr.msgnum & 0xff); - msg->msg.data_b3_req.fakencci = MAKE_NCCI(chan->plci, 0, chan->ncci); - msg->msg.data_b3_req.flags = ack; /* Will be set to 0 on actual sending */ - actcapi_debug_msg(xmit_skb, 1); - chan->queued += len; - skb_queue_tail(&card->sndq, xmit_skb); - act2000_schedule_tx(card); - return len; -} - - -/* Read the Status-replies from the Interface */ -static int -act2000_readstatus(u_char __user *buf, int len, act2000_card *card) -{ - int count; - u_char __user *p; - - for (p = buf, count = 0; count < len; p++, count++) { - if (card->status_buf_read == card->status_buf_write) - return count; - put_user(*card->status_buf_read++, p); - if (card->status_buf_read > card->status_buf_end) - card->status_buf_read = card->status_buf; - } - return count; -} - -/* - * Find card with given driverId - */ -static inline act2000_card * -act2000_findcard(int driverid) -{ - act2000_card *p = cards; - - while (p) { - if (p->myid == driverid) - return p; - p = p->next; - } - return (act2000_card *) 0; -} - -/* - * Wrapper functions for interface to linklevel - */ -static int -if_command(isdn_ctrl *c) -{ - act2000_card *card = act2000_findcard(c->driver); - - if (card) - return (act2000_command(card, c)); - printk(KERN_ERR - "act2000: if_command %d called with invalid driverId %d!\n", - c->command, c->driver); - return -ENODEV; -} - -static int -if_writecmd(const u_char __user *buf, int len, int id, int channel) -{ - act2000_card *card = act2000_findcard(id); - - if (card) { - if (!(card->flags & ACT2000_FLAGS_RUNNING)) - return -ENODEV; - return (len); - } - printk(KERN_ERR - "act2000: if_writecmd called with invalid driverId!\n"); - return -ENODEV; -} - -static int -if_readstatus(u_char __user *buf, int len, int id, int channel) -{ - act2000_card *card = act2000_findcard(id); - - if (card) { - if (!(card->flags & ACT2000_FLAGS_RUNNING)) - return -ENODEV; - return (act2000_readstatus(buf, len, card)); - } - printk(KERN_ERR - "act2000: if_readstatus called with invalid driverId!\n"); - return -ENODEV; -} - -static int -if_sendbuf(int id, int channel, int ack, struct sk_buff *skb) -{ - act2000_card *card = act2000_findcard(id); - - if (card) { - if (!(card->flags & ACT2000_FLAGS_RUNNING)) - return -ENODEV; - return (act2000_sendbuf(card, channel, ack, skb)); - } - printk(KERN_ERR - "act2000: if_sendbuf called with invalid driverId!\n"); - return -ENODEV; -} - - -/* - * Allocate a new card-struct, initialize it - * link it into cards-list. - */ -static void -act2000_alloccard(int bus, int port, int irq, char *id) -{ - int i; - act2000_card *card; - if (!(card = kzalloc(sizeof(act2000_card), GFP_KERNEL))) { - printk(KERN_WARNING - "act2000: (%s) Could not allocate card-struct.\n", id); - return; - } - spin_lock_init(&card->lock); - spin_lock_init(&card->mnlock); - skb_queue_head_init(&card->sndq); - skb_queue_head_init(&card->rcvq); - skb_queue_head_init(&card->ackq); - INIT_WORK(&card->snd_tq, act2000_transmit); - INIT_WORK(&card->rcv_tq, actcapi_dispatch); - INIT_WORK(&card->poll_tq, act2000_receive); - init_timer(&card->ptimer); - card->interface.owner = THIS_MODULE; - card->interface.channels = ACT2000_BCH; - card->interface.maxbufsize = 4000; - card->interface.command = if_command; - card->interface.writebuf_skb = if_sendbuf; - card->interface.writecmd = if_writecmd; - card->interface.readstat = if_readstatus; - card->interface.features = - ISDN_FEATURE_L2_X75I | - ISDN_FEATURE_L2_HDLC | - ISDN_FEATURE_L3_TRANS | - ISDN_FEATURE_P_UNKNOWN; - card->interface.hl_hdrlen = 20; - card->ptype = ISDN_PTYPE_EURO; - strlcpy(card->interface.id, id, sizeof(card->interface.id)); - for (i = 0; i < ACT2000_BCH; i++) { - card->bch[i].plci = 0x8000; - card->bch[i].ncci = 0x8000; - card->bch[i].l2prot = ISDN_PROTO_L2_X75I; - card->bch[i].l3prot = ISDN_PROTO_L3_TRANS; - } - card->myid = -1; - card->bus = bus; - card->port = port; - card->irq = irq; - card->next = cards; - cards = card; -} - -/* - * register card at linklevel - */ -static int -act2000_registercard(act2000_card *card) -{ - switch (card->bus) { - case ACT2000_BUS_ISA: - break; - case ACT2000_BUS_MCA: - case ACT2000_BUS_PCMCIA: - default: - printk(KERN_WARNING - "act2000: Illegal BUS type %d\n", - card->bus); - return -1; - } - if (!register_isdn(&card->interface)) { - printk(KERN_WARNING - "act2000: Unable to register %s\n", - card->interface.id); - return -1; - } - card->myid = card->interface.channels; - sprintf(card->regname, "act2000-isdn (%s)", card->interface.id); - return 0; -} - -static void -unregister_card(act2000_card *card) -{ - isdn_ctrl cmd; - - cmd.command = ISDN_STAT_UNLOAD; - cmd.driver = card->myid; - card->interface.statcallb(&cmd); - switch (card->bus) { - case ACT2000_BUS_ISA: - act2000_isa_release(card); - break; - case ACT2000_BUS_MCA: - case ACT2000_BUS_PCMCIA: - default: - printk(KERN_WARNING - "act2000: Invalid BUS type %d\n", - card->bus); - break; - } -} - -static int -act2000_addcard(int bus, int port, int irq, char *id) -{ - act2000_card *p; - act2000_card *q = NULL; - int initialized; - int added = 0; - int failed = 0; - int i; - - if (!bus) - bus = ACT2000_BUS_ISA; - if (port != -1) { - /* Port defined, do fixed setup */ - act2000_alloccard(bus, port, irq, id); - } else { - /* No port defined, perform autoprobing. - * This may result in more than one card detected. - */ - switch (bus) { - case ACT2000_BUS_ISA: - for (i = 0; i < ARRAY_SIZE(act2000_isa_ports); i++) - if (act2000_isa_detect(act2000_isa_ports[i])) { - printk(KERN_INFO "act2000: Detected " - "ISA card at port 0x%x\n", - act2000_isa_ports[i]); - act2000_alloccard(bus, - act2000_isa_ports[i], irq, id); - } - break; - case ACT2000_BUS_MCA: - case ACT2000_BUS_PCMCIA: - default: - printk(KERN_WARNING - "act2000: addcard: Invalid BUS type %d\n", bus); - } - } - if (!cards) - return 1; - p = cards; - while (p) { - initialized = 0; - if (!p->interface.statcallb) { - /* Not yet registered. - * Try to register and activate it. - */ - added++; - switch (p->bus) { - case ACT2000_BUS_ISA: - if (act2000_isa_detect(p->port)) { - if (act2000_registercard(p)) - break; - if (act2000_isa_config_port(p, p->port)) { - printk(KERN_WARNING - "act2000: Could not request port 0x%04x\n", - p->port); - unregister_card(p); - p->interface.statcallb = NULL; - break; - } - if (act2000_isa_config_irq(p, p->irq)) { - printk(KERN_INFO - "act2000: No IRQ available, fallback to polling\n"); - /* Fall back to polled operation */ - p->irq = 0; - } - printk(KERN_INFO - "act2000: ISA" - "-type card at port " - "0x%04x ", - p->port); - if (p->irq) - printk("irq %d\n", p->irq); - else - printk("polled\n"); - initialized = 1; - } - break; - case ACT2000_BUS_MCA: - case ACT2000_BUS_PCMCIA: - default: - printk(KERN_WARNING - "act2000: addcard: Invalid BUS type %d\n", - p->bus); - } - } else - /* Card already initialized */ - initialized = 1; - if (initialized) { - /* Init OK, next card ... */ - q = p; - p = p->next; - } else { - /* Init failed, remove card from list, free memory */ - printk(KERN_WARNING - "act2000: Initialization of %s failed\n", - p->interface.id); - if (q) { - q->next = p->next; - kfree(p); - p = q->next; - } else { - cards = p->next; - kfree(p); - p = cards; - } - failed++; - } - } - return (added - failed); -} - -#define DRIVERNAME "IBM Active 2000 ISDN driver" - -static int __init act2000_init(void) -{ - printk(KERN_INFO "%s\n", DRIVERNAME); - if (!cards) - act2000_addcard(act_bus, act_port, act_irq, act_id); - if (!cards) - printk(KERN_INFO "act2000: No cards defined yet\n"); - return 0; -} - -static void __exit act2000_exit(void) -{ - act2000_card *card = cards; - act2000_card *last; - while (card) { - unregister_card(card); - del_timer_sync(&card->ptimer); - card = card->next; - } - card = cards; - while (card) { - last = card; - card = card->next; - act2000_clear_msn(last); - kfree(last); - } - printk(KERN_INFO "%s unloaded\n", DRIVERNAME); -} - -module_init(act2000_init); -module_exit(act2000_exit); diff --git a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig index f5b714cd7618..68e54d9f2f53 100644 --- a/drivers/isdn/i4l/Kconfig +++ b/drivers/isdn/i4l/Kconfig @@ -123,16 +123,6 @@ comment "ISDN4Linux hardware drivers" source "drivers/isdn/hisax/Kconfig" - -menu "Active cards" - -source "drivers/isdn/icn/Kconfig" - -source "drivers/isdn/pcbit/Kconfig" - -source "drivers/isdn/act2000/Kconfig" - -endmenu # end ISDN_I4L endif diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 2175225af742..947d5c978b8f 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -1572,7 +1572,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) #endif return; } - port->flags |= ASYNC_CLOSING; + info->closing = 1; tty->closing = 1; /* @@ -1603,6 +1603,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) info->ncarrier = 0; tty_port_close_end(port, tty); + info->closing = 0; #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_close normal exit\n"); #endif @@ -2236,7 +2237,7 @@ isdn_tty_at_cout(char *msg, modem_info *info) l = strlen(msg); spin_lock_irqsave(&info->readlock, flags); - if (port->flags & ASYNC_CLOSING) { + if (info->closing) { spin_unlock_irqrestore(&info->readlock, flags); return; } @@ -2386,13 +2387,12 @@ isdn_tty_modem_result(int code, modem_info *info) case RESULT_NO_CARRIER: #ifdef ISDN_DEBUG_MODEM_HUP printk(KERN_DEBUG "modem_result: NO CARRIER %d %d\n", - (info->port.flags & ASYNC_CLOSING), - (!info->port.tty)); + info->closing, !info->port.tty); #endif m->mdmreg[REG_RINGCNT] = 0; del_timer(&info->nc_timer); info->ncarrier = 0; - if ((info->port.flags & ASYNC_CLOSING) || (!info->port.tty)) + if (info->closing || !info->port.tty) return; #ifdef CONFIG_ISDN_AUDIO @@ -2525,7 +2525,7 @@ isdn_tty_modem_result(int code, modem_info *info) } } if (code == RESULT_NO_CARRIER) { - if ((info->port.flags & ASYNC_CLOSING) || (!info->port.tty)) + if (info->closing || (!info->port.tty)) return; if (info->port.flags & ASYNC_CHECK_CD) diff --git a/drivers/isdn/icn/Kconfig b/drivers/isdn/icn/Kconfig deleted file mode 100644 index 4534f21a1852..000000000000 --- a/drivers/isdn/icn/Kconfig +++ /dev/null @@ -1,12 +0,0 @@ -config ISDN_DRV_ICN - tristate "ICN 2B and 4B support" - depends on ISA - help - This enables support for two kinds of ISDN-cards made by a German - company called ICN. 2B is the standard version for a single ISDN - line with two B-channels, 4B supports two ISDN lines. For running - this card, additional firmware is necessary, which has to be - downloaded into the card using a utility which is distributed - separately. See <file:Documentation/isdn/README> and - <file:Documentation/isdn/README.icn> for more - information. diff --git a/drivers/isdn/icn/Makefile b/drivers/isdn/icn/Makefile deleted file mode 100644 index d9b476fcf384..000000000000 --- a/drivers/isdn/icn/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# Makefile for the icn ISDN device driver - -# Each configuration option enables a list of files. - -obj-$(CONFIG_ISDN_DRV_ICN) += icn.o diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c deleted file mode 100644 index 358a574d9e8b..000000000000 --- a/drivers/isdn/icn/icn.c +++ /dev/null @@ -1,1693 +0,0 @@ -/* $Id: icn.c,v 1.65.6.8 2001/09/23 22:24:55 kai Exp $ - * - * ISDN low-level module for the ICN active ISDN-Card. - * - * Copyright 1994,95,96 by Fritz Elfert (fritz@isdn4linux.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include "icn.h" -#include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/sched.h> - -static int portbase = ICN_BASEADDR; -static unsigned long membase = ICN_MEMADDR; -static char *icn_id = "\0"; -static char *icn_id2 = "\0"; - -MODULE_DESCRIPTION("ISDN4Linux: Driver for ICN active ISDN card"); -MODULE_AUTHOR("Fritz Elfert"); -MODULE_LICENSE("GPL"); -module_param(portbase, int, 0); -MODULE_PARM_DESC(portbase, "Port address of first card"); -module_param(membase, ulong, 0); -MODULE_PARM_DESC(membase, "Shared memory address of all cards"); -module_param(icn_id, charp, 0); -MODULE_PARM_DESC(icn_id, "ID-String of first card"); -module_param(icn_id2, charp, 0); -MODULE_PARM_DESC(icn_id2, "ID-String of first card, second S0 (4B only)"); - -/* - * Verbose bootcode- and protocol-downloading. - */ -#undef BOOT_DEBUG - -/* - * Verbose Shmem-Mapping. - */ -#undef MAP_DEBUG - -static char -*revision = "$Revision: 1.65.6.8 $"; - -static int icn_addcard(int, char *, char *); - -/* - * Free send-queue completely. - * Parameter: - * card = pointer to card struct - * channel = channel number - */ -static void -icn_free_queue(icn_card *card, int channel) -{ - struct sk_buff_head *queue = &card->spqueue[channel]; - struct sk_buff *skb; - - skb_queue_purge(queue); - card->xlen[channel] = 0; - card->sndcount[channel] = 0; - if ((skb = card->xskb[channel])) { - card->xskb[channel] = NULL; - dev_kfree_skb(skb); - } -} - -/* Put a value into a shift-register, highest bit first. - * Parameters: - * port = port for output (bit 0 is significant) - * val = value to be output - * firstbit = Bit-Number of highest bit - * bitcount = Number of bits to output - */ -static inline void -icn_shiftout(unsigned short port, - unsigned long val, - int firstbit, - int bitcount) -{ - - register u_char s; - register u_char c; - - for (s = firstbit, c = bitcount; c > 0; s--, c--) - OUTB_P((u_char) ((val >> s) & 1) ? 0xff : 0, port); -} - -/* - * disable a cards shared memory - */ -static inline void -icn_disable_ram(icn_card *card) -{ - OUTB_P(0, ICN_MAPRAM); -} - -/* - * enable a cards shared memory - */ -static inline void -icn_enable_ram(icn_card *card) -{ - OUTB_P(0xff, ICN_MAPRAM); -} - -/* - * Map a cards channel0 (Bank0/Bank8) or channel1 (Bank4/Bank12) - * - * must called with holding the devlock - */ -static inline void -icn_map_channel(icn_card *card, int channel) -{ -#ifdef MAP_DEBUG - printk(KERN_DEBUG "icn_map_channel %d %d\n", dev.channel, channel); -#endif - if ((channel == dev.channel) && (card == dev.mcard)) - return; - if (dev.mcard) - icn_disable_ram(dev.mcard); - icn_shiftout(ICN_BANK, chan2bank[channel], 3, 4); /* Select Bank */ - icn_enable_ram(card); - dev.mcard = card; - dev.channel = channel; -#ifdef MAP_DEBUG - printk(KERN_DEBUG "icn_map_channel done\n"); -#endif -} - -/* - * Lock a cards channel. - * Return 0 if requested card/channel is unmapped (failure). - * Return 1 on success. - * - * must called with holding the devlock - */ -static inline int -icn_lock_channel(icn_card *card, int channel) -{ - register int retval; - -#ifdef MAP_DEBUG - printk(KERN_DEBUG "icn_lock_channel %d\n", channel); -#endif - if ((dev.channel == channel) && (card == dev.mcard)) { - dev.chanlock++; - retval = 1; -#ifdef MAP_DEBUG - printk(KERN_DEBUG "icn_lock_channel %d OK\n", channel); -#endif - } else { - retval = 0; -#ifdef MAP_DEBUG - printk(KERN_DEBUG "icn_lock_channel %d FAILED, dc=%d\n", channel, dev.channel); -#endif - } - return retval; -} - -/* - * Release current card/channel lock - * - * must called with holding the devlock - */ -static inline void -__icn_release_channel(void) -{ -#ifdef MAP_DEBUG - printk(KERN_DEBUG "icn_release_channel l=%d\n", dev.chanlock); -#endif - if (dev.chanlock > 0) - dev.chanlock--; -} - -/* - * Release current card/channel lock - */ -static inline void -icn_release_channel(void) -{ - ulong flags; - - spin_lock_irqsave(&dev.devlock, flags); - __icn_release_channel(); - spin_unlock_irqrestore(&dev.devlock, flags); -} - -/* - * Try to map and lock a cards channel. - * Return 1 on success, 0 on failure. - */ -static inline int -icn_trymaplock_channel(icn_card *card, int channel) -{ - ulong flags; - -#ifdef MAP_DEBUG - printk(KERN_DEBUG "trymaplock c=%d dc=%d l=%d\n", channel, dev.channel, - dev.chanlock); -#endif - spin_lock_irqsave(&dev.devlock, flags); - if ((!dev.chanlock) || - ((dev.channel == channel) && (dev.mcard == card))) { - dev.chanlock++; - icn_map_channel(card, channel); - spin_unlock_irqrestore(&dev.devlock, flags); -#ifdef MAP_DEBUG - printk(KERN_DEBUG "trymaplock %d OK\n", channel); -#endif - return 1; - } - spin_unlock_irqrestore(&dev.devlock, flags); -#ifdef MAP_DEBUG - printk(KERN_DEBUG "trymaplock %d FAILED\n", channel); -#endif - return 0; -} - -/* - * Release current card/channel lock, - * then map same or other channel without locking. - */ -static inline void -icn_maprelease_channel(icn_card *card, int channel) -{ - ulong flags; - -#ifdef MAP_DEBUG - printk(KERN_DEBUG "map_release c=%d l=%d\n", channel, dev.chanlock); -#endif - spin_lock_irqsave(&dev.devlock, flags); - if (dev.chanlock > 0) - dev.chanlock--; - if (!dev.chanlock) - icn_map_channel(card, channel); - spin_unlock_irqrestore(&dev.devlock, flags); -} - -/* Get Data from the B-Channel, assemble fragmented packets and put them - * into receive-queue. Wake up any B-Channel-reading processes. - * This routine is called via timer-callback from icn_pollbchan(). - */ - -static void -icn_pollbchan_receive(int channel, icn_card *card) -{ - int mch = channel + ((card->secondhalf) ? 2 : 0); - int eflag; - int cnt; - struct sk_buff *skb; - - if (icn_trymaplock_channel(card, mch)) { - while (rbavl) { - cnt = readb(&rbuf_l); - if ((card->rcvidx[channel] + cnt) > 4000) { - printk(KERN_WARNING - "icn: (%s) bogus packet on ch%d, dropping.\n", - CID, - channel + 1); - card->rcvidx[channel] = 0; - eflag = 0; - } else { - memcpy_fromio(&card->rcvbuf[channel][card->rcvidx[channel]], - &rbuf_d, cnt); - card->rcvidx[channel] += cnt; - eflag = readb(&rbuf_f); - } - rbnext; - icn_maprelease_channel(card, mch & 2); - if (!eflag) { - if ((cnt = card->rcvidx[channel])) { - if (!(skb = dev_alloc_skb(cnt))) { - printk(KERN_WARNING "icn: receive out of memory\n"); - break; - } - memcpy(skb_put(skb, cnt), card->rcvbuf[channel], cnt); - card->rcvidx[channel] = 0; - card->interface.rcvcallb_skb(card->myid, channel, skb); - } - } - if (!icn_trymaplock_channel(card, mch)) - break; - } - icn_maprelease_channel(card, mch & 2); - } -} - -/* Send data-packet to B-Channel, split it up into fragments of - * ICN_FRAGSIZE length. If last fragment is sent out, signal - * success to upper layers via statcallb with ISDN_STAT_BSENT argument. - * This routine is called via timer-callback from icn_pollbchan() or - * directly from icn_sendbuf(). - */ - -static void -icn_pollbchan_send(int channel, icn_card *card) -{ - int mch = channel + ((card->secondhalf) ? 2 : 0); - int cnt; - unsigned long flags; - struct sk_buff *skb; - isdn_ctrl cmd; - - if (!(card->sndcount[channel] || card->xskb[channel] || - !skb_queue_empty(&card->spqueue[channel]))) - return; - if (icn_trymaplock_channel(card, mch)) { - while (sbfree && - (card->sndcount[channel] || - !skb_queue_empty(&card->spqueue[channel]) || - card->xskb[channel])) { - spin_lock_irqsave(&card->lock, flags); - if (card->xmit_lock[channel]) { - spin_unlock_irqrestore(&card->lock, flags); - break; - } - card->xmit_lock[channel]++; - spin_unlock_irqrestore(&card->lock, flags); - skb = card->xskb[channel]; - if (!skb) { - skb = skb_dequeue(&card->spqueue[channel]); - if (skb) { - /* Pop ACK-flag off skb. - * Store length to xlen. - */ - if (*(skb_pull(skb, 1))) - card->xlen[channel] = skb->len; - else - card->xlen[channel] = 0; - } - } - if (!skb) - break; - if (skb->len > ICN_FRAGSIZE) { - writeb(0xff, &sbuf_f); - cnt = ICN_FRAGSIZE; - } else { - writeb(0x0, &sbuf_f); - cnt = skb->len; - } - writeb(cnt, &sbuf_l); - memcpy_toio(&sbuf_d, skb->data, cnt); - skb_pull(skb, cnt); - sbnext; /* switch to next buffer */ - icn_maprelease_channel(card, mch & 2); - spin_lock_irqsave(&card->lock, flags); - card->sndcount[channel] -= cnt; - if (!skb->len) { - if (card->xskb[channel]) - card->xskb[channel] = NULL; - card->xmit_lock[channel] = 0; - spin_unlock_irqrestore(&card->lock, flags); - dev_kfree_skb(skb); - if (card->xlen[channel]) { - cmd.command = ISDN_STAT_BSENT; - cmd.driver = card->myid; - cmd.arg = channel; - cmd.parm.length = card->xlen[channel]; - card->interface.statcallb(&cmd); - } - } else { - card->xskb[channel] = skb; - card->xmit_lock[channel] = 0; - spin_unlock_irqrestore(&card->lock, flags); - } - if (!icn_trymaplock_channel(card, mch)) - break; - } - icn_maprelease_channel(card, mch & 2); - } -} - -/* Send/Receive Data to/from the B-Channel. - * This routine is called via timer-callback. - * It schedules itself while any B-Channel is open. - */ - -static void -icn_pollbchan(unsigned long data) -{ - icn_card *card = (icn_card *) data; - unsigned long flags; - - if (card->flags & ICN_FLAGS_B1ACTIVE) { - icn_pollbchan_receive(0, card); - icn_pollbchan_send(0, card); - } - if (card->flags & ICN_FLAGS_B2ACTIVE) { - icn_pollbchan_receive(1, card); - icn_pollbchan_send(1, card); - } - if (card->flags & (ICN_FLAGS_B1ACTIVE | ICN_FLAGS_B2ACTIVE)) { - /* schedule b-channel polling again */ - spin_lock_irqsave(&card->lock, flags); - mod_timer(&card->rb_timer, jiffies + ICN_TIMER_BCREAD); - card->flags |= ICN_FLAGS_RBTIMER; - spin_unlock_irqrestore(&card->lock, flags); - } else - card->flags &= ~ICN_FLAGS_RBTIMER; -} - -typedef struct icn_stat { - char *statstr; - int command; - int action; -} icn_stat; -/* *INDENT-OFF* */ -static icn_stat icn_stat_table[] = -{ - {"BCON_", ISDN_STAT_BCONN, 1}, /* B-Channel connected */ - {"BDIS_", ISDN_STAT_BHUP, 2}, /* B-Channel disconnected */ - /* - ** add d-channel connect and disconnect support to link-level - */ - {"DCON_", ISDN_STAT_DCONN, 10}, /* D-Channel connected */ - {"DDIS_", ISDN_STAT_DHUP, 11}, /* D-Channel disconnected */ - {"DCAL_I", ISDN_STAT_ICALL, 3}, /* Incoming call dialup-line */ - {"DSCA_I", ISDN_STAT_ICALL, 3}, /* Incoming call 1TR6-SPV */ - {"FCALL", ISDN_STAT_ICALL, 4}, /* Leased line connection up */ - {"CIF", ISDN_STAT_CINF, 5}, /* Charge-info, 1TR6-type */ - {"AOC", ISDN_STAT_CINF, 6}, /* Charge-info, DSS1-type */ - {"CAU", ISDN_STAT_CAUSE, 7}, /* Cause code */ - {"TEI OK", ISDN_STAT_RUN, 0}, /* Card connected to wallplug */ - {"E_L1: ACT FAIL", ISDN_STAT_BHUP, 8}, /* Layer-1 activation failed */ - {"E_L2: DATA LIN", ISDN_STAT_BHUP, 8}, /* Layer-2 data link lost */ - {"E_L1: ACTIVATION FAILED", - ISDN_STAT_BHUP, 8}, /* Layer-1 activation failed */ - {NULL, 0, -1} -}; -/* *INDENT-ON* */ - - -/* - * Check Statusqueue-Pointer from isdn-cards. - * If there are new status-replies from the interface, check - * them against B-Channel-connects/disconnects and set flags accordingly. - * Wake-Up any processes, who are reading the status-device. - * If there are B-Channels open, initiate a timer-callback to - * icn_pollbchan(). - * This routine is called periodically via timer. - */ - -static void -icn_parse_status(u_char *status, int channel, icn_card *card) -{ - icn_stat *s = icn_stat_table; - int action = -1; - unsigned long flags; - isdn_ctrl cmd; - - while (s->statstr) { - if (!strncmp(status, s->statstr, strlen(s->statstr))) { - cmd.command = s->command; - action = s->action; - break; - } - s++; - } - if (action == -1) - return; - cmd.driver = card->myid; - cmd.arg = channel; - switch (action) { - case 11: - spin_lock_irqsave(&card->lock, flags); - icn_free_queue(card, channel); - card->rcvidx[channel] = 0; - - if (card->flags & - ((channel) ? ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE)) { - - isdn_ctrl ncmd; - - card->flags &= ~((channel) ? - ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE); - - memset(&ncmd, 0, sizeof(ncmd)); - - ncmd.driver = card->myid; - ncmd.arg = channel; - ncmd.command = ISDN_STAT_BHUP; - spin_unlock_irqrestore(&card->lock, flags); - card->interface.statcallb(&cmd); - } else - spin_unlock_irqrestore(&card->lock, flags); - break; - case 1: - spin_lock_irqsave(&card->lock, flags); - icn_free_queue(card, channel); - card->flags |= (channel) ? - ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE; - spin_unlock_irqrestore(&card->lock, flags); - break; - case 2: - spin_lock_irqsave(&card->lock, flags); - card->flags &= ~((channel) ? - ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE); - icn_free_queue(card, channel); - card->rcvidx[channel] = 0; - spin_unlock_irqrestore(&card->lock, flags); - break; - case 3: - { - char *t = status + 6; - char *s = strchr(t, ','); - - *s++ = '\0'; - strlcpy(cmd.parm.setup.phone, t, - sizeof(cmd.parm.setup.phone)); - s = strchr(t = s, ','); - *s++ = '\0'; - if (!strlen(t)) - cmd.parm.setup.si1 = 0; - else - cmd.parm.setup.si1 = - simple_strtoul(t, NULL, 10); - s = strchr(t = s, ','); - *s++ = '\0'; - if (!strlen(t)) - cmd.parm.setup.si2 = 0; - else - cmd.parm.setup.si2 = - simple_strtoul(t, NULL, 10); - strlcpy(cmd.parm.setup.eazmsn, s, - sizeof(cmd.parm.setup.eazmsn)); - } - cmd.parm.setup.plan = 0; - cmd.parm.setup.screen = 0; - break; - case 4: - sprintf(cmd.parm.setup.phone, "LEASED%d", card->myid); - sprintf(cmd.parm.setup.eazmsn, "%d", channel + 1); - cmd.parm.setup.si1 = 7; - cmd.parm.setup.si2 = 0; - cmd.parm.setup.plan = 0; - cmd.parm.setup.screen = 0; - break; - case 5: - strlcpy(cmd.parm.num, status + 3, sizeof(cmd.parm.num)); - break; - case 6: - snprintf(cmd.parm.num, sizeof(cmd.parm.num), "%d", - (int) simple_strtoul(status + 7, NULL, 16)); - break; - case 7: - status += 3; - if (strlen(status) == 4) - snprintf(cmd.parm.num, sizeof(cmd.parm.num), "%s%c%c", - status + 2, *status, *(status + 1)); - else - strlcpy(cmd.parm.num, status + 1, sizeof(cmd.parm.num)); - break; - case 8: - spin_lock_irqsave(&card->lock, flags); - card->flags &= ~ICN_FLAGS_B1ACTIVE; - icn_free_queue(card, 0); - card->rcvidx[0] = 0; - spin_unlock_irqrestore(&card->lock, flags); - cmd.arg = 0; - cmd.driver = card->myid; - card->interface.statcallb(&cmd); - cmd.command = ISDN_STAT_DHUP; - cmd.arg = 0; - cmd.driver = card->myid; - card->interface.statcallb(&cmd); - cmd.command = ISDN_STAT_BHUP; - spin_lock_irqsave(&card->lock, flags); - card->flags &= ~ICN_FLAGS_B2ACTIVE; - icn_free_queue(card, 1); - card->rcvidx[1] = 0; - spin_unlock_irqrestore(&card->lock, flags); - cmd.arg = 1; - cmd.driver = card->myid; - card->interface.statcallb(&cmd); - cmd.command = ISDN_STAT_DHUP; - cmd.arg = 1; - cmd.driver = card->myid; - break; - } - card->interface.statcallb(&cmd); - return; -} - -static void -icn_putmsg(icn_card *card, unsigned char c) -{ - ulong flags; - - spin_lock_irqsave(&card->lock, flags); - *card->msg_buf_write++ = (c == 0xff) ? '\n' : c; - if (card->msg_buf_write == card->msg_buf_read) { - if (++card->msg_buf_read > card->msg_buf_end) - card->msg_buf_read = card->msg_buf; - } - if (card->msg_buf_write > card->msg_buf_end) - card->msg_buf_write = card->msg_buf; - spin_unlock_irqrestore(&card->lock, flags); -} - -static void -icn_polldchan(unsigned long data) -{ - icn_card *card = (icn_card *) data; - int mch = card->secondhalf ? 2 : 0; - int avail = 0; - int left; - u_char c; - int ch; - unsigned long flags; - int i; - u_char *p; - isdn_ctrl cmd; - - if (icn_trymaplock_channel(card, mch)) { - avail = msg_avail; - for (left = avail, i = readb(&msg_o); left > 0; i++, left--) { - c = readb(&dev.shmem->comm_buffers.iopc_buf[i & 0xff]); - icn_putmsg(card, c); - if (c == 0xff) { - card->imsg[card->iptr] = 0; - card->iptr = 0; - if (card->imsg[0] == '0' && card->imsg[1] >= '0' && - card->imsg[1] <= '2' && card->imsg[2] == ';') { - ch = (card->imsg[1] - '0') - 1; - p = &card->imsg[3]; - icn_parse_status(p, ch, card); - } else { - p = card->imsg; - if (!strncmp(p, "DRV1.", 5)) { - u_char vstr[10]; - u_char *q = vstr; - - printk(KERN_INFO "icn: (%s) %s\n", CID, p); - if (!strncmp(p + 7, "TC", 2)) { - card->ptype = ISDN_PTYPE_1TR6; - card->interface.features |= ISDN_FEATURE_P_1TR6; - printk(KERN_INFO - "icn: (%s) 1TR6-Protocol loaded and running\n", CID); - } - if (!strncmp(p + 7, "EC", 2)) { - card->ptype = ISDN_PTYPE_EURO; - card->interface.features |= ISDN_FEATURE_P_EURO; - printk(KERN_INFO - "icn: (%s) Euro-Protocol loaded and running\n", CID); - } - p = strstr(card->imsg, "BRV") + 3; - while (*p) { - if (*p >= '0' && *p <= '9') - *q++ = *p; - p++; - } - *q = '\0'; - strcat(vstr, "000"); - vstr[3] = '\0'; - card->fw_rev = (int) simple_strtoul(vstr, NULL, 10); - continue; - - } - } - } else { - card->imsg[card->iptr] = c; - if (card->iptr < 59) - card->iptr++; - } - } - writeb((readb(&msg_o) + avail) & 0xff, &msg_o); - icn_release_channel(); - } - if (avail) { - cmd.command = ISDN_STAT_STAVAIL; - cmd.driver = card->myid; - cmd.arg = avail; - card->interface.statcallb(&cmd); - } - spin_lock_irqsave(&card->lock, flags); - if (card->flags & (ICN_FLAGS_B1ACTIVE | ICN_FLAGS_B2ACTIVE)) - if (!(card->flags & ICN_FLAGS_RBTIMER)) { - /* schedule b-channel polling */ - card->flags |= ICN_FLAGS_RBTIMER; - del_timer(&card->rb_timer); - card->rb_timer.function = icn_pollbchan; - card->rb_timer.data = (unsigned long) card; - card->rb_timer.expires = jiffies + ICN_TIMER_BCREAD; - add_timer(&card->rb_timer); - } - /* schedule again */ - mod_timer(&card->st_timer, jiffies + ICN_TIMER_DCREAD); - spin_unlock_irqrestore(&card->lock, flags); -} - -/* Append a packet to the transmit buffer-queue. - * Parameters: - * channel = Number of B-channel - * skb = pointer to sk_buff - * card = pointer to card-struct - * Return: - * Number of bytes transferred, -E??? on error - */ - -static int -icn_sendbuf(int channel, int ack, struct sk_buff *skb, icn_card *card) -{ - int len = skb->len; - unsigned long flags; - struct sk_buff *nskb; - - if (len > 4000) { - printk(KERN_WARNING - "icn: Send packet too large\n"); - return -EINVAL; - } - if (len) { - if (!(card->flags & (channel) ? ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE)) - return 0; - if (card->sndcount[channel] > ICN_MAX_SQUEUE) - return 0; -#warning TODO test headroom or use skb->nb to flag ACK - nskb = skb_clone(skb, GFP_ATOMIC); - if (nskb) { - /* Push ACK flag as one - * byte in front of data. - */ - *(skb_push(nskb, 1)) = ack ? 1 : 0; - skb_queue_tail(&card->spqueue[channel], nskb); - dev_kfree_skb(skb); - } else - len = 0; - spin_lock_irqsave(&card->lock, flags); - card->sndcount[channel] += len; - spin_unlock_irqrestore(&card->lock, flags); - } - return len; -} - -/* - * Check card's status after starting the bootstrap loader. - * On entry, the card's shared memory has already to be mapped. - * Return: - * 0 on success (Boot loader ready) - * -EIO on failure (timeout) - */ -static int -icn_check_loader(int cardnumber) -{ - int timer = 0; - - while (1) { -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "Loader %d ?\n", cardnumber); -#endif - if (readb(&dev.shmem->data_control.scns) || - readb(&dev.shmem->data_control.scnr)) { - if (timer++ > 5) { - printk(KERN_WARNING - "icn: Boot-Loader %d timed out.\n", - cardnumber); - icn_release_channel(); - return -EIO; - } -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "Loader %d TO?\n", cardnumber); -#endif - msleep_interruptible(ICN_BOOT_TIMEOUT1); - } else { -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "Loader %d OK\n", cardnumber); -#endif - icn_release_channel(); - return 0; - } - } -} - -/* Load the boot-code into the interface-card's memory and start it. - * Always called from user-process. - * - * Parameters: - * buffer = pointer to packet - * Return: - * 0 if successfully loaded - */ - -#ifdef BOOT_DEBUG -#define SLEEP(sec) { \ - int slsec = sec; \ - printk(KERN_DEBUG "SLEEP(%d)\n", slsec); \ - while (slsec) { \ - msleep_interruptible(1000); \ - slsec--; \ - } \ - } -#else -#define SLEEP(sec) -#endif - -static int -icn_loadboot(u_char __user *buffer, icn_card *card) -{ - int ret; - u_char *codebuf; - unsigned long flags; - -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "icn_loadboot called, buffaddr=%08lx\n", (ulong) buffer); -#endif - if (!(codebuf = kmalloc(ICN_CODE_STAGE1, GFP_KERNEL))) { - printk(KERN_WARNING "icn: Could not allocate code buffer\n"); - ret = -ENOMEM; - goto out; - } - if (copy_from_user(codebuf, buffer, ICN_CODE_STAGE1)) { - ret = -EFAULT; - goto out_kfree; - } - if (!card->rvalid) { - if (!request_region(card->port, ICN_PORTLEN, card->regname)) { - printk(KERN_WARNING - "icn: (%s) ports 0x%03x-0x%03x in use.\n", - CID, - card->port, - card->port + ICN_PORTLEN); - ret = -EBUSY; - goto out_kfree; - } - card->rvalid = 1; - if (card->doubleS0) - card->other->rvalid = 1; - } - if (!dev.mvalid) { - if (!request_mem_region(dev.memaddr, 0x4000, "icn-isdn (all cards)")) { - printk(KERN_WARNING - "icn: memory at 0x%08lx in use.\n", dev.memaddr); - ret = -EBUSY; - goto out_kfree; - } - dev.shmem = ioremap(dev.memaddr, 0x4000); - dev.mvalid = 1; - } - OUTB_P(0, ICN_RUN); /* Reset Controller */ - OUTB_P(0, ICN_MAPRAM); /* Disable RAM */ - icn_shiftout(ICN_CFG, 0x0f, 3, 4); /* Windowsize= 16k */ - icn_shiftout(ICN_CFG, dev.memaddr, 23, 10); /* Set RAM-Addr. */ -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "shmem=%08lx\n", dev.memaddr); -#endif - SLEEP(1); -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "Map Bank 0\n"); -#endif - spin_lock_irqsave(&dev.devlock, flags); - icn_map_channel(card, 0); /* Select Bank 0 */ - icn_lock_channel(card, 0); /* Lock Bank 0 */ - spin_unlock_irqrestore(&dev.devlock, flags); - SLEEP(1); - memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1); /* Copy code */ -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "Bootloader transferred\n"); -#endif - if (card->doubleS0) { - SLEEP(1); -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "Map Bank 8\n"); -#endif - spin_lock_irqsave(&dev.devlock, flags); - __icn_release_channel(); - icn_map_channel(card, 2); /* Select Bank 8 */ - icn_lock_channel(card, 2); /* Lock Bank 8 */ - spin_unlock_irqrestore(&dev.devlock, flags); - SLEEP(1); - memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1); /* Copy code */ -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "Bootloader transferred\n"); -#endif - } - SLEEP(1); - OUTB_P(0xff, ICN_RUN); /* Start Boot-Code */ - if ((ret = icn_check_loader(card->doubleS0 ? 2 : 1))) { - goto out_kfree; - } - if (!card->doubleS0) { - ret = 0; - goto out_kfree; - } - /* reached only, if we have a Double-S0-Card */ -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "Map Bank 0\n"); -#endif - spin_lock_irqsave(&dev.devlock, flags); - icn_map_channel(card, 0); /* Select Bank 0 */ - icn_lock_channel(card, 0); /* Lock Bank 0 */ - spin_unlock_irqrestore(&dev.devlock, flags); - SLEEP(1); - ret = (icn_check_loader(1)); - -out_kfree: - kfree(codebuf); -out: - return ret; -} - -static int -icn_loadproto(u_char __user *buffer, icn_card *card) -{ - register u_char __user *p = buffer; - u_char codebuf[256]; - uint left = ICN_CODE_STAGE2; - uint cnt; - int timer; - unsigned long flags; - -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "icn_loadproto called\n"); -#endif - if (!access_ok(VERIFY_READ, buffer, ICN_CODE_STAGE2)) - return -EFAULT; - timer = 0; - spin_lock_irqsave(&dev.devlock, flags); - if (card->secondhalf) { - icn_map_channel(card, 2); - icn_lock_channel(card, 2); - } else { - icn_map_channel(card, 0); - icn_lock_channel(card, 0); - } - spin_unlock_irqrestore(&dev.devlock, flags); - while (left) { - if (sbfree) { /* If there is a free buffer... */ - cnt = left; - if (cnt > 256) - cnt = 256; - if (copy_from_user(codebuf, p, cnt)) { - icn_maprelease_channel(card, 0); - return -EFAULT; - } - memcpy_toio(&sbuf_l, codebuf, cnt); /* copy data */ - sbnext; /* switch to next buffer */ - p += cnt; - left -= cnt; - timer = 0; - } else { -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "boot 2 !sbfree\n"); -#endif - if (timer++ > 5) { - icn_maprelease_channel(card, 0); - return -EIO; - } - schedule_timeout_interruptible(10); - } - } - writeb(0x20, &sbuf_n); - timer = 0; - while (1) { - if (readb(&cmd_o) || readb(&cmd_i)) { -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "Proto?\n"); -#endif - if (timer++ > 5) { - printk(KERN_WARNING - "icn: (%s) Protocol timed out.\n", - CID); -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "Proto TO!\n"); -#endif - icn_maprelease_channel(card, 0); - return -EIO; - } -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "Proto TO?\n"); -#endif - msleep_interruptible(ICN_BOOT_TIMEOUT1); - } else { - if ((card->secondhalf) || (!card->doubleS0)) { -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "Proto loaded, install poll-timer %d\n", - card->secondhalf); -#endif - spin_lock_irqsave(&card->lock, flags); - init_timer(&card->st_timer); - card->st_timer.expires = jiffies + ICN_TIMER_DCREAD; - card->st_timer.function = icn_polldchan; - card->st_timer.data = (unsigned long) card; - add_timer(&card->st_timer); - card->flags |= ICN_FLAGS_RUNNING; - if (card->doubleS0) { - init_timer(&card->other->st_timer); - card->other->st_timer.expires = jiffies + ICN_TIMER_DCREAD; - card->other->st_timer.function = icn_polldchan; - card->other->st_timer.data = (unsigned long) card->other; - add_timer(&card->other->st_timer); - card->other->flags |= ICN_FLAGS_RUNNING; - } - spin_unlock_irqrestore(&card->lock, flags); - } - icn_maprelease_channel(card, 0); - return 0; - } - } -} - -/* Read the Status-replies from the Interface */ -static int -icn_readstatus(u_char __user *buf, int len, icn_card *card) -{ - int count; - u_char __user *p; - - for (p = buf, count = 0; count < len; p++, count++) { - if (card->msg_buf_read == card->msg_buf_write) - return count; - if (put_user(*card->msg_buf_read++, p)) - return -EFAULT; - if (card->msg_buf_read > card->msg_buf_end) - card->msg_buf_read = card->msg_buf; - } - return count; -} - -/* Put command-strings into the command-queue of the Interface */ -static int -icn_writecmd(const u_char *buf, int len, int user, icn_card *card) -{ - int mch = card->secondhalf ? 2 : 0; - int pp; - int i; - int count; - int xcount; - int ocount; - int loop; - unsigned long flags; - int lastmap_channel; - struct icn_card *lastmap_card; - u_char *p; - isdn_ctrl cmd; - u_char msg[0x100]; - - ocount = 1; - xcount = loop = 0; - while (len) { - count = cmd_free; - if (count > len) - count = len; - if (user) { - if (copy_from_user(msg, buf, count)) - return -EFAULT; - } else - memcpy(msg, buf, count); - - spin_lock_irqsave(&dev.devlock, flags); - lastmap_card = dev.mcard; - lastmap_channel = dev.channel; - icn_map_channel(card, mch); - - icn_putmsg(card, '>'); - for (p = msg, pp = readb(&cmd_i), i = count; i > 0; i--, p++, pp - ++) { - writeb((*p == '\n') ? 0xff : *p, - &dev.shmem->comm_buffers.pcio_buf[pp & 0xff]); - len--; - xcount++; - icn_putmsg(card, *p); - if ((*p == '\n') && (i > 1)) { - icn_putmsg(card, '>'); - ocount++; - } - ocount++; - } - writeb((readb(&cmd_i) + count) & 0xff, &cmd_i); - if (lastmap_card) - icn_map_channel(lastmap_card, lastmap_channel); - spin_unlock_irqrestore(&dev.devlock, flags); - if (len) { - mdelay(1); - if (loop++ > 20) - break; - } else - break; - } - if (len && (!user)) - printk(KERN_WARNING "icn: writemsg incomplete!\n"); - cmd.command = ISDN_STAT_STAVAIL; - cmd.driver = card->myid; - cmd.arg = ocount; - card->interface.statcallb(&cmd); - return xcount; -} - -/* - * Delete card's pending timers, send STOP to linklevel - */ -static void -icn_stopcard(icn_card *card) -{ - unsigned long flags; - isdn_ctrl cmd; - - spin_lock_irqsave(&card->lock, flags); - if (card->flags & ICN_FLAGS_RUNNING) { - card->flags &= ~ICN_FLAGS_RUNNING; - del_timer(&card->st_timer); - del_timer(&card->rb_timer); - spin_unlock_irqrestore(&card->lock, flags); - cmd.command = ISDN_STAT_STOP; - cmd.driver = card->myid; - card->interface.statcallb(&cmd); - if (card->doubleS0) - icn_stopcard(card->other); - } else - spin_unlock_irqrestore(&card->lock, flags); -} - -static void -icn_stopallcards(void) -{ - icn_card *p = cards; - - while (p) { - icn_stopcard(p); - p = p->next; - } -} - -/* - * Unmap all cards, because some of them may be mapped accidetly during - * autoprobing of some network drivers (SMC-driver?) - */ -static void -icn_disable_cards(void) -{ - icn_card *card = cards; - - while (card) { - if (!request_region(card->port, ICN_PORTLEN, "icn-isdn")) { - printk(KERN_WARNING - "icn: (%s) ports 0x%03x-0x%03x in use.\n", - CID, - card->port, - card->port + ICN_PORTLEN); - } else { - OUTB_P(0, ICN_RUN); /* Reset Controller */ - OUTB_P(0, ICN_MAPRAM); /* Disable RAM */ - release_region(card->port, ICN_PORTLEN); - } - card = card->next; - } -} - -static int -icn_command(isdn_ctrl *c, icn_card *card) -{ - ulong a; - ulong flags; - int i; - char cbuf[80]; - isdn_ctrl cmd; - icn_cdef cdef; - char __user *arg; - - switch (c->command) { - case ISDN_CMD_IOCTL: - memcpy(&a, c->parm.num, sizeof(ulong)); - arg = (char __user *)a; - switch (c->arg) { - case ICN_IOCTL_SETMMIO: - if (dev.memaddr != (a & 0x0ffc000)) { - if (!request_mem_region(a & 0x0ffc000, 0x4000, "icn-isdn (all cards)")) { - printk(KERN_WARNING - "icn: memory at 0x%08lx in use.\n", - a & 0x0ffc000); - return -EINVAL; - } - release_mem_region(a & 0x0ffc000, 0x4000); - icn_stopallcards(); - spin_lock_irqsave(&card->lock, flags); - if (dev.mvalid) { - iounmap(dev.shmem); - release_mem_region(dev.memaddr, 0x4000); - } - dev.mvalid = 0; - dev.memaddr = a & 0x0ffc000; - spin_unlock_irqrestore(&card->lock, flags); - printk(KERN_INFO - "icn: (%s) mmio set to 0x%08lx\n", - CID, - dev.memaddr); - } - break; - case ICN_IOCTL_GETMMIO: - return (long) dev.memaddr; - case ICN_IOCTL_SETPORT: - if (a == 0x300 || a == 0x310 || a == 0x320 || a == 0x330 - || a == 0x340 || a == 0x350 || a == 0x360 || - a == 0x308 || a == 0x318 || a == 0x328 || a == 0x338 - || a == 0x348 || a == 0x358 || a == 0x368) { - if (card->port != (unsigned short) a) { - if (!request_region((unsigned short) a, ICN_PORTLEN, "icn-isdn")) { - printk(KERN_WARNING - "icn: (%s) ports 0x%03x-0x%03x in use.\n", - CID, (int) a, (int) a + ICN_PORTLEN); - return -EINVAL; - } - release_region((unsigned short) a, ICN_PORTLEN); - icn_stopcard(card); - spin_lock_irqsave(&card->lock, flags); - if (card->rvalid) - release_region(card->port, ICN_PORTLEN); - card->port = (unsigned short) a; - card->rvalid = 0; - if (card->doubleS0) { - card->other->port = (unsigned short) a; - card->other->rvalid = 0; - } - spin_unlock_irqrestore(&card->lock, flags); - printk(KERN_INFO - "icn: (%s) port set to 0x%03x\n", - CID, card->port); - } - } else - return -EINVAL; - break; - case ICN_IOCTL_GETPORT: - return (int) card->port; - case ICN_IOCTL_GETDOUBLE: - return (int) card->doubleS0; - case ICN_IOCTL_DEBUGVAR: - if (copy_to_user(arg, - &card, - sizeof(ulong))) - return -EFAULT; - a += sizeof(ulong); - { - ulong l = (ulong)&dev; - if (copy_to_user(arg, - &l, - sizeof(ulong))) - return -EFAULT; - } - return 0; - case ICN_IOCTL_LOADBOOT: - if (dev.firstload) { - icn_disable_cards(); - dev.firstload = 0; - } - icn_stopcard(card); - return (icn_loadboot(arg, card)); - case ICN_IOCTL_LOADPROTO: - icn_stopcard(card); - if ((i = (icn_loadproto(arg, card)))) - return i; - if (card->doubleS0) - i = icn_loadproto(arg + ICN_CODE_STAGE2, card->other); - return i; - break; - case ICN_IOCTL_ADDCARD: - if (!dev.firstload) - return -EBUSY; - if (copy_from_user(&cdef, - arg, - sizeof(cdef))) - return -EFAULT; - return (icn_addcard(cdef.port, cdef.id1, cdef.id2)); - break; - case ICN_IOCTL_LEASEDCFG: - if (a) { - if (!card->leased) { - card->leased = 1; - while (card->ptype == ISDN_PTYPE_UNKNOWN) { - msleep_interruptible(ICN_BOOT_TIMEOUT1); - } - msleep_interruptible(ICN_BOOT_TIMEOUT1); - sprintf(cbuf, "00;FV2ON\n01;EAZ%c\n02;EAZ%c\n", - (a & 1) ? '1' : 'C', (a & 2) ? '2' : 'C'); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); - printk(KERN_INFO - "icn: (%s) Leased-line mode enabled\n", - CID); - cmd.command = ISDN_STAT_RUN; - cmd.driver = card->myid; - cmd.arg = 0; - card->interface.statcallb(&cmd); - } - } else { - if (card->leased) { - card->leased = 0; - sprintf(cbuf, "00;FV2OFF\n"); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); - printk(KERN_INFO - "icn: (%s) Leased-line mode disabled\n", - CID); - cmd.command = ISDN_STAT_RUN; - cmd.driver = card->myid; - cmd.arg = 0; - card->interface.statcallb(&cmd); - } - } - return 0; - default: - return -EINVAL; - } - break; - case ISDN_CMD_DIAL: - if (!(card->flags & ICN_FLAGS_RUNNING)) - return -ENODEV; - if (card->leased) - break; - if ((c->arg & 255) < ICN_BCH) { - char *p; - char dcode[4]; - - a = c->arg; - p = c->parm.setup.phone; - if (*p == 's' || *p == 'S') { - /* Dial for SPV */ - p++; - strcpy(dcode, "SCA"); - } else - /* Normal Dial */ - strcpy(dcode, "CAL"); - snprintf(cbuf, sizeof(cbuf), - "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1), - dcode, p, c->parm.setup.si1, - c->parm.setup.si2, c->parm.setup.eazmsn); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); - } - break; - case ISDN_CMD_ACCEPTD: - if (!(card->flags & ICN_FLAGS_RUNNING)) - return -ENODEV; - if (c->arg < ICN_BCH) { - a = c->arg + 1; - if (card->fw_rev >= 300) { - switch (card->l2_proto[a - 1]) { - case ISDN_PROTO_L2_X75I: - sprintf(cbuf, "%02d;BX75\n", (int) a); - break; - case ISDN_PROTO_L2_HDLC: - sprintf(cbuf, "%02d;BTRA\n", (int) a); - break; - } - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); - } - sprintf(cbuf, "%02d;DCON_R\n", (int) a); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); - } - break; - case ISDN_CMD_ACCEPTB: - if (!(card->flags & ICN_FLAGS_RUNNING)) - return -ENODEV; - if (c->arg < ICN_BCH) { - a = c->arg + 1; - if (card->fw_rev >= 300) - switch (card->l2_proto[a - 1]) { - case ISDN_PROTO_L2_X75I: - sprintf(cbuf, "%02d;BCON_R,BX75\n", (int) a); - break; - case ISDN_PROTO_L2_HDLC: - sprintf(cbuf, "%02d;BCON_R,BTRA\n", (int) a); - break; - } else - sprintf(cbuf, "%02d;BCON_R\n", (int) a); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); - } - break; - case ISDN_CMD_HANGUP: - if (!(card->flags & ICN_FLAGS_RUNNING)) - return -ENODEV; - if (c->arg < ICN_BCH) { - a = c->arg + 1; - sprintf(cbuf, "%02d;BDIS_R\n%02d;DDIS_R\n", (int) a, (int) a); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); - } - break; - case ISDN_CMD_SETEAZ: - if (!(card->flags & ICN_FLAGS_RUNNING)) - return -ENODEV; - if (card->leased) - break; - if (c->arg < ICN_BCH) { - a = c->arg + 1; - if (card->ptype == ISDN_PTYPE_EURO) { - sprintf(cbuf, "%02d;MS%s%s\n", (int) a, - c->parm.num[0] ? "N" : "ALL", c->parm.num); - } else - sprintf(cbuf, "%02d;EAZ%s\n", (int) a, - c->parm.num[0] ? (char *)(c->parm.num) : "0123456789"); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); - } - break; - case ISDN_CMD_CLREAZ: - if (!(card->flags & ICN_FLAGS_RUNNING)) - return -ENODEV; - if (card->leased) - break; - if (c->arg < ICN_BCH) { - a = c->arg + 1; - if (card->ptype == ISDN_PTYPE_EURO) - sprintf(cbuf, "%02d;MSNC\n", (int) a); - else - sprintf(cbuf, "%02d;EAZC\n", (int) a); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); - } - break; - case ISDN_CMD_SETL2: - if (!(card->flags & ICN_FLAGS_RUNNING)) - return -ENODEV; - if ((c->arg & 255) < ICN_BCH) { - a = c->arg; - switch (a >> 8) { - case ISDN_PROTO_L2_X75I: - sprintf(cbuf, "%02d;BX75\n", (int) (a & 255) + 1); - break; - case ISDN_PROTO_L2_HDLC: - sprintf(cbuf, "%02d;BTRA\n", (int) (a & 255) + 1); - break; - default: - return -EINVAL; - } - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); - card->l2_proto[a & 255] = (a >> 8); - } - break; - case ISDN_CMD_SETL3: - if (!(card->flags & ICN_FLAGS_RUNNING)) - return -ENODEV; - return 0; - default: - return -EINVAL; - } - return 0; -} - -/* - * Find card with given driverId - */ -static inline icn_card * -icn_findcard(int driverid) -{ - icn_card *p = cards; - - while (p) { - if (p->myid == driverid) - return p; - p = p->next; - } - return (icn_card *) 0; -} - -/* - * Wrapper functions for interface to linklevel - */ -static int -if_command(isdn_ctrl *c) -{ - icn_card *card = icn_findcard(c->driver); - - if (card) - return (icn_command(c, card)); - printk(KERN_ERR - "icn: if_command %d called with invalid driverId %d!\n", - c->command, c->driver); - return -ENODEV; -} - -static int -if_writecmd(const u_char __user *buf, int len, int id, int channel) -{ - icn_card *card = icn_findcard(id); - - if (card) { - if (!(card->flags & ICN_FLAGS_RUNNING)) - return -ENODEV; - return (icn_writecmd(buf, len, 1, card)); - } - printk(KERN_ERR - "icn: if_writecmd called with invalid driverId!\n"); - return -ENODEV; -} - -static int -if_readstatus(u_char __user *buf, int len, int id, int channel) -{ - icn_card *card = icn_findcard(id); - - if (card) { - if (!(card->flags & ICN_FLAGS_RUNNING)) - return -ENODEV; - return (icn_readstatus(buf, len, card)); - } - printk(KERN_ERR - "icn: if_readstatus called with invalid driverId!\n"); - return -ENODEV; -} - -static int -if_sendbuf(int id, int channel, int ack, struct sk_buff *skb) -{ - icn_card *card = icn_findcard(id); - - if (card) { - if (!(card->flags & ICN_FLAGS_RUNNING)) - return -ENODEV; - return (icn_sendbuf(channel, ack, skb, card)); - } - printk(KERN_ERR - "icn: if_sendbuf called with invalid driverId!\n"); - return -ENODEV; -} - -/* - * Allocate a new card-struct, initialize it - * link it into cards-list and register it at linklevel. - */ -static icn_card * -icn_initcard(int port, char *id) -{ - icn_card *card; - int i; - - if (!(card = kzalloc(sizeof(icn_card), GFP_KERNEL))) { - printk(KERN_WARNING - "icn: (%s) Could not allocate card-struct.\n", id); - return (icn_card *) 0; - } - spin_lock_init(&card->lock); - card->port = port; - card->interface.owner = THIS_MODULE; - card->interface.hl_hdrlen = 1; - card->interface.channels = ICN_BCH; - card->interface.maxbufsize = 4000; - card->interface.command = if_command; - card->interface.writebuf_skb = if_sendbuf; - card->interface.writecmd = if_writecmd; - card->interface.readstat = if_readstatus; - card->interface.features = ISDN_FEATURE_L2_X75I | - ISDN_FEATURE_L2_HDLC | - ISDN_FEATURE_L3_TRANS | - ISDN_FEATURE_P_UNKNOWN; - card->ptype = ISDN_PTYPE_UNKNOWN; - strlcpy(card->interface.id, id, sizeof(card->interface.id)); - card->msg_buf_write = card->msg_buf; - card->msg_buf_read = card->msg_buf; - card->msg_buf_end = &card->msg_buf[sizeof(card->msg_buf) - 1]; - for (i = 0; i < ICN_BCH; i++) { - card->l2_proto[i] = ISDN_PROTO_L2_X75I; - skb_queue_head_init(&card->spqueue[i]); - } - card->next = cards; - cards = card; - if (!register_isdn(&card->interface)) { - cards = cards->next; - printk(KERN_WARNING - "icn: Unable to register %s\n", id); - kfree(card); - return (icn_card *) 0; - } - card->myid = card->interface.channels; - sprintf(card->regname, "icn-isdn (%s)", card->interface.id); - return card; -} - -static int -icn_addcard(int port, char *id1, char *id2) -{ - icn_card *card; - icn_card *card2; - - if (!(card = icn_initcard(port, id1))) { - return -EIO; - } - if (!strlen(id2)) { - printk(KERN_INFO - "icn: (%s) ICN-2B, port 0x%x added\n", - card->interface.id, port); - return 0; - } - if (!(card2 = icn_initcard(port, id2))) { - printk(KERN_INFO - "icn: (%s) half ICN-4B, port 0x%x added\n", id2, port); - return 0; - } - card->doubleS0 = 1; - card->secondhalf = 0; - card->other = card2; - card2->doubleS0 = 1; - card2->secondhalf = 1; - card2->other = card; - printk(KERN_INFO - "icn: (%s and %s) ICN-4B, port 0x%x added\n", - card->interface.id, card2->interface.id, port); - return 0; -} - -#ifndef MODULE -static int __init -icn_setup(char *line) -{ - char *p, *str; - int ints[3]; - static char sid[20]; - static char sid2[20]; - - str = get_options(line, 2, ints); - if (ints[0]) - portbase = ints[1]; - if (ints[0] > 1) - membase = (unsigned long)ints[2]; - if (str && *str) { - strlcpy(sid, str, sizeof(sid)); - icn_id = sid; - if ((p = strchr(sid, ','))) { - *p++ = 0; - strcpy(sid2, p); - icn_id2 = sid2; - } - } - return (1); -} -__setup("icn=", icn_setup); -#endif /* MODULE */ - -static int __init icn_init(void) -{ - char *p; - char rev[21]; - - memset(&dev, 0, sizeof(icn_dev)); - dev.memaddr = (membase & 0x0ffc000); - dev.channel = -1; - dev.mcard = NULL; - dev.firstload = 1; - spin_lock_init(&dev.devlock); - - if ((p = strchr(revision, ':'))) { - strncpy(rev, p + 1, 20); - rev[20] = '\0'; - p = strchr(rev, '$'); - if (p) - *p = 0; - } else - strcpy(rev, " ??? "); - printk(KERN_NOTICE "ICN-ISDN-driver Rev%smem=0x%08lx\n", rev, - dev.memaddr); - return (icn_addcard(portbase, icn_id, icn_id2)); -} - -static void __exit icn_exit(void) -{ - isdn_ctrl cmd; - icn_card *card = cards; - icn_card *last, *tmpcard; - int i; - unsigned long flags; - - icn_stopallcards(); - while (card) { - cmd.command = ISDN_STAT_UNLOAD; - cmd.driver = card->myid; - card->interface.statcallb(&cmd); - spin_lock_irqsave(&card->lock, flags); - if (card->rvalid) { - OUTB_P(0, ICN_RUN); /* Reset Controller */ - OUTB_P(0, ICN_MAPRAM); /* Disable RAM */ - if (card->secondhalf || (!card->doubleS0)) { - release_region(card->port, ICN_PORTLEN); - card->rvalid = 0; - } - for (i = 0; i < ICN_BCH; i++) - icn_free_queue(card, i); - } - tmpcard = card->next; - spin_unlock_irqrestore(&card->lock, flags); - card = tmpcard; - } - card = cards; - cards = NULL; - while (card) { - last = card; - card = card->next; - kfree(last); - } - if (dev.mvalid) { - iounmap(dev.shmem); - release_mem_region(dev.memaddr, 0x4000); - } - printk(KERN_NOTICE "ICN-ISDN-driver unloaded\n"); -} - -module_init(icn_init); -module_exit(icn_exit); diff --git a/drivers/isdn/icn/icn.h b/drivers/isdn/icn/icn.h deleted file mode 100644 index f8f2e76d34bf..000000000000 --- a/drivers/isdn/icn/icn.h +++ /dev/null @@ -1,253 +0,0 @@ -/* $Id: icn.h,v 1.30.6.5 2001/09/23 22:24:55 kai Exp $ - * - * ISDN lowlevel-module for the ICN active ISDN-Card. - * - * Copyright 1994 by Fritz Elfert (fritz@isdn4linux.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#ifndef icn_h -#define icn_h - -#define ICN_IOCTL_SETMMIO 0 -#define ICN_IOCTL_GETMMIO 1 -#define ICN_IOCTL_SETPORT 2 -#define ICN_IOCTL_GETPORT 3 -#define ICN_IOCTL_LOADBOOT 4 -#define ICN_IOCTL_LOADPROTO 5 -#define ICN_IOCTL_LEASEDCFG 6 -#define ICN_IOCTL_GETDOUBLE 7 -#define ICN_IOCTL_DEBUGVAR 8 -#define ICN_IOCTL_ADDCARD 9 - -/* Struct for adding new cards */ -typedef struct icn_cdef { - int port; - char id1[10]; - char id2[10]; -} icn_cdef; - -#if defined(__KERNEL__) || defined(__DEBUGVAR__) - -#ifdef __KERNEL__ -/* Kernel includes */ - -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/major.h> -#include <linux/io.h> -#include <linux/kernel.h> -#include <linux/signal.h> -#include <linux/slab.h> -#include <linux/mm.h> -#include <linux/mman.h> -#include <linux/ioport.h> -#include <linux/timer.h> -#include <linux/wait.h> -#include <linux/delay.h> -#include <linux/isdnif.h> - -#endif /* __KERNEL__ */ - -/* some useful macros for debugging */ -#ifdef ICN_DEBUG_PORT -#define OUTB_P(v, p) {printk(KERN_DEBUG "icn: outb_p(0x%02x,0x%03x)\n", v, p); outb_p(v, p);} -#else -#define OUTB_P outb -#endif - -/* Defaults for Port-Address and shared-memory */ -#define ICN_BASEADDR 0x320 -#define ICN_PORTLEN (0x04) -#define ICN_MEMADDR 0x0d0000 - -#define ICN_FLAGS_B1ACTIVE 1 /* B-Channel-1 is open */ -#define ICN_FLAGS_B2ACTIVE 2 /* B-Channel-2 is open */ -#define ICN_FLAGS_RUNNING 4 /* Cards driver activated */ -#define ICN_FLAGS_RBTIMER 8 /* cyclic scheduling of B-Channel-poll */ - -#define ICN_BOOT_TIMEOUT1 1000 /* Delay for Boot-download (msecs) */ - -#define ICN_TIMER_BCREAD (HZ / 100) /* B-Channel poll-cycle */ -#define ICN_TIMER_DCREAD (HZ / 2) /* D-Channel poll-cycle */ - -#define ICN_CODE_STAGE1 4096 /* Size of bootcode */ -#define ICN_CODE_STAGE2 65536 /* Size of protocol-code */ - -#define ICN_MAX_SQUEUE 8000 /* Max. outstanding send-data (2* hw-buf.) */ -#define ICN_FRAGSIZE (250) /* Max. size of send-fragments */ -#define ICN_BCH 2 /* Number of supported channels per card */ - -/* type-definitions for accessing the mmap-io-areas */ - -#define SHM_DCTL_OFFSET (0) /* Offset to data-controlstructures in shm */ -#define SHM_CCTL_OFFSET (0x1d2) /* Offset to comm-controlstructures in shm */ -#define SHM_CBUF_OFFSET (0x200) /* Offset to comm-buffers in shm */ -#define SHM_DBUF_OFFSET (0x2000) /* Offset to data-buffers in shm */ - -/* - * Layout of card's data buffers - */ -typedef struct { - unsigned char length; /* Bytecount of fragment (max 250) */ - unsigned char endflag; /* 0=last frag., 0xff=frag. continued */ - unsigned char data[ICN_FRAGSIZE]; /* The data */ - /* Fill to 256 bytes */ - char unused[0x100 - ICN_FRAGSIZE - 2]; -} frag_buf; - -/* - * Layout of card's shared memory - */ -typedef union { - struct { - unsigned char scns; /* Index to free SendFrag. */ - unsigned char scnr; /* Index to active SendFrag READONLY */ - unsigned char ecns; /* Index to free RcvFrag. READONLY */ - unsigned char ecnr; /* Index to valid RcvFrag */ - char unused[6]; - unsigned short fuell1; /* Internal Buf Bytecount */ - } data_control; - struct { - char unused[SHM_CCTL_OFFSET]; - unsigned char iopc_i; /* Read-Ptr Status-Queue READONLY */ - unsigned char iopc_o; /* Write-Ptr Status-Queue */ - unsigned char pcio_i; /* Write-Ptr Command-Queue */ - unsigned char pcio_o; /* Read-Ptr Command Queue READONLY */ - } comm_control; - struct { - char unused[SHM_CBUF_OFFSET]; - unsigned char pcio_buf[0x100]; /* Ring-Buffer Command-Queue */ - unsigned char iopc_buf[0x100]; /* Ring-Buffer Status-Queue */ - } comm_buffers; - struct { - char unused[SHM_DBUF_OFFSET]; - frag_buf receive_buf[0x10]; - frag_buf send_buf[0x10]; - } data_buffers; -} icn_shmem; - -/* - * Per card driver data - */ -typedef struct icn_card { - struct icn_card *next; /* Pointer to next device struct */ - struct icn_card *other; /* Pointer to other card for ICN4B */ - unsigned short port; /* Base-port-address */ - int myid; /* Driver-Nr. assigned by linklevel */ - int rvalid; /* IO-portregion has been requested */ - int leased; /* Flag: This Adapter is connected */ - /* to a leased line */ - unsigned short flags; /* Statusflags */ - int doubleS0; /* Flag: ICN4B */ - int secondhalf; /* Flag: Second half of a doubleS0 */ - int fw_rev; /* Firmware revision loaded */ - int ptype; /* Protocol type (1TR6 or Euro) */ - struct timer_list st_timer; /* Timer for Status-Polls */ - struct timer_list rb_timer; /* Timer for B-Channel-Polls */ - u_char rcvbuf[ICN_BCH][4096]; /* B-Channel-Receive-Buffers */ - int rcvidx[ICN_BCH]; /* Index for above buffers */ - int l2_proto[ICN_BCH]; /* Current layer-2-protocol */ - isdn_if interface; /* Interface to upper layer */ - int iptr; /* Index to imsg-buffer */ - char imsg[60]; /* Internal buf for status-parsing */ - char msg_buf[2048]; /* Buffer for status-messages */ - char *msg_buf_write; /* Writepointer for statusbuffer */ - char *msg_buf_read; /* Readpointer for statusbuffer */ - char *msg_buf_end; /* Pointer to end of statusbuffer */ - int sndcount[ICN_BCH]; /* Byte-counters for B-Ch.-send */ - int xlen[ICN_BCH]; /* Byte-counters/Flags for sent-ACK */ - struct sk_buff *xskb[ICN_BCH]; /* Current transmitted skb */ - struct sk_buff_head spqueue[ICN_BCH]; /* Sendqueue */ - char regname[35]; /* Name used for request_region */ - u_char xmit_lock[ICN_BCH]; /* Semaphore for pollbchan_send()*/ - spinlock_t lock; /* protect critical operations */ -} icn_card; - -/* - * Main driver data - */ -typedef struct icn_dev { - spinlock_t devlock; /* spinlock to protect this struct */ - unsigned long memaddr; /* Address of memory mapped buffers */ - icn_shmem __iomem *shmem; /* Pointer to memory-mapped-buffers */ - int mvalid; /* IO-shmem has been requested */ - int channel; /* Currently mapped channel */ - struct icn_card *mcard; /* Currently mapped card */ - int chanlock; /* Semaphore for channel-mapping */ - int firstload; /* Flag: firmware never loaded */ -} icn_dev; - -typedef icn_dev *icn_devptr; - -#ifdef __KERNEL__ - -static icn_card *cards = (icn_card *) 0; -static u_char chan2bank[] = -{0, 4, 8, 12}; /* for icn_map_channel() */ - -static icn_dev dev; - -#endif /* __KERNEL__ */ - -/* Utility-Macros */ - -/* Macros for accessing ports */ -#define ICN_CFG (card->port) -#define ICN_MAPRAM (card->port + 1) -#define ICN_RUN (card->port + 2) -#define ICN_BANK (card->port + 3) - -/* Return true, if there is a free transmit-buffer */ -#define sbfree (((readb(&dev.shmem->data_control.scns) + 1) & 0xf) != \ - readb(&dev.shmem->data_control.scnr)) - -/* Switch to next transmit-buffer */ -#define sbnext (writeb((readb(&dev.shmem->data_control.scns) + 1) & 0xf, \ - &dev.shmem->data_control.scns)) - -/* Shortcuts for transmit-buffer-access */ -#define sbuf_n dev.shmem->data_control.scns -#define sbuf_d dev.shmem->data_buffers.send_buf[readb(&sbuf_n)].data -#define sbuf_l dev.shmem->data_buffers.send_buf[readb(&sbuf_n)].length -#define sbuf_f dev.shmem->data_buffers.send_buf[readb(&sbuf_n)].endflag - -/* Return true, if there is receive-data is available */ -#define rbavl (readb(&dev.shmem->data_control.ecnr) != \ - readb(&dev.shmem->data_control.ecns)) - -/* Switch to next receive-buffer */ -#define rbnext (writeb((readb(&dev.shmem->data_control.ecnr) + 1) & 0xf, \ - &dev.shmem->data_control.ecnr)) - -/* Shortcuts for receive-buffer-access */ -#define rbuf_n dev.shmem->data_control.ecnr -#define rbuf_d dev.shmem->data_buffers.receive_buf[readb(&rbuf_n)].data -#define rbuf_l dev.shmem->data_buffers.receive_buf[readb(&rbuf_n)].length -#define rbuf_f dev.shmem->data_buffers.receive_buf[readb(&rbuf_n)].endflag - -/* Shortcuts for command-buffer-access */ -#define cmd_o (dev.shmem->comm_control.pcio_o) -#define cmd_i (dev.shmem->comm_control.pcio_i) - -/* Return free space in command-buffer */ -#define cmd_free ((readb(&cmd_i) >= readb(&cmd_o)) ? \ - 0x100 - readb(&cmd_i) + readb(&cmd_o) : \ - readb(&cmd_o) - readb(&cmd_i)) - -/* Shortcuts for message-buffer-access */ -#define msg_o (dev.shmem->comm_control.iopc_o) -#define msg_i (dev.shmem->comm_control.iopc_i) - -/* Return length of Message, if avail. */ -#define msg_avail ((readb(&msg_o) > readb(&msg_i)) ? \ - 0x100 - readb(&msg_o) + readb(&msg_i) : \ - readb(&msg_i) - readb(&msg_o)) - -#define CID (card->interface.id) - -#endif /* defined(__KERNEL__) || defined(__DEBUGVAR__) */ -#endif /* icn_h */ diff --git a/drivers/isdn/pcbit/Kconfig b/drivers/isdn/pcbit/Kconfig deleted file mode 100644 index e9b2dd85d410..000000000000 --- a/drivers/isdn/pcbit/Kconfig +++ /dev/null @@ -1,10 +0,0 @@ -config ISDN_DRV_PCBIT - tristate "PCBIT-D support" - depends on ISA && (BROKEN || X86) - help - This enables support for the PCBIT ISDN-card. This card is - manufactured in Portugal by Octal. For running this card, - additional firmware is necessary, which has to be downloaded into - the card using a utility which is distributed separately. See - <file:Documentation/isdn/README> and - <file:Documentation/isdn/README.pcbit> for more information. diff --git a/drivers/isdn/pcbit/Makefile b/drivers/isdn/pcbit/Makefile deleted file mode 100644 index 2d026c3242e8..000000000000 --- a/drivers/isdn/pcbit/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# Makefile for the pcbit ISDN device driver - -# Each configuration option enables a list of files. - -obj-$(CONFIG_ISDN_DRV_PCBIT) += pcbit.o - -# Multipart objects. - -pcbit-y := module.o edss1.o drv.o layer2.o capi.o callbacks.o diff --git a/drivers/isdn/pcbit/callbacks.c b/drivers/isdn/pcbit/callbacks.c deleted file mode 100644 index efb6d6a3639a..000000000000 --- a/drivers/isdn/pcbit/callbacks.c +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Callbacks for the FSM - * - * Copyright (C) 1996 Universidade de Lisboa - * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) - * - * This software may be used and distributed according to the terms of - * the GNU General Public License, incorporated herein by reference. - */ - -/* - * Fix: 19981230 - Carlos Morgado <chbm@techie.com> - * Port of Nelson Escravana's <nelson.escravana@usa.net> fix to CalledPN - * NULL pointer dereference in cb_in_1 (originally fixed in 2.0) - */ - -#include <linux/string.h> -#include <linux/kernel.h> - -#include <linux/types.h> -#include <linux/mm.h> -#include <linux/skbuff.h> - -#include <asm/io.h> - -#include <linux/isdnif.h> - -#include "pcbit.h" -#include "layer2.h" -#include "edss1.h" -#include "callbacks.h" -#include "capi.h" - -ushort last_ref_num = 1; - -/* - * send_conn_req - * - */ - -void cb_out_1(struct pcbit_dev *dev, struct pcbit_chan *chan, - struct callb_data *cbdata) -{ - struct sk_buff *skb; - int len; - ushort refnum; - - -#ifdef DEBUG - printk(KERN_DEBUG "Called Party Number: %s\n", - cbdata->data.setup.CalledPN); -#endif - /* - * hdr - kmalloc in capi_conn_req - * - kfree when msg has been sent - */ - - if ((len = capi_conn_req(cbdata->data.setup.CalledPN, &skb, - chan->proto)) < 0) - { - printk("capi_conn_req failed\n"); - return; - } - - - refnum = last_ref_num++ & 0x7fffU; - - chan->callref = 0; - chan->layer2link = 0; - chan->snum = 0; - chan->s_refnum = refnum; - - pcbit_l2_write(dev, MSG_CONN_REQ, refnum, skb, len); -} - -/* - * rcv CONNECT - * will go into ACTIVE state - * send CONN_ACTIVE_RESP - * send Select protocol request - */ - -void cb_out_2(struct pcbit_dev *dev, struct pcbit_chan *chan, - struct callb_data *data) -{ - isdn_ctrl ictl; - struct sk_buff *skb; - int len; - ushort refnum; - - if ((len = capi_conn_active_resp(chan, &skb)) < 0) - { - printk("capi_conn_active_req failed\n"); - return; - } - - refnum = last_ref_num++ & 0x7fffU; - chan->s_refnum = refnum; - - pcbit_l2_write(dev, MSG_CONN_ACTV_RESP, refnum, skb, len); - - - ictl.command = ISDN_STAT_DCONN; - ictl.driver = dev->id; - ictl.arg = chan->id; - dev->dev_if->statcallb(&ictl); - - /* ACTIVE D-channel */ - - /* Select protocol */ - - if ((len = capi_select_proto_req(chan, &skb, 1 /*outgoing*/)) < 0) { - printk("capi_select_proto_req failed\n"); - return; - } - - refnum = last_ref_num++ & 0x7fffU; - chan->s_refnum = refnum; - - pcbit_l2_write(dev, MSG_SELP_REQ, refnum, skb, len); -} - - -/* - * Incoming call received - * inform user - */ - -void cb_in_1(struct pcbit_dev *dev, struct pcbit_chan *chan, - struct callb_data *cbdata) -{ - isdn_ctrl ictl; - unsigned short refnum; - struct sk_buff *skb; - int len; - - - ictl.command = ISDN_STAT_ICALL; - ictl.driver = dev->id; - ictl.arg = chan->id; - - /* - * ictl.num >= strlen() + strlen() + 5 - */ - - if (cbdata->data.setup.CallingPN == NULL) { - printk(KERN_DEBUG "NULL CallingPN to phone; using 0\n"); - strcpy(ictl.parm.setup.phone, "0"); - } - else { - strcpy(ictl.parm.setup.phone, cbdata->data.setup.CallingPN); - } - if (cbdata->data.setup.CalledPN == NULL) { - printk(KERN_DEBUG "NULL CalledPN to eazmsn; using 0\n"); - strcpy(ictl.parm.setup.eazmsn, "0"); - } - else { - strcpy(ictl.parm.setup.eazmsn, cbdata->data.setup.CalledPN); - } - ictl.parm.setup.si1 = 7; - ictl.parm.setup.si2 = 0; - ictl.parm.setup.plan = 0; - ictl.parm.setup.screen = 0; - -#ifdef DEBUG - printk(KERN_DEBUG "statstr: %s\n", ictl.num); -#endif - - dev->dev_if->statcallb(&ictl); - - - if ((len = capi_conn_resp(chan, &skb)) < 0) { - printk(KERN_DEBUG "capi_conn_resp failed\n"); - return; - } - - refnum = last_ref_num++ & 0x7fffU; - chan->s_refnum = refnum; - - pcbit_l2_write(dev, MSG_CONN_RESP, refnum, skb, len); -} - -/* - * user has replied - * open the channel - * send CONNECT message CONNECT_ACTIVE_REQ in CAPI - */ - -void cb_in_2(struct pcbit_dev *dev, struct pcbit_chan *chan, - struct callb_data *data) -{ - unsigned short refnum; - struct sk_buff *skb; - int len; - - if ((len = capi_conn_active_req(chan, &skb)) < 0) { - printk(KERN_DEBUG "capi_conn_active_req failed\n"); - return; - } - - - refnum = last_ref_num++ & 0x7fffU; - chan->s_refnum = refnum; - - printk(KERN_DEBUG "sending MSG_CONN_ACTV_REQ\n"); - pcbit_l2_write(dev, MSG_CONN_ACTV_REQ, refnum, skb, len); -} - -/* - * CONN_ACK arrived - * start b-proto selection - * - */ - -void cb_in_3(struct pcbit_dev *dev, struct pcbit_chan *chan, - struct callb_data *data) -{ - unsigned short refnum; - struct sk_buff *skb; - int len; - - if ((len = capi_select_proto_req(chan, &skb, 0 /*incoming*/)) < 0) - { - printk("capi_select_proto_req failed\n"); - return; - } - - refnum = last_ref_num++ & 0x7fffU; - chan->s_refnum = refnum; - - pcbit_l2_write(dev, MSG_SELP_REQ, refnum, skb, len); - -} - - -/* - * Received disconnect ind on active state - * send disconnect resp - * send msg to user - */ -void cb_disc_1(struct pcbit_dev *dev, struct pcbit_chan *chan, - struct callb_data *data) -{ - struct sk_buff *skb; - int len; - ushort refnum; - isdn_ctrl ictl; - - if ((len = capi_disc_resp(chan, &skb)) < 0) { - printk("capi_disc_resp failed\n"); - return; - } - - refnum = last_ref_num++ & 0x7fffU; - chan->s_refnum = refnum; - - pcbit_l2_write(dev, MSG_DISC_RESP, refnum, skb, len); - - ictl.command = ISDN_STAT_BHUP; - ictl.driver = dev->id; - ictl.arg = chan->id; - dev->dev_if->statcallb(&ictl); -} - - -/* - * User HANGUP on active/call proceeding state - * send disc.req - */ -void cb_disc_2(struct pcbit_dev *dev, struct pcbit_chan *chan, - struct callb_data *data) -{ - struct sk_buff *skb; - int len; - ushort refnum; - - if ((len = capi_disc_req(chan->callref, &skb, CAUSE_NORMAL)) < 0) - { - printk("capi_disc_req failed\n"); - return; - } - - refnum = last_ref_num++ & 0x7fffU; - chan->s_refnum = refnum; - - pcbit_l2_write(dev, MSG_DISC_REQ, refnum, skb, len); -} - -/* - * Disc confirm received send BHUP - * Problem: when the HL driver sends the disc req itself - * LL receives BHUP - */ -void cb_disc_3(struct pcbit_dev *dev, struct pcbit_chan *chan, - struct callb_data *data) -{ - isdn_ctrl ictl; - - ictl.command = ISDN_STAT_BHUP; - ictl.driver = dev->id; - ictl.arg = chan->id; - dev->dev_if->statcallb(&ictl); -} - -void cb_notdone(struct pcbit_dev *dev, struct pcbit_chan *chan, - struct callb_data *data) -{ -} - -/* - * send activate b-chan protocol - */ -void cb_selp_1(struct pcbit_dev *dev, struct pcbit_chan *chan, - struct callb_data *data) -{ - struct sk_buff *skb; - int len; - ushort refnum; - - if ((len = capi_activate_transp_req(chan, &skb)) < 0) - { - printk("capi_conn_activate_transp_req failed\n"); - return; - } - - refnum = last_ref_num++ & 0x7fffU; - chan->s_refnum = refnum; - - pcbit_l2_write(dev, MSG_ACT_TRANSP_REQ, refnum, skb, len); -} - -/* - * Inform User that the B-channel is available - */ -void cb_open(struct pcbit_dev *dev, struct pcbit_chan *chan, - struct callb_data *data) -{ - isdn_ctrl ictl; - - ictl.command = ISDN_STAT_BCONN; - ictl.driver = dev->id; - ictl.arg = chan->id; - dev->dev_if->statcallb(&ictl); -} diff --git a/drivers/isdn/pcbit/callbacks.h b/drivers/isdn/pcbit/callbacks.h deleted file mode 100644 index a036b4a7ffad..000000000000 --- a/drivers/isdn/pcbit/callbacks.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Callbacks prototypes for FSM - * - * Copyright (C) 1996 Universidade de Lisboa - * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) - * - * This software may be used and distributed according to the terms of - * the GNU General Public License, incorporated herein by reference. - */ - -#ifndef CALLBACKS_H -#define CALLBACKS_H - - -extern void cb_out_1(struct pcbit_dev *dev, struct pcbit_chan *chan, - struct callb_data *data); - -extern void cb_out_2(struct pcbit_dev *dev, struct pcbit_chan *chan, - struct callb_data *data); - -extern void cb_in_1(struct pcbit_dev *dev, struct pcbit_chan *chan, - struct callb_data *data); -extern void cb_in_2(struct pcbit_dev *dev, struct pcbit_chan *chan, - struct callb_data *data); -extern void cb_in_3(struct pcbit_dev *dev, struct pcbit_chan *chan, - struct callb_data *data); - -extern void cb_disc_1(struct pcbit_dev *dev, struct pcbit_chan *chan, - struct callb_data *data); -extern void cb_disc_2(struct pcbit_dev *dev, struct pcbit_chan *chan, - struct callb_data *data); -extern void cb_disc_3(struct pcbit_dev *dev, struct pcbit_chan *chan, - struct callb_data *data); - -extern void cb_notdone(struct pcbit_dev *dev, struct pcbit_chan *chan, - struct callb_data *data); - -extern void cb_selp_1(struct pcbit_dev *dev, struct pcbit_chan *chan, - struct callb_data *data); -extern void cb_open(struct pcbit_dev *dev, struct pcbit_chan *chan, - struct callb_data *data); - -#endif diff --git a/drivers/isdn/pcbit/capi.c b/drivers/isdn/pcbit/capi.c deleted file mode 100644 index 4e3cbf857d60..000000000000 --- a/drivers/isdn/pcbit/capi.c +++ /dev/null @@ -1,649 +0,0 @@ -/* - * CAPI encoder/decoder for - * Portugal Telecom CAPI 2.0 - * - * Copyright (C) 1996 Universidade de Lisboa - * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) - * - * This software may be used and distributed according to the terms of - * the GNU General Public License, incorporated herein by reference. - * - * Not compatible with the AVM Gmbh. CAPI 2.0 - * - */ - -/* - * Documentation: - * - "Common ISDN API - Perfil Português - Versão 2.1", - * Telecom Portugal, Fev 1992. - * - "Common ISDN API - Especificação de protocolos para - * acesso aos canais B", Inesc, Jan 1994. - */ - -/* - * TODO: better decoding of Information Elements - * for debug purposes mainly - * encode our number in CallerPN and ConnectedPN - */ - -#include <linux/string.h> -#include <linux/kernel.h> - -#include <linux/types.h> -#include <linux/slab.h> -#include <linux/mm.h> - -#include <linux/skbuff.h> - -#include <asm/io.h> -#include <asm/string.h> - -#include <linux/isdnif.h> - -#include "pcbit.h" -#include "edss1.h" -#include "capi.h" - - -/* - * Encoding of CAPI messages - * - */ - -int capi_conn_req(const char *calledPN, struct sk_buff **skb, int proto) -{ - ushort len; - - /* - * length - * AppInfoMask - 2 - * BC0 - 3 - * BC1 - 1 - * Chan - 2 - * Keypad - 1 - * CPN - 1 - * CPSA - 1 - * CalledPN - 2 + strlen - * CalledPSA - 1 - * rest... - 4 - * ---------------- - * Total 18 + strlen - */ - - len = 18 + strlen(calledPN); - - if (proto == ISDN_PROTO_L2_TRANS) - len++; - - if ((*skb = dev_alloc_skb(len)) == NULL) { - - printk(KERN_WARNING "capi_conn_req: alloc_skb failed\n"); - return -1; - } - - /* InfoElmMask */ - *((ushort *)skb_put(*skb, 2)) = AppInfoMask; - - if (proto == ISDN_PROTO_L2_TRANS) - { - /* Bearer Capability - Mandatory*/ - *(skb_put(*skb, 1)) = 3; /* BC0.Length */ - *(skb_put(*skb, 1)) = 0x80; /* Speech */ - *(skb_put(*skb, 1)) = 0x10; /* Circuit Mode */ - *(skb_put(*skb, 1)) = 0x23; /* A-law */ - } - else - { - /* Bearer Capability - Mandatory*/ - *(skb_put(*skb, 1)) = 2; /* BC0.Length */ - *(skb_put(*skb, 1)) = 0x88; /* Digital Information */ - *(skb_put(*skb, 1)) = 0x90; /* BC0.Octect4 */ - } - - /* Bearer Capability - Optional*/ - *(skb_put(*skb, 1)) = 0; /* BC1.Length = 0 */ - - *(skb_put(*skb, 1)) = 1; /* ChannelID.Length = 1 */ - *(skb_put(*skb, 1)) = 0x83; /* Basic Interface - Any Channel */ - - *(skb_put(*skb, 1)) = 0; /* Keypad.Length = 0 */ - - - *(skb_put(*skb, 1)) = 0; /* CallingPN.Length = 0 */ - *(skb_put(*skb, 1)) = 0; /* CallingPSA.Length = 0 */ - - /* Called Party Number */ - *(skb_put(*skb, 1)) = strlen(calledPN) + 1; - *(skb_put(*skb, 1)) = 0x81; - memcpy(skb_put(*skb, strlen(calledPN)), calledPN, strlen(calledPN)); - - /* '#' */ - - *(skb_put(*skb, 1)) = 0; /* CalledPSA.Length = 0 */ - - /* LLC.Length = 0; */ - /* HLC0.Length = 0; */ - /* HLC1.Length = 0; */ - /* UTUS.Length = 0; */ - memset(skb_put(*skb, 4), 0, 4); - - return len; -} - -int capi_conn_resp(struct pcbit_chan *chan, struct sk_buff **skb) -{ - - if ((*skb = dev_alloc_skb(5)) == NULL) { - - printk(KERN_WARNING "capi_conn_resp: alloc_skb failed\n"); - return -1; - } - - *((ushort *)skb_put(*skb, 2)) = chan->callref; - *(skb_put(*skb, 1)) = 0x01; /* ACCEPT_CALL */ - *(skb_put(*skb, 1)) = 0; - *(skb_put(*skb, 1)) = 0; - - return 5; -} - -int capi_conn_active_req(struct pcbit_chan *chan, struct sk_buff **skb) -{ - /* - * 8 bytes - */ - - if ((*skb = dev_alloc_skb(8)) == NULL) { - - printk(KERN_WARNING "capi_conn_active_req: alloc_skb failed\n"); - return -1; - } - - *((ushort *)skb_put(*skb, 2)) = chan->callref; - -#ifdef DEBUG - printk(KERN_DEBUG "Call Reference: %04x\n", chan->callref); -#endif - - *(skb_put(*skb, 1)) = 0; /* BC.Length = 0; */ - *(skb_put(*skb, 1)) = 0; /* ConnectedPN.Length = 0 */ - *(skb_put(*skb, 1)) = 0; /* PSA.Length */ - *(skb_put(*skb, 1)) = 0; /* LLC.Length = 0; */ - *(skb_put(*skb, 1)) = 0; /* HLC.Length = 0; */ - *(skb_put(*skb, 1)) = 0; /* UTUS.Length = 0; */ - - return 8; -} - -int capi_conn_active_resp(struct pcbit_chan *chan, struct sk_buff **skb) -{ - /* - * 2 bytes - */ - - if ((*skb = dev_alloc_skb(2)) == NULL) { - - printk(KERN_WARNING "capi_conn_active_resp: alloc_skb failed\n"); - return -1; - } - - *((ushort *)skb_put(*skb, 2)) = chan->callref; - - return 2; -} - - -int capi_select_proto_req(struct pcbit_chan *chan, struct sk_buff **skb, - int outgoing) -{ - - /* - * 18 bytes - */ - - if ((*skb = dev_alloc_skb(18)) == NULL) { - - printk(KERN_WARNING "capi_select_proto_req: alloc_skb failed\n"); - return -1; - } - - *((ushort *)skb_put(*skb, 2)) = chan->callref; - - /* Layer2 protocol */ - - switch (chan->proto) { - case ISDN_PROTO_L2_X75I: - *(skb_put(*skb, 1)) = 0x05; /* LAPB */ - break; - case ISDN_PROTO_L2_HDLC: - *(skb_put(*skb, 1)) = 0x02; - break; - case ISDN_PROTO_L2_TRANS: - /* - * Voice (a-law) - */ - *(skb_put(*skb, 1)) = 0x06; - break; - default: -#ifdef DEBUG - printk(KERN_DEBUG "Transparent\n"); -#endif - *(skb_put(*skb, 1)) = 0x03; - break; - } - - *(skb_put(*skb, 1)) = (outgoing ? 0x02 : 0x42); /* Don't ask */ - *(skb_put(*skb, 1)) = 0x00; - - *((ushort *) skb_put(*skb, 2)) = MRU; - - - *(skb_put(*skb, 1)) = 0x08; /* Modulo */ - *(skb_put(*skb, 1)) = 0x07; /* Max Window */ - - *(skb_put(*skb, 1)) = 0x01; /* No Layer3 Protocol */ - - /* - * 2 - layer3 MTU [10] - * - Modulo [12] - * - Window - * - layer1 proto [14] - * - bitrate - * - sub-channel [16] - * - layer1dataformat [17] - */ - - memset(skb_put(*skb, 8), 0, 8); - - return 18; -} - - -int capi_activate_transp_req(struct pcbit_chan *chan, struct sk_buff **skb) -{ - - if ((*skb = dev_alloc_skb(7)) == NULL) { - - printk(KERN_WARNING "capi_activate_transp_req: alloc_skb failed\n"); - return -1; - } - - *((ushort *)skb_put(*skb, 2)) = chan->callref; - - - *(skb_put(*skb, 1)) = chan->layer2link; /* Layer2 id */ - *(skb_put(*skb, 1)) = 0x00; /* Transmit by default */ - - *((ushort *) skb_put(*skb, 2)) = MRU; - - *(skb_put(*skb, 1)) = 0x01; /* Enables reception*/ - - return 7; -} - -int capi_tdata_req(struct pcbit_chan *chan, struct sk_buff *skb) -{ - ushort data_len; - - - /* - * callref - 2 - * layer2link - 1 - * wBlockLength - 2 - * data - 4 - * sernum - 1 - */ - - data_len = skb->len; - - if (skb_headroom(skb) < 10) - { - printk(KERN_CRIT "No headspace (%u) on headroom %p for capi header\n", skb_headroom(skb), skb); - } - else - { - skb_push(skb, 10); - } - - *((u16 *) (skb->data)) = chan->callref; - skb->data[2] = chan->layer2link; - *((u16 *) (skb->data + 3)) = data_len; - - chan->s_refnum = (chan->s_refnum + 1) % 8; - *((u32 *) (skb->data + 5)) = chan->s_refnum; - - skb->data[9] = 0; /* HDLC frame number */ - - return 10; -} - -int capi_tdata_resp(struct pcbit_chan *chan, struct sk_buff **skb) - -{ - if ((*skb = dev_alloc_skb(4)) == NULL) { - - printk(KERN_WARNING "capi_tdata_resp: alloc_skb failed\n"); - return -1; - } - - *((ushort *)skb_put(*skb, 2)) = chan->callref; - - *(skb_put(*skb, 1)) = chan->layer2link; - *(skb_put(*skb, 1)) = chan->r_refnum; - - return (*skb)->len; -} - -int capi_disc_req(ushort callref, struct sk_buff **skb, u_char cause) -{ - - if ((*skb = dev_alloc_skb(6)) == NULL) { - - printk(KERN_WARNING "capi_disc_req: alloc_skb failed\n"); - return -1; - } - - *((ushort *)skb_put(*skb, 2)) = callref; - - *(skb_put(*skb, 1)) = 2; /* Cause.Length = 2; */ - *(skb_put(*skb, 1)) = 0x80; - *(skb_put(*skb, 1)) = 0x80 | cause; - - /* - * Change it: we should send 'Sic transit gloria Mundi' here ;-) - */ - - *(skb_put(*skb, 1)) = 0; /* UTUS.Length = 0; */ - - return 6; -} - -int capi_disc_resp(struct pcbit_chan *chan, struct sk_buff **skb) -{ - if ((*skb = dev_alloc_skb(2)) == NULL) { - - printk(KERN_WARNING "capi_disc_resp: alloc_skb failed\n"); - return -1; - } - - *((ushort *)skb_put(*skb, 2)) = chan->callref; - - return 2; -} - - -/* - * Decoding of CAPI messages - * - */ - -int capi_decode_conn_ind(struct pcbit_chan *chan, - struct sk_buff *skb, - struct callb_data *info) -{ - int CIlen, len; - - /* Call Reference [CAPI] */ - chan->callref = *((ushort *)skb->data); - skb_pull(skb, 2); - -#ifdef DEBUG - printk(KERN_DEBUG "Call Reference: %04x\n", chan->callref); -#endif - - /* Channel Identification */ - - /* Expect - Len = 1 - Octect 3 = 0100 10CC - [ 7 Basic, 4 , 2-1 chan ] - */ - - CIlen = skb->data[0]; -#ifdef DEBUG - if (CIlen == 1) { - - if (((skb->data[1]) & 0xFC) == 0x48) - printk(KERN_DEBUG "decode_conn_ind: chan ok\n"); - printk(KERN_DEBUG "phyChan = %d\n", skb->data[1] & 0x03); - } - else - printk(KERN_DEBUG "conn_ind: CIlen = %d\n", CIlen); -#endif - skb_pull(skb, CIlen + 1); - - /* Calling Party Number */ - /* An "additional service" as far as Portugal Telecom is concerned */ - - len = skb->data[0]; - - if (len > 0) { - int count = 1; - -#ifdef DEBUG - printk(KERN_DEBUG "CPN: Octect 3 %02x\n", skb->data[1]); -#endif - if ((skb->data[1] & 0x80) == 0) - count = 2; - - if (!(info->data.setup.CallingPN = kmalloc(len - count + 1, GFP_ATOMIC))) - return -1; - - skb_copy_from_linear_data_offset(skb, count + 1, - info->data.setup.CallingPN, - len - count); - info->data.setup.CallingPN[len - count] = 0; - - } - else { - info->data.setup.CallingPN = NULL; - printk(KERN_DEBUG "NULL CallingPN\n"); - } - - skb_pull(skb, len + 1); - - /* Calling Party Subaddress */ - skb_pull(skb, skb->data[0] + 1); - - /* Called Party Number */ - - len = skb->data[0]; - - if (len > 0) { - int count = 1; - - if ((skb->data[1] & 0x80) == 0) - count = 2; - - if (!(info->data.setup.CalledPN = kmalloc(len - count + 1, GFP_ATOMIC))) - return -1; - - skb_copy_from_linear_data_offset(skb, count + 1, - info->data.setup.CalledPN, - len - count); - info->data.setup.CalledPN[len - count] = 0; - - } - else { - info->data.setup.CalledPN = NULL; - printk(KERN_DEBUG "NULL CalledPN\n"); - } - - skb_pull(skb, len + 1); - - /* Called Party Subaddress */ - skb_pull(skb, skb->data[0] + 1); - - /* LLC */ - skb_pull(skb, skb->data[0] + 1); - - /* HLC */ - skb_pull(skb, skb->data[0] + 1); - - /* U2U */ - skb_pull(skb, skb->data[0] + 1); - - return 0; -} - -/* - * returns errcode - */ - -int capi_decode_conn_conf(struct pcbit_chan *chan, struct sk_buff *skb, - int *complete) -{ - int errcode; - - chan->callref = *((ushort *)skb->data); /* Update CallReference */ - skb_pull(skb, 2); - - errcode = *((ushort *) skb->data); /* read errcode */ - skb_pull(skb, 2); - - *complete = *(skb->data); - skb_pull(skb, 1); - - /* FIX ME */ - /* This is actually a firmware bug */ - if (!*complete) - { - printk(KERN_DEBUG "complete=%02x\n", *complete); - *complete = 1; - } - - - /* Optional Bearer Capability */ - skb_pull(skb, *(skb->data) + 1); - - /* Channel Identification */ - skb_pull(skb, *(skb->data) + 1); - - /* High Layer Compatibility follows */ - skb_pull(skb, *(skb->data) + 1); - - return errcode; -} - -int capi_decode_conn_actv_ind(struct pcbit_chan *chan, struct sk_buff *skb) -{ - ushort len; -#ifdef DEBUG - char str[32]; -#endif - - /* Yet Another Bearer Capability */ - skb_pull(skb, *(skb->data) + 1); - - - /* Connected Party Number */ - len = *(skb->data); - -#ifdef DEBUG - if (len > 1 && len < 31) { - skb_copy_from_linear_data_offset(skb, 2, str, len - 1); - str[len] = 0; - printk(KERN_DEBUG "Connected Party Number: %s\n", str); - } - else - printk(KERN_DEBUG "actv_ind CPN len = %d\n", len); -#endif - - skb_pull(skb, len + 1); - - /* Connected Subaddress */ - skb_pull(skb, *(skb->data) + 1); - - /* Low Layer Capability */ - skb_pull(skb, *(skb->data) + 1); - - /* High Layer Capability */ - skb_pull(skb, *(skb->data) + 1); - - return 0; -} - -int capi_decode_conn_actv_conf(struct pcbit_chan *chan, struct sk_buff *skb) -{ - ushort errcode; - - errcode = *((ushort *)skb->data); - skb_pull(skb, 2); - - /* Channel Identification - skb_pull(skb, skb->data[0] + 1); - */ - return errcode; -} - - -int capi_decode_sel_proto_conf(struct pcbit_chan *chan, struct sk_buff *skb) -{ - ushort errcode; - - chan->layer2link = *(skb->data); - skb_pull(skb, 1); - - errcode = *((ushort *)skb->data); - skb_pull(skb, 2); - - return errcode; -} - -int capi_decode_actv_trans_conf(struct pcbit_chan *chan, struct sk_buff *skb) -{ - ushort errcode; - - if (chan->layer2link != *(skb->data)) - printk("capi_decode_actv_trans_conf: layer2link doesn't match\n"); - - skb_pull(skb, 1); - - errcode = *((ushort *)skb->data); - skb_pull(skb, 2); - - return errcode; -} - -int capi_decode_disc_ind(struct pcbit_chan *chan, struct sk_buff *skb) -{ - ushort len; -#ifdef DEBUG - int i; -#endif - /* Cause */ - - len = *(skb->data); - skb_pull(skb, 1); - -#ifdef DEBUG - - for (i = 0; i < len; i++) - printk(KERN_DEBUG "Cause Octect %d: %02x\n", i + 3, - *(skb->data + i)); -#endif - - skb_pull(skb, len); - - return 0; -} - -#ifdef DEBUG -int capi_decode_debug_188(u_char *hdr, ushort hdrlen) -{ - char str[64]; - int len; - - len = hdr[0]; - - if (len < 64 && len == hdrlen - 1) { - memcpy(str, hdr + 1, hdrlen - 1); - str[hdrlen - 1] = 0; - printk("%s\n", str); - } - else - printk("debug message incorrect\n"); - - return 0; -} -#endif diff --git a/drivers/isdn/pcbit/capi.h b/drivers/isdn/pcbit/capi.h deleted file mode 100644 index 635f63476944..000000000000 --- a/drivers/isdn/pcbit/capi.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * CAPI encode/decode prototypes and defines - * - * Copyright (C) 1996 Universidade de Lisboa - * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) - * - * This software may be used and distributed according to the terms of - * the GNU General Public License, incorporated herein by reference. - */ - -#ifndef CAPI_H -#define CAPI_H - - -#define REQ_CAUSE 0x01 -#define REQ_DISPLAY 0x04 -#define REQ_USER_TO_USER 0x08 - -#define AppInfoMask REQ_CAUSE | REQ_DISPLAY | REQ_USER_TO_USER - -/* Connection Setup */ -extern int capi_conn_req(const char *calledPN, struct sk_buff **buf, - int proto); -extern int capi_decode_conn_conf(struct pcbit_chan *chan, struct sk_buff *skb, - int *complete); - -extern int capi_decode_conn_ind(struct pcbit_chan *chan, struct sk_buff *skb, - struct callb_data *info); -extern int capi_conn_resp(struct pcbit_chan *chan, struct sk_buff **skb); - -extern int capi_conn_active_req(struct pcbit_chan *chan, struct sk_buff **skb); -extern int capi_decode_conn_actv_conf(struct pcbit_chan *chan, - struct sk_buff *skb); - -extern int capi_decode_conn_actv_ind(struct pcbit_chan *chan, - struct sk_buff *skb); -extern int capi_conn_active_resp(struct pcbit_chan *chan, - struct sk_buff **skb); - -/* Data */ -extern int capi_select_proto_req(struct pcbit_chan *chan, struct sk_buff **skb, - int outgoing); -extern int capi_decode_sel_proto_conf(struct pcbit_chan *chan, - struct sk_buff *skb); - -extern int capi_activate_transp_req(struct pcbit_chan *chan, - struct sk_buff **skb); -extern int capi_decode_actv_trans_conf(struct pcbit_chan *chan, - struct sk_buff *skb); - -extern int capi_tdata_req(struct pcbit_chan *chan, struct sk_buff *skb); -extern int capi_tdata_resp(struct pcbit_chan *chan, struct sk_buff **skb); - -/* Connection Termination */ -extern int capi_disc_req(ushort callref, struct sk_buff **skb, u_char cause); - -extern int capi_decode_disc_ind(struct pcbit_chan *chan, struct sk_buff *skb); -extern int capi_disc_resp(struct pcbit_chan *chan, struct sk_buff **skb); - -#ifdef DEBUG -extern int capi_decode_debug_188(u_char *hdr, ushort hdrlen); -#endif - -static inline struct pcbit_chan * -capi_channel(struct pcbit_dev *dev, struct sk_buff *skb) -{ - ushort callref; - - callref = *((ushort *)skb->data); - skb_pull(skb, 2); - - if (dev->b1->callref == callref) - return dev->b1; - else if (dev->b2->callref == callref) - return dev->b2; - - return NULL; -} - -#endif diff --git a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c deleted file mode 100644 index 4172e22ae7ed..000000000000 --- a/drivers/isdn/pcbit/drv.c +++ /dev/null @@ -1,1077 +0,0 @@ -/* - * PCBIT-D interface with isdn4linux - * - * Copyright (C) 1996 Universidade de Lisboa - * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) - * - * This software may be used and distributed according to the terms of - * the GNU General Public License, incorporated herein by reference. - */ - -/* - * Fixes: - * - * Nuno Grilo <l38486@alfa.ist.utl.pt> - * fixed msn_list NULL pointer dereference. - * - */ - -#include <linux/module.h> - - -#include <linux/kernel.h> - -#include <linux/types.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/string.h> -#include <linux/skbuff.h> - -#include <linux/isdnif.h> -#include <asm/string.h> -#include <asm/io.h> -#include <linux/ioport.h> - -#include "pcbit.h" -#include "edss1.h" -#include "layer2.h" -#include "capi.h" - - -extern ushort last_ref_num; - -static int pcbit_ioctl(isdn_ctrl *ctl); - -static char *pcbit_devname[MAX_PCBIT_CARDS] = { - "pcbit0", - "pcbit1", - "pcbit2", - "pcbit3" -}; - -/* - * prototypes - */ - -static int pcbit_command(isdn_ctrl *ctl); -static int pcbit_stat(u_char __user *buf, int len, int, int); -static int pcbit_xmit(int driver, int chan, int ack, struct sk_buff *skb); -static int pcbit_writecmd(const u_char __user *, int, int, int); - -static int set_protocol_running(struct pcbit_dev *dev); - -static void pcbit_clear_msn(struct pcbit_dev *dev); -static void pcbit_set_msn(struct pcbit_dev *dev, char *list); -static int pcbit_check_msn(struct pcbit_dev *dev, char *msn); - - -int pcbit_init_dev(int board, int mem_base, int irq) -{ - struct pcbit_dev *dev; - isdn_if *dev_if; - - if ((dev = kzalloc(sizeof(struct pcbit_dev), GFP_KERNEL)) == NULL) - { - printk("pcbit_init: couldn't malloc pcbit_dev struct\n"); - return -ENOMEM; - } - - dev_pcbit[board] = dev; - init_waitqueue_head(&dev->set_running_wq); - spin_lock_init(&dev->lock); - - if (mem_base >= 0xA0000 && mem_base <= 0xFFFFF) { - dev->ph_mem = mem_base; - if (!request_mem_region(dev->ph_mem, 4096, "PCBIT mem")) { - printk(KERN_WARNING - "PCBIT: memory region %lx-%lx already in use\n", - dev->ph_mem, dev->ph_mem + 4096); - kfree(dev); - dev_pcbit[board] = NULL; - return -EACCES; - } - dev->sh_mem = ioremap(dev->ph_mem, 4096); - } - else - { - printk("memory address invalid"); - kfree(dev); - dev_pcbit[board] = NULL; - return -EACCES; - } - - dev->b1 = kzalloc(sizeof(struct pcbit_chan), GFP_KERNEL); - if (!dev->b1) { - printk("pcbit_init: couldn't malloc pcbit_chan struct\n"); - iounmap(dev->sh_mem); - release_mem_region(dev->ph_mem, 4096); - kfree(dev); - return -ENOMEM; - } - - dev->b2 = kzalloc(sizeof(struct pcbit_chan), GFP_KERNEL); - if (!dev->b2) { - printk("pcbit_init: couldn't malloc pcbit_chan struct\n"); - kfree(dev->b1); - iounmap(dev->sh_mem); - release_mem_region(dev->ph_mem, 4096); - kfree(dev); - return -ENOMEM; - } - - dev->b2->id = 1; - - INIT_WORK(&dev->qdelivery, pcbit_deliver); - - /* - * interrupts - */ - - if (request_irq(irq, &pcbit_irq_handler, 0, pcbit_devname[board], dev) != 0) - { - kfree(dev->b1); - kfree(dev->b2); - iounmap(dev->sh_mem); - release_mem_region(dev->ph_mem, 4096); - kfree(dev); - dev_pcbit[board] = NULL; - return -EIO; - } - - dev->irq = irq; - - /* next frame to be received */ - dev->rcv_seq = 0; - dev->send_seq = 0; - dev->unack_seq = 0; - - dev->hl_hdrlen = 16; - - dev_if = kmalloc(sizeof(isdn_if), GFP_KERNEL); - - if (!dev_if) { - free_irq(irq, dev); - kfree(dev->b1); - kfree(dev->b2); - iounmap(dev->sh_mem); - release_mem_region(dev->ph_mem, 4096); - kfree(dev); - dev_pcbit[board] = NULL; - return -EIO; - } - - dev->dev_if = dev_if; - - dev_if->owner = THIS_MODULE; - - dev_if->channels = 2; - - dev_if->features = (ISDN_FEATURE_P_EURO | ISDN_FEATURE_L3_TRANS | - ISDN_FEATURE_L2_HDLC | ISDN_FEATURE_L2_TRANS); - - dev_if->writebuf_skb = pcbit_xmit; - dev_if->hl_hdrlen = 16; - - dev_if->maxbufsize = MAXBUFSIZE; - dev_if->command = pcbit_command; - - dev_if->writecmd = pcbit_writecmd; - dev_if->readstat = pcbit_stat; - - - strcpy(dev_if->id, pcbit_devname[board]); - - if (!register_isdn(dev_if)) { - free_irq(irq, dev); - kfree(dev->b1); - kfree(dev->b2); - iounmap(dev->sh_mem); - release_mem_region(dev->ph_mem, 4096); - kfree(dev); - dev_pcbit[board] = NULL; - return -EIO; - } - - dev->id = dev_if->channels; - - - dev->l2_state = L2_DOWN; - dev->free = 511; - - /* - * set_protocol_running(dev); - */ - - return 0; -} - -#ifdef MODULE -void pcbit_terminate(int board) -{ - struct pcbit_dev *dev; - - dev = dev_pcbit[board]; - - if (dev) { - /* unregister_isdn(dev->dev_if); */ - free_irq(dev->irq, dev); - pcbit_clear_msn(dev); - kfree(dev->dev_if); - if (dev->b1->fsm_timer.function) - del_timer(&dev->b1->fsm_timer); - if (dev->b2->fsm_timer.function) - del_timer(&dev->b2->fsm_timer); - kfree(dev->b1); - kfree(dev->b2); - iounmap(dev->sh_mem); - release_mem_region(dev->ph_mem, 4096); - kfree(dev); - } -} -#endif - -static int pcbit_command(isdn_ctrl *ctl) -{ - struct pcbit_dev *dev; - struct pcbit_chan *chan; - struct callb_data info; - - dev = finddev(ctl->driver); - - if (!dev) - { - printk("pcbit_command: unknown device\n"); - return -1; - } - - chan = (ctl->arg & 0x0F) ? dev->b2 : dev->b1; - - - switch (ctl->command) { - case ISDN_CMD_IOCTL: - return pcbit_ioctl(ctl); - break; - case ISDN_CMD_DIAL: - info.type = EV_USR_SETUP_REQ; - info.data.setup.CalledPN = (char *) &ctl->parm.setup.phone; - pcbit_fsm_event(dev, chan, EV_USR_SETUP_REQ, &info); - break; - case ISDN_CMD_ACCEPTD: - pcbit_fsm_event(dev, chan, EV_USR_SETUP_RESP, NULL); - break; - case ISDN_CMD_ACCEPTB: - printk("ISDN_CMD_ACCEPTB - not really needed\n"); - break; - case ISDN_CMD_HANGUP: - pcbit_fsm_event(dev, chan, EV_USR_RELEASE_REQ, NULL); - break; - case ISDN_CMD_SETL2: - chan->proto = (ctl->arg >> 8); - break; - case ISDN_CMD_CLREAZ: - pcbit_clear_msn(dev); - break; - case ISDN_CMD_SETEAZ: - pcbit_set_msn(dev, ctl->parm.num); - break; - case ISDN_CMD_SETL3: - if ((ctl->arg >> 8) != ISDN_PROTO_L3_TRANS) - printk(KERN_DEBUG "L3 protocol unknown\n"); - break; - default: - printk(KERN_DEBUG "pcbit_command: unknown command\n"); - break; - }; - - return 0; -} - -/* - * Another Hack :-( - * on some conditions the board stops sending TDATA_CONFs - * let's see if we can turn around the problem - */ - -#ifdef BLOCK_TIMER -static void pcbit_block_timer(unsigned long data) -{ - struct pcbit_chan *chan; - struct pcbit_dev *dev; - isdn_ctrl ictl; - - chan = (struct pcbit_chan *)data; - - dev = chan2dev(chan); - - if (dev == NULL) { - printk(KERN_DEBUG "pcbit: chan2dev failed\n"); - return; - } - - del_timer(&chan->block_timer); - chan->block_timer.function = NULL; - -#ifdef DEBUG - printk(KERN_DEBUG "pcbit_block_timer\n"); -#endif - chan->queued = 0; - ictl.driver = dev->id; - ictl.command = ISDN_STAT_BSENT; - ictl.arg = chan->id; - dev->dev_if->statcallb(&ictl); -} -#endif - -static int pcbit_xmit(int driver, int chnum, int ack, struct sk_buff *skb) -{ - ushort hdrlen; - int refnum, len; - struct pcbit_chan *chan; - struct pcbit_dev *dev; - - dev = finddev(driver); - if (dev == NULL) - { - printk("finddev returned NULL"); - return -1; - } - - chan = chnum ? dev->b2 : dev->b1; - - - if (chan->fsm_state != ST_ACTIVE) - return -1; - - if (chan->queued >= MAX_QUEUED) - { -#ifdef DEBUG_QUEUE - printk(KERN_DEBUG - "pcbit: %d packets already in queue - write fails\n", - chan->queued); -#endif - /* - * packet stays on the head of the device queue - * since dev_start_xmit will fail - * see net/core/dev.c - */ -#ifdef BLOCK_TIMER - if (chan->block_timer.function == NULL) { - init_timer(&chan->block_timer); - chan->block_timer.function = &pcbit_block_timer; - chan->block_timer.data = (long) chan; - chan->block_timer.expires = jiffies + 1 * HZ; - add_timer(&chan->block_timer); - } -#endif - return 0; - } - - - chan->queued++; - - len = skb->len; - - hdrlen = capi_tdata_req(chan, skb); - - refnum = last_ref_num++ & 0x7fffU; - chan->s_refnum = refnum; - - pcbit_l2_write(dev, MSG_TDATA_REQ, refnum, skb, hdrlen); - - return len; -} - -static int pcbit_writecmd(const u_char __user *buf, int len, int driver, int channel) -{ - struct pcbit_dev *dev; - int i, j; - const u_char *loadbuf; - u_char *ptr = NULL; - u_char *cbuf; - - int errstat; - - dev = finddev(driver); - - if (!dev) - { - printk("pcbit_writecmd: couldn't find device"); - return -ENODEV; - } - - switch (dev->l2_state) { - case L2_LWMODE: - /* check (size <= rdp_size); write buf into board */ - if (len < 0 || len > BANK4 + 1 || len > 1024) - { - printk("pcbit_writecmd: invalid length %d\n", len); - return -EINVAL; - } - - cbuf = memdup_user(buf, len); - if (IS_ERR(cbuf)) - return PTR_ERR(cbuf); - - memcpy_toio(dev->sh_mem, cbuf, len); - kfree(cbuf); - return len; - case L2_FWMODE: - /* this is the hard part */ - /* dumb board */ - /* get it into kernel space */ - if ((ptr = kmalloc(len, GFP_KERNEL)) == NULL) - return -ENOMEM; - if (copy_from_user(ptr, buf, len)) { - kfree(ptr); - return -EFAULT; - } - loadbuf = ptr; - - errstat = 0; - - for (i = 0; i < len; i++) - { - for (j = 0; j < LOAD_RETRY; j++) - if (!(readb(dev->sh_mem + dev->loadptr))) - break; - - if (j == LOAD_RETRY) - { - errstat = -ETIME; - printk("TIMEOUT i=%d\n", i); - break; - } - writeb(loadbuf[i], dev->sh_mem + dev->loadptr + 1); - writeb(0x01, dev->sh_mem + dev->loadptr); - - dev->loadptr += 2; - if (dev->loadptr > LOAD_ZONE_END) - dev->loadptr = LOAD_ZONE_START; - } - kfree(ptr); - - return errstat ? errstat : len; - default: - return -EBUSY; - } -} - -/* - * demultiplexing of messages - * - */ - -void pcbit_l3_receive(struct pcbit_dev *dev, ulong msg, - struct sk_buff *skb, - ushort hdr_len, ushort refnum) -{ - struct pcbit_chan *chan; - struct sk_buff *skb2; - unsigned short len; - struct callb_data cbdata; - int complete, err; - isdn_ctrl ictl; - - switch (msg) { - - case MSG_TDATA_IND: - if (!(chan = capi_channel(dev, skb))) { - printk(KERN_WARNING - "CAPI header: unknown channel id\n"); - break; - } - chan->r_refnum = skb->data[7]; - skb_pull(skb, 8); - - dev->dev_if->rcvcallb_skb(dev->id, chan->id, skb); - - if (capi_tdata_resp(chan, &skb2) > 0) - pcbit_l2_write(dev, MSG_TDATA_RESP, refnum, - skb2, skb2->len); - return; - break; - case MSG_TDATA_CONF: - if (!(chan = capi_channel(dev, skb))) { - printk(KERN_WARNING - "CAPI header: unknown channel id\n"); - break; - } - -#ifdef DEBUG - if ((*((ushort *)(skb->data + 2))) != 0) { - printk(KERN_DEBUG "TDATA_CONF error\n"); - } -#endif -#ifdef BLOCK_TIMER - if (chan->queued == MAX_QUEUED) { - del_timer(&chan->block_timer); - chan->block_timer.function = NULL; - } - -#endif - chan->queued--; - - ictl.driver = dev->id; - ictl.command = ISDN_STAT_BSENT; - ictl.arg = chan->id; - dev->dev_if->statcallb(&ictl); - break; - - case MSG_CONN_IND: - /* - * channel: 1st not used will do - * if both are used we're in trouble - */ - - if (!dev->b1->fsm_state) - chan = dev->b1; - else if (!dev->b2->fsm_state) - chan = dev->b2; - else { - printk(KERN_INFO - "Incoming connection: no channels available"); - - if ((len = capi_disc_req(*(ushort *)(skb->data), &skb2, CAUSE_NOCHAN)) > 0) - pcbit_l2_write(dev, MSG_DISC_REQ, refnum, skb2, len); - break; - } - - cbdata.data.setup.CalledPN = NULL; - cbdata.data.setup.CallingPN = NULL; - - capi_decode_conn_ind(chan, skb, &cbdata); - cbdata.type = EV_NET_SETUP; - - pcbit_fsm_event(dev, chan, EV_NET_SETUP, NULL); - - if (pcbit_check_msn(dev, cbdata.data.setup.CallingPN)) - pcbit_fsm_event(dev, chan, EV_USR_PROCED_REQ, &cbdata); - else - pcbit_fsm_event(dev, chan, EV_USR_RELEASE_REQ, NULL); - - kfree(cbdata.data.setup.CalledPN); - kfree(cbdata.data.setup.CallingPN); - break; - - case MSG_CONN_CONF: - /* - * We should be able to find the channel by the message - * reference number. The current version of the firmware - * doesn't sent the ref number correctly. - */ -#ifdef DEBUG - printk(KERN_DEBUG "refnum=%04x b1=%04x b2=%04x\n", refnum, - dev->b1->s_refnum, - dev->b2->s_refnum); -#endif - /* We just try to find a channel in the right state */ - - if (dev->b1->fsm_state == ST_CALL_INIT) - chan = dev->b1; - else { - if (dev->b2->s_refnum == ST_CALL_INIT) - chan = dev->b2; - else { - chan = NULL; - printk(KERN_WARNING "Connection Confirm - no channel in Call Init state\n"); - break; - } - } - if (capi_decode_conn_conf(chan, skb, &complete)) { - printk(KERN_DEBUG "conn_conf indicates error\n"); - pcbit_fsm_event(dev, chan, EV_ERROR, NULL); - } - else - if (complete) - pcbit_fsm_event(dev, chan, EV_NET_CALL_PROC, NULL); - else - pcbit_fsm_event(dev, chan, EV_NET_SETUP_ACK, NULL); - break; - case MSG_CONN_ACTV_IND: - - if (!(chan = capi_channel(dev, skb))) { - printk(KERN_WARNING - "CAPI header: unknown channel id\n"); - break; - } - - if (capi_decode_conn_actv_ind(chan, skb)) { - printk("error in capi_decode_conn_actv_ind\n"); - /* pcbit_fsm_event(dev, chan, EV_ERROR, NULL); */ - break; - } - chan->r_refnum = refnum; - pcbit_fsm_event(dev, chan, EV_NET_CONN, NULL); - break; - case MSG_CONN_ACTV_CONF: - - if (!(chan = capi_channel(dev, skb))) { - printk(KERN_WARNING - "CAPI header: unknown channel id\n"); - break; - } - - if (capi_decode_conn_actv_conf(chan, skb) == 0) - pcbit_fsm_event(dev, chan, EV_NET_CONN_ACK, NULL); - - else - printk(KERN_DEBUG "decode_conn_actv_conf failed\n"); - break; - - case MSG_SELP_CONF: - - if (!(chan = capi_channel(dev, skb))) { - printk(KERN_WARNING - "CAPI header: unknown channel id\n"); - break; - } - - if (!(err = capi_decode_sel_proto_conf(chan, skb))) - pcbit_fsm_event(dev, chan, EV_NET_SELP_RESP, NULL); - else { - /* Error */ - printk("error %d - capi_decode_sel_proto_conf\n", err); - } - break; - case MSG_ACT_TRANSP_CONF: - if (!(chan = capi_channel(dev, skb))) { - printk(KERN_WARNING - "CAPI header: unknown channel id\n"); - break; - } - - if (!capi_decode_actv_trans_conf(chan, skb)) - pcbit_fsm_event(dev, chan, EV_NET_ACTV_RESP, NULL); - break; - - case MSG_DISC_IND: - - if (!(chan = capi_channel(dev, skb))) { - printk(KERN_WARNING - "CAPI header: unknown channel id\n"); - break; - } - - if (!capi_decode_disc_ind(chan, skb)) - pcbit_fsm_event(dev, chan, EV_NET_DISC, NULL); - else - printk(KERN_WARNING "capi_decode_disc_ind - error\n"); - break; - case MSG_DISC_CONF: - if (!(chan = capi_channel(dev, skb))) { - printk(KERN_WARNING - "CAPI header: unknown channel id\n"); - break; - } - - if (!capi_decode_disc_ind(chan, skb)) - pcbit_fsm_event(dev, chan, EV_NET_RELEASE, NULL); - else - printk(KERN_WARNING "capi_decode_disc_conf - error\n"); - break; - case MSG_INFO_IND: -#ifdef DEBUG - printk(KERN_DEBUG "received Info Indication - discarded\n"); -#endif - break; -#ifdef DEBUG - case MSG_DEBUG_188: - capi_decode_debug_188(skb->data, skb->len); - break; - - default: - printk(KERN_DEBUG "pcbit_l3_receive: unknown message %08lx\n", - msg); - break; -#endif - } - - kfree_skb(skb); - -} - -/* - * Single statbuf - * should be a statbuf per device - */ - -static char statbuf[STATBUF_LEN]; -static int stat_st = 0; -static int stat_end = 0; - -static int pcbit_stat(u_char __user *buf, int len, int driver, int channel) -{ - int stat_count; - stat_count = stat_end - stat_st; - - if (stat_count < 0) - stat_count = STATBUF_LEN - stat_st + stat_end; - - /* FIXME: should we sleep and wait for more cookies ? */ - if (len > stat_count) - len = stat_count; - - if (stat_st < stat_end) - { - if (copy_to_user(buf, statbuf + stat_st, len)) - return -EFAULT; - stat_st += len; - } - else - { - if (len > STATBUF_LEN - stat_st) - { - if (copy_to_user(buf, statbuf + stat_st, - STATBUF_LEN - stat_st)) - return -EFAULT; - if (copy_to_user(buf, statbuf, - len - (STATBUF_LEN - stat_st))) - return -EFAULT; - - stat_st = len - (STATBUF_LEN - stat_st); - } - else - { - if (copy_to_user(buf, statbuf + stat_st, len)) - return -EFAULT; - - stat_st += len; - - if (stat_st == STATBUF_LEN) - stat_st = 0; - } - } - - if (stat_st == stat_end) - stat_st = stat_end = 0; - - return len; -} - -static void pcbit_logstat(struct pcbit_dev *dev, char *str) -{ - int i; - isdn_ctrl ictl; - - for (i = stat_end; i < strlen(str); i++) - { - statbuf[i] = str[i]; - stat_end = (stat_end + 1) % STATBUF_LEN; - if (stat_end == stat_st) - stat_st = (stat_st + 1) % STATBUF_LEN; - } - - ictl.command = ISDN_STAT_STAVAIL; - ictl.driver = dev->id; - ictl.arg = strlen(str); - dev->dev_if->statcallb(&ictl); -} - -void pcbit_state_change(struct pcbit_dev *dev, struct pcbit_chan *chan, - unsigned short i, unsigned short ev, unsigned short f) -{ - char buf[256]; - - sprintf(buf, "change on device: %d channel:%d\n%s -> %s -> %s\n", - dev->id, chan->id, - isdn_state_table[i], strisdnevent(ev), isdn_state_table[f] - ); - -#ifdef DEBUG - printk("%s", buf); -#endif - - pcbit_logstat(dev, buf); -} - -static void set_running_timeout(unsigned long ptr) -{ - struct pcbit_dev *dev; - -#ifdef DEBUG - printk(KERN_DEBUG "set_running_timeout\n"); -#endif - dev = (struct pcbit_dev *) ptr; - - dev->l2_state = L2_DOWN; - wake_up_interruptible(&dev->set_running_wq); -} - -static int set_protocol_running(struct pcbit_dev *dev) -{ - isdn_ctrl ctl; - - init_timer(&dev->set_running_timer); - - dev->set_running_timer.function = &set_running_timeout; - dev->set_running_timer.data = (ulong) dev; - dev->set_running_timer.expires = jiffies + SET_RUN_TIMEOUT; - - /* kick it */ - - dev->l2_state = L2_STARTING; - - writeb((0x80U | ((dev->rcv_seq & 0x07) << 3) | (dev->send_seq & 0x07)), - dev->sh_mem + BANK4); - - add_timer(&dev->set_running_timer); - - wait_event(dev->set_running_wq, dev->l2_state == L2_RUNNING || - dev->l2_state == L2_DOWN); - - del_timer(&dev->set_running_timer); - - if (dev->l2_state == L2_RUNNING) - { - printk(KERN_DEBUG "pcbit: running\n"); - - dev->unack_seq = dev->send_seq; - - dev->writeptr = dev->sh_mem; - dev->readptr = dev->sh_mem + BANK2; - - /* tell the good news to the upper layer */ - ctl.driver = dev->id; - ctl.command = ISDN_STAT_RUN; - - dev->dev_if->statcallb(&ctl); - } - else - { - printk(KERN_DEBUG "pcbit: initialization failed\n"); - printk(KERN_DEBUG "pcbit: firmware not loaded\n"); - -#ifdef DEBUG - printk(KERN_DEBUG "Bank3 = %02x\n", - readb(dev->sh_mem + BANK3)); -#endif - writeb(0x40, dev->sh_mem + BANK4); - - /* warn the upper layer */ - ctl.driver = dev->id; - ctl.command = ISDN_STAT_STOP; - - dev->dev_if->statcallb(&ctl); - - return -EL2HLT; /* Level 2 halted */ - } - - return 0; -} - -static int pcbit_ioctl(isdn_ctrl *ctl) -{ - struct pcbit_dev *dev; - struct pcbit_ioctl *cmd; - - dev = finddev(ctl->driver); - - if (!dev) - { - printk(KERN_DEBUG "pcbit_ioctl: unknown device\n"); - return -ENODEV; - } - - cmd = (struct pcbit_ioctl *) ctl->parm.num; - - switch (ctl->arg) { - case PCBIT_IOCTL_GETSTAT: - cmd->info.l2_status = dev->l2_state; - break; - - case PCBIT_IOCTL_STRLOAD: - if (dev->l2_state == L2_RUNNING) - return -EBUSY; - - dev->unack_seq = dev->send_seq = dev->rcv_seq = 0; - - dev->writeptr = dev->sh_mem; - dev->readptr = dev->sh_mem + BANK2; - - dev->l2_state = L2_LOADING; - break; - - case PCBIT_IOCTL_LWMODE: - if (dev->l2_state != L2_LOADING) - return -EINVAL; - - dev->l2_state = L2_LWMODE; - break; - - case PCBIT_IOCTL_FWMODE: - if (dev->l2_state == L2_RUNNING) - return -EBUSY; - dev->loadptr = LOAD_ZONE_START; - dev->l2_state = L2_FWMODE; - - break; - case PCBIT_IOCTL_ENDLOAD: - if (dev->l2_state == L2_RUNNING) - return -EBUSY; - dev->l2_state = L2_DOWN; - break; - - case PCBIT_IOCTL_SETBYTE: - if (dev->l2_state == L2_RUNNING) - return -EBUSY; - - /* check addr */ - if (cmd->info.rdp_byte.addr > BANK4) - return -EFAULT; - - writeb(cmd->info.rdp_byte.value, dev->sh_mem + cmd->info.rdp_byte.addr); - break; - case PCBIT_IOCTL_GETBYTE: - if (dev->l2_state == L2_RUNNING) - return -EBUSY; - - /* check addr */ - - if (cmd->info.rdp_byte.addr > BANK4) - { - printk("getbyte: invalid addr %04x\n", cmd->info.rdp_byte.addr); - return -EFAULT; - } - - cmd->info.rdp_byte.value = readb(dev->sh_mem + cmd->info.rdp_byte.addr); - break; - case PCBIT_IOCTL_RUNNING: - if (dev->l2_state == L2_RUNNING) - return -EBUSY; - return set_protocol_running(dev); - break; - case PCBIT_IOCTL_WATCH188: - if (dev->l2_state != L2_LOADING) - return -EINVAL; - pcbit_l2_write(dev, MSG_WATCH188, 0x0001, NULL, 0); - break; - case PCBIT_IOCTL_PING188: - if (dev->l2_state != L2_LOADING) - return -EINVAL; - pcbit_l2_write(dev, MSG_PING188_REQ, 0x0001, NULL, 0); - break; - case PCBIT_IOCTL_APION: - if (dev->l2_state != L2_LOADING) - return -EINVAL; - pcbit_l2_write(dev, MSG_API_ON, 0x0001, NULL, 0); - break; - case PCBIT_IOCTL_STOP: - dev->l2_state = L2_DOWN; - writeb(0x40, dev->sh_mem + BANK4); - dev->rcv_seq = 0; - dev->send_seq = 0; - dev->unack_seq = 0; - break; - default: - printk("error: unknown ioctl\n"); - break; - }; - return 0; -} - -/* - * MSN list handling - * - * if null reject all calls - * if first entry has null MSN accept all calls - */ - -static void pcbit_clear_msn(struct pcbit_dev *dev) -{ - struct msn_entry *ptr, *back; - - for (ptr = dev->msn_list; ptr;) - { - back = ptr->next; - kfree(ptr); - ptr = back; - } - - dev->msn_list = NULL; -} - -static void pcbit_set_msn(struct pcbit_dev *dev, char *list) -{ - struct msn_entry *ptr; - struct msn_entry *back = NULL; - char *cp, *sp; - int len; - - if (strlen(list) == 0) { - ptr = kmalloc(sizeof(struct msn_entry), GFP_ATOMIC); - if (!ptr) { - printk(KERN_WARNING "kmalloc failed\n"); - return; - } - - ptr->msn = NULL; - - ptr->next = dev->msn_list; - dev->msn_list = ptr; - - return; - } - - if (dev->msn_list) - for (back = dev->msn_list; back->next; back = back->next); - - sp = list; - - do { - cp = strchr(sp, ','); - if (cp) - len = cp - sp; - else - len = strlen(sp); - - ptr = kmalloc(sizeof(struct msn_entry), GFP_ATOMIC); - - if (!ptr) { - printk(KERN_WARNING "kmalloc failed\n"); - return; - } - ptr->next = NULL; - - ptr->msn = kmalloc(len + 1, GFP_ATOMIC); - if (!ptr->msn) { - printk(KERN_WARNING "kmalloc failed\n"); - kfree(ptr); - return; - } - - memcpy(ptr->msn, sp, len); - ptr->msn[len] = 0; - -#ifdef DEBUG - printk(KERN_DEBUG "msn: %s\n", ptr->msn); -#endif - if (dev->msn_list == NULL) - dev->msn_list = ptr; - else - back->next = ptr; - back = ptr; - sp += len; - } while (cp); -} - -/* - * check if we do signal or reject an incoming call - */ -static int pcbit_check_msn(struct pcbit_dev *dev, char *msn) -{ - struct msn_entry *ptr; - - for (ptr = dev->msn_list; ptr; ptr = ptr->next) { - - if (ptr->msn == NULL) - return 1; - - if (strcmp(ptr->msn, msn) == 0) - return 1; - } - - return 0; -} diff --git a/drivers/isdn/pcbit/edss1.c b/drivers/isdn/pcbit/edss1.c deleted file mode 100644 index b2262ba6f0c9..000000000000 --- a/drivers/isdn/pcbit/edss1.c +++ /dev/null @@ -1,313 +0,0 @@ -/* - * DSS.1 Finite State Machine - * base: ITU-T Rec Q.931 - * - * Copyright (C) 1996 Universidade de Lisboa - * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) - * - * This software may be used and distributed according to the terms of - * the GNU General Public License, incorporated herein by reference. - */ - -/* - * TODO: complete the FSM - * move state/event descriptions to a user space logger - */ - -#include <linux/string.h> -#include <linux/kernel.h> - -#include <linux/types.h> -#include <linux/mm.h> -#include <linux/skbuff.h> - -#include <linux/timer.h> -#include <asm/io.h> - -#include <linux/isdnif.h> - -#include "pcbit.h" -#include "edss1.h" -#include "layer2.h" -#include "callbacks.h" - - -const char * const isdn_state_table[] = { - "Closed", - "Call initiated", - "Overlap sending", - "Outgoing call proceeding", - "NOT DEFINED", - "Call delivered", - "Call present", - "Call received", - "Connect request", - "Incoming call proceeding", - "Active", - "Disconnect request", - "Disconnect indication", - "NOT DEFINED", - "NOT DEFINED", - "Suspend request", - "NOT DEFINED", - "Resume request", - "NOT DEFINED", - "Release Request", - "NOT DEFINED", - "NOT DEFINED", - "NOT DEFINED", - "NOT DEFINED", - "NOT DEFINED", - "Overlap receiving", - "Select protocol on B-Channel", - "Activate B-channel protocol" -}; - -#ifdef DEBUG_ERRS -static -struct CauseValue { - byte nr; - char *descr; -} cvlist[] = { - {0x01, "Unallocated (unassigned) number"}, - {0x02, "No route to specified transit network"}, - {0x03, "No route to destination"}, - {0x04, "Send special information tone"}, - {0x05, "Misdialled trunk prefix"}, - {0x06, "Channel unacceptable"}, - {0x07, "Channel awarded and being delivered in an established channel"}, - {0x08, "Preemption"}, - {0x09, "Preemption - circuit reserved for reuse"}, - {0x10, "Normal call clearing"}, - {0x11, "User busy"}, - {0x12, "No user responding"}, - {0x13, "No answer from user (user alerted)"}, - {0x14, "Subscriber absent"}, - {0x15, "Call rejected"}, - {0x16, "Number changed"}, - {0x1a, "non-selected user clearing"}, - {0x1b, "Destination out of order"}, - {0x1c, "Invalid number format (address incomplete)"}, - {0x1d, "Facility rejected"}, - {0x1e, "Response to Status enquiry"}, - {0x1f, "Normal, unspecified"}, - {0x22, "No circuit/channel available"}, - {0x26, "Network out of order"}, - {0x27, "Permanent frame mode connection out-of-service"}, - {0x28, "Permanent frame mode connection operational"}, - {0x29, "Temporary failure"}, - {0x2a, "Switching equipment congestion"}, - {0x2b, "Access information discarded"}, - {0x2c, "Requested circuit/channel not available"}, - {0x2e, "Precedence call blocked"}, - {0x2f, "Resource unavailable, unspecified"}, - {0x31, "Quality of service unavailable"}, - {0x32, "Requested facility not subscribed"}, - {0x35, "Outgoing calls barred within CUG"}, - {0x37, "Incoming calls barred within CUG"}, - {0x39, "Bearer capability not authorized"}, - {0x3a, "Bearer capability not presently available"}, - {0x3e, "Inconsistency in designated outgoing access information and subscriber class"}, - {0x3f, "Service or option not available, unspecified"}, - {0x41, "Bearer capability not implemented"}, - {0x42, "Channel type not implemented"}, - {0x43, "Requested facility not implemented"}, - {0x44, "Only restricted digital information bearer capability is available"}, - {0x4f, "Service or option not implemented"}, - {0x51, "Invalid call reference value"}, - {0x52, "Identified channel does not exist"}, - {0x53, "A suspended call exists, but this call identity does not"}, - {0x54, "Call identity in use"}, - {0x55, "No call suspended"}, - {0x56, "Call having the requested call identity has been cleared"}, - {0x57, "User not member of CUG"}, - {0x58, "Incompatible destination"}, - {0x5a, "Non-existent CUG"}, - {0x5b, "Invalid transit network selection"}, - {0x5f, "Invalid message, unspecified"}, - {0x60, "Mandatory information element is missing"}, - {0x61, "Message type non-existent or not implemented"}, - {0x62, "Message not compatible with call state or message type non-existent or not implemented"}, - {0x63, "Information element/parameter non-existent or not implemented"}, - {0x64, "Invalid information element contents"}, - {0x65, "Message not compatible with call state"}, - {0x66, "Recovery on timer expiry"}, - {0x67, "Parameter non-existent or not implemented - passed on"}, - {0x6e, "Message with unrecognized parameter discarded"}, - {0x6f, "Protocol error, unspecified"}, - {0x7f, "Interworking, unspecified"} -}; - -#endif - -static struct isdn_event_desc { - unsigned short ev; - char *desc; -} isdn_event_table[] = { - {EV_USR_SETUP_REQ, "CC->L3: Setup Request"}, - {EV_USR_SETUP_RESP, "CC->L3: Setup Response"}, - {EV_USR_PROCED_REQ, "CC->L3: Proceeding Request"}, - {EV_USR_RELEASE_REQ, "CC->L3: Release Request"}, - - {EV_NET_SETUP, "NET->TE: setup "}, - {EV_NET_CALL_PROC, "NET->TE: call proceeding"}, - {EV_NET_SETUP_ACK, "NET->TE: setup acknowledge (more info needed)"}, - {EV_NET_CONN, "NET->TE: connect"}, - {EV_NET_CONN_ACK, "NET->TE: connect acknowledge"}, - {EV_NET_DISC, "NET->TE: disconnect indication"}, - {EV_NET_RELEASE, "NET->TE: release"}, - {EV_NET_RELEASE_COMP, "NET->TE: release complete"}, - {EV_NET_SELP_RESP, "Board: Select B-channel protocol ack"}, - {EV_NET_ACTV_RESP, "Board: Activate B-channel protocol ack"}, - {EV_TIMER, "Timeout"}, - {0, "NULL"} -}; - -char *strisdnevent(ushort ev) -{ - struct isdn_event_desc *entry; - - for (entry = isdn_event_table; entry->ev; entry++) - if (entry->ev == ev) - break; - - return entry->desc; -} - -/* - * Euro ISDN finite state machine - */ - -static struct fsm_timer_entry fsm_timers[] = { - {ST_CALL_PROC, 10}, - {ST_DISC_REQ, 2}, - {ST_ACTIVE_SELP, 5}, - {ST_ACTIVE_ACTV, 5}, - {ST_INCM_PROC, 10}, - {ST_CONN_REQ, 2}, - {0xff, 0} -}; - -static struct fsm_entry fsm_table[] = { -/* Connect Phase */ - /* Outgoing */ - {ST_NULL, ST_CALL_INIT, EV_USR_SETUP_REQ, cb_out_1}, - - {ST_CALL_INIT, ST_OVER_SEND, EV_NET_SETUP_ACK, cb_notdone}, - {ST_CALL_INIT, ST_CALL_PROC, EV_NET_CALL_PROC, NULL}, - {ST_CALL_INIT, ST_NULL, EV_NET_DISC, cb_out_2}, - - {ST_CALL_PROC, ST_ACTIVE_SELP, EV_NET_CONN, cb_out_2}, - {ST_CALL_PROC, ST_NULL, EV_NET_DISC, cb_disc_1}, - {ST_CALL_PROC, ST_DISC_REQ, EV_USR_RELEASE_REQ, cb_disc_2}, - - /* Incoming */ - {ST_NULL, ST_CALL_PRES, EV_NET_SETUP, NULL}, - - {ST_CALL_PRES, ST_INCM_PROC, EV_USR_PROCED_REQ, cb_in_1}, - {ST_CALL_PRES, ST_DISC_REQ, EV_USR_RELEASE_REQ, cb_disc_2}, - - {ST_INCM_PROC, ST_CONN_REQ, EV_USR_SETUP_RESP, cb_in_2}, - {ST_INCM_PROC, ST_DISC_REQ, EV_USR_RELEASE_REQ, cb_disc_2}, - - {ST_CONN_REQ, ST_ACTIVE_SELP, EV_NET_CONN_ACK, cb_in_3}, - - /* Active */ - {ST_ACTIVE, ST_NULL, EV_NET_DISC, cb_disc_1}, - {ST_ACTIVE, ST_DISC_REQ, EV_USR_RELEASE_REQ, cb_disc_2}, - {ST_ACTIVE, ST_NULL, EV_NET_RELEASE, cb_disc_3}, - - /* Disconnect */ - - {ST_DISC_REQ, ST_NULL, EV_NET_DISC, cb_disc_1}, - {ST_DISC_REQ, ST_NULL, EV_NET_RELEASE, cb_disc_3}, - - /* protocol selection */ - {ST_ACTIVE_SELP, ST_ACTIVE_ACTV, EV_NET_SELP_RESP, cb_selp_1}, - {ST_ACTIVE_SELP, ST_DISC_REQ, EV_USR_RELEASE_REQ, cb_disc_2}, - - {ST_ACTIVE_ACTV, ST_ACTIVE, EV_NET_ACTV_RESP, cb_open}, - {ST_ACTIVE_ACTV, ST_DISC_REQ, EV_USR_RELEASE_REQ, cb_disc_2}, - - /* Timers */ - {ST_CALL_PROC, ST_DISC_REQ, EV_TIMER, cb_disc_2}, - {ST_DISC_REQ, ST_NULL, EV_TIMER, cb_disc_3}, - {ST_ACTIVE_SELP, ST_DISC_REQ, EV_TIMER, cb_disc_2}, - {ST_ACTIVE_ACTV, ST_DISC_REQ, EV_TIMER, cb_disc_2}, - {ST_INCM_PROC, ST_DISC_REQ, EV_TIMER, cb_disc_2}, - {ST_CONN_REQ, ST_CONN_REQ, EV_TIMER, cb_in_2}, - - {0xff, 0, 0, NULL} -}; - - -static void pcbit_fsm_timer(unsigned long data) -{ - struct pcbit_dev *dev; - struct pcbit_chan *chan; - - chan = (struct pcbit_chan *) data; - - del_timer(&chan->fsm_timer); - chan->fsm_timer.function = NULL; - - dev = chan2dev(chan); - - if (dev == NULL) { - printk(KERN_WARNING "pcbit: timer for unknown device\n"); - return; - } - - pcbit_fsm_event(dev, chan, EV_TIMER, NULL); -} - - -void pcbit_fsm_event(struct pcbit_dev *dev, struct pcbit_chan *chan, - unsigned short event, struct callb_data *data) -{ - struct fsm_entry *action; - struct fsm_timer_entry *tentry; - unsigned long flags; - - spin_lock_irqsave(&dev->lock, flags); - - for (action = fsm_table; action->init != 0xff; action++) - if (action->init == chan->fsm_state && action->event == event) - break; - - if (action->init == 0xff) { - - spin_unlock_irqrestore(&dev->lock, flags); - printk(KERN_DEBUG "fsm error: event %x on state %x\n", - event, chan->fsm_state); - return; - } - - if (chan->fsm_timer.function) { - del_timer(&chan->fsm_timer); - chan->fsm_timer.function = NULL; - } - - chan->fsm_state = action->final; - - pcbit_state_change(dev, chan, action->init, event, action->final); - - for (tentry = fsm_timers; tentry->init != 0xff; tentry++) - if (tentry->init == chan->fsm_state) - break; - - if (tentry->init != 0xff) { - init_timer(&chan->fsm_timer); - chan->fsm_timer.function = &pcbit_fsm_timer; - chan->fsm_timer.data = (ulong) chan; - chan->fsm_timer.expires = jiffies + tentry->timeout * HZ; - add_timer(&chan->fsm_timer); - } - - spin_unlock_irqrestore(&dev->lock, flags); - - if (action->callb) - action->callb(dev, chan, data); - -} diff --git a/drivers/isdn/pcbit/edss1.h b/drivers/isdn/pcbit/edss1.h deleted file mode 100644 index 2f6b3a8edfba..000000000000 --- a/drivers/isdn/pcbit/edss1.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * DSS.1 module definitions - * - * Copyright (C) 1996 Universidade de Lisboa - * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) - * - * This software may be used and distributed according to the terms of - * the GNU General Public License, incorporated herein by reference. - */ - -#ifndef EDSS1_H -#define EDSS1_H - -/* ISDN states */ - -#define ST_NULL 0 -#define ST_CALL_INIT 1 /* Call initiated */ -#define ST_OVER_SEND 2 /* Overlap sending - Requests More Info 4 call */ -#define ST_CALL_PROC 3 /* Call Proceeding */ -#define ST_CALL_DELV 4 -#define ST_CALL_PRES 6 /* Call Present - Received CONN.IND */ -#define ST_CALL_RECV 7 /* Alerting sent */ -#define ST_CONN_REQ 8 /* Answered - waiting 4 CONN.CONF */ -#define ST_INCM_PROC 9 -#define ST_ACTIVE 10 -#define ST_DISC_REQ 11 -#define ST_DISC_IND 12 -#define ST_SUSP_REQ 15 -#define ST_RESM_REQ 17 -#define ST_RELS_REQ 19 -#define ST_OVER_RECV 25 - -#define ST_ACTIVE_SELP 26 /* Select protocol on B-Channel */ -#define ST_ACTIVE_ACTV 27 /* Activate B-channel protocol */ - -#define MAX_STATE ST_ACTIVE_ACTV - -#define EV_NULL 0 -#define EV_USR_SETUP_REQ 1 -#define EV_USR_SETUP_RESP 2 -#define EV_USR_PROCED_REQ 3 -#define EV_USR_RELEASE_REQ 4 -#define EV_USR_REJECT_REQ 4 - -#define EV_NET_SETUP 16 -#define EV_NET_CALL_PROC 17 -#define EV_NET_SETUP_ACK 18 -#define EV_NET_CONN 19 -#define EV_NET_CONN_ACK 20 - -#define EV_NET_SELP_RESP 21 -#define EV_NET_ACTV_RESP 22 - -#define EV_NET_DISC 23 -#define EV_NET_RELEASE 24 -#define EV_NET_RELEASE_COMP 25 - -#define EV_TIMER 26 -#define EV_ERROR 32 - -/* - * Cause values - * only the ones we use - */ - -#define CAUSE_NORMAL 0x10U -#define CAUSE_NOCHAN 0x22U - -struct callb_data { - unsigned short type; - union { - struct ConnInfo { - char *CalledPN; - char *CallingPN; - } setup; - unsigned short cause; - } data; -}; - -struct fsm_entry { - unsigned short init; - unsigned short final; - unsigned short event; - void (*callb)(struct pcbit_dev *, struct pcbit_chan *, struct callb_data*); -}; - -struct fsm_timer_entry { - unsigned short init; - unsigned long timeout; /* in seconds */ -}; - -extern const char * const isdn_state_table[]; - -void pcbit_fsm_event(struct pcbit_dev *, struct pcbit_chan *, - unsigned short event, struct callb_data *); -char *strisdnevent(ushort ev); - -#endif diff --git a/drivers/isdn/pcbit/layer2.c b/drivers/isdn/pcbit/layer2.c deleted file mode 100644 index 46e1240ae074..000000000000 --- a/drivers/isdn/pcbit/layer2.c +++ /dev/null @@ -1,712 +0,0 @@ -/* - * PCBIT-D low-layer interface - * - * Copyright (C) 1996 Universidade de Lisboa - * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) - * - * This software may be used and distributed according to the terms of - * the GNU General Public License, incorporated herein by reference. - */ - -/* - * 19991203 - Fernando Carvalho - takion@superbofh.org - * Hacked to compile with egcs and run with current version of isdn modules - */ - -/* - * Based on documentation provided by Inesc: - * - "Interface com bus do PC para o PCBIT e PCBIT-D", Inesc, Jan 93 - */ - -/* - * TODO: better handling of errors - * re-write/remove debug printks - */ - -#include <linux/string.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/workqueue.h> -#include <linux/mm.h> -#include <linux/skbuff.h> - -#include <linux/isdnif.h> - -#include <asm/io.h> - - -#include "pcbit.h" -#include "layer2.h" -#include "edss1.h" - -#undef DEBUG_FRAG - - -/* - * Prototypes - */ - -static void pcbit_transmit(struct pcbit_dev *dev); - -static void pcbit_recv_ack(struct pcbit_dev *dev, unsigned char ack); - -static void pcbit_l2_error(struct pcbit_dev *dev); -static void pcbit_l2_active_conf(struct pcbit_dev *dev, u_char info); -static void pcbit_l2_err_recover(unsigned long data); - -static void pcbit_firmware_bug(struct pcbit_dev *dev); - -static __inline__ void -pcbit_sched_delivery(struct pcbit_dev *dev) -{ - schedule_work(&dev->qdelivery); -} - - -/* - * Called from layer3 - */ - -int -pcbit_l2_write(struct pcbit_dev *dev, ulong msg, ushort refnum, - struct sk_buff *skb, unsigned short hdr_len) -{ - struct frame_buf *frame, - *ptr; - unsigned long flags; - - if (dev->l2_state != L2_RUNNING && dev->l2_state != L2_LOADING) { - dev_kfree_skb(skb); - return -1; - } - if ((frame = kmalloc(sizeof(struct frame_buf), - GFP_ATOMIC)) == NULL) { - dev_kfree_skb(skb); - return -1; - } - frame->msg = msg; - frame->refnum = refnum; - frame->copied = 0; - frame->hdr_len = hdr_len; - - if (skb) - frame->dt_len = skb->len - hdr_len; - else - frame->dt_len = 0; - - frame->skb = skb; - - frame->next = NULL; - - spin_lock_irqsave(&dev->lock, flags); - - if (dev->write_queue == NULL) { - dev->write_queue = frame; - spin_unlock_irqrestore(&dev->lock, flags); - pcbit_transmit(dev); - } else { - for (ptr = dev->write_queue; ptr->next; ptr = ptr->next); - ptr->next = frame; - - spin_unlock_irqrestore(&dev->lock, flags); - } - return 0; -} - -static __inline__ void -pcbit_tx_update(struct pcbit_dev *dev, ushort len) -{ - u_char info; - - dev->send_seq = (dev->send_seq + 1) % 8; - - dev->fsize[dev->send_seq] = len; - info = 0; - info |= dev->rcv_seq << 3; - info |= dev->send_seq; - - writeb(info, dev->sh_mem + BANK4); - -} - -/* - * called by interrupt service routine or by write_2 - */ - -static void -pcbit_transmit(struct pcbit_dev *dev) -{ - struct frame_buf *frame = NULL; - unsigned char unacked; - int flen; /* fragment frame length including all headers */ - int free; - int count, - cp_len; - unsigned long flags; - unsigned short tt; - - if (dev->l2_state != L2_RUNNING && dev->l2_state != L2_LOADING) - return; - - unacked = (dev->send_seq + (8 - dev->unack_seq)) & 0x07; - - spin_lock_irqsave(&dev->lock, flags); - - if (dev->free > 16 && dev->write_queue && unacked < 7) { - - if (!dev->w_busy) - dev->w_busy = 1; - else { - spin_unlock_irqrestore(&dev->lock, flags); - return; - } - - - frame = dev->write_queue; - free = dev->free; - - spin_unlock_irqrestore(&dev->lock, flags); - - if (frame->copied == 0) { - - /* Type 0 frame */ - - ulong msg; - - if (frame->skb) - flen = FRAME_HDR_LEN + PREHDR_LEN + frame->skb->len; - else - flen = FRAME_HDR_LEN + PREHDR_LEN; - - if (flen > free) - flen = free; - - msg = frame->msg; - - /* - * Board level 2 header - */ - - pcbit_writew(dev, flen - FRAME_HDR_LEN); - - pcbit_writeb(dev, GET_MSG_CPU(msg)); - - pcbit_writeb(dev, GET_MSG_PROC(msg)); - - /* TH */ - pcbit_writew(dev, frame->hdr_len + PREHDR_LEN); - - /* TD */ - pcbit_writew(dev, frame->dt_len); - - - /* - * Board level 3 fixed-header - */ - - /* LEN = TH */ - pcbit_writew(dev, frame->hdr_len + PREHDR_LEN); - - /* XX */ - pcbit_writew(dev, 0); - - /* C + S */ - pcbit_writeb(dev, GET_MSG_CMD(msg)); - pcbit_writeb(dev, GET_MSG_SCMD(msg)); - - /* NUM */ - pcbit_writew(dev, frame->refnum); - - count = FRAME_HDR_LEN + PREHDR_LEN; - } else { - /* Type 1 frame */ - - flen = 2 + (frame->skb->len - frame->copied); - - if (flen > free) - flen = free; - - /* TT */ - tt = ((ushort) (flen - 2)) | 0x8000U; /* Type 1 */ - pcbit_writew(dev, tt); - - count = 2; - } - - if (frame->skb) { - cp_len = frame->skb->len - frame->copied; - if (cp_len > flen - count) - cp_len = flen - count; - - memcpy_topcbit(dev, frame->skb->data + frame->copied, - cp_len); - frame->copied += cp_len; - } - /* bookkeeping */ - dev->free -= flen; - pcbit_tx_update(dev, flen); - - spin_lock_irqsave(&dev->lock, flags); - - if (frame->skb == NULL || frame->copied == frame->skb->len) { - - dev->write_queue = frame->next; - - if (frame->skb != NULL) { - /* free frame */ - dev_kfree_skb(frame->skb); - } - kfree(frame); - } - dev->w_busy = 0; - spin_unlock_irqrestore(&dev->lock, flags); - } else { - spin_unlock_irqrestore(&dev->lock, flags); -#ifdef DEBUG - printk(KERN_DEBUG "unacked %d free %d write_queue %s\n", - unacked, dev->free, dev->write_queue ? "not empty" : - "empty"); -#endif - } -} - - -/* - * deliver a queued frame to the upper layer - */ - -void -pcbit_deliver(struct work_struct *work) -{ - struct frame_buf *frame; - unsigned long flags, msg; - struct pcbit_dev *dev = - container_of(work, struct pcbit_dev, qdelivery); - - spin_lock_irqsave(&dev->lock, flags); - - while ((frame = dev->read_queue)) { - dev->read_queue = frame->next; - spin_unlock_irqrestore(&dev->lock, flags); - - msg = 0; - SET_MSG_CPU(msg, 0); - SET_MSG_PROC(msg, 0); - SET_MSG_CMD(msg, frame->skb->data[2]); - SET_MSG_SCMD(msg, frame->skb->data[3]); - - frame->refnum = *((ushort *)frame->skb->data + 4); - frame->msg = *((ulong *)&msg); - - skb_pull(frame->skb, 6); - - pcbit_l3_receive(dev, frame->msg, frame->skb, frame->hdr_len, - frame->refnum); - - kfree(frame); - - spin_lock_irqsave(&dev->lock, flags); - } - - spin_unlock_irqrestore(&dev->lock, flags); -} - -/* - * Reads BANK 2 & Reassembles - */ - -static void -pcbit_receive(struct pcbit_dev *dev) -{ - unsigned short tt; - u_char cpu, - proc; - struct frame_buf *frame = NULL; - unsigned long flags; - u_char type1; - - if (dev->l2_state != L2_RUNNING && dev->l2_state != L2_LOADING) - return; - - tt = pcbit_readw(dev); - - if ((tt & 0x7fffU) > 511) { - printk(KERN_INFO "pcbit: invalid frame length -> TT=%04x\n", - tt); - pcbit_l2_error(dev); - return; - } - if (!(tt & 0x8000U)) { /* Type 0 */ - type1 = 0; - - if (dev->read_frame) { - printk(KERN_DEBUG "pcbit_receive: Type 0 frame and read_frame != NULL\n"); - /* discard previous queued frame */ - kfree_skb(dev->read_frame->skb); - kfree(dev->read_frame); - dev->read_frame = NULL; - } - frame = kzalloc(sizeof(struct frame_buf), GFP_ATOMIC); - - if (frame == NULL) { - printk(KERN_WARNING "kmalloc failed\n"); - return; - } - - cpu = pcbit_readb(dev); - proc = pcbit_readb(dev); - - - if (cpu != 0x06 && cpu != 0x02) { - printk(KERN_DEBUG "pcbit: invalid cpu value\n"); - kfree(frame); - pcbit_l2_error(dev); - return; - } - /* - * we discard cpu & proc on receiving - * but we read it to update the pointer - */ - - frame->hdr_len = pcbit_readw(dev); - frame->dt_len = pcbit_readw(dev); - - /* - * 0 sized packet - * I don't know if they are an error or not... - * But they are very frequent - * Not documented - */ - - if (frame->hdr_len == 0) { - kfree(frame); -#ifdef DEBUG - printk(KERN_DEBUG "0 sized frame\n"); -#endif - pcbit_firmware_bug(dev); - return; - } - /* sanity check the length values */ - if (frame->hdr_len > 1024 || frame->dt_len > 2048) { -#ifdef DEBUG - printk(KERN_DEBUG "length problem: "); - printk(KERN_DEBUG "TH=%04x TD=%04x\n", - frame->hdr_len, - frame->dt_len); -#endif - pcbit_l2_error(dev); - kfree(frame); - return; - } - /* minimum frame read */ - - frame->skb = dev_alloc_skb(frame->hdr_len + frame->dt_len + - ((frame->hdr_len + 15) & ~15)); - - if (!frame->skb) { - printk(KERN_DEBUG "pcbit_receive: out of memory\n"); - kfree(frame); - return; - } - /* 16 byte alignment for IP */ - if (frame->dt_len) - skb_reserve(frame->skb, (frame->hdr_len + 15) & ~15); - - } else { - /* Type 1 */ - type1 = 1; - tt &= 0x7fffU; - - if (!(frame = dev->read_frame)) { - printk("Type 1 frame and no frame queued\n"); - /* usually after an error: toss frame */ - dev->readptr += tt; - if (dev->readptr > dev->sh_mem + BANK2 + BANKLEN) - dev->readptr -= BANKLEN; - return; - - } - } - - memcpy_frompcbit(dev, skb_put(frame->skb, tt), tt); - - frame->copied += tt; - spin_lock_irqsave(&dev->lock, flags); - if (frame->copied == frame->hdr_len + frame->dt_len) { - - if (type1) { - dev->read_frame = NULL; - } - if (dev->read_queue) { - struct frame_buf *ptr; - for (ptr = dev->read_queue; ptr->next; ptr = ptr->next); - ptr->next = frame; - } else - dev->read_queue = frame; - - } else { - dev->read_frame = frame; - } - spin_unlock_irqrestore(&dev->lock, flags); -} - -/* - * The board sends 0 sized frames - * They are TDATA_CONFs that get messed up somehow - * gotta send a fake acknowledgment to the upper layer somehow - */ - -static __inline__ void -pcbit_fake_conf(struct pcbit_dev *dev, struct pcbit_chan *chan) -{ - isdn_ctrl ictl; - - if (chan->queued) { - chan->queued--; - - ictl.driver = dev->id; - ictl.command = ISDN_STAT_BSENT; - ictl.arg = chan->id; - dev->dev_if->statcallb(&ictl); - } -} - -static void -pcbit_firmware_bug(struct pcbit_dev *dev) -{ - struct pcbit_chan *chan; - - chan = dev->b1; - - if (chan->fsm_state == ST_ACTIVE) { - pcbit_fake_conf(dev, chan); - } - chan = dev->b2; - - if (chan->fsm_state == ST_ACTIVE) { - pcbit_fake_conf(dev, chan); - } -} - -irqreturn_t -pcbit_irq_handler(int interrupt, void *devptr) -{ - struct pcbit_dev *dev; - u_char info, - ack_seq, - read_seq; - - dev = (struct pcbit_dev *) devptr; - - if (!dev) { - printk(KERN_WARNING "pcbit_irq_handler: wrong device\n"); - return IRQ_NONE; - } - if (dev->interrupt) { - printk(KERN_DEBUG "pcbit: reentering interrupt handler\n"); - return IRQ_HANDLED; - } - dev->interrupt = 1; - - info = readb(dev->sh_mem + BANK3); - - if (dev->l2_state == L2_STARTING || dev->l2_state == L2_ERROR) { - pcbit_l2_active_conf(dev, info); - dev->interrupt = 0; - return IRQ_HANDLED; - } - if (info & 0x40U) { /* E bit set */ -#ifdef DEBUG - printk(KERN_DEBUG "pcbit_irq_handler: E bit on\n"); -#endif - pcbit_l2_error(dev); - dev->interrupt = 0; - return IRQ_HANDLED; - } - if (dev->l2_state != L2_RUNNING && dev->l2_state != L2_LOADING) { - dev->interrupt = 0; - return IRQ_HANDLED; - } - ack_seq = (info >> 3) & 0x07U; - read_seq = (info & 0x07U); - - dev->interrupt = 0; - - if (read_seq != dev->rcv_seq) { - while (read_seq != dev->rcv_seq) { - pcbit_receive(dev); - dev->rcv_seq = (dev->rcv_seq + 1) % 8; - } - pcbit_sched_delivery(dev); - } - if (ack_seq != dev->unack_seq) { - pcbit_recv_ack(dev, ack_seq); - } - info = dev->rcv_seq << 3; - info |= dev->send_seq; - - writeb(info, dev->sh_mem + BANK4); - return IRQ_HANDLED; -} - - -static void -pcbit_l2_active_conf(struct pcbit_dev *dev, u_char info) -{ - u_char state; - - state = dev->l2_state; - -#ifdef DEBUG - printk(KERN_DEBUG "layer2_active_confirm\n"); -#endif - - - if (info & 0x80U) { - dev->rcv_seq = info & 0x07U; - dev->l2_state = L2_RUNNING; - } else - dev->l2_state = L2_DOWN; - - if (state == L2_STARTING) - wake_up_interruptible(&dev->set_running_wq); - - if (state == L2_ERROR && dev->l2_state == L2_RUNNING) { - pcbit_transmit(dev); - } -} - -static void -pcbit_l2_err_recover(unsigned long data) -{ - - struct pcbit_dev *dev; - struct frame_buf *frame; - - dev = (struct pcbit_dev *) data; - - del_timer(&dev->error_recover_timer); - if (dev->w_busy || dev->r_busy) { - init_timer(&dev->error_recover_timer); - dev->error_recover_timer.expires = jiffies + ERRTIME; - add_timer(&dev->error_recover_timer); - return; - } - dev->w_busy = dev->r_busy = 1; - - if (dev->read_frame) { - kfree_skb(dev->read_frame->skb); - kfree(dev->read_frame); - dev->read_frame = NULL; - } - if (dev->write_queue) { - frame = dev->write_queue; -#ifdef FREE_ON_ERROR - dev->write_queue = dev->write_queue->next; - - if (frame->skb) { - dev_kfree_skb(frame->skb); - } - kfree(frame); -#else - frame->copied = 0; -#endif - } - dev->rcv_seq = dev->send_seq = dev->unack_seq = 0; - dev->free = 511; - dev->l2_state = L2_ERROR; - - /* this is an hack... */ - pcbit_firmware_bug(dev); - - dev->writeptr = dev->sh_mem; - dev->readptr = dev->sh_mem + BANK2; - - writeb((0x80U | ((dev->rcv_seq & 0x07) << 3) | (dev->send_seq & 0x07)), - dev->sh_mem + BANK4); - dev->w_busy = dev->r_busy = 0; - -} - -static void -pcbit_l2_error(struct pcbit_dev *dev) -{ - if (dev->l2_state == L2_RUNNING) { - - printk(KERN_INFO "pcbit: layer 2 error\n"); - -#ifdef DEBUG - log_state(dev); -#endif - - dev->l2_state = L2_DOWN; - - init_timer(&dev->error_recover_timer); - dev->error_recover_timer.function = &pcbit_l2_err_recover; - dev->error_recover_timer.data = (ulong) dev; - dev->error_recover_timer.expires = jiffies + ERRTIME; - add_timer(&dev->error_recover_timer); - } -} - -/* - * Description: - * if board acks frames - * update dev->free - * call pcbit_transmit to write possible queued frames - */ - -static void -pcbit_recv_ack(struct pcbit_dev *dev, unsigned char ack) -{ - int i, - count; - int unacked; - - unacked = (dev->send_seq + (8 - dev->unack_seq)) & 0x07; - - /* dev->unack_seq < ack <= dev->send_seq; */ - - if (unacked) { - - if (dev->send_seq > dev->unack_seq) { - if (ack <= dev->unack_seq || ack > dev->send_seq) { - printk(KERN_DEBUG - "layer 2 ack unacceptable - dev %d", - dev->id); - - pcbit_l2_error(dev); - } else if (ack > dev->send_seq && ack <= dev->unack_seq) { - printk(KERN_DEBUG - "layer 2 ack unacceptable - dev %d", - dev->id); - pcbit_l2_error(dev); - } - } - /* ack is acceptable */ - - - i = dev->unack_seq; - - do { - dev->unack_seq = i = (i + 1) % 8; - dev->free += dev->fsize[i]; - } while (i != ack); - - count = 0; - while (count < 7 && dev->write_queue) { - u8 lsend_seq = dev->send_seq; - - pcbit_transmit(dev); - - if (dev->send_seq == lsend_seq) - break; - count++; - } - } else - printk(KERN_DEBUG "recv_ack: unacked = 0\n"); -} diff --git a/drivers/isdn/pcbit/layer2.h b/drivers/isdn/pcbit/layer2.h deleted file mode 100644 index be1327bc162a..000000000000 --- a/drivers/isdn/pcbit/layer2.h +++ /dev/null @@ -1,281 +0,0 @@ -/* - * PCBIT-D low-layer interface definitions - * - * Copyright (C) 1996 Universidade de Lisboa - * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) - * - * This software may be used and distributed according to the terms of - * the GNU General Public License, incorporated herein by reference. - */ - -/* - * 19991203 - Fernando Carvalho - takion@superbofh.org - * Hacked to compile with egcs and run with current version of isdn modules - */ - -#ifndef LAYER2_H -#define LAYER2_H - -#include <linux/interrupt.h> - -#include <asm/byteorder.h> - -#define BANK1 0x0000U /* PC -> Board */ -#define BANK2 0x01ffU /* Board -> PC */ -#define BANK3 0x03feU /* Att Board */ -#define BANK4 0x03ffU /* Att PC */ - -#define BANKLEN 0x01FFU - -#define LOAD_ZONE_START 0x03f8U -#define LOAD_ZONE_END 0x03fdU - -#define LOAD_RETRY 18000000 - - - -/* TAM - XX - C - S - NUM */ -#define PREHDR_LEN 8 -/* TT - M - I - TH - TD */ -#define FRAME_HDR_LEN 8 - -#define MSG_CONN_REQ 0x08000100 -#define MSG_CONN_CONF 0x00000101 -#define MSG_CONN_IND 0x00000102 -#define MSG_CONN_RESP 0x08000103 - -#define MSG_CONN_ACTV_REQ 0x08000300 -#define MSG_CONN_ACTV_CONF 0x00000301 -#define MSG_CONN_ACTV_IND 0x00000302 -#define MSG_CONN_ACTV_RESP 0x08000303 - -#define MSG_DISC_REQ 0x08000400 -#define MSG_DISC_CONF 0x00000401 -#define MSG_DISC_IND 0x00000402 -#define MSG_DISC_RESP 0x08000403 - -#define MSG_TDATA_REQ 0x0908E200 -#define MSG_TDATA_CONF 0x0000E201 -#define MSG_TDATA_IND 0x0000E202 -#define MSG_TDATA_RESP 0x0908E203 - -#define MSG_SELP_REQ 0x09004000 -#define MSG_SELP_CONF 0x00004001 - -#define MSG_ACT_TRANSP_REQ 0x0908E000 -#define MSG_ACT_TRANSP_CONF 0x0000E001 - -#define MSG_STPROT_REQ 0x09004100 -#define MSG_STPROT_CONF 0x00004101 - -#define MSG_PING188_REQ 0x09030500 -#define MSG_PING188_CONF 0x000005bc - -#define MSG_WATCH188 0x09030400 - -#define MSG_API_ON 0x08020102 -#define MSG_POOL_PCBIT 0x08020400 -#define MSG_POOL_PCBIT_CONF 0x00000401 - -#define MSG_INFO_IND 0x00002602 -#define MSG_INFO_RESP 0x08002603 - -#define MSG_DEBUG_188 0x0000ff00 - -/* - - long 4 3 2 1 - Intel 1 2 3 4 -*/ - -#ifdef __LITTLE_ENDIAN -#define SET_MSG_SCMD(msg, ch) (msg = (msg & 0xffffff00) | (((ch) & 0xff))) -#define SET_MSG_CMD(msg, ch) (msg = (msg & 0xffff00ff) | (((ch) & 0xff) << 8)) -#define SET_MSG_PROC(msg, ch) (msg = (msg & 0xff00ffff) | (((ch) & 0xff) << 16)) -#define SET_MSG_CPU(msg, ch) (msg = (msg & 0x00ffffff) | (((ch) & 0xff) << 24)) - -#define GET_MSG_SCMD(msg) ((msg) & 0xFF) -#define GET_MSG_CMD(msg) ((msg) >> 8 & 0xFF) -#define GET_MSG_PROC(msg) ((msg) >> 16 & 0xFF) -#define GET_MSG_CPU(msg) ((msg) >> 24) - -#else -#error "Non-Intel CPU" -#endif - -#define MAX_QUEUED 7 - -#define SCHED_READ 0x01 -#define SCHED_WRITE 0x02 - -#define SET_RUN_TIMEOUT 2 * HZ /* 2 seconds */ - -struct frame_buf { - ulong msg; - unsigned int refnum; - unsigned int dt_len; - unsigned int hdr_len; - struct sk_buff *skb; - unsigned int copied; - struct frame_buf *next; -}; - -extern int pcbit_l2_write(struct pcbit_dev *dev, ulong msg, ushort refnum, - struct sk_buff *skb, unsigned short hdr_len); - -extern irqreturn_t pcbit_irq_handler(int interrupt, void *); - -extern struct pcbit_dev *dev_pcbit[MAX_PCBIT_CARDS]; - -#ifdef DEBUG -static __inline__ void log_state(struct pcbit_dev *dev) { - printk(KERN_DEBUG "writeptr = %ld\n", - (ulong) (dev->writeptr - dev->sh_mem)); - printk(KERN_DEBUG "readptr = %ld\n", - (ulong) (dev->readptr - (dev->sh_mem + BANK2))); - printk(KERN_DEBUG "{rcv_seq=%01x, send_seq=%01x, unack_seq=%01x}\n", - dev->rcv_seq, dev->send_seq, dev->unack_seq); -} -#endif - -static __inline__ struct pcbit_dev *chan2dev(struct pcbit_chan *chan) -{ - struct pcbit_dev *dev; - int i; - - - for (i = 0; i < MAX_PCBIT_CARDS; i++) - if ((dev = dev_pcbit[i])) - if (dev->b1 == chan || dev->b2 == chan) - return dev; - return NULL; - -} - -static __inline__ struct pcbit_dev *finddev(int id) -{ - struct pcbit_dev *dev; - int i; - - for (i = 0; i < MAX_PCBIT_CARDS; i++) - if ((dev = dev_pcbit[i])) - if (dev->id == id) - return dev; - return NULL; -} - - -/* - * Support routines for reading and writing in the board - */ - -static __inline__ void pcbit_writeb(struct pcbit_dev *dev, unsigned char dt) -{ - writeb(dt, dev->writeptr++); - if (dev->writeptr == dev->sh_mem + BANKLEN) - dev->writeptr = dev->sh_mem; -} - -static __inline__ void pcbit_writew(struct pcbit_dev *dev, unsigned short dt) -{ - int dist; - - dist = BANKLEN - (dev->writeptr - dev->sh_mem); - switch (dist) { - case 2: - writew(dt, dev->writeptr); - dev->writeptr = dev->sh_mem; - break; - case 1: - writeb((u_char) (dt & 0x00ffU), dev->writeptr); - dev->writeptr = dev->sh_mem; - writeb((u_char) (dt >> 8), dev->writeptr++); - break; - default: - writew(dt, dev->writeptr); - dev->writeptr += 2; - break; - }; -} - -static __inline__ void memcpy_topcbit(struct pcbit_dev *dev, u_char *data, - int len) -{ - int diff; - - diff = len - (BANKLEN - (dev->writeptr - dev->sh_mem)); - - if (diff > 0) - { - memcpy_toio(dev->writeptr, data, len - diff); - memcpy_toio(dev->sh_mem, data + (len - diff), diff); - dev->writeptr = dev->sh_mem + diff; - } - else - { - memcpy_toio(dev->writeptr, data, len); - - dev->writeptr += len; - if (diff == 0) - dev->writeptr = dev->sh_mem; - } -} - -static __inline__ unsigned char pcbit_readb(struct pcbit_dev *dev) -{ - unsigned char val; - - val = readb(dev->readptr++); - if (dev->readptr == dev->sh_mem + BANK2 + BANKLEN) - dev->readptr = dev->sh_mem + BANK2; - - return val; -} - -static __inline__ unsigned short pcbit_readw(struct pcbit_dev *dev) -{ - int dist; - unsigned short val; - - dist = BANKLEN - (dev->readptr - (dev->sh_mem + BANK2)); - switch (dist) { - case 2: - val = readw(dev->readptr); - dev->readptr = dev->sh_mem + BANK2; - break; - case 1: - val = readb(dev->readptr); - dev->readptr = dev->sh_mem + BANK2; - val = (readb(dev->readptr++) << 8) | val; - break; - default: - val = readw(dev->readptr); - dev->readptr += 2; - break; - }; - return val; -} - -static __inline__ void memcpy_frompcbit(struct pcbit_dev *dev, u_char *data, int len) -{ - int diff; - - diff = len - (BANKLEN - (dev->readptr - (dev->sh_mem + BANK2))); - if (diff > 0) - { - memcpy_fromio(data, dev->readptr, len - diff); - memcpy_fromio(data + (len - diff), dev->sh_mem + BANK2 , diff); - dev->readptr = dev->sh_mem + BANK2 + diff; - } - else - { - memcpy_fromio(data, dev->readptr, len); - dev->readptr += len; - if (diff == 0) - dev->readptr = dev->sh_mem + BANK2; - } -} - - -#endif diff --git a/drivers/isdn/pcbit/module.c b/drivers/isdn/pcbit/module.c deleted file mode 100644 index 0a59bd0b8210..000000000000 --- a/drivers/isdn/pcbit/module.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * PCBIT-D module support - * - * Copyright (C) 1996 Universidade de Lisboa - * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) - * - * This software may be used and distributed according to the terms of - * the GNU General Public License, incorporated herein by reference. - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/string.h> -#include <linux/kernel.h> -#include <linux/skbuff.h> - -#include <linux/isdnif.h> -#include "pcbit.h" - -MODULE_DESCRIPTION("ISDN4Linux: Driver for PCBIT-T card"); -MODULE_AUTHOR("Pedro Roque Marques"); -MODULE_LICENSE("GPL"); - -static int mem[MAX_PCBIT_CARDS]; -static int irq[MAX_PCBIT_CARDS]; - -module_param_array(mem, int, NULL, 0); -module_param_array(irq, int, NULL, 0); - -static int num_boards; -struct pcbit_dev *dev_pcbit[MAX_PCBIT_CARDS]; - -static int __init pcbit_init(void) -{ - int board; - - num_boards = 0; - - printk(KERN_NOTICE - "PCBIT-D device driver v 0.5-fjpc0 19991204 - " - "Copyright (C) 1996 Universidade de Lisboa\n"); - - if (mem[0] || irq[0]) - { - for (board = 0; board < MAX_PCBIT_CARDS && mem[board] && irq[board]; board++) - { - if (!mem[board]) - mem[board] = 0xD0000; - if (!irq[board]) - irq[board] = 5; - - if (pcbit_init_dev(board, mem[board], irq[board]) == 0) - num_boards++; - - else - { - printk(KERN_WARNING - "pcbit_init failed for dev %d", - board + 1); - return -EIO; - } - } - } - - /* Hardcoded default settings detection */ - - if (!num_boards) - { - printk(KERN_INFO - "Trying to detect board using default settings\n"); - if (pcbit_init_dev(0, 0xD0000, 5) == 0) - num_boards++; - else - return -EIO; - } - return 0; -} - -static void __exit pcbit_exit(void) -{ -#ifdef MODULE - int board; - - for (board = 0; board < num_boards; board++) - pcbit_terminate(board); - printk(KERN_NOTICE - "PCBIT-D module unloaded\n"); -#endif -} - -#ifndef MODULE -#define MAX_PARA (MAX_PCBIT_CARDS * 2) -static int __init pcbit_setup(char *line) -{ - int i, j, argc; - char *str; - int ints[MAX_PARA + 1]; - - str = get_options(line, MAX_PARA, ints); - argc = ints[0]; - i = 0; - j = 1; - - while (argc && (i < MAX_PCBIT_CARDS)) { - - if (argc) { - mem[i] = ints[j]; - j++; argc--; - } - - if (argc) { - irq[i] = ints[j]; - j++; argc--; - } - - i++; - } - return (1); -} -__setup("pcbit=", pcbit_setup); -#endif - -module_init(pcbit_init); -module_exit(pcbit_exit); diff --git a/drivers/isdn/pcbit/pcbit.h b/drivers/isdn/pcbit/pcbit.h deleted file mode 100644 index 0a5a99440a80..000000000000 --- a/drivers/isdn/pcbit/pcbit.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - * PCBIT-D device driver definitions - * - * Copyright (C) 1996 Universidade de Lisboa - * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) - * - * This software may be used and distributed according to the terms of - * the GNU General Public License, incorporated herein by reference. - */ - -#ifndef PCBIT_H -#define PCBIT_H - -#include <linux/workqueue.h> - -#define MAX_PCBIT_CARDS 4 - - -#define BLOCK_TIMER - -#ifdef __KERNEL__ - -struct pcbit_chan { - unsigned short id; - unsigned short callref; /* Call Reference */ - unsigned char proto; /* layer2protocol */ - unsigned char queued; /* unacked data messages */ - unsigned char layer2link; /* used in TData */ - unsigned char snum; /* used in TData */ - unsigned short s_refnum; - unsigned short r_refnum; - unsigned short fsm_state; - struct timer_list fsm_timer; -#ifdef BLOCK_TIMER - struct timer_list block_timer; -#endif -}; - -struct msn_entry { - char *msn; - struct msn_entry *next; -}; - -struct pcbit_dev { - /* board */ - - volatile unsigned char __iomem *sh_mem; /* RDP address */ - unsigned long ph_mem; - unsigned int irq; - unsigned int id; - unsigned int interrupt; /* set during interrupt - processing */ - spinlock_t lock; - /* isdn4linux */ - - struct msn_entry *msn_list; /* ISDN address list */ - - isdn_if *dev_if; - - ushort ll_hdrlen; - ushort hl_hdrlen; - - /* link layer */ - unsigned char l2_state; - - struct frame_buf *read_queue; - struct frame_buf *read_frame; - struct frame_buf *write_queue; - - /* Protocol start */ - wait_queue_head_t set_running_wq; - struct timer_list set_running_timer; - - struct timer_list error_recover_timer; - - struct work_struct qdelivery; - - u_char w_busy; - u_char r_busy; - - volatile unsigned char __iomem *readptr; - volatile unsigned char __iomem *writeptr; - - ushort loadptr; - - unsigned short fsize[8]; /* sent layer2 frames size */ - - unsigned char send_seq; - unsigned char rcv_seq; - unsigned char unack_seq; - - unsigned short free; - - /* channels */ - - struct pcbit_chan *b1; - struct pcbit_chan *b2; -}; - -#define STATS_TIMER (10 * HZ) -#define ERRTIME (HZ / 10) - -/* MRU */ -#define MAXBUFSIZE 1534 -#define MRU MAXBUFSIZE - -#define STATBUF_LEN 2048 -/* - * - */ - -#endif /* __KERNEL__ */ - -/* isdn_ctrl only allows a long sized argument */ - -struct pcbit_ioctl { - union { - struct byte_op { - ushort addr; - ushort value; - } rdp_byte; - unsigned long l2_status; - } info; -}; - - - -#define PCBIT_IOCTL_GETSTAT 0x01 /* layer2 status */ -#define PCBIT_IOCTL_LWMODE 0x02 /* linear write mode */ -#define PCBIT_IOCTL_STRLOAD 0x03 /* start load mode */ -#define PCBIT_IOCTL_ENDLOAD 0x04 /* end load mode */ -#define PCBIT_IOCTL_SETBYTE 0x05 /* set byte */ -#define PCBIT_IOCTL_GETBYTE 0x06 /* get byte */ -#define PCBIT_IOCTL_RUNNING 0x07 /* set protocol running */ -#define PCBIT_IOCTL_WATCH188 0x08 /* set watch 188 */ -#define PCBIT_IOCTL_PING188 0x09 /* ping 188 */ -#define PCBIT_IOCTL_FWMODE 0x0A /* firmware write mode */ -#define PCBIT_IOCTL_STOP 0x0B /* stop protocol */ -#define PCBIT_IOCTL_APION 0x0C /* issue API_ON */ - -#ifndef __KERNEL__ - -#define PCBIT_GETSTAT (PCBIT_IOCTL_GETSTAT + IIOCDRVCTL) -#define PCBIT_LWMODE (PCBIT_IOCTL_LWMODE + IIOCDRVCTL) -#define PCBIT_STRLOAD (PCBIT_IOCTL_STRLOAD + IIOCDRVCTL) -#define PCBIT_ENDLOAD (PCBIT_IOCTL_ENDLOAD + IIOCDRVCTL) -#define PCBIT_SETBYTE (PCBIT_IOCTL_SETBYTE + IIOCDRVCTL) -#define PCBIT_GETBYTE (PCBIT_IOCTL_GETBYTE + IIOCDRVCTL) -#define PCBIT_RUNNING (PCBIT_IOCTL_RUNNING + IIOCDRVCTL) -#define PCBIT_WATCH188 (PCBIT_IOCTL_WATCH188 + IIOCDRVCTL) -#define PCBIT_PING188 (PCBIT_IOCTL_PING188 + IIOCDRVCTL) -#define PCBIT_FWMODE (PCBIT_IOCTL_FWMODE + IIOCDRVCTL) -#define PCBIT_STOP (PCBIT_IOCTL_STOP + IIOCDRVCTL) -#define PCBIT_APION (PCBIT_IOCTL_APION + IIOCDRVCTL) - -#define MAXSUPERLINE 3000 - -#endif - -#define L2_DOWN 0 -#define L2_LOADING 1 -#define L2_LWMODE 2 -#define L2_FWMODE 3 -#define L2_STARTING 4 -#define L2_RUNNING 5 -#define L2_ERROR 6 - -void pcbit_deliver(struct work_struct *work); -int pcbit_init_dev(int board, int mem_base, int irq); -void pcbit_terminate(int board); -void pcbit_l3_receive(struct pcbit_dev *dev, ulong msg, struct sk_buff *skb, - ushort hdr_len, ushort refnum); -void pcbit_state_change(struct pcbit_dev *dev, struct pcbit_chan *chan, - unsigned short i, unsigned short ev, unsigned short f); - -#endif |