📄 b1lli.c
字号:
/* * $Id: b1lli.c,v 1.1.1.1 1999/11/15 13:42:16 vadim Exp $ * * ISDN lowlevel-module for AVM B1-card. * * (c) Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: b1lli.c,v $ * Revision 1.1.1.1 1999/11/15 13:42:16 vadim * Initial import * * Revision 1.1.2.11 1998/10/25 14:36:18 fritz * Backported from MIPS (Cobalt). * * Revision 1.1.2.10 1998/03/20 20:34:41 calle * port valid check now only for T1, because of the PCI and PCMCIA cards. * * Revision 1.1.2.9 1998/03/20 14:38:20 calle * capidrv: prepared state machines for suspend/resume/hold * capidrv: fix bug in state machine if B1/T1 is out of nccis * b1capi: changed some errno returns. * b1capi: detect if you try to add same T1 to different io address. * b1capi: change number of nccis depending on number of channels. * b1lli: cosmetics * * Revision 1.1.2.8 1998/03/18 17:43:29 calle * T1 with fastlink, bugfix for multicontroller support in capidrv.c * * Revision 1.1.2.7 1998/03/04 17:33:50 calle * Changes for T1. * * Revision 1.1.2.6 1998/02/27 15:40:44 calle * T1 running with slow link. bugfix in capi_release. * * Revision 1.1.2.5 1998/02/13 16:28:28 calle * first step for T1 * * Revision 1.1.2.4 1998/01/27 16:12:51 calle * Support for PCMCIA B1/M1/M2 ready. * * Revision 1.1.2.3 1998/01/15 15:33:37 calle * print cardtype, d2 protocol and linetype after load. * * Revision 1.1.2.2 1997/11/26 10:46:55 calle * prepared for M1 (Mobile) and T1 (PMX) cards. * prepared to set configuration after load to support other D-channel * protocols, point-to-point and leased lines. * * Revision 1.1.2.1 1997/07/13 12:16:46 calle * bug fix for more than one controller in connect_req. * * Revision 1.1 1997/03/04 21:50:28 calle * Frirst version in isdn4linux * * Revision 2.2 1997/02/12 09:31:39 calle * new version * * Revision 1.1 1997/01/31 10:32:20 calle * Initial revision * * *//* #define FASTLINK_DEBUG */#include <linux/kernel.h>#include <linux/skbuff.h>#include <linux/delay.h>#include <linux/mm.h>#include <asm/segment.h>#include <asm/io.h>#include <linux/capi.h>#include <linux/b1lli.h>#include "compat.h"#include "capicmd.h"#include "capiutil.h"extern int showcapimsgs;/* * LLI Messages to the ISDN-ControllerISDN Controller */#define SEND_POLL 0x72 /* * after load <- RECEIVE_POLL */#define SEND_INIT 0x11 /* * first message <- RECEIVE_INIT * int32 NumApplications int32 * NumNCCIs int32 BoardNumber */#define SEND_REGISTER 0x12 /* * register an application int32 * ApplIDId int32 NumMessages * int32 NumB3Connections int32 * NumB3Blocks int32 B3Size * * AnzB3Connection != 0 && * AnzB3Blocks >= 1 && B3Size >= 1 */#define SEND_RELEASE 0x14 /* * deregister an application int32 * ApplID */#define SEND_MESSAGE 0x15 /* * send capi-message int32 length * capi-data ... */#define SEND_DATA_B3_REQ 0x13 /* * send capi-data-message int32 * MsgLength capi-data ... int32 * B3Length data .... */#define SEND_CONFIG 0x21 /* */#define SEND_POLLACK 0x73 /* T1 Watchdog *//* * LLI Messages from the ISDN-ControllerISDN Controller */#define RECEIVE_POLL 0x32 /* * <- after SEND_POLL */#define RECEIVE_INIT 0x27 /* * <- after SEND_INIT int32 length * byte total length b1struct board * driver revision b1struct card * type b1struct reserved b1struct * serial number b1struct driver * capability b1struct d-channel * protocol b1struct CAPI-2.0 * profile b1struct capi version */#define RECEIVE_MESSAGE 0x21 /* * <- after SEND_MESSAGE int32 * AppllID int32 Length capi-data * .... */#define RECEIVE_DATA_B3_IND 0x22 /* * received data int32 AppllID * int32 Length capi-data ... * int32 B3Length data ... */#define RECEIVE_START 0x23 /* * Handshake */#define RECEIVE_STOP 0x24 /* * Handshake */#define RECEIVE_NEW_NCCI 0x25 /* * int32 AppllID int32 NCCI int32 * WindowSize */#define RECEIVE_FREE_NCCI 0x26 /* * int32 AppllID int32 NCCI */#define RECEIVE_RELEASE 0x26 /* * int32 AppllID int32 0xffffffff */#define RECEIVE_TASK_READY 0x31 /* * int32 tasknr * int32 Length Taskname ... */#define WRITE_REGISTER 0x00#define READ_REGISTER 0x01/* * port offsets */#define B1_READ 0x00#define B1_WRITE 0x01#define B1_INSTAT 0x02#define B1_OUTSTAT 0x03#define B1_RESET 0x10#define B1_ANALYSE 0x04/* Hema card T1 */#define T1_FASTLINK 0x00#define T1_SLOWLINK 0x08#define T1_READ B1_READ#define T1_WRITE B1_WRITE#define T1_INSTAT B1_INSTAT#define T1_OUTSTAT B1_OUTSTAT#define T1_IRQENABLE 0x05#define T1_FIFOSTAT 0x06#define T1_RESETLINK 0x10#define T1_ANALYSE 0x11#define T1_IRQMASTER 0x12#define T1_IDENT 0x17#define T1_RESETBOARD 0x1f#define T1F_IREADY 0x01#define T1F_IHALF 0x02#define T1F_IFULL 0x04#define T1F_IEMPTY 0x08#define T1F_IFLAGS 0xF0#define T1F_OREADY 0x10#define T1F_OHALF 0x20#define T1F_OEMPTY 0x40#define T1F_OFULL 0x80#define T1F_OFLAGS 0xF0/* there are HEMA cards with 1k and 4k FIFO out */#define FIFO_OUTBSIZE 256#define FIFO_INPBSIZE 512#define HEMA_VERSION_ID 0#define HEMA_PAL_ID 0#define B1_STAT0(cardtype) ((cardtype) == AVM_CARDTYPE_M1 ? 0x81200000l : 0x80A00000l)#define B1_STAT1(cardtype) (0x80E00000l)static inline unsigned char b1outp(unsigned int base, unsigned short offset, unsigned char value){ outb(value, base + offset); return inb(base + B1_ANALYSE);}static inline void t1outp(unsigned int base, unsigned short offset, unsigned char value){ outb(value, base + offset);}static inline unsigned char t1inp(unsigned int base, unsigned short offset){ return inb(base + offset);}static inline int B1_isfastlink(unsigned int base){ return (inb(base + T1_IDENT) & ~0x82) == 1;}static inline unsigned char B1_fifostatus(unsigned int base){ return inb(base + T1_FIFOSTAT);}static inline int B1_rx_full(unsigned int base){ return inb(base + B1_INSTAT) & 0x1;}static inline unsigned char B1_get_byte(unsigned int base){ unsigned long i = jiffies + 1 * HZ; /* maximum wait time 1 sec */ while (!B1_rx_full(base) && i > jiffies); if (B1_rx_full(base)) return inb(base + B1_READ); printk(KERN_CRIT "b1lli(0x%x): rx not full after 1 second\n", base); return 0;}static inline unsigned int B1_get_word(unsigned int base){ unsigned int val = 0; val |= B1_get_byte(base); val |= (B1_get_byte(base) << 8); val |= (B1_get_byte(base) << 16); val |= (B1_get_byte(base) << 24); return val;}static inline int B1_tx_empty(unsigned int base){ return inb(base + B1_OUTSTAT) & 0x1;}static inline void B1_put_byte(unsigned int base, unsigned char val){ while (!B1_tx_empty(base)); b1outp(base, B1_WRITE, val);}static inline void B1_put_word(unsigned int base, unsigned int val){ B1_put_byte(base, val & 0xff); B1_put_byte(base, (val >> 8) & 0xff); B1_put_byte(base, (val >> 16) & 0xff); B1_put_byte(base, (val >> 24) & 0xff);}static inline unsigned int B1_get_slice(unsigned int base, unsigned char *dp){ unsigned int len, i;#ifdef FASTLINK_DEBUG unsigned wcnt = 0, bcnt = 0;#endif len = i = B1_get_word(base); if (B1_isfastlink(base)) { int status; while (i > 0) { status = B1_fifostatus(base) & (T1F_IREADY|T1F_IHALF); if (i >= FIFO_INPBSIZE) status |= T1F_IFULL; switch (status) { case T1F_IREADY|T1F_IHALF|T1F_IFULL: insb(base+B1_READ, dp, FIFO_INPBSIZE); dp += FIFO_INPBSIZE; i -= FIFO_INPBSIZE;#ifdef FASTLINK_DEBUG wcnt += FIFO_INPBSIZE;#endif break; case T1F_IREADY|T1F_IHALF: insb(base+B1_READ,dp, i);#ifdef FASTLINK_DEBUG wcnt += i;#endif dp += i; i = 0; if (i == 0) break; /* fall through */ default: *dp++ = B1_get_byte(base); i--;#ifdef FASTLINK_DEBUG bcnt++;#endif break; } }#ifdef FASTLINK_DEBUG if (wcnt) printk(KERN_DEBUG "b1lli(0x%x): get_slice l=%d w=%d b=%d\n", base, len, wcnt, bcnt);#endif } else { while (i-- > 0) *dp++ = B1_get_byte(base); } return len;}static inline void B1_put_slice(unsigned int base, unsigned char *dp, unsigned int len){ unsigned i = len; B1_put_word(base, i); if (B1_isfastlink(base)) { int status; while (i > 0) { status = B1_fifostatus(base) & (T1F_OREADY|T1F_OHALF); if (i >= FIFO_OUTBSIZE) status |= T1F_OEMPTY; switch (status) { case T1F_OREADY|T1F_OHALF|T1F_OEMPTY: outsb(base+B1_WRITE, dp, FIFO_OUTBSIZE); dp += FIFO_OUTBSIZE; i -= FIFO_OUTBSIZE; break; case T1F_OREADY|T1F_OHALF: outsb(base+B1_WRITE, dp, i); dp += i; i = 0; break; default: B1_put_byte(base, *dp++); i--; break; } } } else { while (i-- > 0) B1_put_byte(base, *dp++); }}static void b1_wr_reg(unsigned int base, unsigned int reg, unsigned int value){ B1_put_byte(base, WRITE_REGISTER); B1_put_word(base, reg); B1_put_word(base, value);}static inline unsigned int b1_rd_reg(unsigned int base, unsigned int reg){ B1_put_byte(base, READ_REGISTER); B1_put_word(base, reg); return B1_get_word(base); }static inline void b1_set_test_bit(unsigned int base, int cardtype, int onoff){ b1_wr_reg(base, B1_STAT0(cardtype), onoff ? 0x21 : 0x20);}static inline int b1_get_test_bit(unsigned int base, int cardtype){ return (b1_rd_reg(base, B1_STAT0(cardtype)) & 0x01) != 0;}static int irq_table[16] ={0, 0, 0, 192, /* irq 3 */ 32, /* irq 4 */ 160, /* irq 5 */ 96, /* irq 6 */ 224, /* irq 7 */ 0, 64, /* irq 9 */ 80, /* irq 10 */ 208, /* irq 11 */ 48, /* irq 12 */ 0, 0, 112, /* irq 15 */};static int hema_irq_table[16] ={0, 0, 0, 0x80, /* irq 3 */ 0, 0x90, /* irq 5 */ 0, 0xA0, /* irq 7 */ 0, 0xB0, /* irq 9 */ 0xC0, /* irq 10 */ 0xD0, /* irq 11 */ 0xE0, /* irq 12 */ 0, 0, 0xF0, /* irq 15 */};int B1_valid_irq(unsigned irq, int cardtype){ switch (cardtype) { default: case AVM_CARDTYPE_M1: case AVM_CARDTYPE_M2: case AVM_CARDTYPE_B1: return irq_table[irq & 0xf] != 0; case AVM_CARDTYPE_T1: return hema_irq_table[irq & 0xf] != 0; }}int B1_valid_port(unsigned port, int cardtype){ switch (cardtype) { default: case AVM_CARDTYPE_M1: case AVM_CARDTYPE_M2: case AVM_CARDTYPE_B1:#if 0 /* problem with PCMCIA and PCI cards */ switch (port) { case 0x150: case 0x250: case 0x300: case 0x340: return 1; } return 0;#else return 1;#endif case AVM_CARDTYPE_T1: return ((port & 0x7) == 0) && ((port & 0x30) != 0x30); }}void B1_setinterrupt(unsigned int base, unsigned irq, int cardtype){ switch (cardtype) { case AVM_CARDTYPE_T1: t1outp(base, B1_INSTAT, 0x00); t1outp(base, B1_INSTAT, 0x02); t1outp(base, T1_IRQMASTER, 0x08); default: case AVM_CARDTYPE_M1: case AVM_CARDTYPE_M2: case AVM_CARDTYPE_B1: b1outp(base, B1_INSTAT, 0x00); b1outp(base, B1_RESET, irq_table[irq]); b1outp(base, B1_INSTAT, 0x02); }}unsigned char B1_disable_irq(unsigned int base){ return b1outp(base, B1_INSTAT, 0x00);}void T1_disable_irq(unsigned int base){ t1outp(base, T1_IRQMASTER, 0x00);}void B1_reset(unsigned int base){ b1outp(base, B1_RESET, 0); udelay(55 * 2 * 1000); /* 2 TIC's */ b1outp(base, B1_RESET, 1); udelay(55 * 2 * 1000); /* 2 TIC's */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -