diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-05-07 02:55:41 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-05-07 02:55:41 +0000 |
commit | dcec8a13bf565e47942a1751a9cec21bec5648fe (patch) | |
tree | 548b69625b18cc2e88c3e68d0923be546c9ebb03 /drivers/isdn/avmb1/b1lli.c | |
parent | 2e0f55e79c49509b7ff70ff1a10e1e9e90a3dfd4 (diff) |
o Merge with Linux 2.1.99.
o Fix ancient bug in the ELF loader making ldd crash.
o Fix ancient bug in the keyboard code for SGI, SNI and Jazz.
Diffstat (limited to 'drivers/isdn/avmb1/b1lli.c')
-rw-r--r-- | drivers/isdn/avmb1/b1lli.c | 313 |
1 files changed, 234 insertions, 79 deletions
diff --git a/drivers/isdn/avmb1/b1lli.c b/drivers/isdn/avmb1/b1lli.c index 64292ef21..1c4c0b806 100644 --- a/drivers/isdn/avmb1/b1lli.c +++ b/drivers/isdn/avmb1/b1lli.c @@ -1,11 +1,35 @@ /* - * $Id: b1lli.c,v 1.1 1997/03/04 21:50:28 calle Exp $ + * $Id: b1lli.c,v 1.6 1998/02/13 07:09:11 calle 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.6 1998/02/13 07:09:11 calle + * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() + * + * Revision 1.5 1998/01/31 11:14:41 calle + * merged changes to 2.0 tree, prepare 2.1.82 to work. + * + * Revision 1.4 1997/12/10 20:00:48 calle + * get changes from 2.0 version + * + * 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.3 1997/10/01 09:21:13 fritz + * Removed old compatibility stuff for 2.0.X kernels. + * From now on, this code is for 2.1.X ONLY! + * Old stuff is still in the separate branch. + * + * Revision 1.2 1997/07/13 12:22:42 calle + * bug fix for more than one controller in connect_req. + * debugoutput now with contrnr. + * + * * Revision 1.1 1997/03/04 21:50:28 calle * Frirst version in isdn4linux * @@ -66,6 +90,9 @@ * B3Length data .... */ +#define SEND_CONFIG 0x21 /* + */ + /* * LLI Messages from the ISDN-ControllerISDN Controller */ @@ -110,6 +137,9 @@ * int32 AppllID int32 0xffffffff */ +#define WRITE_REGISTER 0x00 +#define READ_REGISTER 0x01 + /* * port offsets */ @@ -120,7 +150,11 @@ #define B1_OUTSTAT 0x03 #define B1_RESET 0x10 #define B1_ANALYSE 0x04 +#define B1_IDENT 0x17 /* Hema card T1 */ +#define B1_IRQ_MASTER 0x12 /* Hema card T1 */ +#define B1_STAT0(cardtype) ((cardtype) == AVM_CARDTYPE_M1 ? 0x81200000l : 0x80A00000l) +#define B1_STAT1(cardtype) (0x80E00000l) static inline unsigned char b1outp(unsigned short base, @@ -131,6 +165,100 @@ static inline unsigned char b1outp(unsigned short base, return inb(base + B1_ANALYSE); } +static inline int B1_rx_full(unsigned short base) +{ + return inb(base + B1_INSTAT) & 0x1; +} + +static inline unsigned char B1_get_byte(unsigned short base) +{ + unsigned long i = jiffies + 5 * HZ; /* maximum wait time 5 sec */ + while (!B1_rx_full(base) && i > jiffies); + if (B1_rx_full(base)) + return inb(base + B1_READ); + printk(KERN_CRIT "b1lli: rx not full after 5 second\n"); + return 0; +} + +static inline unsigned int B1_get_word(unsigned short 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 short base) +{ + return inb(base + B1_OUTSTAT) & 0x1; +} + +static inline void B1_put_byte(unsigned short base, unsigned char val) +{ + while (!B1_tx_empty(base)); + b1outp(base, B1_WRITE, val); +} + +static inline void B1_put_word(unsigned short 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 short base, + unsigned char *dp) +{ + unsigned int len, i; + + len = i = B1_get_word(base); + while (i-- > 0) + *dp++ = B1_get_byte(base); + return len; +} + +static inline void B1_put_slice(unsigned short base, + unsigned char *dp, unsigned int len) +{ + B1_put_word(base, len); + while (len-- > 0) + B1_put_byte(base, *dp++); +} + +static void b1_wr_reg(unsigned short 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 short 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 short base, + int cardtype, + int onoff) +{ + b1_wr_reg(base, B1_STAT0(cardtype), onoff ? 0x21 : 0x20); +} + +static inline int b1_get_test_bit(unsigned short base, + int cardtype) +{ + return (b1_rd_reg(base, B1_STAT0(cardtype)) & 0x01) != 0; +} + static int irq_table[16] = {0, 0, @@ -150,14 +278,30 @@ static int irq_table[16] = 112, /* irq 15 */ }; -int B1_valid_irq(unsigned irq) +int B1_valid_irq(unsigned irq, int cardtype) { - return irq_table[irq] != 0; + switch (cardtype) { + default: + case AVM_CARDTYPE_M1: + case AVM_CARDTYPE_M2: + case AVM_CARDTYPE_B1: + return irq_table[irq] != 0; + case AVM_CARDTYPE_T1: + return irq == 5; + } } -unsigned char B1_assign_irq(unsigned short base, unsigned irq) +unsigned char B1_assign_irq(unsigned short base, unsigned irq, int cardtype) { - return b1outp(base, B1_RESET, irq_table[irq]); + switch (cardtype) { + case AVM_CARDTYPE_T1: + return b1outp(base, B1_IRQ_MASTER, 0x08); + default: + case AVM_CARDTYPE_M1: + case AVM_CARDTYPE_M2: + case AVM_CARDTYPE_B1: + return b1outp(base, B1_RESET, irq_table[irq]); + } } unsigned char B1_enable_irq(unsigned short base) @@ -182,24 +326,27 @@ void B1_reset(unsigned short base) udelay(55 * 2 * 1000); /* 2 TIC's */ } -int B1_detect(unsigned short base) +int B1_detect(unsigned short base, int cardtype) { + int onoff, i; + + if (cardtype == AVM_CARDTYPE_T1) + return 0; + /* * Statusregister 0000 00xx */ if ((inb(base + B1_INSTAT) & 0xfc) || (inb(base + B1_OUTSTAT) & 0xfc)) return 1; - /* * Statusregister 0000 001x */ b1outp(base, B1_INSTAT, 0x2); /* enable irq */ - b1outp(base, B1_OUTSTAT, 0x2); + /* b1outp(base, B1_OUTSTAT, 0x2); */ if ((inb(base + B1_INSTAT) & 0xfe) != 0x2 - || (inb(base + B1_OUTSTAT) & 0xfe) != 0x2) + /* || (inb(base + B1_OUTSTAT) & 0xfe) != 0x2 */) return 2; - /* * Statusregister 0000 000x */ @@ -208,72 +355,23 @@ int B1_detect(unsigned short base) if ((inb(base + B1_INSTAT) & 0xfe) || (inb(base + B1_OUTSTAT) & 0xfe)) return 3; + + for (onoff = !0, i= 0; i < 10 ; i++) { + b1_set_test_bit(base, cardtype, onoff); + if (b1_get_test_bit(base, cardtype) != onoff) + return 4; + onoff = !onoff; + } - return 0; -} + if (cardtype == AVM_CARDTYPE_M1) + return 0; -static inline int B1_rx_full(unsigned short base) -{ - return inb(base + B1_INSTAT) & 0x1; -} + if ((b1_rd_reg(base, B1_STAT1(cardtype)) & 0x0f) != 0x01) + return 5; -static inline unsigned char B1_get_byte(unsigned short base) -{ - unsigned long i = jiffies + 5 * HZ; /* maximum wait time 5 sec */ - while (!B1_rx_full(base) && i > jiffies); - if (B1_rx_full(base)) - return inb(base + B1_READ); - printk(KERN_CRIT "b1lli: rx not full after 5 second\n"); return 0; } -static inline unsigned int B1_get_word(unsigned short 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 short base) -{ - return inb(base + B1_OUTSTAT) & 0x1; -} - -static inline void B1_put_byte(unsigned short base, unsigned char val) -{ - while (!B1_tx_empty(base)); - b1outp(base, B1_WRITE, val); -} - -static inline void B1_put_word(unsigned short 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 short base, - unsigned char *dp) -{ - unsigned int len, i; - - len = i = B1_get_word(base); - while (i-- > 0) - *dp++ = B1_get_byte(base); - return len; -} - -static inline void B1_put_slice(unsigned short base, - unsigned char *dp, unsigned int len) -{ - B1_put_word(base, len); - while (len-- > 0) - B1_put_byte(base, *dp++); -} extern int loaddebug; @@ -316,6 +414,62 @@ int B1_load_t4file(unsigned short base, avmb1_t4file * t4file) return 0; } +int B1_load_config(unsigned short base, avmb1_t4file * config) +{ + /* + * Data is in user space !!! + */ + unsigned char buf[256]; + unsigned char *dp; + int i, j, left, retval; + + + dp = config->data; + left = config->len; + if (left) { + B1_put_byte(base, SEND_CONFIG); + B1_put_word(base, 1); + B1_put_byte(base, SEND_CONFIG); + B1_put_word(base, left); + } + while (left > sizeof(buf)) { + retval = copy_from_user(buf, dp, sizeof(buf)); + if (retval) + return -EFAULT; + if (loaddebug) + printk(KERN_DEBUG "b1capi: conf load: %d bytes ..", sizeof(buf)); + for (i = 0; i < sizeof(buf); ) { + B1_put_byte(base, SEND_CONFIG); + for (j=0; j < 4; j++) { + B1_put_byte(base, buf[i++]); + } + } + if (loaddebug) + printk("ok\n"); + left -= sizeof(buf); + dp += sizeof(buf); + } + if (left) { + retval = copy_from_user(buf, dp, left); + if (retval) + return -EFAULT; + if (loaddebug) + printk(KERN_DEBUG "b1capi: conf load: %d bytes ..", left); + for (i = 0; i < left; ) { + B1_put_byte(base, SEND_CONFIG); + for (j=0; j < 4; j++) { + if (i < left) + B1_put_byte(base, buf[i++]); + else + B1_put_byte(base, 0); + } + } + if (loaddebug) + printk("ok\n"); + } + return 0; +} + int B1_loaded(unsigned short base) { int i; @@ -428,7 +582,9 @@ void B1_send_message(unsigned short port, struct sk_buff *skb) CAPIMSG_APPID(skb->data), capi_cmd2str(cmd, subcmd), len); } else { - printk(KERN_DEBUG "b1lli: Put %s\n", capi_message2str(skb->data)); + printk(KERN_DEBUG "b1lli: Put [0x%lx] %s\n", + (unsigned long) contr, + capi_message2str(skb->data)); } } @@ -447,7 +603,7 @@ void B1_send_message(unsigned short port, struct sk_buff *skb) CAPIMSG_APPID(skb->data), capi_cmd2str(cmd, subcmd), len); } else { - printk(KERN_DEBUG "b1lli: Put %s\n", capi_message2str(skb->data)); + printk(KERN_DEBUG "b1lli: Put [0x%lx] %s\n", (unsigned long)contr, capi_message2str(skb->data)); } } save_flags(flags); @@ -499,13 +655,12 @@ void B1_handle_interrupt(avmb1_card * card) capi_cmd2str(cmd, subcmd), MsgLen, DataB3Len); } else { - printk(KERN_DEBUG "b1lli: Got %s\n", capi_message2str(card->msgbuf)); + printk(KERN_DEBUG "b1lli: Got [0x%lx] %s\n", (unsigned long)contr, capi_message2str(card->msgbuf)); } } if (!(skb = dev_alloc_skb(DataB3Len + MsgLen))) { printk(KERN_ERR "b1lli: incoming packet dropped\n"); } else { - SET_SKB_FREE(skb); memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len); CAPIMSG_SETDATA(skb->data, skb->data + MsgLen); @@ -528,14 +683,15 @@ void B1_handle_interrupt(avmb1_card * card) capi_cmd2str(cmd, subcmd), MsgLen); } else { - printk(KERN_DEBUG "b1lli: Got %s\n", capi_message2str(card->msgbuf)); + printk(KERN_DEBUG "b1lli: Got [0x%lx] %s\n", + (unsigned long) contr, + capi_message2str(card->msgbuf)); } } if (!(skb = dev_alloc_skb(MsgLen))) { printk(KERN_ERR "b1lli: incoming packet dropped\n"); } else { - SET_SKB_FREE(skb); memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); avmb1_handle_capimsg(card, ApplId, skb); } @@ -581,10 +737,9 @@ void B1_handle_interrupt(avmb1_card * card) card->versionlen = B1_get_slice(card->port, card->versionbuf); card->cardstate = CARD_ACTIVE; parse_version(card); - printk(KERN_INFO "b1lli: %s-card (%s) with %s now active\n", + printk(KERN_INFO "b1lli: %s-card (%s) now active\n", card->version[VER_CARDTYPE], - card->version[VER_DRIVER], - card->version[VER_PROTO]); + card->version[VER_DRIVER]); avmb1_card_ready(card); break; default: |