pre-2.3.4..
[davej-history.git] / drivers / isdn / hisax / hscx.c
blob980dc76e8a663f4833b1e1be3d4999a92fde1f6e
1 /* $Id: hscx.c,v 1.16 1998/11/15 23:54:48 keil Exp $
3 * hscx.c HSCX specific routines
5 * Author Karsten Keil (keil@isdn4linux.de)
8 * $Log: hscx.c,v $
9 * Revision 1.16 1998/11/15 23:54:48 keil
10 * changes from 2.0
12 * Revision 1.15 1998/08/20 13:50:42 keil
13 * More support for hybrid modem (not working yet)
15 * Revision 1.14 1998/08/13 23:36:33 keil
16 * HiSax 3.1 - don't work stable with current LinkLevel
18 * Revision 1.13 1998/06/26 22:03:28 keil
19 * send flags between hdlc frames
21 * Revision 1.12 1998/06/09 18:26:01 keil
22 * PH_DEACTIVATE B-channel every time signaled to higher layer
24 * Revision 1.11 1998/05/25 14:10:07 keil
25 * HiSax 3.0
26 * X.75 and leased are working again.
28 * Revision 1.10 1998/05/25 12:57:59 keil
29 * HiSax golden code from certification, Don't use !!!
30 * No leased lines, no X75, but many changes.
32 * Revision 1.9 1998/04/15 16:45:33 keil
33 * new init code
35 * Revision 1.8 1998/03/19 13:16:24 keil
36 * fix the correct release of the hscx
38 * Revision 1.7 1998/02/12 23:07:36 keil
39 * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
41 * Revision 1.6 1998/02/02 13:41:12 keil
42 * new init
44 * Revision 1.5 1997/11/06 17:09:34 keil
45 * New 2.1 init code
47 * Revision 1.4 1997/10/29 19:01:06 keil
48 * changes for 2.1
50 * Revision 1.3 1997/07/27 21:38:34 keil
51 * new B-channel interface
53 * Revision 1.2 1997/06/26 11:16:17 keil
54 * first version
59 #define __NO_VERSION__
60 #include "hisax.h"
61 #include "hscx.h"
62 #include "isac.h"
63 #include "isdnl1.h"
64 #include <linux/interrupt.h>
66 static char *HSCXVer[] HISAX_INITDATA =
67 {"A1", "?1", "A2", "?3", "A3", "V2.1", "?6", "?7",
68 "?8", "?9", "?10", "?11", "?12", "?13", "?14", "???"};
70 HISAX_INITFUNC(int
71 HscxVersion(struct IsdnCardState *cs, char *s))
73 int verA, verB;
75 verA = cs->BC_Read_Reg(cs, 0, HSCX_VSTR) & 0xf;
76 verB = cs->BC_Read_Reg(cs, 1, HSCX_VSTR) & 0xf;
77 printk(KERN_INFO "%s HSCX version A: %s B: %s\n", s,
78 HSCXVer[verA], HSCXVer[verB]);
79 if ((verA == 0) | (verA == 0xf) | (verB == 0) | (verB == 0xf))
80 return (1);
81 else
82 return (0);
85 void
86 modehscx(struct BCState *bcs, int mode, int bc)
88 struct IsdnCardState *cs = bcs->cs;
89 int hscx = bcs->hw.hscx.hscx;
91 if (cs->debug & L1_DEB_HSCX)
92 debugl1(cs, "hscx %c mode %d ichan %d",
93 'A' + hscx, mode, bc);
94 bcs->mode = mode;
95 bcs->channel = bc;
96 cs->BC_Write_Reg(cs, hscx, HSCX_XAD1, 0xFF);
97 cs->BC_Write_Reg(cs, hscx, HSCX_XAD2, 0xFF);
98 cs->BC_Write_Reg(cs, hscx, HSCX_RAH2, 0xFF);
99 cs->BC_Write_Reg(cs, hscx, HSCX_XBCH, 0x0);
100 cs->BC_Write_Reg(cs, hscx, HSCX_RLCR, 0x0);
101 cs->BC_Write_Reg(cs, hscx, HSCX_CCR1,
102 test_bit(HW_IPAC, &cs->HW_Flags) ? 0x82 : 0x85);
103 cs->BC_Write_Reg(cs, hscx, HSCX_CCR2, 0x30);
104 cs->BC_Write_Reg(cs, hscx, HSCX_XCCR, 7);
105 cs->BC_Write_Reg(cs, hscx, HSCX_RCCR, 7);
107 /* Switch IOM 1 SSI */
108 if (test_bit(HW_IOM1, &cs->HW_Flags) && (hscx == 0))
109 bc = 1 - bc;
111 if (bc == 0) {
112 cs->BC_Write_Reg(cs, hscx, HSCX_TSAX,
113 test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : 0x2f);
114 cs->BC_Write_Reg(cs, hscx, HSCX_TSAR,
115 test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : 0x2f);
116 } else {
117 cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, 0x3);
118 cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, 0x3);
120 switch (mode) {
121 case (L1_MODE_NULL):
122 cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, 0x1f);
123 cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, 0x1f);
124 cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0x84);
125 break;
126 case (L1_MODE_TRANS):
127 cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0xe4);
128 break;
129 case (L1_MODE_HDLC):
130 cs->BC_Write_Reg(cs, hscx, HSCX_CCR1,
131 test_bit(HW_IPAC, &cs->HW_Flags) ? 0x8a : 0x8d);
132 cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0x8c);
133 break;
135 if (mode)
136 cs->BC_Write_Reg(cs, hscx, HSCX_CMDR, 0x41);
137 cs->BC_Write_Reg(cs, hscx, HSCX_ISTA, 0x00);
140 void
141 hscx_sched_event(struct BCState *bcs, int event)
143 bcs->event |= 1 << event;
144 queue_task(&bcs->tqueue, &tq_immediate);
145 mark_bh(IMMEDIATE_BH);
148 void
149 hscx_l2l1(struct PStack *st, int pr, void *arg)
151 struct sk_buff *skb = arg;
152 long flags;
154 switch (pr) {
155 case (PH_DATA | REQUEST):
156 save_flags(flags);
157 cli();
158 if (st->l1.bcs->tx_skb) {
159 skb_queue_tail(&st->l1.bcs->squeue, skb);
160 restore_flags(flags);
161 } else {
162 st->l1.bcs->tx_skb = skb;
163 test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
164 st->l1.bcs->hw.hscx.count = 0;
165 restore_flags(flags);
166 st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
168 break;
169 case (PH_PULL | INDICATION):
170 if (st->l1.bcs->tx_skb) {
171 printk(KERN_WARNING "hscx_l2l1: this shouldn't happen\n");
172 break;
174 test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
175 st->l1.bcs->tx_skb = skb;
176 st->l1.bcs->hw.hscx.count = 0;
177 st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
178 break;
179 case (PH_PULL | REQUEST):
180 if (!st->l1.bcs->tx_skb) {
181 test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
182 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
183 } else
184 test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
185 break;
186 case (PH_ACTIVATE | REQUEST):
187 test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
188 modehscx(st->l1.bcs, st->l1.mode, st->l1.bc);
189 l1_msg_b(st, pr, arg);
190 break;
191 case (PH_DEACTIVATE | REQUEST):
192 l1_msg_b(st, pr, arg);
193 break;
194 case (PH_DEACTIVATE | CONFIRM):
195 test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
196 test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
197 modehscx(st->l1.bcs, 0, st->l1.bc);
198 st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
199 break;
203 void
204 close_hscxstate(struct BCState *bcs)
206 modehscx(bcs, 0, bcs->channel);
207 if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
208 if (bcs->hw.hscx.rcvbuf) {
209 kfree(bcs->hw.hscx.rcvbuf);
210 bcs->hw.hscx.rcvbuf = NULL;
212 if (bcs->blog) {
213 kfree(bcs->blog);
214 bcs->blog = NULL;
216 discard_queue(&bcs->rqueue);
217 discard_queue(&bcs->squeue);
218 if (bcs->tx_skb) {
219 dev_kfree_skb(bcs->tx_skb);
220 bcs->tx_skb = NULL;
221 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
227 open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs)
229 if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
230 if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
231 printk(KERN_WARNING
232 "HiSax: No memory for hscx.rcvbuf\n");
233 test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
234 return (1);
236 if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
237 printk(KERN_WARNING
238 "HiSax: No memory for bcs->blog\n");
239 test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
240 kfree(bcs->hw.hscx.rcvbuf);
241 bcs->hw.hscx.rcvbuf = NULL;
242 return (2);
244 skb_queue_head_init(&bcs->rqueue);
245 skb_queue_head_init(&bcs->squeue);
247 bcs->tx_skb = NULL;
248 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
249 bcs->event = 0;
250 bcs->hw.hscx.rcvidx = 0;
251 bcs->tx_cnt = 0;
252 return (0);
256 setstack_hscx(struct PStack *st, struct BCState *bcs)
258 bcs->channel = st->l1.bc;
259 if (open_hscxstate(st->l1.hardware, bcs))
260 return (-1);
261 st->l1.bcs = bcs;
262 st->l2.l2l1 = hscx_l2l1;
263 setstack_manager(st);
264 bcs->st = st;
265 setstack_l1_B(st);
266 return (0);
269 HISAX_INITFUNC(void
270 clear_pending_hscx_ints(struct IsdnCardState *cs))
272 int val, eval;
274 val = cs->BC_Read_Reg(cs, 1, HSCX_ISTA);
275 debugl1(cs, "HSCX B ISTA %x", val);
276 if (val & 0x01) {
277 eval = cs->BC_Read_Reg(cs, 1, HSCX_EXIR);
278 debugl1(cs, "HSCX B EXIR %x", eval);
280 if (val & 0x02) {
281 eval = cs->BC_Read_Reg(cs, 0, HSCX_EXIR);
282 debugl1(cs, "HSCX A EXIR %x", eval);
284 val = cs->BC_Read_Reg(cs, 0, HSCX_ISTA);
285 debugl1(cs, "HSCX A ISTA %x", val);
286 val = cs->BC_Read_Reg(cs, 1, HSCX_STAR);
287 debugl1(cs, "HSCX B STAR %x", val);
288 val = cs->BC_Read_Reg(cs, 0, HSCX_STAR);
289 debugl1(cs, "HSCX A STAR %x", val);
290 /* disable all IRQ */
291 cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0xFF);
292 cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0xFF);
295 HISAX_INITFUNC(void
296 inithscx(struct IsdnCardState *cs))
298 cs->bcs[0].BC_SetStack = setstack_hscx;
299 cs->bcs[1].BC_SetStack = setstack_hscx;
300 cs->bcs[0].BC_Close = close_hscxstate;
301 cs->bcs[1].BC_Close = close_hscxstate;
302 cs->bcs[0].hw.hscx.hscx = 0;
303 cs->bcs[1].hw.hscx.hscx = 1;
304 modehscx(cs->bcs, 0, 0);
305 modehscx(cs->bcs + 1, 0, 0);
308 HISAX_INITFUNC(void
309 inithscxisac(struct IsdnCardState *cs, int part))
311 if (part & 1) {
312 clear_pending_isac_ints(cs);
313 clear_pending_hscx_ints(cs);
314 initisac(cs);
315 inithscx(cs);
317 if (part & 2) {
318 /* Reenable all IRQ */
319 cs->writeisac(cs, ISAC_MASK, 0);
320 cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0);
321 cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0);
322 /* RESET Receiver and Transmitter */
323 cs->writeisac(cs, ISAC_CMDR, 0x41);