Ok. I didn't make 2.4.0 in 2000. Tough. I tried, but we had some
[davej-history.git] / drivers / isdn / hisax / hscx.c
blobd8338bc26d8d0d538d6d58f3658a1ebf50cefa1c
1 /* $Id: hscx.c,v 1.21 2000/11/24 17:05:37 kai Exp $
3 * hscx.c HSCX specific routines
5 * Author Karsten Keil (keil@isdn4linux.de)
7 * This file is (c) under GNU PUBLIC LICENSE
9 */
11 #define __NO_VERSION__
12 #include <linux/init.h>
13 #include "hisax.h"
14 #include "hscx.h"
15 #include "isac.h"
16 #include "isdnl1.h"
17 #include <linux/interrupt.h>
19 static char *HSCXVer[] __initdata =
20 {"A1", "?1", "A2", "?3", "A3", "V2.1", "?6", "?7",
21 "?8", "?9", "?10", "?11", "?12", "?13", "?14", "???"};
23 int __init
24 HscxVersion(struct IsdnCardState *cs, char *s)
26 int verA, verB;
28 verA = cs->BC_Read_Reg(cs, 0, HSCX_VSTR) & 0xf;
29 verB = cs->BC_Read_Reg(cs, 1, HSCX_VSTR) & 0xf;
30 printk(KERN_INFO "%s HSCX version A: %s B: %s\n", s,
31 HSCXVer[verA], HSCXVer[verB]);
32 if ((verA == 0) | (verA == 0xf) | (verB == 0) | (verB == 0xf))
33 return (1);
34 else
35 return (0);
38 void
39 modehscx(struct BCState *bcs, int mode, int bc)
41 struct IsdnCardState *cs = bcs->cs;
42 int hscx = bcs->hw.hscx.hscx;
44 if (cs->debug & L1_DEB_HSCX)
45 debugl1(cs, "hscx %c mode %d ichan %d",
46 'A' + hscx, mode, bc);
47 bcs->mode = mode;
48 bcs->channel = bc;
49 cs->BC_Write_Reg(cs, hscx, HSCX_XAD1, 0xFF);
50 cs->BC_Write_Reg(cs, hscx, HSCX_XAD2, 0xFF);
51 cs->BC_Write_Reg(cs, hscx, HSCX_RAH2, 0xFF);
52 cs->BC_Write_Reg(cs, hscx, HSCX_XBCH, 0x0);
53 cs->BC_Write_Reg(cs, hscx, HSCX_RLCR, 0x0);
54 cs->BC_Write_Reg(cs, hscx, HSCX_CCR1,
55 test_bit(HW_IPAC, &cs->HW_Flags) ? 0x82 : 0x85);
56 cs->BC_Write_Reg(cs, hscx, HSCX_CCR2, 0x30);
57 cs->BC_Write_Reg(cs, hscx, HSCX_XCCR, 7);
58 cs->BC_Write_Reg(cs, hscx, HSCX_RCCR, 7);
60 /* Switch IOM 1 SSI */
61 if (test_bit(HW_IOM1, &cs->HW_Flags) && (hscx == 0))
62 bc = 1 - bc;
64 if (bc == 0) {
65 cs->BC_Write_Reg(cs, hscx, HSCX_TSAX,
66 test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : bcs->hw.hscx.tsaxr0);
67 cs->BC_Write_Reg(cs, hscx, HSCX_TSAR,
68 test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : bcs->hw.hscx.tsaxr0);
69 } else {
70 cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, bcs->hw.hscx.tsaxr1);
71 cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, bcs->hw.hscx.tsaxr1);
73 switch (mode) {
74 case (L1_MODE_NULL):
75 cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, 0x1f);
76 cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, 0x1f);
77 cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0x84);
78 break;
79 case (L1_MODE_TRANS):
80 cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0xe4);
81 break;
82 case (L1_MODE_HDLC):
83 cs->BC_Write_Reg(cs, hscx, HSCX_CCR1,
84 test_bit(HW_IPAC, &cs->HW_Flags) ? 0x8a : 0x8d);
85 cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0x8c);
86 break;
88 if (mode)
89 cs->BC_Write_Reg(cs, hscx, HSCX_CMDR, 0x41);
90 cs->BC_Write_Reg(cs, hscx, HSCX_ISTA, 0x00);
93 void
94 hscx_sched_event(struct BCState *bcs, int event)
96 bcs->event |= 1 << event;
97 queue_task(&bcs->tqueue, &tq_immediate);
98 mark_bh(IMMEDIATE_BH);
101 void
102 hscx_l2l1(struct PStack *st, int pr, void *arg)
104 struct sk_buff *skb = arg;
105 long flags;
107 switch (pr) {
108 case (PH_DATA | REQUEST):
109 save_flags(flags);
110 cli();
111 if (st->l1.bcs->tx_skb) {
112 skb_queue_tail(&st->l1.bcs->squeue, skb);
113 restore_flags(flags);
114 } else {
115 st->l1.bcs->tx_skb = skb;
116 test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
117 st->l1.bcs->hw.hscx.count = 0;
118 restore_flags(flags);
119 st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
121 break;
122 case (PH_PULL | INDICATION):
123 if (st->l1.bcs->tx_skb) {
124 printk(KERN_WARNING "hscx_l2l1: this shouldn't happen\n");
125 break;
127 test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
128 st->l1.bcs->tx_skb = skb;
129 st->l1.bcs->hw.hscx.count = 0;
130 st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
131 break;
132 case (PH_PULL | REQUEST):
133 if (!st->l1.bcs->tx_skb) {
134 test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
135 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
136 } else
137 test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
138 break;
139 case (PH_ACTIVATE | REQUEST):
140 test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
141 modehscx(st->l1.bcs, st->l1.mode, st->l1.bc);
142 l1_msg_b(st, pr, arg);
143 break;
144 case (PH_DEACTIVATE | REQUEST):
145 l1_msg_b(st, pr, arg);
146 break;
147 case (PH_DEACTIVATE | CONFIRM):
148 test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
149 test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
150 modehscx(st->l1.bcs, 0, st->l1.bc);
151 st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
152 break;
156 void
157 close_hscxstate(struct BCState *bcs)
159 modehscx(bcs, 0, bcs->channel);
160 if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
161 if (bcs->hw.hscx.rcvbuf) {
162 kfree(bcs->hw.hscx.rcvbuf);
163 bcs->hw.hscx.rcvbuf = NULL;
165 if (bcs->blog) {
166 kfree(bcs->blog);
167 bcs->blog = NULL;
169 discard_queue(&bcs->rqueue);
170 discard_queue(&bcs->squeue);
171 if (bcs->tx_skb) {
172 dev_kfree_skb_any(bcs->tx_skb);
173 bcs->tx_skb = NULL;
174 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
180 open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs)
182 if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
183 if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
184 printk(KERN_WARNING
185 "HiSax: No memory for hscx.rcvbuf\n");
186 test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
187 return (1);
189 if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
190 printk(KERN_WARNING
191 "HiSax: No memory for bcs->blog\n");
192 test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
193 kfree(bcs->hw.hscx.rcvbuf);
194 bcs->hw.hscx.rcvbuf = NULL;
195 return (2);
197 skb_queue_head_init(&bcs->rqueue);
198 skb_queue_head_init(&bcs->squeue);
200 bcs->tx_skb = NULL;
201 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
202 bcs->event = 0;
203 bcs->hw.hscx.rcvidx = 0;
204 bcs->tx_cnt = 0;
205 return (0);
209 setstack_hscx(struct PStack *st, struct BCState *bcs)
211 bcs->channel = st->l1.bc;
212 if (open_hscxstate(st->l1.hardware, bcs))
213 return (-1);
214 st->l1.bcs = bcs;
215 st->l2.l2l1 = hscx_l2l1;
216 setstack_manager(st);
217 bcs->st = st;
218 setstack_l1_B(st);
219 return (0);
222 void __init
223 clear_pending_hscx_ints(struct IsdnCardState *cs)
225 int val, eval;
227 val = cs->BC_Read_Reg(cs, 1, HSCX_ISTA);
228 debugl1(cs, "HSCX B ISTA %x", val);
229 if (val & 0x01) {
230 eval = cs->BC_Read_Reg(cs, 1, HSCX_EXIR);
231 debugl1(cs, "HSCX B EXIR %x", eval);
233 if (val & 0x02) {
234 eval = cs->BC_Read_Reg(cs, 0, HSCX_EXIR);
235 debugl1(cs, "HSCX A EXIR %x", eval);
237 val = cs->BC_Read_Reg(cs, 0, HSCX_ISTA);
238 debugl1(cs, "HSCX A ISTA %x", val);
239 val = cs->BC_Read_Reg(cs, 1, HSCX_STAR);
240 debugl1(cs, "HSCX B STAR %x", val);
241 val = cs->BC_Read_Reg(cs, 0, HSCX_STAR);
242 debugl1(cs, "HSCX A STAR %x", val);
243 /* disable all IRQ */
244 cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0xFF);
245 cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0xFF);
248 void __init
249 inithscx(struct IsdnCardState *cs)
251 cs->bcs[0].BC_SetStack = setstack_hscx;
252 cs->bcs[1].BC_SetStack = setstack_hscx;
253 cs->bcs[0].BC_Close = close_hscxstate;
254 cs->bcs[1].BC_Close = close_hscxstate;
255 cs->bcs[0].hw.hscx.hscx = 0;
256 cs->bcs[1].hw.hscx.hscx = 1;
257 cs->bcs[0].hw.hscx.tsaxr0 = 0x2f;
258 cs->bcs[0].hw.hscx.tsaxr1 = 3;
259 cs->bcs[1].hw.hscx.tsaxr0 = 0x2f;
260 cs->bcs[1].hw.hscx.tsaxr1 = 3;
261 modehscx(cs->bcs, 0, 0);
262 modehscx(cs->bcs + 1, 0, 0);
265 void __init
266 inithscxisac(struct IsdnCardState *cs, int part)
268 if (part & 1) {
269 clear_pending_isac_ints(cs);
270 clear_pending_hscx_ints(cs);
271 initisac(cs);
272 inithscx(cs);
274 if (part & 2) {
275 /* Reenable all IRQ */
276 cs->writeisac(cs, ISAC_MASK, 0);
277 cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0);
278 cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0);
279 /* RESET Receiver and Transmitter */
280 cs->writeisac(cs, ISAC_CMDR, 0x41);