[PATCH] drivers/isdn/act2000/capi.c: #if 0 an unused function
[linux-2.6] / drivers / isdn / hisax / ipacx.c
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 //----------------------------------------------------------
35 static void ph_command(struct IsdnCardState *cs, unsigned int command);
36 static inline void cic_int(struct IsdnCardState *cs);
37 static void dch_l2l1(struct PStack *st, int pr, void *arg);
38 static void dbusy_timer_handler(struct IsdnCardState *cs);
39 static void ipacx_new_ph(struct IsdnCardState *cs);
40 static void dch_bh(struct IsdnCardState *cs);
41 static void dch_empty_fifo(struct IsdnCardState *cs, int count);
42 static void dch_fill_fifo(struct IsdnCardState *cs);
43 static inline void dch_int(struct IsdnCardState *cs);
44 static void __devinit dch_setstack(struct PStack *st, struct IsdnCardState *cs);
45 static void __devinit dch_init(struct IsdnCardState *cs);
46 static void bch_l2l1(struct PStack *st, int pr, void *arg);
47 static void bch_empty_fifo(struct BCState *bcs, int count);
48 static void bch_fill_fifo(struct BCState *bcs);
49 static void bch_int(struct IsdnCardState *cs, u_char hscx);
50 static void bch_mode(struct BCState *bcs, int mode, int bc);
51 static void bch_close_state(struct BCState *bcs);
52 static int bch_open_state(struct IsdnCardState *cs, struct BCState *bcs);
53 static int bch_setstack(struct PStack *st, struct BCState *bcs);
54 static void __devinit bch_init(struct IsdnCardState *cs, int hscx);
55 static void __init clear_pending_ints(struct IsdnCardState *cs);
56
57 //----------------------------------------------------------
58 // Issue Layer 1 command to chip
59 //----------------------------------------------------------
60 static void 
61 ph_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 //----------------------------------------------------------
75 static inline void 
76 cic_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 //----------------------------------------------------------
96 static void
97 dch_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 //----------------------------------------------------------
202 static void
203 dbusy_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 //----------------------------------------------------------
237 static void
238 ipacx_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 //----------------------------------------------------------
282 static void
283 dch_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 //----------------------------------------------------------
312 static void 
313 dch_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 //----------------------------------------------------------
347 static void 
348 dch_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 //----------------------------------------------------------
394 static inline void 
395 dch_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 //----------------------------------------------------------
489 static void __devinit
490 dch_setstack(struct PStack *st, struct IsdnCardState *cs)
491 {
492         st->l1.l1hw = dch_l2l1;
493 }
494
495 //----------------------------------------------------------
496 //----------------------------------------------------------
497 static void __devinit
498 dch_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 //----------------------------------------------------------
522 static void
523 bch_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 //----------------------------------------------------------
585 static void
586 bch_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 //----------------------------------------------------------
626 static void
627 bch_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 //----------------------------------------------------------
669 static void
670 bch_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 //----------------------------------------------------------
789 static void
790 bch_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 //----------------------------------------------------------
837 static void
838 bch_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 //----------------------------------------------------------
862 static int
863 bch_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 //----------------------------------------------------------
893 static int
894 bch_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 //----------------------------------------------------------
908 static void __devinit
909 bch_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 //----------------------------------------------------------
926 void 
927 interrupt_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 //----------------------------------------------------------
946 static void __init
947 clear_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 //----------------------------------------------------------
968 void __init
969 init_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
995 void __devinit
996 setup_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