Hopefully get the Kconfig PCI stuff right, finally.
[linux-2.6/linux-mips.git] / drivers / isdn / hisax / isac.c
blob10154acd8fc37e217a2bcb55b7fcf225b6223b3b
1 /* $Id: isac.c,v 1.28.6.3 2001/09/23 22:24:49 kai Exp $
3 * ISAC specific routines
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
7 *
8 * This software may be used and distributed according to the terms
9 * of the GNU General Public License, incorporated herein by reference.
11 * For changes and modifications please read
12 * ../../../Documentation/isdn/HiSax.cert
16 #include "hisax.h"
17 #include "isac.h"
18 #include "arcofi.h"
19 #include "isdnl1.h"
20 #include <linux/interrupt.h>
21 #include <linux/init.h>
23 #define DBUSY_TIMER_VALUE 80
24 #define ARCOFI_USE 1
26 static char *ISACVer[] __devinitdata =
27 {"2086/2186 V1.1", "2085 B1", "2085 B2",
28 "2085 V2.3"};
30 static inline u8
31 isac_read(struct IsdnCardState *cs, u8 addr)
33 return cs->dc_hw_ops->read_reg(cs, addr);
36 static inline void
37 isac_write(struct IsdnCardState *cs, u8 addr, u8 val)
39 cs->dc_hw_ops->write_reg(cs, addr, val);
42 static inline void
43 isac_write_fifo(struct IsdnCardState *cs, u8 *p, int len)
45 return cs->dc_hw_ops->write_fifo(cs, p, len);
48 static void
49 ISACVersion(struct IsdnCardState *cs, char *s)
51 int val;
53 val = isac_read(cs, ISAC_RBCH);
54 printk(KERN_INFO "%s ISAC version (%x): %s\n", s, val, ISACVer[(val >> 5) & 3]);
57 static void
58 ph_command(struct IsdnCardState *cs, unsigned int command)
60 if (cs->debug & L1_DEB_ISAC)
61 debugl1(cs, "ph_command %x", command);
62 isac_write(cs, ISAC_CIX0, (command << 2) | 3);
66 static void
67 isac_new_ph(struct IsdnCardState *cs)
69 switch (cs->dc.isac.ph_state) {
70 case (ISAC_IND_RS):
71 case (ISAC_IND_EI):
72 ph_command(cs, ISAC_CMD_DUI);
73 l1_msg(cs, HW_RESET | INDICATION, NULL);
74 break;
75 case (ISAC_IND_DID):
76 l1_msg(cs, HW_DEACTIVATE | CONFIRM, NULL);
77 break;
78 case (ISAC_IND_DR):
79 l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
80 break;
81 case (ISAC_IND_PU):
82 l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
83 break;
84 case (ISAC_IND_RSY):
85 l1_msg(cs, HW_RSYNC | INDICATION, NULL);
86 break;
87 case (ISAC_IND_ARD):
88 l1_msg(cs, HW_INFO2 | INDICATION, NULL);
89 break;
90 case (ISAC_IND_AI8):
91 l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
92 break;
93 case (ISAC_IND_AI10):
94 l1_msg(cs, HW_INFO4_P10 | INDICATION, NULL);
95 break;
96 default:
97 break;
101 static void
102 isac_bh(void *data)
104 struct IsdnCardState *cs = data;
105 struct PStack *stptr;
107 if (!cs)
108 return;
109 if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
110 if (cs->debug)
111 debugl1(cs, "D-Channel Busy cleared");
112 stptr = cs->stlist;
113 while (stptr != NULL) {
114 L1L2(stptr, PH_PAUSE | CONFIRM, NULL);
115 stptr = stptr->next;
118 if (test_and_clear_bit(D_L1STATECHANGE, &cs->event))
119 isac_new_ph(cs);
120 if (test_and_clear_bit(D_RCVBUFREADY, &cs->event))
121 DChannel_proc_rcv(cs);
122 if (test_and_clear_bit(D_XMTBUFREADY, &cs->event))
123 DChannel_proc_xmt(cs);
124 #if ARCOFI_USE
125 if (!test_bit(HW_ARCOFI, &cs->HW_Flags))
126 return;
127 if (test_and_clear_bit(D_RX_MON1, &cs->event))
128 arcofi_fsm(cs, ARCOFI_RX_END, NULL);
129 if (test_and_clear_bit(D_TX_MON1, &cs->event))
130 arcofi_fsm(cs, ARCOFI_TX_END, NULL);
131 #endif
134 void
135 isac_empty_fifo(struct IsdnCardState *cs, int count)
137 recv_empty_fifo_d(cs, count);
138 isac_write(cs, ISAC_CMDR, 0x80);
141 static void
142 isac_fill_fifo(struct IsdnCardState *cs)
144 int count, more;
145 unsigned char *p;
147 p = xmit_fill_fifo_d(cs, 32, &count, &more);
148 if (!p)
149 return;
151 isac_write_fifo(cs, p, count);
152 isac_write(cs, ISAC_CMDR, more ? 0x8 : 0xa);
153 if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
154 debugl1(cs, "isac_fill_fifo dbusytimer running");
155 del_timer(&cs->dbusytimer);
157 init_timer(&cs->dbusytimer);
158 cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
159 add_timer(&cs->dbusytimer);
162 void
163 isac_interrupt(struct IsdnCardState *cs, u8 val)
165 u8 exval, v1;
166 unsigned int count;
168 if (cs->debug & L1_DEB_ISAC)
169 debugl1(cs, "ISAC interrupt %x", val);
170 if (val & 0x80) { /* RME */
171 exval = isac_read(cs, ISAC_RSTA);
172 if ((exval & 0x70) != 0x20) {
173 if (exval & 0x40) {
174 if (cs->debug & L1_DEB_WARN)
175 debugl1(cs, "ISAC RDO");
176 #ifdef ERROR_STATISTIC
177 cs->err_rx++;
178 #endif
180 if (!(exval & 0x20)) {
181 if (cs->debug & L1_DEB_WARN)
182 debugl1(cs, "ISAC CRC error");
183 #ifdef ERROR_STATISTIC
184 cs->err_crc++;
185 #endif
187 isac_write(cs, ISAC_CMDR, 0x80);
188 cs->rcvidx = 0;
189 } else {
190 count = isac_read(cs, ISAC_RBCL) & 0x1f;
191 if (count == 0)
192 count = 32;
193 isac_empty_fifo(cs, count);
194 recv_rme_d(cs);
196 cs->rcvidx = 0;
197 sched_d_event(cs, D_RCVBUFREADY);
199 if (val & 0x40) { /* RPF */
200 isac_empty_fifo(cs, 32);
202 if (val & 0x20) { /* RSC */
203 /* never */
204 if (cs->debug & L1_DEB_WARN)
205 debugl1(cs, "ISAC RSC interrupt");
207 if (val & 0x10) { /* XPR */
208 xmit_xpr_d(cs);
210 if (val & 0x04) { /* CISQ */
211 exval = isac_read(cs, ISAC_CIR0);
212 if (cs->debug & L1_DEB_ISAC)
213 debugl1(cs, "ISAC CIR0 %02X", exval );
214 if (exval & 2) {
215 cs->dc.isac.ph_state = (exval >> 2) & 0xf;
216 if (cs->debug & L1_DEB_ISAC)
217 debugl1(cs, "ph_state change %x", cs->dc.isac.ph_state);
218 sched_d_event(cs, D_L1STATECHANGE);
220 if (exval & 1) {
221 exval = isac_read(cs, ISAC_CIR1);
222 if (cs->debug & L1_DEB_ISAC)
223 debugl1(cs, "ISAC CIR1 %02X", exval );
226 if (val & 0x02) { /* SIN */
227 /* never */
228 if (cs->debug & L1_DEB_WARN)
229 debugl1(cs, "ISAC SIN interrupt");
231 if (val & 0x01) { /* EXI */
232 exval = isac_read(cs, ISAC_EXIR);
233 if (cs->debug & L1_DEB_WARN)
234 debugl1(cs, "ISAC EXIR %02x", exval);
235 if (exval & 0x80) { /* XMR */
236 debugl1(cs, "ISAC XMR");
237 printk(KERN_WARNING "HiSax: ISAC XMR\n");
239 if (exval & 0x40) { /* XDU */
240 xmit_xdu_d(cs, NULL);
242 if (exval & 0x04) { /* MOS */
243 v1 = isac_read(cs, ISAC_MOSR);
244 if (cs->debug & L1_DEB_MONITOR)
245 debugl1(cs, "ISAC MOSR %02x", v1);
246 #if ARCOFI_USE
247 if (v1 & 0x08) {
248 if (!cs->dc.isac.mon_rx) {
249 if (!(cs->dc.isac.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
250 if (cs->debug & L1_DEB_WARN)
251 debugl1(cs, "ISAC MON RX out of memory!");
252 cs->dc.isac.mocr &= 0xf0;
253 cs->dc.isac.mocr |= 0x0a;
254 isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
255 goto afterMONR0;
256 } else
257 cs->dc.isac.mon_rxp = 0;
259 if (cs->dc.isac.mon_rxp >= MAX_MON_FRAME) {
260 cs->dc.isac.mocr &= 0xf0;
261 cs->dc.isac.mocr |= 0x0a;
262 isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
263 cs->dc.isac.mon_rxp = 0;
264 if (cs->debug & L1_DEB_WARN)
265 debugl1(cs, "ISAC MON RX overflow!");
266 goto afterMONR0;
268 cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp++] = isac_read(cs, ISAC_MOR0);
269 if (cs->debug & L1_DEB_MONITOR)
270 debugl1(cs, "ISAC MOR0 %02x", cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp -1]);
271 if (cs->dc.isac.mon_rxp == 1) {
272 cs->dc.isac.mocr |= 0x04;
273 isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
276 afterMONR0:
277 if (v1 & 0x80) {
278 if (!cs->dc.isac.mon_rx) {
279 if (!(cs->dc.isac.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
280 if (cs->debug & L1_DEB_WARN)
281 debugl1(cs, "ISAC MON RX out of memory!");
282 cs->dc.isac.mocr &= 0x0f;
283 cs->dc.isac.mocr |= 0xa0;
284 isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
285 goto afterMONR1;
286 } else
287 cs->dc.isac.mon_rxp = 0;
289 if (cs->dc.isac.mon_rxp >= MAX_MON_FRAME) {
290 cs->dc.isac.mocr &= 0x0f;
291 cs->dc.isac.mocr |= 0xa0;
292 isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
293 cs->dc.isac.mon_rxp = 0;
294 if (cs->debug & L1_DEB_WARN)
295 debugl1(cs, "ISAC MON RX overflow!");
296 goto afterMONR1;
298 cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp++] = isac_read(cs, ISAC_MOR1);
299 if (cs->debug & L1_DEB_MONITOR)
300 debugl1(cs, "ISAC MOR1 %02x", cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp -1]);
301 cs->dc.isac.mocr |= 0x40;
302 isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
304 afterMONR1:
305 if (v1 & 0x04) {
306 cs->dc.isac.mocr &= 0xf0;
307 isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
308 cs->dc.isac.mocr |= 0x0a;
309 isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
310 sched_d_event(cs, D_RX_MON0);
312 if (v1 & 0x40) {
313 cs->dc.isac.mocr &= 0x0f;
314 isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
315 cs->dc.isac.mocr |= 0xa0;
316 isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
317 sched_d_event(cs, D_RX_MON1);
319 if (v1 & 0x02) {
320 if ((!cs->dc.isac.mon_tx) || (cs->dc.isac.mon_txc &&
321 (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc) &&
322 !(v1 & 0x08))) {
323 cs->dc.isac.mocr &= 0xf0;
324 isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
325 cs->dc.isac.mocr |= 0x0a;
326 isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
327 if (cs->dc.isac.mon_txc &&
328 (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc))
329 sched_d_event(cs, D_TX_MON0);
330 goto AfterMOX0;
332 if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) {
333 sched_d_event(cs, D_TX_MON0);
334 goto AfterMOX0;
336 isac_write(cs, ISAC_MOX0,
337 cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]);
338 if (cs->debug & L1_DEB_MONITOR)
339 debugl1(cs, "ISAC %02x -> MOX0", cs->dc.isac.mon_tx[cs->dc.isac.mon_txp -1]);
341 AfterMOX0:
342 if (v1 & 0x20) {
343 if ((!cs->dc.isac.mon_tx) || (cs->dc.isac.mon_txc &&
344 (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc) &&
345 !(v1 & 0x80))) {
346 cs->dc.isac.mocr &= 0x0f;
347 isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
348 cs->dc.isac.mocr |= 0xa0;
349 isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
350 if (cs->dc.isac.mon_txc &&
351 (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc))
352 sched_d_event(cs, D_TX_MON1);
353 goto AfterMOX1;
355 if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) {
356 sched_d_event(cs, D_TX_MON1);
357 goto AfterMOX1;
359 isac_write(cs, ISAC_MOX1,
360 cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]);
361 if (cs->debug & L1_DEB_MONITOR)
362 debugl1(cs, "ISAC %02x -> MOX1", cs->dc.isac.mon_tx[cs->dc.isac.mon_txp -1]);
364 AfterMOX1:;
365 #endif
370 static void
371 ISAC_l1hw(struct PStack *st, int pr, void *arg)
373 struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
374 struct sk_buff *skb = arg;
375 int val;
377 switch (pr) {
378 case (PH_DATA |REQUEST):
379 xmit_data_req_d(cs, skb);
380 break;
381 case (PH_PULL |INDICATION):
382 xmit_pull_ind_d(cs, skb);
383 break;
384 case (PH_PULL | REQUEST):
385 xmit_pull_req_d(st);
386 break;
387 case (HW_RESET | REQUEST):
388 if ((cs->dc.isac.ph_state == ISAC_IND_EI) ||
389 (cs->dc.isac.ph_state == ISAC_IND_DR) ||
390 (cs->dc.isac.ph_state == ISAC_IND_RS))
391 ph_command(cs, ISAC_CMD_TIM);
392 else
393 ph_command(cs, ISAC_CMD_RS);
394 break;
395 case (HW_ENABLE | REQUEST):
396 ph_command(cs, ISAC_CMD_TIM);
397 break;
398 case (HW_INFO3 | REQUEST):
399 ph_command(cs, ISAC_CMD_AR8);
400 break;
401 case (HW_TESTLOOP | REQUEST):
402 val = 0;
403 if (1 & (long) arg)
404 val |= 0x0c;
405 if (2 & (long) arg)
406 val |= 0x3;
407 if (test_bit(HW_IOM1, &cs->HW_Flags)) {
408 /* IOM 1 Mode */
409 if (!val) {
410 isac_write(cs, ISAC_SPCR, 0xa);
411 isac_write(cs, ISAC_ADF1, 0x2);
412 } else {
413 isac_write(cs, ISAC_SPCR, val);
414 isac_write(cs, ISAC_ADF1, 0xa);
416 } else {
417 /* IOM 2 Mode */
418 isac_write(cs, ISAC_SPCR, val);
419 if (val)
420 isac_write(cs, ISAC_ADF1, 0x8);
421 else
422 isac_write(cs, ISAC_ADF1, 0x0);
424 break;
425 case (HW_DEACTIVATE | RESPONSE):
426 skb_queue_purge(&cs->rq);
427 skb_queue_purge(&cs->sq);
428 if (cs->tx_skb) {
429 dev_kfree_skb_any(cs->tx_skb);
430 cs->tx_skb = NULL;
432 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
433 del_timer(&cs->dbusytimer);
434 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
435 sched_d_event(cs, D_CLEARBUSY);
436 break;
437 default:
438 if (cs->debug & L1_DEB_WARN)
439 debugl1(cs, "isac_l1hw unknown %04x", pr);
440 break;
444 static int
445 setstack_isac(struct PStack *st, struct IsdnCardState *cs)
447 st->l1.l1hw = ISAC_l1hw;
448 return 0;
451 static void
452 DC_Close_isac(struct IsdnCardState *cs) {
453 if (cs->dc.isac.mon_rx) {
454 kfree(cs->dc.isac.mon_rx);
455 cs->dc.isac.mon_rx = NULL;
457 if (cs->dc.isac.mon_tx) {
458 kfree(cs->dc.isac.mon_tx);
459 cs->dc.isac.mon_tx = NULL;
463 static void
464 dbusy_timer_handler(struct IsdnCardState *cs)
466 struct PStack *stptr;
467 int rbch, star;
469 if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
470 rbch = isac_read(cs, ISAC_RBCH);
471 star = isac_read(cs, ISAC_STAR);
472 if (cs->debug)
473 debugl1(cs, "D-Channel Busy RBCH %02x STAR %02x",
474 rbch, star);
475 if (rbch & ISAC_RBCH_XAC) { /* D-Channel Busy */
476 test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
477 stptr = cs->stlist;
478 while (stptr != NULL) {
479 L1L2(stptr, PH_PAUSE | INDICATION, NULL);
480 stptr = stptr->next;
482 } else {
483 /* discard frame; reset transceiver */
484 test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags);
485 if (cs->tx_skb) {
486 dev_kfree_skb_any(cs->tx_skb);
487 cs->tx_cnt = 0;
488 cs->tx_skb = NULL;
489 } else {
490 printk(KERN_WARNING "HiSax: ISAC D-Channel Busy no skb\n");
491 debugl1(cs, "D-Channel Busy no skb");
493 isac_write(cs, ISAC_CMDR, 0x01); /* Transmitter reset */
494 cs->card_ops->irq_func(cs->irq, cs, NULL);
499 static struct dc_l1_ops isac_l1_ops = {
500 .fill_fifo = isac_fill_fifo,
501 .open = setstack_isac,
502 .close = DC_Close_isac,
503 .bh_func = isac_bh,
504 .dbusy_func = dbusy_timer_handler,
507 void __devinit
508 initisac(struct IsdnCardState *cs)
510 int val, eval;
512 dc_l1_init(cs, &isac_l1_ops);
514 val = isac_read(cs, ISAC_STAR);
515 debugl1(cs, "ISAC STAR %x", val);
516 val = isac_read(cs, ISAC_MODE);
517 debugl1(cs, "ISAC MODE %x", val);
518 val = isac_read(cs, ISAC_ADF2);
519 debugl1(cs, "ISAC ADF2 %x", val);
520 val = isac_read(cs, ISAC_ISTA);
521 debugl1(cs, "ISAC ISTA %x", val);
522 if (val & 0x01) {
523 eval = isac_read(cs, ISAC_EXIR);
524 debugl1(cs, "ISAC EXIR %x", eval);
526 /* Disable all IRQ */
527 isac_write(cs, ISAC_MASK, 0xFF);
529 cs->dc.isac.mon_tx = NULL;
530 cs->dc.isac.mon_rx = NULL;
531 cs->dc.isac.mocr = 0xaa;
532 if (test_bit(HW_IOM1, &cs->HW_Flags)) {
533 /* IOM 1 Mode */
534 isac_write(cs, ISAC_ADF2, 0x0);
535 isac_write(cs, ISAC_SPCR, 0xa);
536 isac_write(cs, ISAC_ADF1, 0x2);
537 isac_write(cs, ISAC_STCR, 0x70);
538 isac_write(cs, ISAC_MODE, 0xc9);
539 } else {
540 /* IOM 2 Mode */
541 if (!cs->dc.isac.adf2)
542 cs->dc.isac.adf2 = 0x80;
543 isac_write(cs, ISAC_ADF2, cs->dc.isac.adf2);
544 isac_write(cs, ISAC_SQXR, 0x2f);
545 isac_write(cs, ISAC_SPCR, 0x00);
546 isac_write(cs, ISAC_STCR, 0x70);
547 isac_write(cs, ISAC_MODE, 0xc9);
548 isac_write(cs, ISAC_TIMR, 0x00);
549 isac_write(cs, ISAC_ADF1, 0x00);
551 ph_command(cs, ISAC_CMD_RS);
552 isac_write(cs, ISAC_MASK, 0x0);
554 val = isac_read(cs, ISAC_CIR0);
555 debugl1(cs, "ISAC CIR0 %x", val);
556 cs->dc.isac.ph_state = (val >> 2) & 0xf;
557 sched_d_event(cs, D_L1STATECHANGE);
559 /* RESET Receiver and Transmitter */
560 isac_write(cs, ISAC_CMDR, 0x41);
564 isac_setup(struct IsdnCardState *cs, struct dc_hw_ops *isac_ops)
566 cs->dc_hw_ops = isac_ops;
567 ISACVersion(cs, "HiSax:");
568 return 0;