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: stable/11/sys/dev/ctau/ctddk.c 315221 2017-03-14 02:06:03Z pfg $");
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
45static void ct_hdlc_interrupt (ct_chan_t *c, int imvr);
46static void ct_e1_interrupt (ct_board_t *b);
47static void ct_scc_interrupt (ct_board_t *b);
48static void ct_e1timer_interrupt (ct_chan_t *c);
49
50static 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
55int 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
65int 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 = NULL;
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 */
131void 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
144static 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 */
153static 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
165void 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 */
186static 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 */
210static 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
231int 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
247int ct_get_clk (ct_chan_t *c)
248{
249	return c->num ? c->board->opt.clk1 : c->board->opt.clk0;
250}
251
252int 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
264int 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
273int 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 */
285void 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 */
303void 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 */
391void 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 */
428void 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
457int 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
481int ct_get_dpll (ct_chan_t *c)
482{
483	return (c->hopt.rxs == CLK_RXS_DPLL_INT);
484}
485
486void 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
495int 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 */
503void 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 */
512void 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
519int 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 */
527void 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
534int 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 */
542void 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
564static 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
575static 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 */
630void 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
722static 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
871static 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
1013int 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
1021int 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
1029int ct_buf_free (ct_chan_t *c)
1030{
1031	return (NBUF + c->tn - c->te - 1) % NBUF;
1032}
1033
1034int 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
1063int 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
1087int 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
1108int 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
1120int 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
1129int 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 */
1139void ct_register_transmit (ct_chan_t *c, void (*func) (ct_chan_t*, void*, int))
1140{
1141	c->call_on_tx = func;
1142}
1143
1144void ct_register_receive (ct_chan_t *c, void (*func) (ct_chan_t*, char*, int))
1145{
1146	c->call_on_rx = func;
1147}
1148
1149void ct_register_error (ct_chan_t *c, void (*func) (ct_chan_t*, int))
1150{
1151	c->call_on_err = func;
1152}
1153
1154void ct_register_scc (ct_chan_t *c, void (*func) (ct_chan_t*))
1155{
1156	c->call_on_scc = func;
1157}
1158
1159void ct_register_modem (ct_chan_t *c, void (*func) (ct_chan_t*))
1160{
1161	c->call_on_msig = func;
1162}
1163