summaryrefslogtreecommitdiffstats
path: root/drivers/isdn/avmb1/b1lli.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-05-07 02:55:41 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-05-07 02:55:41 +0000
commitdcec8a13bf565e47942a1751a9cec21bec5648fe (patch)
tree548b69625b18cc2e88c3e68d0923be546c9ebb03 /drivers/isdn/avmb1/b1lli.c
parent2e0f55e79c49509b7ff70ff1a10e1e9e90a3dfd4 (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.c313
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: