]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/dev/ctau/ctddk.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / dev / ctau / ctddk.c
1 /*-
2  * DDK library for Cronyx-Tau adapters.
3  *
4  * Copyright (C) 1998-1999 Cronyx Engineering.
5  * Author: Alexander Kvitchenko, <aak@cronyx.ru>
6  *
7  * Copyright (C) 1999-2003 Cronyx Engineering.
8  * Author: Roman Kurakin, <rik@cronyx.ru>
9  *
10  * This source is derived from
11  * Diagnose utility for Cronyx-Tau adapter:
12  * by Serge Vakulenko, <vak@cronyx.ru>
13  *
14  * This software is distributed with NO WARRANTIES, not even the implied
15  * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  * Authors grant any other persons or organisations permission to use
18  * or modify this software as long as this message is kept with the software,
19  * all derivative works or modified versions.
20  *
21  * Cronyx Id: ctddk.c,v 1.1.2.3 2003/11/14 16:55:36 rik Exp $
22  */
23 #include <sys/cdefs.h>
24 __FBSDID("$FreeBSD$");
25
26 #include <dev/cx/machdep.h>
27 #include <dev/ctau/ctddk.h>
28 #include <dev/ctau/ctaureg.h>
29 #include <dev/ctau/hdc64570.h>
30 #include <dev/ctau/ds2153.h>
31 #include <dev/ctau/am8530.h>
32 #include <dev/ctau/lxt318.h>
33 #include <dev/cx/cronyxfw.h>
34 #include <dev/ctau/ctaufw.h>
35 #include <dev/ctau/ctau2fw.h>
36
37 #ifndef CT_DDK_NO_G703
38 #include <dev/ctau/ctaug7fw.h>
39 #endif
40
41 #ifndef CT_DDK_NO_E1
42 #include <dev/ctau/ctaue1fw.h>
43 #endif
44
45 static void ct_hdlc_interrupt (ct_chan_t *c, int imvr);
46 static void ct_e1_interrupt (ct_board_t *b);
47 static void ct_scc_interrupt (ct_board_t *b);
48 static void ct_e1timer_interrupt (ct_chan_t *c);
49
50 static short porttab [] = {            /* standard base port set */
51         0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0,
52         0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0x3c0, 0x3e0, 0
53 };
54
55 int ct_find (port_t *board_ports)
56 {
57         int i, n;
58
59         for (i=0, n=0; porttab[i] && n<NBRD; i++)
60                 if (ct_probe_board (porttab[i], -1, -1))
61                         board_ports[n++] = porttab[i];
62         return n;
63 }
64
65 int ct_open_board (ct_board_t *b, int num, port_t port, int irq, int dma)
66 {
67         ct_chan_t *c;
68         const unsigned char *fw;
69         const cr_dat_tst_t *ft;
70         long flen;
71
72         if (num >= NBRD || ! ct_probe_board (port, irq, dma))
73                 return 0;
74
75         /* init callback pointers */
76         for (c=b->chan; c<b->chan+NCHAN; ++c) {
77                 c->call_on_tx = 0;
78                 c->call_on_rx = 0;
79                 c->call_on_msig = 0;
80                 c->call_on_scc = 0;
81                 c->call_on_err = 0;
82         }
83
84         /* init DDK channel variables */
85         for (c=b->chan; c<b->chan+NCHAN; ++c) {
86                 c->sccrx_empty = c->scctx_empty = 1;
87                 c->sccrx_b = c->sccrx_e = 0;
88                 c->scctx_b = c->scctx_e = 0;
89                 c->e1_first_int = 1;
90         }
91
92         /* init board structure */
93         ct_init (b, num, port, irq, dma, ctau_fw_data, 
94                 ctau_fw_len, ctau_fw_tvec, ctau2_fw_data);
95
96         /* determine which firmware should be loaded */
97         fw = ctau_fw_data;
98         flen = ctau_fw_len;
99         ft = ctau_fw_tvec;
100         switch (b->type) {
101         case B_TAU2:
102         case B_TAU2_G703:
103         case B_TAU2_E1:
104         case B_TAU2_E1D:
105                 fw = ctau2_fw_data;
106                 flen = 0;
107                 ft = 0;
108                 break;
109 #ifndef CT_DDK_NO_G703
110         case B_TAU_G703:
111                 fw = ctaug703_fw_data;
112                 flen = ctaug703_fw_len;
113                 ft = ctaug703_fw_tvec;
114                 break;
115 #endif
116 #ifndef CT_DDK_NO_E1
117         case B_TAU_E1:
118                 fw = ctaue1_fw_data;
119                 flen = ctaue1_fw_len;
120                 ft = ctaue1_fw_tvec;
121                 break;
122 #endif
123         }
124         /* Load firmware and set up board */
125         return ct_setup_board (b, fw, flen, ft);
126 }
127
128 /*
129  * must be called on the exit
130  */
131 void ct_close_board (ct_board_t *b)
132 {
133         ct_setup_board (b, 0, 0, 0);
134
135         /* Reset the controller. */
136         outb (BCR0(b->port), 0);
137
138         /* Disable DMA channel. */
139         ct_disable_dma (b);
140
141         ct_led (b, 0);
142 }
143
144 static void ct_g703_rate (ct_chan_t *c, unsigned long rate)
145 {
146         c->gopt.rate = rate;
147         ct_setup_g703 (c->board);
148 }
149
150 /*
151  * Set up baud rate.
152  */
153 static void ct_chan_baud (ct_chan_t *c, unsigned long baud)
154 {
155         c->baud = baud;
156         if (baud) {
157                 c->hopt.txs = CLK_INT;
158         } else {
159                 ct_set_dpll (c, 0);
160                 c->hopt.txs = CLK_LINE;
161         }
162         ct_update_chan (c);
163 }
164
165 void ct_set_baud (ct_chan_t *c, unsigned long baud)
166 {
167         unsigned long r;
168
169         if (c->mode == M_E1)
170                 return;
171         if (c->mode == M_G703) {
172                 if      (baud >= 2048000)  r = 2048;
173                 else if (baud >= 1024000)  r = 1024;
174                 else if (baud >= 512000)   r = 512;
175                 else if (baud >= 256000)   r = 256;
176                 else if (baud >= 128000)   r = 128;
177                 else                       r = 64;
178                 ct_g703_rate (c, r);
179         } else
180                 ct_chan_baud (c, baud);
181 }
182
183 /*
184  * Configure Tau/E1 board.
185  */
186 static void ct_e1_config (ct_board_t *b, unsigned char cfg)
187 {
188         if (cfg == b->opt.cfg)
189                 return;
190
191         if (cfg == CFG_B)
192                 b->chan[1].mode = M_HDLC;
193         else
194                 b->chan[1].mode = M_E1;
195
196         /* Recovering synchronization */
197         if (b->opt.cfg == CFG_B) {
198                 ct_chan_baud (b->chan+1, 0);
199                 ct_set_invtxc (b->chan+1, 0);
200                 ct_set_invrxc (b->chan+1, 0);
201                 ct_set_nrzi (b->chan+1, 0);
202         }
203         b->opt.cfg = cfg;
204         ct_setup_e1 (b);
205 }
206
207 /*
208  * Config Tau/G.703 board
209  */
210 static void ct_g703_config (ct_board_t *b, unsigned char cfg)
211 {
212         if (cfg == b->opt.cfg)
213                 return;
214
215         if (cfg == CFG_B)
216                 b->chan[1].mode = M_HDLC;
217         else
218                 b->chan[1].mode = M_G703;
219
220         /* Recovering synchronization */
221         if (b->opt.cfg == CFG_B) {
222                 ct_chan_baud (b->chan+1, 0);
223                 ct_set_invtxc (b->chan+1, 0);
224                 ct_set_invrxc (b->chan+1, 0);
225                 ct_set_nrzi (b->chan+1, 0);
226         }
227         b->opt.cfg = cfg;
228         ct_setup_g703 (b);
229 }
230
231 int ct_set_clk (ct_chan_t *c, int clk)
232 {
233         if (c->num)
234                 c->board->opt.clk1 = clk;
235         else
236                 c->board->opt.clk0 = clk;
237         if (c->mode == M_E1) {
238                 ct_setup_e1 (c->board);
239                 return 0;
240         } if (c->mode == M_G703) {
241                 ct_setup_g703 (c->board);
242                 return 0;
243         } else
244                 return -1;
245 }
246
247 int ct_get_clk (ct_chan_t *c)
248 {
249         return c->num ? c->board->opt.clk1 : c->board->opt.clk0;
250 }
251
252 int ct_set_ts (ct_chan_t *c, unsigned long ts)
253 {
254         if (! (c->mode == M_E1))
255                 return -1;
256         if (c->num)
257                 c->board->opt.s1 = ts;
258         else
259                 c->board->opt.s0 = ts;
260         ct_setup_e1 (c->board);
261         return 0;
262 }
263
264 int ct_set_subchan (ct_board_t *b, unsigned long ts)
265 {
266         if (b->chan[0].mode != M_E1)
267                 return -1;
268         b->opt.s2 = ts;
269         ct_setup_e1 (b);
270         return 0;
271 }
272
273 int ct_set_higain (ct_chan_t *c, int on)
274 {
275         if (! (c->mode == M_E1))
276                 return -1;
277         c->gopt.higain = on ? 1 : 0;
278         ct_setup_e1 (c->board);
279         return 0;
280 }
281
282 /*
283  * Start service channel.
284  */
285 void ct_start_scc (ct_chan_t *c, char *rxbuf, char *txbuf)
286 {
287         c->sccrx = rxbuf;
288         c->scctx = txbuf;
289
290         /* Enable interrupts from service channel. */
291         if (c->board->type != B_TAU_E1 && c->board->type != B_TAU_E1C &&
292             c->board->type != B_TAU2_E1)
293                 return;
294
295         cte_out2 (c->board->port, c->num ? AM_IMR : AM_IMR | AM_A,
296                  IMR_TX | IMR_RX_ALL);
297         cte_out2 (c->board->port, AM_MICR, MICR_MIE);
298 }
299
300 /*
301  * Start HDLC channel.
302  */
303 void ct_start_chan (ct_chan_t *c, ct_buf_t *cb, unsigned long phys)
304 {
305         int i, ier0;
306         unsigned long bound;
307
308         if (cb) {
309                 /* Set up descriptors, align to 64k boundary.
310                  * If 64k boundary is inside buffers
311                  * buffers will begin on this boundary
312                  * (there were allocated additional space for this) */
313                 c->tdesc = cb->descbuf;
314                 c->tdphys[0] = phys + ((char*)c->tdesc - (char*)cb);
315                 bound = ((c->tdphys[0] + 0xffff) & ~(0xffffUL));
316                 if (bound < c->tdphys[0] + 2*NBUF*sizeof(ct_desc_t)) {
317                         c->tdesc = (ct_desc_t*) ((char*) c->tdesc +
318                                 (bound - c->tdphys[0]));
319                         c->tdphys[0] = bound;
320                 }
321                 c->rdesc = c->tdesc + NBUF;
322
323                 /* Set buffers. */
324                 for (i=0; i<NBUF; ++i) {
325                         c->rbuf[i] = cb->rbuffer[i];
326                         c->tbuf[i] = cb->tbuffer[i];
327                 }
328
329                 /* Set buffer physical addresses */
330                 for (i=0; i<NBUF; ++i) {
331                         c->rphys[i] = phys + ((char*)c->rbuf[i] - (char*)cb);
332                         c->tphys[i] = phys + ((char*)c->tbuf[i] - (char*)cb);
333                         c->rdphys[i] = phys + ((char*)(c->rdesc+i) - (char*)cb);
334                         c->tdphys[i] = phys + ((char*)(c->tdesc+i) - (char*)cb);
335                 }
336         }
337         /* Set up block chains. */
338         /* receive buffers */
339         for (i=0; i<NBUF; ++i) {
340                 B_NEXT (c->rdesc[i]) = c->rdphys[(i+1) % NBUF] & 0xffff;
341                 B_PTR (c->rdesc[i]) = c->rphys[i];
342                 B_LEN (c->rdesc[i]) = DMABUFSZ;
343                 B_STATUS (c->rdesc[i]) = 0;
344         }
345         /* transmit buffers */
346         for (i=0; i<NBUF; ++i) {
347                 B_NEXT (c->tdesc[i]) = c->tdphys[(i+1) % NBUF] & 0xffff;
348                 B_PTR (c->tdesc[i]) = c->tphys[i];
349                 B_LEN (c->tdesc[i]) = DMABUFSZ;
350                 B_STATUS (c->tdesc[i]) = FST_EOM;
351                 c->attach[i] = 0;
352         }
353
354         if (c->type & T_E1) {
355                 c->mode = M_E1;
356                 if (c->num && c->board->opt.cfg == CFG_B)
357                         c->mode = M_HDLC;
358         }
359         if (c->type & T_G703) {
360                 c->mode = M_G703;
361                 if (c->num && c->board->opt.cfg == CFG_B)
362                         c->mode = M_HDLC;
363         }
364         ct_update_chan (c);
365
366         /* enable receiver */
367         c->rn = 0;
368         ct_start_receiver (c, 1 , c->rphys[0], DMABUFSZ, c->rdphys[0],
369                 c->rdphys[NBUF-1]);
370         outb (c->IE1, inb (c->IE1) | IE1_CDCDE);
371         outb (c->IE0, inb (c->IE0) | IE0_RX_INTE);
372         ier0 = inb (IER0(c->board->port));
373         ier0 |= c->num ? IER0_RX_INTE_1 : IER0_RX_INTE_0;
374         outb (IER0(c->board->port), ier0);
375
376         /* Enable transmitter */
377         c->tn = 0;
378         c->te = 0;
379         ct_start_transmitter (c, 1 , c->tphys[0], DMABUFSZ, c->tdphys[0],
380                 c->tdphys[0]);
381         outb (c->TX.DIR, DIR_CHAIN_EOME | DIR_CHAIN_BOFE | DIR_CHAIN_COFE);
382
383         /* Clear DTR and RTS */
384         ct_set_dtr (c, 0);
385         ct_set_rts (c, 0);
386 }
387
388 /*
389  * Turn receiver on/off
390  */
391 void ct_enable_receive (ct_chan_t *c, int on)
392 {
393         unsigned char st3, ier0, ier1;
394
395         st3 = inb (c->ST3);
396         /* enable or disable receiver */
397         if (on && ! (st3 & ST3_RX_ENABLED)) {
398                 c->rn = 0;
399                 ct_start_receiver (c, 1 , c->rphys[0], DMABUFSZ, c->rdphys[0],
400                         c->rdphys[NBUF-1]);
401                 /* enable status interrupt */
402                 outb (c->IE1, inb (c->IE1) | IE1_CDCDE);
403                 outb (c->IE0, inb (c->IE0) | IE0_RX_INTE);
404                 ier0 = inb (IER0(c->board->port));
405                 ier0 |= c->num ? IER0_RX_INTE_1 : IER0_RX_INTE_0;
406                 outb (IER0(c->board->port), ier0);
407                 ct_set_rts (c, 1);
408         } else if (! on && (st3 & ST3_RX_ENABLED)) {
409                 ct_set_rts (c, 0);
410                 outb (c->CMD, CMD_RX_DISABLE);
411
412                 ier0 = inb (IER0(c->board->port));
413                 ier0 &= c->num ? ~(IER0_RX_INTE_1 | IER0_RX_RDYE_1) :
414                         ~(IER0_RX_INTE_0 | IER0_RX_RDYE_0);
415                 outb (IER0(c->board->port), ier0);
416
417                 ier1 = inb (IER1(c->board->port));
418                 ier1 &= c->num ? ~(IER1_RX_DMERE_1 | IER1_RX_DME_1) :
419                         ~(IER1_RX_DMERE_0 | IER1_RX_DME_0);
420                 outb (IER1(c->board->port), ier1);
421         }
422
423 }
424
425 /*
426  * Turn transmitter on/off
427  */
428 void ct_enable_transmit (ct_chan_t *c, int on)
429 {
430         unsigned char st3, ier0, ier1;
431
432         st3 = inb (c->ST3);
433         /* enable or disable receiver */
434         if (on && ! (st3 & ST3_TX_ENABLED)) {
435                 c->tn = 0;
436                 c->te = 0;
437                 ct_start_transmitter (c, 1 , c->tphys[0], DMABUFSZ,
438                         c->tdphys[0], c->tdphys[0]);
439                 outb (c->TX.DIR,
440                         DIR_CHAIN_EOME | DIR_CHAIN_BOFE | DIR_CHAIN_COFE);
441         } else if (! on && (st3 & ST3_TX_ENABLED)) {
442                 outb (c->CMD, CMD_TX_DISABLE);
443
444                 ier0 = inb (IER0(c->board->port));
445                 ier0 &= c->num ? ~(IER0_TX_INTE_1 | IER0_TX_RDYE_1) :
446                         ~(IER0_TX_INTE_0 | IER0_TX_RDYE_0);
447                 outb (IER0(c->board->port), ier0);
448
449                 ier1 = inb (IER1(c->board->port));
450                 ier1 &= c->num ? ~(IER1_TX_DMERE_1 | IER1_TX_DME_1) :
451                         ~(IER1_TX_DMERE_0 | IER1_TX_DME_0);
452                 outb (IER1(c->board->port), ier1);
453         }
454
455 }
456
457 int ct_set_config (ct_board_t *b, int cfg)
458 {
459         if (b->opt.cfg == cfg)
460                 return 0;
461         switch (b->type) {
462         case B_TAU_G703:
463         case B_TAU_G703C:
464         case B_TAU2_G703:
465                 if (cfg == CFG_C)
466                         return -1;
467                 ct_g703_config (b, cfg);
468                 return 0;
469         case B_TAU_E1:
470         case B_TAU_E1C:
471         case B_TAU_E1D:
472         case B_TAU2_E1:
473         case B_TAU2_E1D:
474                 ct_e1_config (b, cfg);
475                 return 0;
476         default:
477                 return cfg == CFG_A ? 0 : -1;
478         }
479 }
480
481 int ct_get_dpll (ct_chan_t *c)
482 {
483         return (c->hopt.rxs == CLK_RXS_DPLL_INT);
484 }
485
486 void ct_set_dpll (ct_chan_t *c, int on)
487 {
488         if (on && ct_get_baud (c))
489                 c->hopt.rxs = CLK_RXS_DPLL_INT;
490         else
491                 c->hopt.rxs = CLK_LINE;
492         ct_update_chan (c);
493 }
494
495 int ct_get_nrzi (ct_chan_t *c)
496 {
497         return (c->opt.md2.encod == MD2_ENCOD_NRZI);
498 }
499
500 /*
501  * Change line encoding to NRZI, default is NRZ
502  */
503 void ct_set_nrzi (ct_chan_t *c, int on)
504 {
505         c->opt.md2.encod = on ? MD2_ENCOD_NRZI : MD2_ENCOD_NRZ;
506         outb (c->MD2, *(unsigned char*)&c->opt.md2);
507 }
508
509 /*
510  * Transmit clock inversion
511  */
512 void ct_set_invtxc (ct_chan_t *c, int on)
513 {
514         if (on) c->board->bcr2 |=  (c->num ? BCR2_INVTXC1 : BCR2_INVTXC0);
515         else    c->board->bcr2 &= ~(c->num ? BCR2_INVTXC1 : BCR2_INVTXC0);
516         outb (BCR2(c->board->port), c->board->bcr2);
517 }
518
519 int ct_get_invtxc (ct_chan_t *c)
520 {
521         return (c->board->bcr2 & (c->num ? BCR2_INVTXC1 : BCR2_INVTXC0)) != 0;
522 }
523
524 /*
525  * Receive clock inversion
526  */
527 void ct_set_invrxc (ct_chan_t *c, int on)
528 {
529         if (on) c->board->bcr2 |=  (c->num ? BCR2_INVRXC1 : BCR2_INVRXC0);
530         else    c->board->bcr2 &= ~(c->num ? BCR2_INVRXC1 : BCR2_INVRXC0);
531         outb (BCR2(c->board->port), c->board->bcr2);
532 }
533
534 int ct_get_invrxc (ct_chan_t *c)
535 {
536         return (c->board->bcr2 & (c->num ? BCR2_INVRXC1 : BCR2_INVRXC0)) != 0;
537 }
538
539 /*
540  * Main interrupt handler
541  */
542 void ct_int_handler (ct_board_t *b)
543 {
544         unsigned char bsr0, imvr;
545         ct_chan_t *c;
546
547         while ((bsr0 = inb (BSR0(b->port))) & BSR0_INTR) {
548                 if (bsr0 & BSR0_RDYERR) {
549                         outb (BCR1(b->port), b->bcr1);
550                 } else if (bsr0 & BSR0_GINT) {
551                         if (b->type == B_TAU_E1 || b->type == B_TAU_E1C ||
552                             b->type == B_TAU_E1D || b->type == B_TAU2_E1 ||
553                             b->type == B_TAU2_E1D)
554                                 ct_e1_interrupt (b);
555                 } else if (bsr0 & BSR0_HDINT) {
556                         /* Read the interrupt modified vector register. */
557                         imvr = inb (IACK(b->port));
558                         c = b->chan + (imvr & IMVR_CHAN1 ? 1 : 0);
559                         ct_hdlc_interrupt (c, imvr);
560                 }
561         }
562 }
563
564 static void ct_e1_interrupt (ct_board_t *b)
565 {
566         unsigned char sr;
567
568         sr = inb (E1SR(b->port));
569
570         if (sr & E1SR_SCC_IRQ) ct_scc_interrupt (b);
571         if (sr & E1SR_E0_IRQ1) ct_e1timer_interrupt (b->chan + 0);
572         if (sr & E1SR_E1_IRQ1) ct_e1timer_interrupt (b->chan + 1);
573 }
574
575 static void ct_scc_interrupt (ct_board_t *b)
576 {
577         unsigned char rsr;
578         unsigned char ivr, a = AM_A;            /* assume channel A */
579         ct_chan_t *c = b->chan;
580
581         ivr = cte_in2 (b->port, AM_IVR);
582         if (! (ivr & IVR_A))
583                 ++c, a = 0;                     /* really channel B */
584
585         switch (ivr & IVR_REASON) {
586         case IVR_TXRDY:                         /* transmitter empty */
587                 c->scctx_b = (c->scctx_b + 1) % SCCBUFSZ;
588                 if (c->scctx_b == c->scctx_e) {
589                         c->scctx_empty = 1;
590                         cte_out2c (c, AM_CR | CR_RST_TXINT);
591                 } else
592                         cte_out2d (c, c->scctx[c->scctx_b]);
593                 break;
594
595         case IVR_RXERR:                 /* receive error */
596         case IVR_RX:                    /* receive character available */
597                 rsr = cte_in2 (b->port, a|AM_RSR);
598
599                 if (rsr & RSR_RXOVRN) {         /* rx overrun */
600                         if (c->call_on_err)
601                                 c->call_on_err (c, CT_SCC_OVERRUN);
602                 } else if (rsr & RSR_FRME) {    /* frame error */
603                         if (c->call_on_err)
604                                 c->call_on_err (c, CT_SCC_FRAME);
605                 } else {
606                         c->sccrx[c->sccrx_e] = cte_in2d (c);
607                         c->sccrx_e = (c->sccrx_e + 1) % SCCBUFSZ;
608                         c->sccrx_empty &= 0;
609                         if (c->call_on_scc)
610                                 c->call_on_scc (c);
611                         if (c->sccrx_e == c->sccrx_b && ! c->sccrx_empty)
612                                 if (c->call_on_err)
613                                         c->call_on_err (c, CT_SCC_OVERFLOW);
614                 }
615                 if (rsr)
616                         cte_out2c (c, CR_RST_ERROR);
617                 break;
618
619         case IVR_STATUS:                /* external status interrupt */
620                 /* Unexpected SCC status interrupt. */
621                 cte_out2c (c, CR_RST_EXTINT);
622                 break;
623         }
624 }
625
626 /*
627  * G.703 mode channel: process 1-second timer interrupts.
628  * Read error and request registers, and fill the status field.
629  */
630 void ct_g703_timer (ct_chan_t *c)
631 {
632         int bpv, cd, tsterr, tstreq;
633
634         /* Count seconds.
635          * During the first second after the channel startup
636          * the status registers are not stable yet,
637          * we will so skip the first second. */
638         ++c->cursec;
639         if (c->mode != M_G703)
640                 return;
641         if (c->totsec + c->cursec <= 1)
642                 return;
643         c->status = 0;
644
645         cd = ct_get_cd (c);
646
647         bpv = inb (GERR (c->board->port)) & (c->num ? GERR_BPV1 : GERR_BPV0);
648         outb (GERR (c->board->port), bpv);
649
650         tsterr = inb (GERR (c->board->port)) & (c->num ? GERR_ERR1 : GERR_ERR0);
651         outb (GERR (c->board->port), tsterr);
652
653         tstreq = inb (GLDR (c->board->port)) &
654                 (c->num ? GLDR_LREQ1 : GLDR_LREQ0);
655         outb (GLDR (c->board->port), tstreq);
656
657         /* Compute the SNMP-compatible channel status. */
658         if (bpv)
659                 ++c->currnt.bpv;          /* bipolar violation */
660         if (! cd)
661                 c->status |= ESTS_LOS;    /* loss of signal */
662         if (tsterr)
663                 c->status |= ESTS_TSTERR; /* test error */
664         if (tstreq)
665                 c->status |= ESTS_TSTREQ; /* test code detected */
666
667         if (! c->status)
668                 c->status = ESTS_NOALARM;
669
670         /* Unavaiable second -- loss of carrier, or receiving test code. */
671         if ((! cd) || tstreq)
672                 /* Unavailable second -- no other counters. */
673                 ++c->currnt.uas;
674         else {
675                 /* Line errored second -- any BPV. */
676                 if (bpv)
677                         ++c->currnt.les;
678
679                 /* Collect data for computing
680                  * degraded minutes. */
681                 ++c->degsec;
682                 if (cd && bpv)
683                         ++c->degerr;
684         }
685
686         /* Degraded minutes -- having more than 50% error intervals. */
687         if (c->cursec / 60 == 0) {
688                 if (c->degerr*2 > c->degsec)
689                         ++c->currnt.dm;
690                 c->degsec = 0;
691                 c->degerr = 0;
692         }
693
694         /* Rotate statistics every 15 minutes. */
695         if (c->cursec > 15*60) {
696                 int i;
697
698                 for (i=47; i>0; --i)
699                         c->interval[i] = c->interval[i-1];
700                 c->interval[0] = c->currnt;
701
702                 /* Accumulate total statistics. */
703                 c->total.bpv   += c->currnt.bpv;
704                 c->total.fse   += c->currnt.fse;
705                 c->total.crce  += c->currnt.crce;
706                 c->total.rcrce += c->currnt.rcrce;
707                 c->total.uas   += c->currnt.uas;
708                 c->total.les   += c->currnt.les;
709                 c->total.es    += c->currnt.es;
710                 c->total.bes   += c->currnt.bes;
711                 c->total.ses   += c->currnt.ses;
712                 c->total.oofs  += c->currnt.oofs;
713                 c->total.css   += c->currnt.css;
714                 c->total.dm    += c->currnt.dm;
715                 memset (&c->currnt, 0, sizeof (c->currnt));
716
717                 c->totsec += c->cursec;
718                 c->cursec = 0;
719         }
720 }
721
722 static void ct_e1timer_interrupt (ct_chan_t *c)
723 {
724         unsigned short port;
725         unsigned char sr1, sr2, ssr;
726         unsigned long bpv, fas, crc4, ebit, pcv, oof;
727
728         port = c->num ? E1CS1(c->board->port) : E1CS0(c->board->port);
729
730         sr2 = cte_ins (port, DS_SR2, 0xff);
731         /* is it timer interrupt ? */
732         if (! (sr2 & SR2_SEC))
733                 return;
734
735         /* first interrupts should be ignored */
736         if (c->e1_first_int > 0) {
737                 c->e1_first_int --;
738                 return;
739         }
740
741         ++c->cursec;
742         c->status = 0;
743
744         /* Compute the SNMP-compatible channel status. */
745         sr1 = cte_ins (port, DS_SR1, 0xff);
746         ssr = cte_in (port, DS_SSR);
747         oof = 0;
748
749         if (sr1 & (SR1_RCL | SR1_RLOS))
750                 c->status |= ESTS_LOS;          /* loss of signal */
751         if (sr1 & SR1_RUA1)
752                 c->status |= ESTS_AIS;          /* receiving all ones */
753         if (c->gopt.cas && (sr1 & SR1_RSA1))
754                 c->status |= ESTS_AIS16;        /* signaling all ones */
755         if (c->gopt.cas && (sr1 & SR1_RDMA))
756                 c->status |= ESTS_FARLOMF;      /* alarm in timeslot 16 */
757         if (sr1 & SR1_RRA)
758                 c->status |= ESTS_FARLOF;       /* far loss of framing */
759
760         /* Controlled slip second -- any slip event. */
761         if (sr1 & SR1_RSLIP) {
762                 ++c->currnt.css;
763         }
764
765         if (ssr & SSR_SYNC) {
766                 c->status |= ESTS_LOF;          /* loss of framing */
767                 ++oof;                          /* out of framing */
768         }
769         if ((c->gopt.cas && (ssr & SSR_SYNC_CAS)) ||
770             (c->gopt.crc4 && (ssr & SSR_SYNC_CRC4))) {
771                 c->status |= ESTS_LOMF;         /* loss of multiframing */
772                 ++oof;                          /* out of framing */
773         }
774
775         if (! c->status)
776                 c->status = ESTS_NOALARM;
777
778         /* Get error counters. */
779         bpv = VCR (cte_in (port, DS_VCR1), cte_in (port, DS_VCR2));
780         fas = FASCR (cte_in (port, DS_FASCR1), cte_in (port, DS_FASCR2));
781         crc4 = CRCCR (cte_in (port, DS_CRCCR1), cte_in (port, DS_CRCCR2));
782         ebit = EBCR (cte_in (port, DS_EBCR1), cte_in (port, DS_EBCR2));
783
784         c->currnt.bpv += bpv;
785         c->currnt.fse += fas;
786         if (c->gopt.crc4) {
787                 c->currnt.crce += crc4;
788                 c->currnt.rcrce += ebit;
789         }
790
791         /* Path code violation is frame sync error if CRC4 disabled,
792          * or CRC error if CRC4 enabled. */
793         pcv = fas;
794         if (c->gopt.crc4)
795                 pcv += crc4;
796
797         /* Unavaiable second -- receiving all ones, or
798          * loss of carrier, or loss of signal. */
799         if (sr1 & (SR1_RUA1 | SR1_RCL | SR1_RLOS))
800                 /* Unavailable second -- no other counters. */
801                 ++c->currnt.uas;
802         else {
803                 /* Line errored second -- any BPV. */
804                 if (bpv)
805                         ++c->currnt.les;
806
807                 /* Errored second -- any PCV, or out of frame sync,
808                  * or any slip events. */
809                 if (pcv || oof || (sr1 & SR1_RSLIP))
810                         ++c->currnt.es;
811
812                 /* Severely errored framing second -- out of frame sync. */
813                 if (oof)
814                         ++c->currnt.oofs;
815
816                 /* Severely errored seconds --
817                  * 832 or more PCVs, or 2048 or more BPVs. */
818                 if (bpv >= 2048 || pcv >= 832)
819                         ++c->currnt.ses;
820                 else {
821                         /* Bursty errored seconds --
822                          * no SES and more than 1 PCV. */
823                         if (pcv > 1)
824                                 ++c->currnt.bes;
825
826                         /* Collect data for computing
827                          * degraded minutes. */
828                         ++c->degsec;
829                         c->degerr += bpv + pcv;
830                 }
831         }
832
833         /* Degraded minutes -- having error rate more than 10e-6,
834          * not counting unavailable and severely errored seconds. */
835         if (c->cursec / 60 == 0) {
836                 if (c->degerr > c->degsec * 2048 / 1000)
837                         ++c->currnt.dm;
838                 c->degsec = 0;
839                 c->degerr = 0;
840         }
841
842         /* Rotate statistics every 15 minutes. */
843         if (c->cursec > 15*60) {
844                 int i;
845
846                 for (i=47; i>0; --i)
847                         c->interval[i] = c->interval[i-1];
848                 c->interval[0] = c->currnt;
849
850                 /* Accumulate total statistics. */
851                 c->total.bpv   += c->currnt.bpv;
852                 c->total.fse   += c->currnt.fse;
853                 c->total.crce  += c->currnt.crce;
854                 c->total.rcrce += c->currnt.rcrce;
855                 c->total.uas   += c->currnt.uas;
856                 c->total.les   += c->currnt.les;
857                 c->total.es    += c->currnt.es;
858                 c->total.bes   += c->currnt.bes;
859                 c->total.ses   += c->currnt.ses;
860                 c->total.oofs  += c->currnt.oofs;
861                 c->total.css   += c->currnt.css;
862                 c->total.dm    += c->currnt.dm;
863                 for (i=0; i<sizeof (c->currnt); ++i)
864                         *(((char *)(&c->currnt))+i)=0;
865
866                 c->totsec += c->cursec;
867                 c->cursec = 0;
868         }
869 }
870
871 static void ct_hdlc_interrupt (ct_chan_t *c, int imvr)
872 {
873         int i, dsr, st1, st2, cda;
874
875         switch (imvr & IMVR_VECT_MASK) {
876         case IMVR_RX_DMOK:              /* receive DMA normal end */
877                 dsr = inb (c->RX.DSR);
878                 cda = inw (c->RX.CDA);
879                 for (i=0; i<NBUF; ++i)
880                         if (cda == (unsigned short) c->rdphys[i])
881                                 break;
882                 if (i >= NBUF)
883                         i = c->rn; /* cannot happen */
884                 while (c->rn != i) {
885                         int cst = B_STATUS (c->rdesc[c->rn]);
886                         if (cst == FST_EOM) {
887                                 /* process data */
888                                 if (c->call_on_rx)
889                                          c->call_on_rx (c, c->rbuf[c->rn],
890                                                 B_LEN(c->rdesc[c->rn]));
891                                 ++c->ipkts;
892                                 c->ibytes += B_LEN(c->rdesc[c->rn]);
893                         } else if (cst & ST2_OVRN) {
894                                 /* Receive overrun error */
895                                 if (c->call_on_err)
896                                         c->call_on_err (c, CT_OVERRUN);
897                                 ++c->ierrs;
898                         } else if (cst & (ST2_HDLC_RBIT |
899                                 ST2_HDLC_ABT | ST2_HDLC_SHRT)) {
900                                 /* Receive frame error */
901                                 if (c->call_on_err)
902                                         c->call_on_err (c, CT_FRAME);
903                                 ++c->ierrs;
904                         } else if ((cst & ST2_HDLC_EOM)
905                                 && (cst & ST2_HDLC_CRCE)) {
906                                 /* Receive CRC error */
907                                 if (c->call_on_err)
908                                         c->call_on_err (c, CT_CRC);
909                                 ++c->ierrs;
910                         } else if (! (cst & ST2_HDLC_EOM)) {
911                                 /* Frame dose not fit in the buffer.*/
912                                 if (c->call_on_err)
913                                         c->call_on_err (c, CT_OVERFLOW);
914                                 ++c->ierrs;
915                         }
916
917                         B_NEXT (c->rdesc[c->rn]) =
918                                 c->rdphys[(c->rn+1) % NBUF] & 0xffff;
919                         B_PTR (c->rdesc[c->rn]) = c->rphys[c->rn];
920                         B_LEN (c->rdesc[c->rn]) = DMABUFSZ;
921                         B_STATUS (c->rdesc[c->rn]) = 0;
922                         c->rn = (c->rn + 1) % NBUF;
923                 }
924                 outw (c->RX.EDA, (unsigned short) c->rdphys[(i+NBUF-1)%NBUF]);
925                 /* Clear DMA interrupt. */
926                 if (inb (c->RX.DSR) & DSR_DMA_ENABLE) {
927                         outb (c->RX.DSR, dsr);
928                 } else {
929                         outb (c->RX.DSR, (dsr & 0xfc) | DSR_DMA_ENABLE);
930                 }
931                 ++c->rintr;
932                 break;
933
934         case IMVR_RX_INT:               /* receive status */
935                 st1 = inb (c->ST1);
936                 st2 = inb (c->ST2);
937                 if (st1 & ST1_CDCD){
938                         if (c->call_on_msig)
939                                 c->call_on_msig (c);
940                         ++c->mintr;
941                 }
942                 /* Clear interrupt. */
943                 outb (c->ST1, st1);
944                 outb (c->ST2, st2);
945                 ++c->rintr;
946                 break;
947
948         case IMVR_RX_DMERR:             /* receive DMA error */
949                 dsr = inb (c->RX.DSR);
950                 if (dsr & (DSR_CHAIN_BOF | DSR_CHAIN_COF)) {
951                         if (c->call_on_err)
952                                 c->call_on_err (c, CT_OVERFLOW);
953                         ++c->ierrs;
954                         for (i=0; i<NBUF; ++i) {
955                                 B_LEN (c->rdesc[i]) = DMABUFSZ;
956                                 B_STATUS (c->rdesc[i]) = 0;
957                         }
958                         ct_start_receiver (c, 1, c->rphys[0], DMABUFSZ,
959                                 c->rdphys[0], c->rdphys[NBUF-1]);
960                         c->rn = 0;
961                 }
962                 /* Clear DMA interrupt. */
963                 outb (c->RX.DSR, dsr);
964                 ++c->rintr;
965                 break;
966
967         case IMVR_TX_DMOK:              /* transmit DMA normal end */
968         case IMVR_TX_DMERR:             /* transmit DMA error      */
969                 dsr = inb (c->TX.DSR);
970                 cda = inw (c->TX.CDA);
971
972                 for (i=0; i<NBUF && cda != (unsigned short)c->tdphys[i]; ++i)
973                         continue;
974                 if (i >= NBUF)
975                         i = 1; /* cannot happen */
976                 if (dsr & DSR_CHAIN_COF) {
977                         if (c->call_on_err)
978                                 c->call_on_err (c, CT_UNDERRUN);
979                         ++c->oerrs;
980                 }
981                 while (c->tn != i) {
982                         if (c->call_on_tx)
983                                 c->call_on_tx (c, c->attach[c->tn],
984                                         B_LEN(c->tdesc[c->tn]));
985                         ++c->opkts;
986                         c->obytes += B_LEN(c->tdesc[c->tn]);
987
988                         c->tn = (c->tn + 1) % NBUF;
989                         /* Clear DMA interrupt. */
990                         outb (c->TX.DSR, DSR_CHAIN_EOM | DSR_DMA_CONTINUE);
991                 }
992                 outb (c->TX.DSR, dsr & ~DSR_CHAIN_EOM);
993                 ++c->tintr;
994                 break;
995
996         case IMVR_TX_INT:               /* transmit error, HDLC only */
997                 st1 = inb (c->ST1);
998                 if (st1 & ST1_HDLC_UDRN) {
999                         if (c->call_on_err)
1000                                 c->call_on_err (c, CT_UNDERRUN);
1001                         ++c->oerrs;
1002                 }
1003                 outb (c->ST1, st1);
1004                 ++c->tintr;
1005                 break;
1006
1007         default:
1008                 /* Unknown interrupt - cannot happen. */
1009                 break;
1010         }
1011 }
1012
1013 int ct_receive_enabled (ct_chan_t *c)
1014 {
1015         int st3;
1016
1017         st3 = inb (c->ST3);
1018         return (st3 & ST3_RX_ENABLED) ? 1 : 0;
1019 }
1020
1021 int ct_transmit_enabled (ct_chan_t *c)
1022 {
1023         int st3;
1024
1025         st3 = inb (c->ST3);
1026         return (st3 & ST3_TX_ENABLED) ? 1 : 0;
1027 }
1028
1029 int ct_buf_free (ct_chan_t *c)
1030 {
1031         return (NBUF + c->tn - c->te - 1) % NBUF;
1032 }
1033
1034 int ct_send_packet (ct_chan_t *c, unsigned char *data, int len,
1035         void *attachment)
1036 {
1037         int dsr, ne;
1038
1039         if (len > DMABUFSZ)
1040                 return -2;
1041
1042         /* Is it really free? */
1043         ne = (c->te+1) % NBUF;
1044         if (ne == c->tn)
1045                 return -1;
1046
1047         /* Set up the tx descriptor. */
1048         B_LEN (c->tdesc[c->te]) = len;
1049         B_STATUS (c->tdesc[c->te]) = FST_EOM;
1050         c->attach[c->te] = attachment;
1051         if (c->tbuf[c->te] != data)
1052                 memcpy (c->tbuf[c->te], data, len);
1053
1054         /* Start the transmitter. */
1055         c->te = ne;
1056         outw (c->TX.EDA, (unsigned short) c->tdphys[ne]);
1057         dsr = inb (c->TX.DSR);
1058         if (! (dsr & DSR_DMA_ENABLE))
1059                 outb (c->TX.DSR, DSR_DMA_ENABLE);
1060         return 0;
1061 }
1062
1063 int scc_write (ct_chan_t *c, unsigned char *d, int len)
1064 {
1065         int i, free;
1066
1067         /* determining free place in buffer */
1068         if (c->scctx_empty)
1069                 free = SCCBUFSZ;
1070         else
1071                 free = (SCCBUFSZ + c->scctx_b - c->scctx_e) % SCCBUFSZ;
1072
1073         if (len > free)
1074                 return -1;
1075
1076         for (i=0; i<len; i++){
1077                 c->scctx[c->scctx_e] = d[i];
1078                 c->scctx_e = (c->scctx_e+1) % SCCBUFSZ;
1079         }
1080         if (c->scctx_empty && len) {
1081                 cte_out2d (c, c->scctx[c->scctx_b]);
1082                 c->scctx_empty = 0;
1083         }
1084         return 0;
1085 }
1086
1087 int scc_read (ct_chan_t *c, unsigned char *d, int len)
1088 {
1089         int i, bytes;
1090
1091         if (c->sccrx_empty)
1092                 bytes = 0;
1093         else
1094                 bytes = (SCCBUFSZ + c->sccrx_e - 1 - c->sccrx_b) %
1095                                 SCCBUFSZ + 1;
1096         if (len > bytes)
1097                 return -1;
1098
1099         for (i=0; i<len; i++){
1100                 d[i] = c->sccrx[c->sccrx_b];
1101                 c->sccrx_b = (c->sccrx_b+1) % SCCBUFSZ;
1102         }
1103         if (c->sccrx_b==c->sccrx_e)
1104                 c->sccrx_empty = 1;
1105         return 0;
1106 }
1107
1108 int sccrx_check (ct_chan_t *c)
1109 {
1110         int bytes;
1111
1112         if (c->sccrx_empty)
1113                 bytes = 0;
1114         else
1115                 bytes = (SCCBUFSZ + c->sccrx_e - 1 - c->sccrx_b) %
1116                                 SCCBUFSZ + 1;
1117         return bytes;
1118 }
1119
1120 int scc_read_byte (ct_chan_t *c)
1121 {
1122         unsigned char a;
1123
1124         if (scc_read (c, &a, 1) < 0)
1125                 return -1;
1126         return a;
1127 }
1128
1129 int scc_write_byte (ct_chan_t *c, unsigned char b)
1130 {
1131         if (scc_write (c, &b, 1) < 0)
1132                 return -1;
1133         return b;
1134 }
1135
1136 /*
1137  * Register event processing functions
1138  */
1139 void ct_register_transmit (ct_chan_t *c, void (*func) (ct_chan_t*, void*, int))
1140 {
1141         c->call_on_tx = func;
1142 }
1143
1144 void ct_register_receive (ct_chan_t *c, void (*func) (ct_chan_t*, char*, int))
1145 {
1146         c->call_on_rx = func;
1147 }
1148
1149 void ct_register_error (ct_chan_t *c, void (*func) (ct_chan_t*, int))
1150 {
1151         c->call_on_err = func;
1152 }
1153
1154 void ct_register_scc (ct_chan_t *c, void (*func) (ct_chan_t*))
1155 {
1156         c->call_on_scc = func;
1157 }
1158
1159 void ct_register_modem (ct_chan_t *c, void (*func) (ct_chan_t*))
1160 {
1161         c->call_on_msig = func;
1162 }