aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/hisax/ipacx.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/isdn/hisax/ipacx.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/isdn/hisax/ipacx.c')
-rw-r--r--drivers/isdn/hisax/ipacx.c1004
1 files changed, 1004 insertions, 0 deletions
diff --git a/drivers/isdn/hisax/ipacx.c b/drivers/isdn/hisax/ipacx.c
new file mode 100644
index 000000000000..6485e232d869
--- /dev/null
+++ b/drivers/isdn/hisax/ipacx.c
@@ -0,0 +1,1004 @@
1/*
2 *
3 * IPACX specific routines
4 *
5 * Author Joerg Petersohn
6 * Derived from hisax_isac.c, isac.c, hscx.c and others
7 *
8 * This software may be used and distributed according to the terms
9 * of the GNU General Public License, incorporated herein by reference.
10 *
11 */
12#include <linux/kernel.h>
13#include <linux/config.h>
14#include <linux/init.h>
15#include "hisax_if.h"
16#include "hisax.h"
17#include "isdnl1.h"
18#include "ipacx.h"
19
20#define DBUSY_TIMER_VALUE 80
21#define TIMER3_VALUE 7000
22#define MAX_DFRAME_LEN_L1 300
23#define B_FIFO_SIZE 64
24#define D_FIFO_SIZE 32
25
26
27// ipacx interrupt mask values
28#define _MASK_IMASK 0x2E // global mask
29#define _MASKB_IMASK 0x0B
30#define _MASKD_IMASK 0x03 // all on
31
32//----------------------------------------------------------
33// local function declarations
34//----------------------------------------------------------
35static void ph_command(struct IsdnCardState *cs, unsigned int command);
36static inline void cic_int(struct IsdnCardState *cs);
37static void dch_l2l1(struct PStack *st, int pr, void *arg);
38static void dbusy_timer_handler(struct IsdnCardState *cs);
39static void ipacx_new_ph(struct IsdnCardState *cs);
40static void dch_bh(struct IsdnCardState *cs);
41static void dch_empty_fifo(struct IsdnCardState *cs, int count);
42static void dch_fill_fifo(struct IsdnCardState *cs);
43static inline void dch_int(struct IsdnCardState *cs);
44static void __devinit dch_setstack(struct PStack *st, struct IsdnCardState *cs);
45static void __devinit dch_init(struct IsdnCardState *cs);
46static void bch_l2l1(struct PStack *st, int pr, void *arg);
47static void bch_empty_fifo(struct BCState *bcs, int count);
48static void bch_fill_fifo(struct BCState *bcs);
49static void bch_int(struct IsdnCardState *cs, u_char hscx);
50static void bch_mode(struct BCState *bcs, int mode, int bc);
51static void bch_close_state(struct BCState *bcs);
52static int bch_open_state(struct IsdnCardState *cs, struct BCState *bcs);
53static int bch_setstack(struct PStack *st, struct BCState *bcs);
54static void __devinit bch_init(struct IsdnCardState *cs, int hscx);
55static void __init clear_pending_ints(struct IsdnCardState *cs);
56
57//----------------------------------------------------------
58// Issue Layer 1 command to chip
59//----------------------------------------------------------
60static void
61ph_command(struct IsdnCardState *cs, unsigned int command)
62{
63 if (cs->debug &L1_DEB_ISAC)
64 debugl1(cs, "ph_command (%#x) in (%#x)", command,
65 cs->dc.isac.ph_state);
66//###################################
67// printk(KERN_INFO "ph_command (%#x)\n", command);
68//###################################
69 cs->writeisac(cs, IPACX_CIX0, (command << 4) | 0x0E);
70}
71
72//----------------------------------------------------------
73// Transceiver interrupt handler
74//----------------------------------------------------------
75static inline void
76cic_int(struct IsdnCardState *cs)
77{
78 u_char event;
79
80 event = cs->readisac(cs, IPACX_CIR0) >> 4;
81 if (cs->debug &L1_DEB_ISAC) debugl1(cs, "cic_int(event=%#x)", event);
82//#########################################
83// printk(KERN_INFO "cic_int(%x)\n", event);
84//#########################################
85 cs->dc.isac.ph_state = event;
86 schedule_event(cs, D_L1STATECHANGE);
87}
88
89//==========================================================
90// D channel functions
91//==========================================================
92
93//----------------------------------------------------------
94// Command entry point
95//----------------------------------------------------------
96static void
97dch_l2l1(struct PStack *st, int pr, void *arg)
98{
99 struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
100 struct sk_buff *skb = arg;
101 u_char cda1_cr, cda2_cr;
102
103 switch (pr) {
104 case (PH_DATA |REQUEST):
105 if (cs->debug &DEB_DLOG_HEX) LogFrame(cs, skb->data, skb->len);
106 if (cs->debug &DEB_DLOG_VERBOSE) dlogframe(cs, skb, 0);
107 if (cs->tx_skb) {
108 skb_queue_tail(&cs->sq, skb);
109#ifdef L2FRAME_DEBUG
110 if (cs->debug &L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA Queued", 0);
111#endif
112 } else {
113 cs->tx_skb = skb;
114 cs->tx_cnt = 0;
115#ifdef L2FRAME_DEBUG
116 if (cs->debug &L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA", 0);
117#endif
118 dch_fill_fifo(cs);
119 }
120 break;
121
122 case (PH_PULL |INDICATION):
123 if (cs->tx_skb) {
124 if (cs->debug & L1_DEB_WARN)
125 debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
126 skb_queue_tail(&cs->sq, skb);
127 break;
128 }
129 if (cs->debug & DEB_DLOG_HEX) LogFrame(cs, skb->data, skb->len);
130 if (cs->debug & DEB_DLOG_VERBOSE) dlogframe(cs, skb, 0);
131 cs->tx_skb = skb;
132 cs->tx_cnt = 0;
133#ifdef L2FRAME_DEBUG
134 if (cs->debug & L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
135#endif
136 dch_fill_fifo(cs);
137 break;
138
139 case (PH_PULL | REQUEST):
140#ifdef L2FRAME_DEBUG
141 if (cs->debug & L1_DEB_LAPD) debugl1(cs, "-> PH_REQUEST_PULL");
142#endif
143 if (!cs->tx_skb) {
144 clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
145 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
146 } else
147 set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
148 break;
149
150 case (HW_RESET | REQUEST):
151 case (HW_ENABLE | REQUEST):
152 if ((cs->dc.isac.ph_state == IPACX_IND_RES) ||
153 (cs->dc.isac.ph_state == IPACX_IND_DR) ||
154 (cs->dc.isac.ph_state == IPACX_IND_DC))
155 ph_command(cs, IPACX_CMD_TIM);
156 else
157 ph_command(cs, IPACX_CMD_RES);
158 break;
159
160 case (HW_INFO3 | REQUEST):
161 ph_command(cs, IPACX_CMD_AR8);
162 break;
163
164 case (HW_TESTLOOP | REQUEST):
165 cs->writeisac(cs, IPACX_CDA_TSDP10, 0x80); // Timeslot 0 is B1
166 cs->writeisac(cs, IPACX_CDA_TSDP11, 0x81); // Timeslot 0 is B1
167 cda1_cr = cs->readisac(cs, IPACX_CDA1_CR);
168 cda2_cr = cs->readisac(cs, IPACX_CDA2_CR);
169 if ((long)arg &1) { // loop B1
170 cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr |0x0a);
171 }
172 else { // B1 off
173 cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr &~0x0a);
174 }
175 if ((long)arg &2) { // loop B2
176 cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr |0x14);
177 }
178 else { // B2 off
179 cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr &~0x14);
180 }
181 break;
182
183 case (HW_DEACTIVATE | RESPONSE):
184 skb_queue_purge(&cs->rq);
185 skb_queue_purge(&cs->sq);
186 if (cs->tx_skb) {
187 dev_kfree_skb_any(cs->tx_skb);
188 cs->tx_skb = NULL;
189 }
190 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
191 del_timer(&cs->dbusytimer);
192 break;
193
194 default:
195 if (cs->debug &L1_DEB_WARN) debugl1(cs, "dch_l2l1 unknown %04x", pr);
196 break;
197 }
198}
199
200//----------------------------------------------------------
201//----------------------------------------------------------
202static void
203dbusy_timer_handler(struct IsdnCardState *cs)
204{
205 struct PStack *st;
206 int rbchd, stard;
207
208 if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
209 rbchd = cs->readisac(cs, IPACX_RBCHD);
210 stard = cs->readisac(cs, IPACX_STARD);
211 if (cs->debug)
212 debugl1(cs, "D-Channel Busy RBCHD %02x STARD %02x", rbchd, stard);
213 if (!(stard &0x40)) { // D-Channel Busy
214 set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
215 for (st = cs->stlist; st; st = st->next) {
216 st->l1.l1l2(st, PH_PAUSE | INDICATION, NULL); // flow control on
217 }
218 } else {
219 // seems we lost an interrupt; reset transceiver */
220 clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags);
221 if (cs->tx_skb) {
222 dev_kfree_skb_any(cs->tx_skb);
223 cs->tx_cnt = 0;
224 cs->tx_skb = NULL;
225 } else {
226 printk(KERN_WARNING "HiSax: ISAC D-Channel Busy no skb\n");
227 debugl1(cs, "D-Channel Busy no skb");
228 }
229 cs->writeisac(cs, IPACX_CMDRD, 0x01); // Tx reset, generates XPR
230 }
231 }
232}
233
234//----------------------------------------------------------
235// L1 state machine intermediate layer to isdnl1 module
236//----------------------------------------------------------
237static void
238ipacx_new_ph(struct IsdnCardState *cs)
239{
240 switch (cs->dc.isac.ph_state) {
241 case (IPACX_IND_RES):
242 ph_command(cs, IPACX_CMD_DI);
243 l1_msg(cs, HW_RESET | INDICATION, NULL);
244 break;
245
246 case (IPACX_IND_DC):
247 l1_msg(cs, HW_DEACTIVATE | CONFIRM, NULL);
248 break;
249
250 case (IPACX_IND_DR):
251 l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
252 break;
253
254 case (IPACX_IND_PU):
255 l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
256 break;
257
258 case (IPACX_IND_RSY):
259 l1_msg(cs, HW_RSYNC | INDICATION, NULL);
260 break;
261
262 case (IPACX_IND_AR):
263 l1_msg(cs, HW_INFO2 | INDICATION, NULL);
264 break;
265
266 case (IPACX_IND_AI8):
267 l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
268 break;
269
270 case (IPACX_IND_AI10):
271 l1_msg(cs, HW_INFO4_P10 | INDICATION, NULL);
272 break;
273
274 default:
275 break;
276 }
277}
278
279//----------------------------------------------------------
280// bottom half handler for D channel
281//----------------------------------------------------------
282static void
283dch_bh(struct IsdnCardState *cs)
284{
285 struct PStack *st;
286
287 if (!cs) return;
288
289 if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
290 if (cs->debug) debugl1(cs, "D-Channel Busy cleared");
291 for (st = cs->stlist; st; st = st->next) {
292 st->l1.l1l2(st, PH_PAUSE | CONFIRM, NULL);
293 }
294 }
295
296 if (test_and_clear_bit(D_RCVBUFREADY, &cs->event)) {
297 DChannel_proc_rcv(cs);
298 }
299
300 if (test_and_clear_bit(D_XMTBUFREADY, &cs->event)) {
301 DChannel_proc_xmt(cs);
302 }
303
304 if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
305 ipacx_new_ph(cs);
306 }
307}
308
309//----------------------------------------------------------
310// Fill buffer from receive FIFO
311//----------------------------------------------------------
312static void
313dch_empty_fifo(struct IsdnCardState *cs, int count)
314{
315 u_char *ptr;
316
317 if ((cs->debug &L1_DEB_ISAC) && !(cs->debug &L1_DEB_ISAC_FIFO))
318 debugl1(cs, "dch_empty_fifo()");
319
320 // message too large, remove
321 if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) {
322 if (cs->debug &L1_DEB_WARN)
323 debugl1(cs, "dch_empty_fifo() incoming message too large");
324 cs->writeisac(cs, IPACX_CMDRD, 0x80); // RMC
325 cs->rcvidx = 0;
326 return;
327 }
328
329 ptr = cs->rcvbuf + cs->rcvidx;
330 cs->rcvidx += count;
331
332 cs->readisacfifo(cs, ptr, count);
333 cs->writeisac(cs, IPACX_CMDRD, 0x80); // RMC
334
335 if (cs->debug &L1_DEB_ISAC_FIFO) {
336 char *t = cs->dlog;
337
338 t += sprintf(t, "dch_empty_fifo() cnt %d", count);
339 QuickHex(t, ptr, count);
340 debugl1(cs, cs->dlog);
341 }
342}
343
344//----------------------------------------------------------
345// Fill transmit FIFO
346//----------------------------------------------------------
347static void
348dch_fill_fifo(struct IsdnCardState *cs)
349{
350 int count;
351 u_char cmd, *ptr;
352
353 if ((cs->debug &L1_DEB_ISAC) && !(cs->debug &L1_DEB_ISAC_FIFO))
354 debugl1(cs, "dch_fill_fifo()");
355
356 if (!cs->tx_skb) return;
357 count = cs->tx_skb->len;
358 if (count <= 0) return;
359
360 if (count > D_FIFO_SIZE) {
361 count = D_FIFO_SIZE;
362 cmd = 0x08; // XTF
363 } else {
364 cmd = 0x0A; // XTF | XME
365 }
366
367 ptr = cs->tx_skb->data;
368 skb_pull(cs->tx_skb, count);
369 cs->tx_cnt += count;
370 cs->writeisacfifo(cs, ptr, count);
371 cs->writeisac(cs, IPACX_CMDRD, cmd);
372
373 // set timeout for transmission contol
374 if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
375 debugl1(cs, "dch_fill_fifo dbusytimer running");
376 del_timer(&cs->dbusytimer);
377 }
378 init_timer(&cs->dbusytimer);
379 cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
380 add_timer(&cs->dbusytimer);
381
382 if (cs->debug &L1_DEB_ISAC_FIFO) {
383 char *t = cs->dlog;
384
385 t += sprintf(t, "dch_fill_fifo() cnt %d", count);
386 QuickHex(t, ptr, count);
387 debugl1(cs, cs->dlog);
388 }
389}
390
391//----------------------------------------------------------
392// D channel interrupt handler
393//----------------------------------------------------------
394static inline void
395dch_int(struct IsdnCardState *cs)
396{
397 struct sk_buff *skb;
398 u_char istad, rstad;
399 int count;
400
401 istad = cs->readisac(cs, IPACX_ISTAD);
402//##############################################
403// printk(KERN_WARNING "dch_int(istad=%02x)\n", istad);
404//##############################################
405
406 if (istad &0x80) { // RME
407 rstad = cs->readisac(cs, IPACX_RSTAD);
408 if ((rstad &0xf0) != 0xa0) { // !(VFR && !RDO && CRC && !RAB)
409 if (!(rstad &0x80))
410 if (cs->debug &L1_DEB_WARN)
411 debugl1(cs, "dch_int(): invalid frame");
412 if ((rstad &0x40))
413 if (cs->debug &L1_DEB_WARN)
414 debugl1(cs, "dch_int(): RDO");
415 if (!(rstad &0x20))
416 if (cs->debug &L1_DEB_WARN)
417 debugl1(cs, "dch_int(): CRC error");
418 cs->writeisac(cs, IPACX_CMDRD, 0x80); // RMC
419 } else { // received frame ok
420 count = cs->readisac(cs, IPACX_RBCLD);
421 if (count) count--; // RSTAB is last byte
422 count &= D_FIFO_SIZE-1;
423 if (count == 0) count = D_FIFO_SIZE;
424 dch_empty_fifo(cs, count);
425 if ((count = cs->rcvidx) > 0) {
426 cs->rcvidx = 0;
427 if (!(skb = dev_alloc_skb(count)))
428 printk(KERN_WARNING "HiSax dch_int(): receive out of memory\n");
429 else {
430 memcpy(skb_put(skb, count), cs->rcvbuf, count);
431 skb_queue_tail(&cs->rq, skb);
432 }
433 }
434 }
435 cs->rcvidx = 0;
436 schedule_event(cs, D_RCVBUFREADY);
437 }
438
439 if (istad &0x40) { // RPF
440 dch_empty_fifo(cs, D_FIFO_SIZE);
441 }
442
443 if (istad &0x20) { // RFO
444 if (cs->debug &L1_DEB_WARN) debugl1(cs, "dch_int(): RFO");
445 cs->writeisac(cs, IPACX_CMDRD, 0x40); //RRES
446 }
447
448 if (istad &0x10) { // XPR
449 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
450 del_timer(&cs->dbusytimer);
451 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
452 schedule_event(cs, D_CLEARBUSY);
453 if (cs->tx_skb) {
454 if (cs->tx_skb->len) {
455 dch_fill_fifo(cs);
456 goto afterXPR;
457 }
458 else {
459 dev_kfree_skb_irq(cs->tx_skb);
460 cs->tx_skb = NULL;
461 cs->tx_cnt = 0;
462 }
463 }
464 if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
465 cs->tx_cnt = 0;
466 dch_fill_fifo(cs);
467 }
468 else {
469 schedule_event(cs, D_XMTBUFREADY);
470 }
471 }
472 afterXPR:
473
474 if (istad &0x0C) { // XDU or XMR
475 if (cs->debug &L1_DEB_WARN) debugl1(cs, "dch_int(): XDU");
476 if (cs->tx_skb) {
477 skb_push(cs->tx_skb, cs->tx_cnt); // retransmit
478 cs->tx_cnt = 0;
479 dch_fill_fifo(cs);
480 } else {
481 printk(KERN_WARNING "HiSax: ISAC XDU no skb\n");
482 debugl1(cs, "ISAC XDU no skb");
483 }
484 }
485}
486
487//----------------------------------------------------------
488//----------------------------------------------------------
489static void __devinit
490dch_setstack(struct PStack *st, struct IsdnCardState *cs)
491{
492 st->l1.l1hw = dch_l2l1;
493}
494
495//----------------------------------------------------------
496//----------------------------------------------------------
497static void __devinit
498dch_init(struct IsdnCardState *cs)
499{
500 printk(KERN_INFO "HiSax: IPACX ISDN driver v0.1.0\n");
501
502 cs->setstack_d = dch_setstack;
503
504 cs->dbusytimer.function = (void *) dbusy_timer_handler;
505 cs->dbusytimer.data = (long) cs;
506 init_timer(&cs->dbusytimer);
507
508 cs->writeisac(cs, IPACX_TR_CONF0, 0x00); // clear LDD
509 cs->writeisac(cs, IPACX_TR_CONF2, 0x00); // enable transmitter
510 cs->writeisac(cs, IPACX_MODED, 0xC9); // transparent mode 0, RAC, stop/go
511 cs->writeisac(cs, IPACX_MON_CR, 0x00); // disable monitor channel
512}
513
514
515//==========================================================
516// B channel functions
517//==========================================================
518
519//----------------------------------------------------------
520// Entry point for commands
521//----------------------------------------------------------
522static void
523bch_l2l1(struct PStack *st, int pr, void *arg)
524{
525 struct BCState *bcs = st->l1.bcs;
526 struct sk_buff *skb = arg;
527 u_long flags;
528
529 switch (pr) {
530 case (PH_DATA | REQUEST):
531 spin_lock_irqsave(&bcs->cs->lock, flags);
532 if (bcs->tx_skb) {
533 skb_queue_tail(&bcs->squeue, skb);
534 } else {
535 bcs->tx_skb = skb;
536 set_bit(BC_FLG_BUSY, &bcs->Flag);
537 bcs->hw.hscx.count = 0;
538 bch_fill_fifo(bcs);
539 }
540 spin_unlock_irqrestore(&bcs->cs->lock, flags);
541 break;
542 case (PH_PULL | INDICATION):
543 spin_lock_irqsave(&bcs->cs->lock, flags);
544 if (bcs->tx_skb) {
545 printk(KERN_WARNING "HiSax bch_l2l1(): this shouldn't happen\n");
546 } else {
547 set_bit(BC_FLG_BUSY, &bcs->Flag);
548 bcs->tx_skb = skb;
549 bcs->hw.hscx.count = 0;
550 bch_fill_fifo(bcs);
551 }
552 spin_unlock_irqrestore(&bcs->cs->lock, flags);
553 break;
554 case (PH_PULL | REQUEST):
555 if (!bcs->tx_skb) {
556 clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
557 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
558 } else
559 set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
560 break;
561 case (PH_ACTIVATE | REQUEST):
562 spin_lock_irqsave(&bcs->cs->lock, flags);
563 set_bit(BC_FLG_ACTIV, &bcs->Flag);
564 bch_mode(bcs, st->l1.mode, st->l1.bc);
565 spin_unlock_irqrestore(&bcs->cs->lock, flags);
566 l1_msg_b(st, pr, arg);
567 break;
568 case (PH_DEACTIVATE | REQUEST):
569 l1_msg_b(st, pr, arg);
570 break;
571 case (PH_DEACTIVATE | CONFIRM):
572 spin_lock_irqsave(&bcs->cs->lock, flags);
573 clear_bit(BC_FLG_ACTIV, &bcs->Flag);
574 clear_bit(BC_FLG_BUSY, &bcs->Flag);
575 bch_mode(bcs, 0, st->l1.bc);
576 spin_unlock_irqrestore(&bcs->cs->lock, flags);
577 st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
578 break;
579 }
580}
581
582//----------------------------------------------------------
583// Read B channel fifo to receive buffer
584//----------------------------------------------------------
585static void
586bch_empty_fifo(struct BCState *bcs, int count)
587{
588 u_char *ptr, hscx;
589 struct IsdnCardState *cs;
590 int cnt;
591
592 cs = bcs->cs;
593 hscx = bcs->hw.hscx.hscx;
594 if ((cs->debug &L1_DEB_HSCX) && !(cs->debug &L1_DEB_HSCX_FIFO))
595 debugl1(cs, "bch_empty_fifo()");
596
597 // message too large, remove
598 if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
599 if (cs->debug &L1_DEB_WARN)
600 debugl1(cs, "bch_empty_fifo() incoming packet too large");
601 cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x80); // RMC
602 bcs->hw.hscx.rcvidx = 0;
603 return;
604 }
605
606 ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
607 cnt = count;
608 while (cnt--) *ptr++ = cs->BC_Read_Reg(cs, hscx, IPACX_RFIFOB);
609 cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x80); // RMC
610
611 ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
612 bcs->hw.hscx.rcvidx += count;
613
614 if (cs->debug &L1_DEB_HSCX_FIFO) {
615 char *t = bcs->blog;
616
617 t += sprintf(t, "bch_empty_fifo() B-%d cnt %d", hscx, count);
618 QuickHex(t, ptr, count);
619 debugl1(cs, bcs->blog);
620 }
621}
622
623//----------------------------------------------------------
624// Fill buffer to transmit FIFO
625//----------------------------------------------------------
626static void
627bch_fill_fifo(struct BCState *bcs)
628{
629 struct IsdnCardState *cs;
630 int more, count, cnt;
631 u_char *ptr, *p, hscx;
632
633 cs = bcs->cs;
634 if ((cs->debug &L1_DEB_HSCX) && !(cs->debug &L1_DEB_HSCX_FIFO))
635 debugl1(cs, "bch_fill_fifo()");
636
637 if (!bcs->tx_skb) return;
638 if (bcs->tx_skb->len <= 0) return;
639
640 hscx = bcs->hw.hscx.hscx;
641 more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
642 if (bcs->tx_skb->len > B_FIFO_SIZE) {
643 more = 1;
644 count = B_FIFO_SIZE;
645 } else {
646 count = bcs->tx_skb->len;
647 }
648 cnt = count;
649
650 p = ptr = bcs->tx_skb->data;
651 skb_pull(bcs->tx_skb, count);
652 bcs->tx_cnt -= count;
653 bcs->hw.hscx.count += count;
654 while (cnt--) cs->BC_Write_Reg(cs, hscx, IPACX_XFIFOB, *p++);
655 cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, (more ? 0x08 : 0x0a));
656
657 if (cs->debug &L1_DEB_HSCX_FIFO) {
658 char *t = bcs->blog;
659
660 t += sprintf(t, "chb_fill_fifo() B-%d cnt %d", hscx, count);
661 QuickHex(t, ptr, count);
662 debugl1(cs, bcs->blog);
663 }
664}
665
666//----------------------------------------------------------
667// B channel interrupt handler
668//----------------------------------------------------------
669static void
670bch_int(struct IsdnCardState *cs, u_char hscx)
671{
672 u_char istab;
673 struct BCState *bcs;
674 struct sk_buff *skb;
675 int count;
676 u_char rstab;
677
678 bcs = cs->bcs + hscx;
679 istab = cs->BC_Read_Reg(cs, hscx, IPACX_ISTAB);
680//##############################################
681// printk(KERN_WARNING "bch_int(istab=%02x)\n", istab);
682//##############################################
683 if (!test_bit(BC_FLG_INIT, &bcs->Flag)) return;
684
685 if (istab &0x80) { // RME
686 rstab = cs->BC_Read_Reg(cs, hscx, IPACX_RSTAB);
687 if ((rstab &0xf0) != 0xa0) { // !(VFR && !RDO && CRC && !RAB)
688 if (!(rstab &0x80))
689 if (cs->debug &L1_DEB_WARN)
690 debugl1(cs, "bch_int() B-%d: invalid frame", hscx);
691 if ((rstab &0x40) && (bcs->mode != L1_MODE_NULL))
692 if (cs->debug &L1_DEB_WARN)
693 debugl1(cs, "bch_int() B-%d: RDO mode=%d", hscx, bcs->mode);
694 if (!(rstab &0x20))
695 if (cs->debug &L1_DEB_WARN)
696 debugl1(cs, "bch_int() B-%d: CRC error", hscx);
697 cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x80); // RMC
698 }
699 else { // received frame ok
700 count = cs->BC_Read_Reg(cs, hscx, IPACX_RBCLB) &(B_FIFO_SIZE-1);
701 if (count == 0) count = B_FIFO_SIZE;
702 bch_empty_fifo(bcs, count);
703 if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
704 if (cs->debug &L1_DEB_HSCX_FIFO)
705 debugl1(cs, "bch_int Frame %d", count);
706 if (!(skb = dev_alloc_skb(count)))
707 printk(KERN_WARNING "HiSax bch_int(): receive frame out of memory\n");
708 else {
709 memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
710 skb_queue_tail(&bcs->rqueue, skb);
711 }
712 }
713 }
714 bcs->hw.hscx.rcvidx = 0;
715 schedule_event(bcs, B_RCVBUFREADY);
716 }
717
718 if (istab &0x40) { // RPF
719 bch_empty_fifo(bcs, B_FIFO_SIZE);
720
721 if (bcs->mode == L1_MODE_TRANS) { // queue every chunk
722 // receive transparent audio data
723 if (!(skb = dev_alloc_skb(B_FIFO_SIZE)))
724 printk(KERN_WARNING "HiSax bch_int(): receive transparent out of memory\n");
725 else {
726 memcpy(skb_put(skb, B_FIFO_SIZE), bcs->hw.hscx.rcvbuf, B_FIFO_SIZE);
727 skb_queue_tail(&bcs->rqueue, skb);
728 }
729 bcs->hw.hscx.rcvidx = 0;
730 schedule_event(bcs, B_RCVBUFREADY);
731 }
732 }
733
734 if (istab &0x20) { // RFO
735 if (cs->debug &L1_DEB_WARN)
736 debugl1(cs, "bch_int() B-%d: RFO error", hscx);
737 cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x40); // RRES
738 }
739
740 if (istab &0x10) { // XPR
741 if (bcs->tx_skb) {
742 if (bcs->tx_skb->len) {
743 bch_fill_fifo(bcs);
744 goto afterXPR;
745 } else {
746 if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
747 (PACKET_NOACK != bcs->tx_skb->pkt_type)) {
748 u_long flags;
749 spin_lock_irqsave(&bcs->aclock, flags);
750 bcs->ackcnt += bcs->hw.hscx.count;
751 spin_unlock_irqrestore(&bcs->aclock, flags);
752 schedule_event(bcs, B_ACKPENDING);
753 }
754 }
755 dev_kfree_skb_irq(bcs->tx_skb);
756 bcs->hw.hscx.count = 0;
757 bcs->tx_skb = NULL;
758 }
759 if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
760 bcs->hw.hscx.count = 0;
761 set_bit(BC_FLG_BUSY, &bcs->Flag);
762 bch_fill_fifo(bcs);
763 } else {
764 clear_bit(BC_FLG_BUSY, &bcs->Flag);
765 schedule_event(bcs, B_XMTBUFREADY);
766 }
767 }
768 afterXPR:
769
770 if (istab &0x04) { // XDU
771 if (bcs->mode == L1_MODE_TRANS) {
772 bch_fill_fifo(bcs);
773 }
774 else {
775 if (bcs->tx_skb) { // restart transmitting the whole frame
776 skb_push(bcs->tx_skb, bcs->hw.hscx.count);
777 bcs->tx_cnt += bcs->hw.hscx.count;
778 bcs->hw.hscx.count = 0;
779 }
780 cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x01); // XRES
781 if (cs->debug &L1_DEB_WARN)
782 debugl1(cs, "bch_int() B-%d XDU error", hscx);
783 }
784 }
785}
786
787//----------------------------------------------------------
788//----------------------------------------------------------
789static void
790bch_mode(struct BCState *bcs, int mode, int bc)
791{
792 struct IsdnCardState *cs = bcs->cs;
793 int hscx = bcs->hw.hscx.hscx;
794
795 bc = bc ? 1 : 0; // in case bc is greater than 1
796 if (cs->debug & L1_DEB_HSCX)
797 debugl1(cs, "mode_bch() switch B-% mode %d chan %d", hscx, mode, bc);
798 bcs->mode = mode;
799 bcs->channel = bc;
800
801 // map controller to according timeslot
802 if (!hscx)
803 {
804 cs->writeisac(cs, IPACX_BCHA_TSDP_BC1, 0x80 | bc);
805 cs->writeisac(cs, IPACX_BCHA_CR, 0x88);
806 }
807 else
808 {
809 cs->writeisac(cs, IPACX_BCHB_TSDP_BC1, 0x80 | bc);
810 cs->writeisac(cs, IPACX_BCHB_CR, 0x88);
811 }
812
813 switch (mode) {
814 case (L1_MODE_NULL):
815 cs->BC_Write_Reg(cs, hscx, IPACX_MODEB, 0xC0); // rec off
816 cs->BC_Write_Reg(cs, hscx, IPACX_EXMB, 0x30); // std adj.
817 cs->BC_Write_Reg(cs, hscx, IPACX_MASKB, 0xFF); // ints off
818 cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x41); // validate adjustments
819 break;
820 case (L1_MODE_TRANS):
821 cs->BC_Write_Reg(cs, hscx, IPACX_MODEB, 0x88); // ext transp mode
822 cs->BC_Write_Reg(cs, hscx, IPACX_EXMB, 0x00); // xxx00000
823 cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x41); // validate adjustments
824 cs->BC_Write_Reg(cs, hscx, IPACX_MASKB, _MASKB_IMASK);
825 break;
826 case (L1_MODE_HDLC):
827 cs->BC_Write_Reg(cs, hscx, IPACX_MODEB, 0xC8); // transp mode 0
828 cs->BC_Write_Reg(cs, hscx, IPACX_EXMB, 0x01); // idle=hdlc flags crc enabled
829 cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x41); // validate adjustments
830 cs->BC_Write_Reg(cs, hscx, IPACX_MASKB, _MASKB_IMASK);
831 break;
832 }
833}
834
835//----------------------------------------------------------
836//----------------------------------------------------------
837static void
838bch_close_state(struct BCState *bcs)
839{
840 bch_mode(bcs, 0, bcs->channel);
841 if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
842 if (bcs->hw.hscx.rcvbuf) {
843 kfree(bcs->hw.hscx.rcvbuf);
844 bcs->hw.hscx.rcvbuf = NULL;
845 }
846 if (bcs->blog) {
847 kfree(bcs->blog);
848 bcs->blog = NULL;
849 }
850 skb_queue_purge(&bcs->rqueue);
851 skb_queue_purge(&bcs->squeue);
852 if (bcs->tx_skb) {
853 dev_kfree_skb_any(bcs->tx_skb);
854 bcs->tx_skb = NULL;
855 clear_bit(BC_FLG_BUSY, &bcs->Flag);
856 }
857 }
858}
859
860//----------------------------------------------------------
861//----------------------------------------------------------
862static int
863bch_open_state(struct IsdnCardState *cs, struct BCState *bcs)
864{
865 if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
866 if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
867 printk(KERN_WARNING
868 "HiSax open_bchstate(): No memory for hscx.rcvbuf\n");
869 clear_bit(BC_FLG_INIT, &bcs->Flag);
870 return (1);
871 }
872 if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
873 printk(KERN_WARNING
874 "HiSax open_bchstate: No memory for bcs->blog\n");
875 clear_bit(BC_FLG_INIT, &bcs->Flag);
876 kfree(bcs->hw.hscx.rcvbuf);
877 bcs->hw.hscx.rcvbuf = NULL;
878 return (2);
879 }
880 skb_queue_head_init(&bcs->rqueue);
881 skb_queue_head_init(&bcs->squeue);
882 }
883 bcs->tx_skb = NULL;
884 clear_bit(BC_FLG_BUSY, &bcs->Flag);
885 bcs->event = 0;
886 bcs->hw.hscx.rcvidx = 0;
887 bcs->tx_cnt = 0;
888 return (0);
889}
890
891//----------------------------------------------------------
892//----------------------------------------------------------
893static int
894bch_setstack(struct PStack *st, struct BCState *bcs)
895{
896 bcs->channel = st->l1.bc;
897 if (bch_open_state(st->l1.hardware, bcs)) return (-1);
898 st->l1.bcs = bcs;
899 st->l2.l2l1 = bch_l2l1;
900 setstack_manager(st);
901 bcs->st = st;
902 setstack_l1_B(st);
903 return (0);
904}
905
906//----------------------------------------------------------
907//----------------------------------------------------------
908static void __devinit
909bch_init(struct IsdnCardState *cs, int hscx)
910{
911 cs->bcs[hscx].BC_SetStack = bch_setstack;
912 cs->bcs[hscx].BC_Close = bch_close_state;
913 cs->bcs[hscx].hw.hscx.hscx = hscx;
914 cs->bcs[hscx].cs = cs;
915 bch_mode(cs->bcs + hscx, 0, hscx);
916}
917
918
919//==========================================================
920// Shared functions
921//==========================================================
922
923//----------------------------------------------------------
924// Main interrupt handler
925//----------------------------------------------------------
926void
927interrupt_ipacx(struct IsdnCardState *cs)
928{
929 u_char ista;
930
931 while ((ista = cs->readisac(cs, IPACX_ISTA))) {
932//#################################################
933// printk(KERN_WARNING "interrupt_ipacx(ista=%02x)\n", ista);
934//#################################################
935 if (ista &0x80) bch_int(cs, 0); // B channel interrupts
936 if (ista &0x40) bch_int(cs, 1);
937
938 if (ista &0x01) dch_int(cs); // D channel
939 if (ista &0x10) cic_int(cs); // Layer 1 state
940 }
941}
942
943//----------------------------------------------------------
944// Clears chip interrupt status
945//----------------------------------------------------------
946static void __init
947clear_pending_ints(struct IsdnCardState *cs)
948{
949 int ista;
950
951 // all interrupts off
952 cs->writeisac(cs, IPACX_MASK, 0xff);
953 cs->writeisac(cs, IPACX_MASKD, 0xff);
954 cs->BC_Write_Reg(cs, 0, IPACX_MASKB, 0xff);
955 cs->BC_Write_Reg(cs, 1, IPACX_MASKB, 0xff);
956
957 ista = cs->readisac(cs, IPACX_ISTA);
958 if (ista &0x80) cs->BC_Read_Reg(cs, 0, IPACX_ISTAB);
959 if (ista &0x40) cs->BC_Read_Reg(cs, 1, IPACX_ISTAB);
960 if (ista &0x10) cs->readisac(cs, IPACX_CIR0);
961 if (ista &0x01) cs->readisac(cs, IPACX_ISTAD);
962}
963
964//----------------------------------------------------------
965// Does chip configuration work
966// Work to do depends on bit mask in part
967//----------------------------------------------------------
968void __init
969init_ipacx(struct IsdnCardState *cs, int part)
970{
971 if (part &1) { // initialise chip
972//##################################################
973// printk(KERN_INFO "init_ipacx(%x)\n", part);
974//##################################################
975 clear_pending_ints(cs);
976 bch_init(cs, 0);
977 bch_init(cs, 1);
978 dch_init(cs);
979 }
980 if (part &2) { // reenable all interrupts and start chip
981 cs->BC_Write_Reg(cs, 0, IPACX_MASKB, _MASKB_IMASK);
982 cs->BC_Write_Reg(cs, 1, IPACX_MASKB, _MASKB_IMASK);
983 cs->writeisac(cs, IPACX_MASKD, _MASKD_IMASK);
984 cs->writeisac(cs, IPACX_MASK, _MASK_IMASK); // global mask register
985
986 // reset HDLC Transmitters/receivers
987 cs->writeisac(cs, IPACX_CMDRD, 0x41);
988 cs->BC_Write_Reg(cs, 0, IPACX_CMDRB, 0x41);
989 cs->BC_Write_Reg(cs, 1, IPACX_CMDRB, 0x41);
990 ph_command(cs, IPACX_CMD_RES);
991 }
992}
993
994
995void __devinit
996setup_ipacx(struct IsdnCardState *cs)
997{
998 INIT_WORK(&cs->tqueue, (void *)(void *) dch_bh, cs);
999 cs->dbusytimer.function = (void *) dbusy_timer_handler;
1000 cs->dbusytimer.data = (long) cs;
1001 init_timer(&cs->dbusytimer);
1002}
1003//----------------- end of file -----------------------
1004