1/*
2 * Middle-level code for Cronyx Tau32-PCI adapters.
3 *
4 * Copyright (C) 2004 Cronyx Engineering
5 * Copyright (C) 2004 Roman Kurakin <rik@FreeBSD.org>
6 *
7 * This software is distributed with NO WARRANTIES, not even the implied
8 * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 *
10 * Authors grant any other persons or organisations a permission to use,
11 * modify and redistribute this software in source and binary forms,
12 * as long as this message is kept with the software, all derivative
13 * works or modified versions.
14 *
15 * $Cronyx: ceddk.c,v 1.2.6.2 2005/11/17 16:04:13 rik Exp $
16 */
17
18#include <sys/cdefs.h>
19__FBSDID("$FreeBSD$");
20
21#include <dev/cx/machdep.h>
22#include <dev/ce/ceddk.h>
23
24#undef CE_DDK_DEBUG_ENABLED
25#ifdef CE_DDK_DEBUG_ENABLED
26#ifdef __FreeBSD__
27# define CE_DDK_DEBUG(b,c,s) \
28	do { \
29		if (c) { \
30			printf("ce%d-%d: ",(b)->num,(c)->num); \
31		} else { \
32			printf("ce%d-*: ",(b)->num); \
33		} \
34		printf s; \
35	} while (0)
36#else
37# define CE_DDK_DEBUG(b,c,s)	do {} while (0)
38#endif
39#else
40# define CE_DDK_DEBUG(b,c,s)	do {} while (0)
41#endif
42
43#if 0
44#define ENTER() \
45	static int enter=0; \
46	do { \
47	enter++; \
48	printf ("%s: >> enter (%16llx) %d\n", __FUNCTION__, rdtsc (), enter); \
49	} while (0)
50
51#define EXIT(val...) \
52	do { \
53	enter--; \
54	printf ("%s: << exit  (%16llx) %d line %d\n", __FUNCTION__, rdtsc (), enter, __LINE__); \
55	return val; \
56	} while (0)
57#else
58#define ENTER() \
59	do {} while (0)
60
61#define EXIT(val...) \
62	do {return val;} while (0)
63#endif
64
65#define CE_ENQUEUE(list,item) \
66	do { \
67		TAU32_UserRequest **last; \
68		last = &(list); \
69		while (*last) { \
70			last = &(*last)->next; \
71		} \
72		(*last) = (item); \
73		(item)->next = NULL; \
74	} while (0)
75
76#define CE_ENQUEUE_HEAD(list,item) \
77	do { \
78		(item)->next = list; \
79		list = item; \
80	} while (0)
81
82#define CE_DEQUEUE(list,item) \
83	do { \
84		item = list; \
85		if (list) { \
86			list = (item)->next; \
87		} \
88	} while (0)
89
90#define CE_PREREQUEST(b,c,list,item) \
91	do { \
92		item = list; \
93		if (!item) { \
94			CE_DDK_DEBUG (b, c, ("Fatal error, no free structs " \
95					     "for UserRequest (%s:%d)\n", \
96					     __FUNCTION__, __LINE__)); \
97		} \
98	} while (0)
99
100#define CE_DUMP_QUEUE(list) \
101	do { \
102		TAU32_UserRequest *item; \
103		int i = 0; \
104		item = list; \
105		while (item) { \
106			printf ("item%d: %p\n", i, item); \
107			item = item->next; \
108			i++; \
109		} \
110	} while (0)
111
112#define CE_FIND_ITEM(list,item,flag) \
113	do { \
114		TAU32_UserRequest *citem; \
115		flag = 0; \
116		for (citem = list; citem; citem = citem->next) { \
117			if (citem == item) { \
118				flag = 1; \
119				break; \
120			} \
121		} \
122	} while (0)
123
124#define CE_LAST_ITEM(list,item) \
125	do { \
126		TAU32_UserRequest **last; \
127		last = &(list); \
128		while ((*last) && (*last)->next) { \
129			last = &(*last)->next; \
130		} \
131		(item) = (*last); \
132	} while (0)
133
134#define CE_ASSERT(a) \
135	do { \
136		if (!(a)) { \
137			printf ("ASSERT: %d %s\n", __LINE__, #a); \
138			__asm __volatile ("int $3"); \
139		} \
140	} while (0)
141
142static void _ce_set_ts (ce_chan_t *c, unsigned long ts);
143static void _ce_submit_configure_e1 (ce_chan_t *c, char *rname);
144
145#ifdef CE_DDK_DEBUG_ENABLED
146static char *ce_err2str (unsigned long err)
147{
148	switch (err) {
149	case TAU32_SUCCESSFUL:
150		return "Successful";
151	case TAU32_ERROR_ALLOCATION:
152		return "Allocation error, not enough tx/rx descriptors";
153	case TAU32_ERROR_BUS:
154		return "PEB could not access to host memory by PCI bus for load/store information";
155	case TAU32_ERROR_FAIL:
156		return "PEB action request failed";
157	case TAU32_ERROR_TIMEOUT:
158		return "PEB action request timeout";
159	case TAU32_ERROR_CANCELLED:
160		return "request has been canceled";
161	case TAU32_ERROR_TX_UNDERFLOW:
162		return "transmission underflow";
163	case TAU32_ERROR_TX_PROTOCOL:
164		return "TX_PROTOCOL";
165	case TAU32_ERROR_RX_OVERFLOW:
166		return "RX_OVERFLOW";
167	case TAU32_ERROR_RX_ABORT:
168		return "RX_ABORT";
169	case TAU32_ERROR_RX_CRC:
170		return "RX_CRC";
171	case TAU32_ERROR_RX_SHORT:
172		return "RX_SHORT";
173	case TAU32_ERROR_RX_SYNC:
174		return "RX_SYNC";
175	case TAU32_ERROR_RX_FRAME:
176		return "RX_FRAME";
177	case TAU32_ERROR_RX_LONG:
178		return "RX_LONG";
179	case TAU32_ERROR_RX_SPLIT:
180		return "frame has splitted between two requests due rx-gap allocation";
181	case TAU32_ERROR_RX_UNFIT:
182		return "frame can't be fit into request buffer";
183	case TAU32_ERROR_TSP:
184		return "ERROR_TSP";
185	case TAU32_ERROR_RSP:
186		return "ERROR_RSP";
187	case TAU32_ERROR_INT_OVER_TX:
188		return "ERROR INT OVER TX";
189	case TAU32_ERROR_INT_OVER_RX:
190		return "ERROR INT OVER RX";
191	case TAU32_ERROR_INT_STORM:
192		return "irq storm";
193	case TAU32_ERROR_INT_E1LOST:
194		return "ERROR_E1LOST";
195	default:
196		return ("Unknown error");
197	}
198}
199#endif
200
201void ce_set_dtr (ce_chan_t *c, int on)
202{
203	c->dtr = on?1:0;
204}
205
206void ce_set_rts (ce_chan_t *c, int on)
207{
208	c->rts = on?1:0;
209}
210
211static void TAU32_CALLBACK_TYPE ce_on_receive
212	(TAU32_UserContext *pContext, TAU32_UserRequest *req)
213{
214	ce_buf_item_t *item = (ce_buf_item_t *)req;
215	ce_chan_t *c;
216	ce_board_t *b;
217	unsigned int error;
218	int len;
219
220	ENTER ();
221	if (!req || !req->sys) {
222		EXIT ();
223	}
224
225	c = (ce_chan_t *)req->sys;
226	b = c->board;
227
228	len = req->Io.Rx.Received;
229	error = req->ErrorCode;
230
231	c->rintr++;
232	if (error == TAU32_SUCCESSFUL) {
233		if (req->Io.Rx.FrameEnd) {
234			c->ipkts++;
235		} else {
236			CE_DDK_DEBUG (b, c, ("No FrameEnd\n"));
237			/* probably do something in some cases*/
238		}
239		c->ibytes += len;
240		if (c->receive)
241			c->receive (c, item->buf, len);
242	} else if (error & TAU32_ERROR_BUS) {
243		c->overrun++;
244		if (c->error)
245			c->error (c, CE_OVERRUN);
246	} else {
247		CE_DDK_DEBUG (b, c, ("Another receive error: %x\n", error));
248		/* Do some procesing */
249	}
250
251	CE_ASSERT (!req->pInternal);
252	CE_ENQUEUE (c->rx_queue, req);
253	while (c->rx_queue) {
254		CE_DEQUEUE (c->rx_queue, req);
255		CE_ASSERT (req);
256		item = (ce_buf_item_t *)req;
257		req->Command = TAU32_Rx_Data;
258		req->Io.Rx.Channel = c->num;
259		req->pCallback = ce_on_receive;
260		req->Io.Rx.BufferLength = BUFSZ+4;
261		req->Io.Rx.PhysicalDataAddress = item->phys;
262		if (!TAU32_SubmitRequest (b->ddk.pControllerObject, req)) {
263			CE_DDK_DEBUG (b, c, ("RX submition failure\n"));
264			c->rx_pending--;
265			CE_ENQUEUE_HEAD (c->rx_queue, req);
266			break;
267		}
268	}
269	EXIT ();
270}
271
272static void TAU32_CALLBACK_TYPE ce_on_transmit
273	(TAU32_UserContext *pContext, TAU32_UserRequest *req)
274{
275	int len;
276	unsigned int error;
277	ce_chan_t *c;
278	ENTER ();
279
280	if (!req || !req->sys) {
281		EXIT ();
282	}
283
284	c = (ce_chan_t *)req->sys;
285
286	len = req->Io.Tx.Transmitted;
287	error = req->ErrorCode;
288
289	c->tintr++;
290	if (error == TAU32_SUCCESSFUL) {
291		c->obytes += len;
292		c->opkts++;
293	} else if (error & TAU32_ERROR_BUS) {
294		c->underrun++;
295		if (c->error)
296			c->error (c, CE_UNDERRUN);
297	} else {
298		CE_DDK_DEBUG (c->board, c, ("Another transmit error: %x\n",
299				error));
300		/* Do some procesing */
301	}
302
303	CE_ENQUEUE (c->tx_queue, req);
304	c->tx_pending--;
305
306	if (c->transmit)
307		c->transmit (c, 0, len);
308	EXIT ();
309}
310
311int ce_transmit_space (ce_chan_t *c)
312{
313	return c->tx_pending < (TAU32_IO_QUEUE);
314}
315
316int ce_send_packet (ce_chan_t *c, unsigned char *buf, int len, void *tag)
317{
318	TAU32_UserRequest *req;
319	ce_buf_item_t *item;
320
321	ENTER ();
322
323	if (!ce_transmit_space (c)) {
324		EXIT (-1);
325	}
326
327	if (len <= 0 || len > BUFSZ) {
328		EXIT (-2);
329	}
330
331	CE_DEQUEUE (c->tx_queue, req);
332	CE_ASSERT (req);
333	item = (ce_buf_item_t *)req;
334
335	if (buf != item->buf)
336		memcpy (item->buf, buf, len);
337
338	CE_ASSERT (!req->pInternal);
339
340	req->Command = TAU32_Tx_Data | TAU32_Tx_FrameEnd;
341	req->Io.Tx.Channel = c->num;
342	req->pCallback = ce_on_transmit;
343	req->Io.Tx.DataLength = len;
344	req->Io.Tx.PhysicalDataAddress = item->phys;
345	c->tx_pending++;
346	if (!TAU32_SubmitRequest (c->board->ddk.pControllerObject, req)) {
347		CE_DDK_DEBUG (c->board, c, ("Can't submit packet for "
348					    "transmission\n"));
349		CE_ENQUEUE_HEAD (c->tx_queue, req);
350		c->tx_pending--;
351		EXIT (-3);
352	}
353	EXIT (0);
354}
355
356static void TAU32_CALLBACK_TYPE ce_on_config
357	(TAU32_UserContext *pContext, TAU32_UserRequest *req)
358{
359	ce_board_t *b = (ce_board_t *) pContext;
360	ENTER ();
361	b->cr.pending--;
362	if (req->ErrorCode)
363		CE_DDK_DEBUG (b, (ce_chan_t*)0, ("Config request failure: %lx\n",
364			      req->ErrorCode));
365	EXIT ();
366}
367
368static void TAU32_CALLBACK_TYPE ce_on_config_stop
369	(TAU32_UserContext *pContext, TAU32_UserRequest *req)
370{
371	int i, first;
372	TAU32_UserRequest *rreq;
373	ce_board_t *b = (ce_board_t *) pContext;
374	ce_chan_t *c = b->chan + req->Io.ChannelNumber;
375
376	ENTER ();
377	/* Stop all requests */
378	CE_ASSERT (0);/* Buggy */
379	CE_LAST_ITEM (c->rx_queue, rreq);
380	/* A little hacky, try to guess which is a first */
381	first = rreq ? (c->rx_item - (ce_buf_item_t *)rreq) + 1 : 0;
382	for (i = 0; i < TAU32_IO_QUEUE; i++) {
383		int is_pending;
384		rreq = &c->rx_item[(i + first) % TAU32_IO_QUEUE].req;
385		CE_FIND_ITEM (c->rx_queue, rreq, is_pending);
386		if (!is_pending)
387			continue;
388		TAU32_CancelRequest (b->ddk.pControllerObject, rreq, 1);
389		rreq->Command = TAU32_Rx_Data;
390		rreq->Io.Rx.Channel = c->num;
391		rreq->Io.Rx.BufferLength = BUFSZ+4;
392		rreq->Io.Rx.PhysicalDataAddress = ((ce_buf_item_t *)rreq)->phys;
393		c->rx_pending++;
394		if (!TAU32_SubmitRequest (b->ddk.pControllerObject, rreq)) {
395			CE_ASSERT (0);/* Buggy */
396			c->rx_pending--;
397			break;
398		}
399	}
400
401	c->tx_pending = 0;
402/*	c->rx_pending = 0;*/
403	EXIT ();
404}
405
406static int ce_cfg_submit (ce_board_t *b)
407{
408	TAU32_UserRequest *req;
409	ENTER ();
410
411	CE_DEQUEUE (b->cr.queue, req);
412	CE_ASSERT (req);
413	CE_ASSERT (!req->pInternal);
414
415	req->pCallback = ce_on_config;
416	b->cr.pending++;
417
418	CE_DDK_DEBUG (b, (ce_chan_t *)0, ("config request pending: %d\n",
419		      b->cr.pending));
420
421	if (!TAU32_SubmitRequest (b->ddk.pControllerObject, req)) {
422		CE_ENQUEUE_HEAD (b->cr.queue, req);
423		CE_DDK_DEBUG (b, (ce_chan_t *)0, ("Fail to submit config request\n"));
424		b->cr.pending--;
425		EXIT (0);
426	}
427
428	EXIT (1);
429}
430
431void ce_init_board (ce_board_t *b)
432{
433	int i;
434
435	b->cr.queue = NULL;
436
437	for (i = 0; i < CONFREQSZ; i++) {
438		CE_ENQUEUE (b->cr.queue, b->cr.req + i);
439	}
440
441	b->chan[0].config = TAU32_ais_on_loss;
442
443	/* lloop = off, rloop = off */
444	b->chan[0].config |= TAU32_LineNormal;
445	b->chan[0].lloop = 0;
446	b->chan[0].rloop = 0;
447
448	/* unfram=off, scrambler=off, use16=off, crc4=off,
449	   higain=off, monitor=off*/
450	b->chan[0].config |= (b->ddk.Interfaces == 2 ? TAU32_framed_cas_cross :
451						       TAU32_framed_cas_set);
452	b->chan[0].unfram = 0;
453	b->chan[0].scrambler = 0;
454	b->chan[0].use16 = 0;
455	b->chan[0].crc4 = 0;
456	b->chan[0].higain = 0;
457	b->chan[0].monitor = 0;
458
459	if (b->ddk.Interfaces == 2) {
460		b->chan[1].config = TAU32_ais_on_loss;
461		/* lloop = off, rloop = off */
462		b->chan[1].config |= TAU32_LineNormal;
463		/* unfram=off, scrambler=off, use16=off, crc4=off,
464		   higain=off, monitor=off*/
465		b->chan[1].config |= TAU32_framed_cas_cross;
466		b->chan[1].unfram = 0;
467		b->chan[1].scrambler = 0;
468		b->chan[1].use16 = 0;
469		b->chan[1].crc4 = 0;
470		b->chan[1].higain = 0;
471		b->chan[1].monitor = 0;
472	}
473
474	for (i = 0; i < NCHAN; i++) {
475		/* Chan0 ts=1-15,17-31, Chan1 ts=1-2 */
476		b->chan[i].type = i < b->ddk.Interfaces ? T_E1 : T_DATA;
477		b->chan[i].ts = (i == 0 ? 0xfffefffe :
478				(i != 1 ? 0 :
479				(b->ddk.Interfaces == 2 ? 0x6: 0)));
480		b->chan[i].dir = (b->ddk.Interfaces == 2) ? (i%2) : 0;
481		b->chan[i].mtu = 1504;
482	}
483#if 0
484	/* c->num == 0 */
485	req = b->cr.queue;
486	/* We must have some here */
487	CE_ASSERT (req);
488	req->Command = TAU32_Configure_E1;
489	req->Io.InterfaceConfig.Interface = TAU32_E1_A;
490	req->Io.InterfaceConfig.Config = b->chan[0].config;
491	req->Io.InterfaceConfig.UnframedTsMask = 0;
492	if (!ce_cfg_submit (b)) {
493		CE_DDK_DEBUG (b, b->chan + 0,
494			      ("Submit request failure, line %d\n",
495			      __LINE__));
496	}
497	/* c->num == 1 */
498	if (b->ddk.Interfaces == 2) {
499		req = b->cr.queue;
500		/* We must have some here */
501		CE_ASSERT (req);
502		req->Command = TAU32_Configure_E1;
503		req->Io.InterfaceConfig.Interface = TAU32_E1_B;
504		req->Io.InterfaceConfig.Config = b->chan[1].config;
505		req->Io.InterfaceConfig.UnframedTsMask = 0;
506		if (!ce_cfg_submit (b)) {
507			CE_DDK_DEBUG (b, b->chan + 1,
508				      ("Submit request failure, line %d\n",
509				      __LINE__));
510		}
511	}
512#endif
513	/* Set default cross matrix */
514	for (i = 0; i < 32; i++) {
515		/* -X-> Peb */
516		b->dxc[i] = TAU32_CROSS_OFF;
517		/* Link2 -> Link1 */
518		b->dxc[i + 32] = i + 64;
519		/* Link1 -> Link2 */
520		b->dxc[i + 64] = i + 32;
521	}
522
523	/* We have only mux mode for now. Later we will also have cross mode */
524	b->mux = 1;
525}
526
527void ce_start_chan (ce_chan_t *c, int tx, int rx, ce_buf_t *cb,
528	unsigned long phys)
529{
530	int i;
531	ce_board_t *b = c->board;
532
533/*	c->config = TAU32_ais_on_loss | TAU32_framed_cas_cross;*/
534
535	if (cb) {
536		CE_DDK_DEBUG (b, c, ("ce_buf_t virt:%p phys:%p\n", cb,
537			      (void *)phys));
538		c->tx_item = cb->tx_item;
539		c->rx_item = cb->rx_item;
540		c->tx_queue = NULL;
541		c->rx_queue = NULL;
542		for (i = 0; i < TAU32_IO_QUEUE; i++) {
543			c->tx_item[i].phys = phys +
544				((char *)(c->tx_item[i].buf)-(char *)cb);
545			c->rx_item[i].phys = phys +
546				((char *)(c->rx_item[i].buf)-(char *)cb);
547			cb->tx_item[i].req.sys = c;
548			cb->rx_item[i].req.sys = c;
549			CE_DDK_DEBUG (b, c, ("tx_item[%d].buf virt:%p phys:%p\n",
550				      i, c->tx_item[i].buf,
551				      (void *)c->tx_item[i].phys));
552			CE_DDK_DEBUG (b, c, ("rx_item[%d].buf virt:%p phys:%p\n",
553				      i, c->rx_item[i].buf,
554				      (void *)c->rx_item[i].phys));
555			CE_ENQUEUE (c->rx_queue, &c->rx_item[i].req);
556			CE_ENQUEUE (c->tx_queue, &c->tx_item[i].req);
557		}
558		c->tx_pending = 0;
559		c->rx_pending = 0;
560	}
561
562	/* submit rx */
563	while (1) {
564		ce_buf_item_t *item;
565		TAU32_UserRequest *req;
566
567		CE_DEQUEUE (c->rx_queue, req);
568		if (!req)
569			break;
570		item = (ce_buf_item_t *) req;
571		CE_ASSERT (c->rx_pending < TAU32_IO_QUEUE);
572		req->Command = TAU32_Rx_Data;
573		req->Io.Rx.Channel = c->num;
574		req->pCallback = ce_on_receive;
575		req->Io.Rx.BufferLength = c->mtu + (c->phony ? 0 : 4);
576		req->Io.Rx.PhysicalDataAddress = item->phys;
577		c->rx_pending++;
578		if (!TAU32_SubmitRequest (b->ddk.pControllerObject, req)) {
579			CE_DDK_DEBUG (b, c, ("Faild to submit rx request\n"));
580			/*XXXRIK: shouldn't happen, but ... */
581			CE_ASSERT (0);
582			c->rx_pending--;
583			break;
584		}
585	}
586
587	if (tx | rx) {
588		TAU32_UserRequest *req;
589		CE_PREREQUEST (b, c, b->cr.queue, req);
590		if (!req)
591 			return;
592		req->Command = TAU32_Configure_Commit |
593			       (tx ? TAU32_Tx_Start : 0) |
594			       (rx ? TAU32_Rx_Start : 0);
595		req->Io.ChannelNumber = c->num;
596		if (!ce_cfg_submit (b)) {
597			CE_DDK_DEBUG (b, c, ("Can't start chan\n"));
598			/* Do some error processing */
599			return;
600		}
601	}
602
603	/* If we run just after ce_board_init we have prope values.
604	 * Else I hope you didn't set ts to incorrect value.
605	 */
606	_ce_set_ts (c, c->ts);
607	if (c->num < b->ddk.Interfaces) {
608		/* The same for other modes. We don't check them.
609		 * We hope that config is correctly set. Just as we have
610		 * after ce_board_init. If channel was stoped we hope that
611		 * it's config was not broken just after it and we didn't
612		 * brake it before start.
613		 */
614		_ce_submit_configure_e1 (c, "start_init");
615	}
616}
617
618void ce_stop_chan (ce_chan_t *c)
619{
620	ce_board_t *b = c->board;
621	TAU32_UserRequest *req;
622	CE_DEQUEUE (b->cr.queue, req);
623
624	/* XXXRIK: This function should be for comleteness, but for now I
625	 * don't use it. So I just start to write and didn't finished it yet.
626	 * It and it is VERY BUGGY!!! Do not use it. If you really
627	 * need it ask me to fix it or rewrite it by your self.
628	 * Note: most buggy part of it in ce_on_config_stop!
629	 */
630	if (!req) {
631		CE_DDK_DEBUG (b, c, ("Fatal error, no free structs for "
632			      "UserRequest (%s:%d)\n", __FUNCTION__, __LINE__));
633		return;
634	}
635	req->Command = TAU32_Configure_Commit |
636		       TAU32_Tx_Stop | TAU32_Rx_Stop;
637	req->Command = 0;
638	req->Io.ChannelNumber = c->num;
639	req->pCallback = ce_on_config_stop;
640	b->cr.pending++;
641
642	if (!TAU32_SubmitRequest (b->ddk.pControllerObject, req)) {
643		CE_ENQUEUE_HEAD (b->cr.queue, req);
644		CE_DDK_DEBUG (b, c, ("Can't stop chan\n"));
645		b->cr.pending--;
646	}
647}
648
649
650void ce_register_transmit (ce_chan_t *c,
651	void (*func) (ce_chan_t*, void*, int))
652{
653	c->transmit = func;
654}
655
656void ce_register_receive (ce_chan_t *c,
657	void (*func) (ce_chan_t*, unsigned char*, int))
658{
659	c->receive = func;
660}
661
662void ce_register_error (ce_chan_t *c,
663	void (*func) (ce_chan_t*, int))
664{
665	c->error = func;
666}
667
668void TAU32_CALLBACK_TYPE ce_error_callback (TAU32_UserContext *pContext,
669						int Item, unsigned NotifyBits)
670{
671	ce_board_t *b = (ce_board_t *) pContext;
672	ENTER ();
673	if (NotifyBits & (TAU32_ERROR_FAIL | TAU32_ERROR_TIMEOUT
674		| TAU32_ERROR_INT_OVER_TX | TAU32_ERROR_INT_OVER_RX
675		| TAU32_ERROR_INT_STORM)) {
676		/* Fatal: adapter failure, need reset & restart */
677		/* RIKXXX: probably I should add CE_FAILURE for ce_error */
678		CE_DDK_DEBUG (b, (ce_chan_t *)0, ("Err, disable interrupts: %s\n",
679				ce_err2str (NotifyBits)));
680/*		TAU32_DisableInterrupts (b->ddk.pControllerObject);*/
681		EXIT ();
682	}
683	if (Item >= 0) {
684		/* channel error */
685		ce_chan_t *c = b->chan + Item;
686		if (NotifyBits & TAU32_ERROR_TX_UNDERFLOW) {
687			c->underrun++;
688			if (c->error)
689				c->error (c, CE_UNDERRUN);
690		}
691		if (NotifyBits & TAU32_ERROR_RX_OVERFLOW) {
692			c->overrun++;
693			if (c->error)
694				c->error (c, CE_OVERFLOW);
695		}
696		if (NotifyBits & (TAU32_ERROR_RX_FRAME | TAU32_ERROR_RX_ABORT |
697		    TAU32_ERROR_RX_SHORT | TAU32_ERROR_RX_LONG |
698		    TAU32_ERROR_RX_SYNC | TAU32_ERROR_RX_SPLIT |
699		    TAU32_ERROR_RX_UNFIT)) {
700			c->frame++;
701			CE_DDK_DEBUG (b, c, ("Frame error: %x\n", NotifyBits));
702			if (c->error)
703				c->error (c, CE_FRAME);
704		}
705		if(NotifyBits & TAU32_ERROR_RX_CRC) {
706			c->crc++;
707			if (c->error)
708				c->error (c, CE_CRC);
709		}
710	} else {
711		CE_DDK_DEBUG (b, (ce_chan_t *)0, ("Another error: %x\n",
712			      NotifyBits));
713		/* Adapter error, do smth */
714	}
715	EXIT ();
716}
717
718void TAU32_CALLBACK_TYPE ce_status_callback(TAU32_UserContext *pContext,
719						int Item, unsigned NotifyBits)
720{
721	ce_board_t *b = (ce_board_t *) pContext;
722	ENTER ();
723	if(Item >= 0) {
724		/* e1 status */
725		ce_chan_t *c = b->chan + Item;
726		c->acc_status |= b->ddk.InterfacesInfo[Item].Status;
727/*		CE_DDK_DEBUG (b, c, ("Current status: %x\n", c->acc_status));*/
728	} else {
729		CE_DDK_DEBUG (b, (ce_chan_t *)0, ("Another status: %x\n", NotifyBits));
730		/* Adapter status, do smth. */
731	}
732	EXIT ();
733}
734
735int ce_get_cd (ce_chan_t *c)
736{
737	unsigned int e1status = c->board->ddk.InterfacesInfo[c->dir].Status;
738
739	return (c->ts && !(e1status & (TAU32_RCL | TAU32_E1OFF)));
740}
741
742int ce_get_cts (ce_chan_t *c)
743{
744	return 0;
745}
746
747int ce_get_dsr (ce_chan_t *c)
748{
749	return 0;
750}
751
752void ce_e1_timer (ce_chan_t *c)
753{
754	unsigned bpv, fas, crc4, ebit, pcv, oof, css;
755	unsigned int acc_status;
756	ce_board_t *b = c->board;
757	TAU32_E1_State	*state;
758
759	if (c->num >= b->ddk.Interfaces)
760		return;
761
762	state = &b->ddk.InterfacesInfo[c->num];
763	acc_status = c->acc_status;
764
765	/* Clear acc_status */
766	c->acc_status = b->ddk.InterfacesInfo[c->num].Status;
767
768	/* Count seconds.
769	 * During the first second after the channel startup
770	 * the status registers are not stable yet,
771	 * we will so skip the first second. */
772	++c->cursec;
773	if (! c->totsec && c->cursec <= 1)
774		return;
775
776	c->status = 0;
777
778	/* Compute the SNMP-compatible channel status. */
779	oof = 0;
780
781	if (acc_status & TAU32_RCL)
782		c->status |= ESTS_LOS;		/* loss of signal */
783	if (acc_status & TAU32_RUA1)
784		c->status |= ESTS_AIS;		/* receiving all ones */
785
786	/* Get error counters. */
787	bpv = state->RxViolations;
788	fas = 0;
789	crc4 = 0;
790	ebit = 0;
791	css = 0;
792
793	if (! c->unfram) {
794		if (! c->use16 && (acc_status & TAU32_RSA1))
795			c->status |= ESTS_AIS16;	/* signaling all ones */
796		if (! c->use16 && (acc_status & TAU32_RDMA))
797			c->status |= ESTS_FARLOMF;	/* alarm in timeslot 16 */
798		if (acc_status & TAU32_RRA)
799			c->status |= ESTS_FARLOF;	/* far loss of framing */
800
801		if (acc_status & TAU32_RFAS) {
802			c->status |= ESTS_LOF;		/* loss of framing */
803			++oof;				/* out of framing */
804		}
805		if ((! c->use16 && (acc_status & TAU32_RCAS)) ||
806		    (c->crc4 && (acc_status & TAU32_RCRC4))) {
807			c->status |= ESTS_LOMF;		/* loss of multiframing */
808			++oof;				/* out of framing */
809		}
810		fas = state->FasErrors;
811		crc4 = state->Crc4Errors;
812		ebit = state->FarEndBlockErrors;
813
814		/* Controlled slip second -- any slip event. */
815		css = state->TransmitSlips + state->ReceiveSlips;
816	}
817
818	/* Clear state */
819	state->RxViolations		= 0;
820	state->FasErrors		= 0;
821	state->Crc4Errors		= 0;
822	state->FarEndBlockErrors	= 0;
823	state->TransmitSlips		= 0;
824	state->ReceiveSlips		= 0;
825
826	if (c->status & ESTS_LOS)
827		c->status = ESTS_LOS;
828	else if (c->status & ESTS_AIS)
829		c->status = ESTS_AIS;
830	else if (c->status & ESTS_LOF)
831		c->status = ESTS_LOF;
832	else if (c->status & ESTS_LOMF)
833		c->status &= ~(ESTS_FARLOMF | ESTS_AIS16);
834
835	if (! c->status)
836		c->status = ESTS_NOALARM;
837
838	c->currnt.bpv += bpv;
839	c->currnt.fse += fas;
840	if (c->crc4) {
841		c->currnt.crce += crc4;
842		c->currnt.rcrce += ebit;
843	}
844
845	/* Path code violation is frame sync error if CRC4 disabled,
846	 * or CRC error if CRC4 enabled. */
847	pcv = fas;
848	if (c->crc4)
849		pcv += crc4;
850
851	/* Unavaiable second -- receiving all ones, or
852	 * loss of carrier, or loss of signal. */
853	if (acc_status & (TAU32_RUA1 | TAU32_RCL))
854		/* Unavailable second -- no other counters. */
855		++c->currnt.uas;
856	else {
857		/* Line errored second -- any BPV. */
858		if (bpv)
859			++c->currnt.les;
860
861		/* Errored second -- any PCV, or out of frame sync,
862		 * or any slip events. */
863		if (pcv || oof || css)
864			++c->currnt.es;
865
866		/* Severely errored framing second -- out of frame sync. */
867		if (oof)
868			++c->currnt.oofs;
869
870		/* Severely errored seconds --
871		 * 832 or more PCVs, or 2048 or more BPVs. */
872		if (bpv >= 2048 || pcv >= 832)
873			++c->currnt.ses;
874		else {
875			/* Bursty errored seconds --
876			 * no SES and more than 1 PCV. */
877			if (pcv > 1)
878				++c->currnt.bes;
879
880			/* Collect data for computing
881			 * degraded minutes. */
882			++c->degsec;
883			c->degerr += bpv + pcv;
884		}
885	}
886
887	/* Degraded minutes -- having error rate more than 10e-6,
888	 * not counting unavailable and severely errored seconds. */
889	if (c->cursec % 60 == 0) {
890		if (c->degerr > c->degsec * 2048 / 1000)
891			++c->currnt.dm;
892		c->degsec = 0;
893		c->degerr = 0;
894	}
895
896	/* Rotate statistics every 15 minutes. */
897	if (c->cursec > 15*60) {
898		int i;
899
900		for (i=47; i>0; --i)
901			c->interval[i] = c->interval[i-1];
902		c->interval[0] = c->currnt;
903
904		/* Accumulate total statistics. */
905		c->total.bpv   += c->currnt.bpv;
906		c->total.fse   += c->currnt.fse;
907		c->total.crce  += c->currnt.crce;
908		c->total.rcrce += c->currnt.rcrce;
909		c->total.uas   += c->currnt.uas;
910		c->total.les   += c->currnt.les;
911		c->total.es    += c->currnt.es;
912		c->total.bes   += c->currnt.bes;
913		c->total.ses   += c->currnt.ses;
914		c->total.oofs  += c->currnt.oofs;
915		c->total.css   += c->currnt.css;
916		c->total.dm    += c->currnt.dm;
917		c->currnt.bpv	= 0;
918		c->currnt.fse	= 0;
919		c->currnt.crce	= 0;
920		c->currnt.rcrce	= 0;
921		c->currnt.uas	= 0;
922		c->currnt.les	= 0;
923		c->currnt.es	= 0;
924		c->currnt.bes	= 0;
925		c->currnt.ses	= 0;
926		c->currnt.oofs	= 0;
927		c->currnt.css	= 0;
928		c->currnt.dm	= 0;
929
930		c->totsec += c->cursec;
931		c->cursec = 0;
932	}
933}
934
935void ce_set_baud (ce_chan_t *c, unsigned long baud)
936{
937	TAU32_UserRequest *req;
938	ce_board_t *b = c->board;
939	unsigned long cfg = c->config & ~TAU32_framing_mode_mask;
940	unsigned long ts;
941	unsigned long kbps = (baud + 32000) / 64000 * 64;
942
943	if (!c->unfram || c->num != 0 ||
944		baud == c->baud || b->cr.pending >= CONFREQSZ)
945		return;
946
947	if (!kbps || kbps > 1024) {
948		ts = 0xffffffffUL;
949		cfg |= TAU32_unframed_2048;
950	} else if (kbps > 512) {
951		ts = 0x0000ffffUL;
952		cfg |= TAU32_unframed_1024;
953	} else if (kbps > 256) {
954		ts = 0x000000ffUL;
955		cfg |= TAU32_unframed_512;
956	} else if (kbps > 128) {
957		ts = 0x0000000fUL;
958		cfg |= TAU32_unframed_256;
959	} else if (kbps > 64) {
960		ts = 0x00000003UL;
961		cfg |= TAU32_unframed_128;
962	} else {
963		ts = 0x00000001UL;
964		cfg |= TAU32_unframed_64;
965	}
966
967	/* _ce_set_ts () will set proper baud */
968	_ce_set_ts (c, ts);
969	CE_PREREQUEST (b, c, b->cr.queue, req);
970	if (!req)
971		return;
972	req->Command = TAU32_Configure_E1;
973	req->Io.InterfaceConfig.Interface = TAU32_E1_A;
974	req->Io.InterfaceConfig.Config = cfg;
975	req->Io.InterfaceConfig.UnframedTsMask = ts;
976	if (ce_cfg_submit (b)) {
977		c->baud = baud;
978		c->ts = ts;
979		c->config = cfg;
980	}
981}
982
983void ce_set_lloop (ce_chan_t *c, unsigned char on)
984{
985	TAU32_UserRequest *req;
986	unsigned long cfg = c->config & ~(TAU32_line_mode_mask | TAU32_ais_on_loss);
987	ce_board_t *b = c->board;
988
989	if (c->num >= b->ddk.Interfaces || b->cr.pending >= CONFREQSZ)
990		return;
991	on = on ? 1 : 0;
992	if (on == c->lloop)
993		return;
994
995	cfg |= on ? TAU32_LineLoopInt : (TAU32_LineNormal | TAU32_ais_on_loss);
996	CE_PREREQUEST (b, c, b->cr.queue, req);
997	if (!req)
998		return;
999	req->Command = TAU32_Configure_E1;
1000	req->Io.InterfaceConfig.Interface = c->num ? TAU32_E1_B : TAU32_E1_A;
1001	req->Io.InterfaceConfig.Config = cfg;
1002	req->Io.InterfaceConfig.UnframedTsMask = c->ts;
1003	CE_DDK_DEBUG (b, c, ("Submit lloop\n"));
1004	if (ce_cfg_submit (b)) {
1005		c->lloop = on ? 1 : 0;
1006		c->config = cfg;
1007	}
1008}
1009
1010void ce_set_rloop (ce_chan_t *c, unsigned char on)
1011{
1012	TAU32_UserRequest *req;
1013	unsigned long cfg = c->config & ~TAU32_line_mode_mask;
1014	ce_board_t *b = c->board;
1015
1016	if (c->num >= b->ddk.Interfaces || b->cr.pending >= CONFREQSZ)
1017		return;
1018	on = on ? 1 : 0;
1019	if (on == c->rloop)
1020		return;
1021
1022	cfg |= on ? TAU32_LineLoopExt : TAU32_LineNormal;
1023	CE_PREREQUEST (b, c, b->cr.queue, req);
1024	if (!req)
1025		return;
1026	req->Command = TAU32_Configure_E1;
1027	req->Io.InterfaceConfig.Interface = c->num ? TAU32_E1_B : TAU32_E1_A;
1028	req->Io.InterfaceConfig.Config = cfg;
1029	req->Io.InterfaceConfig.UnframedTsMask = c->ts;
1030	CE_DDK_DEBUG (b, c, ("Submit rloop\n"));
1031	if (ce_cfg_submit (b)) {
1032		c->rloop = on ? 1 : 0;
1033		c->config = cfg;
1034	}
1035}
1036
1037void ce_set_higain (ce_chan_t *c, unsigned char on)
1038{
1039	TAU32_UserRequest *req;
1040	unsigned long cfg = c->config & ~TAU32_higain;
1041	ce_board_t *b = c->board;
1042
1043	if (c->num >= b->ddk.Interfaces || b->cr.pending >= CONFREQSZ)
1044		return;
1045	on = on ? 1 : 0;
1046	if (on == c->higain)
1047		return;
1048
1049	cfg |= on ? TAU32_higain : 0;
1050	CE_PREREQUEST (b, c, b->cr.queue, req);
1051	if (!req)
1052		return;
1053	req->Command = TAU32_Configure_E1;
1054	req->Io.InterfaceConfig.Interface = c->num ? TAU32_E1_B : TAU32_E1_A;
1055	req->Io.InterfaceConfig.Config = cfg;
1056	req->Io.InterfaceConfig.UnframedTsMask = c->ts;
1057	CE_DDK_DEBUG (b, c, ("Submit higain\n"));
1058	if (ce_cfg_submit (b)) {
1059		c->higain = on ? 1 : 0;
1060		c->config = cfg;
1061	}
1062}
1063
1064static void _ce_set_ts (ce_chan_t *c, unsigned long ts)
1065{
1066	TAU32_UserRequest *req;
1067	ce_board_t *b = c->board;
1068	unsigned long mask = 0, omask = 0;
1069	int nts = 0, ots = 0, pts = 0;
1070	int i, k;
1071
1072	if (b->cr.pending >= CONFREQSZ)
1073		return;
1074
1075	/*
1076	 * pts - number of busy "peb" ts
1077	 * ots - current (old) busy ts
1078	 * nts - new busy ts
1079	 */
1080	for (i = 0; i < 32; i++) {
1081		if (c->ts & (1ul << i))
1082			ots++;
1083		if (ts & (1ul << i))
1084			nts++;
1085		if (b->dxc[i] != TAU32_CROSS_OFF)
1086			pts++;
1087	}
1088
1089	CE_DDK_DEBUG (b, c, ("pts: %d ots: %d nts: %d ts: %lx\n", pts, ots, nts,
1090		      ts));
1091	/* 32 - all busy + my old busy == free */
1092	if (32 - pts + ots - nts < 0)
1093		return;
1094
1095	/* Ok. We have enougth "peb" ts. Clean old. */
1096	/* We start from zero, cause this is peb cells */
1097	for (i = 0; i < 32; i++) {
1098		int tin = b->dxc[i];
1099		int t = tin % 32;
1100		if (tin < (c->dir?64:32) || tin > (c->dir?95:63))
1101			continue;
1102		if (c->ts & (1ul << t)) {
1103			b->dxc[tin] = TAU32_CROSS_OFF;
1104			b->dxc[i] = TAU32_CROSS_OFF;
1105			if (b->dxc[t + 32] == TAU32_CROSS_OFF &&
1106			    b->dxc[t + 64] == TAU32_CROSS_OFF) {
1107				b->dxc[t + 32] = t + 64;
1108				b->dxc[t + 64] = t + 32;
1109			}
1110			omask |= (1ul << t);
1111		}
1112	}
1113
1114	k = 0;
1115	/* Set */
1116	for (i = 0; i < 32; i++) {
1117		if ((ts & (1ul << i)) == 0)
1118			continue;
1119		while (b->dxc[k] != TAU32_CROSS_OFF) {
1120			k++;
1121			/* Paranoic */
1122			if (k >= 32) {
1123				CE_DDK_DEBUG (b, c, ("TS count overflow\n"));
1124				return;
1125			}
1126		}
1127		b->dxc[k] = (c->dir?64:32) + i;
1128		b->dxc[(c->dir?64:32) + i] = k;
1129		if (b->dxc[(c->dir?32:64) + i] == (c->dir?64:32) + i)
1130			b->dxc[(c->dir?32:64) + i] = TAU32_CROSS_OFF;
1131		mask |= (1ul << k);
1132	}
1133
1134	c->ts = ts;
1135	c->baud = nts*64000;
1136
1137	CE_PREREQUEST (b, c, b->cr.queue, req);
1138	if (!req)
1139		return;
1140
1141	req->Command = TAU32_Timeslots_Channel | TAU32_Configure_Commit;
1142	req->Io.ChannelNumber = c->num;
1143	req->Io.ChannelConfig.AssignedTsMask = mask;
1144
1145	if (c->phony) {
1146		b->pmask &= ~omask;
1147		b->pmask |= mask;
1148	}
1149
1150	CE_DDK_DEBUG (b, c, ("ts=%lx mask=%lx omask=%lx pmask=%lx\n", c->ts,
1151		      mask, omask, b->pmask));
1152	CE_DDK_DEBUG (b, c, ("Crossmatrix table:\n"));
1153
1154#ifdef CE_DDK_DEBUG_ENABLED
1155	for (i = 0; i < 32*3; i++) {
1156		printf ("%3d\t%s", b->dxc[i], (i%8==7)?"\n":"");
1157		printf ("%s",(i%32==31)?"\n":"");
1158	}
1159#endif
1160
1161	CE_DDK_DEBUG (b, c, ("Submit tsmask\n"));
1162	if (!ce_cfg_submit (b)) {
1163		CE_DDK_DEBUG (b, c, ("Fail to submit tsmask\n"));
1164		/* Do some error processing */
1165		return;
1166	}
1167
1168	CE_DDK_DEBUG (b, c, ("SetCrossMatrix\n"));
1169	if (!TAU32_SetCrossMatrix(b->ddk.pControllerObject, b->dxc, b->pmask)) {
1170		CE_DDK_DEBUG (b, c, ("Faild to SetCrossMatrix\n"));
1171		/* Do some error processing */
1172		return;
1173	}
1174}
1175
1176void ce_set_ts (ce_chan_t *c, unsigned long ts)
1177{
1178	ce_board_t *b = c->board;
1179	ce_chan_t *x;
1180
1181	if (c->ts == ts || b->chan->unfram)
1182		return;
1183
1184	ts &= ~(1ul);
1185
1186	if (!b->chan[c->dir].use16)
1187		ts &= ~(1ul << 16);
1188
1189	for (x = b->chan; x < b->chan + NCHAN; x++) {
1190		if (x == c || x->dir != c->dir)
1191			continue;
1192		ts &= ~x->ts;
1193	}
1194
1195	_ce_set_ts (c, ts);
1196}
1197
1198void ce_set_unfram (ce_chan_t *c, unsigned char on)
1199{
1200	TAU32_UserRequest *req;
1201	ce_board_t *b = c->board;
1202	unsigned long cfg = c->config & ~TAU32_framing_mode_mask;
1203	unsigned long i;
1204
1205	if (c->num != 0 || b->cr.pending + 2*32 + 3>= CONFREQSZ)
1206		return;
1207
1208	on = on ? 1 : 0;
1209
1210	if (on == c->unfram)
1211		return;
1212
1213	if (on) {
1214		ce_set_dir (c, 0);
1215		for (i = 1; i < TAU32_CHANNELS; i++) {
1216			ce_set_ts (b->chan + i, 0);
1217			ce_set_phony (b->chan + i, 0);
1218		}
1219		ce_set_use16 (b->chan + 0, 0);
1220		ce_set_use16 (b->chan + 1, 0);
1221		/* Get current value, previous ce_set request may change it */
1222		cfg = c->config & ~TAU32_framing_mode_mask;
1223		cfg |= TAU32_unframed_2048;
1224		c->unfram = on;
1225		_ce_set_ts (b->chan, ~0ul);
1226		c->config = cfg;
1227		/* XXXRIK: Do extra checks on config queue size*/
1228		if (b->ddk.Interfaces) {
1229			CE_PREREQUEST (b, c, b->cr.queue, req);
1230			if (!req)
1231				return;
1232			req->Command = TAU32_Configure_E1;
1233			req->Io.InterfaceConfig.Interface = TAU32_E1_B;
1234			req->Io.InterfaceConfig.Config = TAU32_LineOff;
1235			req->Io.InterfaceConfig.UnframedTsMask = 0;
1236			CE_DDK_DEBUG (b, c, ("unfram: B line off\n"));
1237			ce_cfg_submit (b);
1238		}
1239		CE_PREREQUEST (b, c, b->cr.queue, req);
1240		if (!req)
1241			return;
1242		req->Command = TAU32_Configure_E1;
1243		req->Io.InterfaceConfig.Interface = TAU32_E1_A;
1244		req->Io.InterfaceConfig.Config = cfg;
1245		req->Io.InterfaceConfig.UnframedTsMask = c->ts;
1246		CE_DDK_DEBUG (b, c, ("Submit unfram\n"));
1247		ce_cfg_submit (b);
1248	} else {
1249		cfg |= TAU32_framed_cas_cross;
1250		CE_PREREQUEST (b, c, b->cr.queue, req);
1251		if (!req)
1252			return;
1253		req->Command = TAU32_Configure_E1;
1254		req->Io.InterfaceConfig.Interface = TAU32_E1_ALL;
1255		req->Io.InterfaceConfig.Config = cfg;
1256		req->Io.InterfaceConfig.UnframedTsMask = 0;
1257		CE_DDK_DEBUG (b, c, ("Submit framed\n"));
1258		ce_cfg_submit (b);
1259		ce_set_ts (c, 0);
1260	}
1261	c->unfram = on;
1262}
1263
1264void ce_set_phony (ce_chan_t *c, unsigned char on)
1265{
1266	TAU32_UserRequest *req;
1267	ce_board_t *b = c->board;
1268	unsigned long mask = 0;
1269	int i;
1270
1271	if ((c->phony && on) || (c->phony == 0 && on == 0) ||
1272	    b->cr.pending >= CONFREQSZ)
1273		return;
1274
1275	CE_PREREQUEST (b, c, b->cr.queue, req);
1276	if (!req)
1277		return;
1278
1279	req->Command = TAU32_Configure_Channel;
1280	req->Io.InterfaceConfig.Config = on ? TAU32_TMA :
1281		(TAU32_HDLC | TAU32_fr_rx_splitcheck | TAU32_fr_rx_fitcheck);
1282	req->Io.ChannelNumber = c->num;
1283	CE_DDK_DEBUG (b, c, ("Submit phony\n"));
1284	if (!ce_cfg_submit (b)) {
1285		/* Do some error processing */
1286		return;
1287	}
1288
1289	for (i = 0; i < 32; i++) {
1290		int t = b->dxc[i] % 32;
1291		if (b->dxc[i] < (c->dir?64:32) || b->dxc[i] > (c->dir?95:63))
1292			continue;
1293		if (c->ts & (1ul << t))
1294			mask |= (1ul << t);
1295	}
1296
1297	CE_DDK_DEBUG (b, c, ("phony mask:%lx\n", mask));
1298
1299	if (on) {
1300		b->pmask |= mask;
1301	} else {
1302		b->pmask &= ~mask;
1303	}
1304
1305	c->phony = on ? 1 : 0;
1306
1307	CE_DDK_DEBUG (b, c, ("Submit (setcrosmatrix) phony\n"));
1308	if (!TAU32_SetCrossMatrix(b->ddk.pControllerObject, b->dxc, b->pmask)) {
1309		/* Do some error processing */
1310		return;
1311	}
1312}
1313
1314void ce_set_scrambler (ce_chan_t *c, unsigned char on)
1315{
1316	TAU32_UserRequest *req;
1317	unsigned long cfg = c->config & ~TAU32_scrambler;
1318	ce_board_t *b = c->board;
1319
1320	if (c->num != 0 || c->unfram == 0 || b->cr.pending >= CONFREQSZ)
1321		return;
1322	on = on ? 1 : 0;
1323	if (on == c->scrambler)
1324		return;
1325
1326	cfg |= on ? TAU32_scrambler : 0;
1327	CE_PREREQUEST (b, c, b->cr.queue, req);
1328	if (!req)
1329		return;
1330	req->Command = TAU32_Configure_E1;
1331	req->Io.InterfaceConfig.Interface = c->num ? TAU32_E1_B : TAU32_E1_A;
1332	req->Io.InterfaceConfig.Config = cfg;
1333	req->Io.InterfaceConfig.UnframedTsMask = c->ts;
1334	CE_DDK_DEBUG (b, c, ("Submit scrambler\n"));
1335	if (ce_cfg_submit (b)) {
1336		c->scrambler = on ? 1 : 0;
1337		c->config = cfg;
1338	}
1339}
1340
1341void ce_set_monitor (ce_chan_t *c, unsigned char on)
1342{
1343	TAU32_UserRequest *req;
1344	unsigned long cfg = c->config & ~TAU32_monitor;
1345	ce_board_t *b = c->board;
1346
1347	if (c->num >= b->ddk.Interfaces || b->cr.pending >= CONFREQSZ)
1348		return;
1349	on = on ? 1 : 0;
1350	if (on == c->monitor)
1351		return;
1352
1353	cfg |= on ? TAU32_monitor : 0;
1354	CE_PREREQUEST (b, c, b->cr.queue, req);
1355	if (!req)
1356		return;
1357	req->Command = TAU32_Configure_E1;
1358	req->Io.InterfaceConfig.Interface = c->num ? TAU32_E1_B : TAU32_E1_A;
1359	req->Io.InterfaceConfig.Config = cfg;
1360	req->Io.InterfaceConfig.UnframedTsMask = c->ts;
1361	CE_DDK_DEBUG (b, c, ("Submit monitor\n"));
1362	if (ce_cfg_submit (b)) {
1363		c->monitor = on ? 1 : 0;
1364		c->config = cfg;
1365	}
1366}
1367
1368static void _ce_submit_configure_e1 (ce_chan_t *c, char *rname)
1369{
1370	TAU32_UserRequest *req;
1371	ce_board_t *b = c->board;
1372
1373	CE_PREREQUEST (b, c, b->cr.queue, req);
1374	if (!req)
1375		return;
1376	req->Command = TAU32_Configure_E1;
1377	req->Io.InterfaceConfig.Interface = c->num == 0 ? TAU32_E1_A : TAU32_E1_B;
1378	req->Io.InterfaceConfig.Config = c->config;
1379	req->Io.InterfaceConfig.UnframedTsMask = c->ts;
1380	CE_DDK_DEBUG (b, c, ("Submit %s\n", rname ? rname : ""));
1381	if (!ce_cfg_submit (b)) {
1382		CE_DDK_DEBUG (b, c, ("Fail to submit %s\n", rname?rname:""));
1383		/* Do some error processing */
1384		return;
1385	}
1386}
1387
1388void ce_set_use16 (ce_chan_t *c, unsigned char on)
1389{
1390	ce_board_t *b = c->board;
1391	ce_chan_t *x;
1392	unsigned long cfg[2];
1393	int use[2];
1394
1395	if (c->num >= b->ddk.Interfaces || b->cr.pending + 2 >= CONFREQSZ)
1396		return;
1397
1398	cfg[0] = b->chan[0].config & ~TAU32_framing_mode_mask;
1399	cfg[1] = b->chan[1].config & ~TAU32_framing_mode_mask;
1400
1401	on = on ? 1 : 0;
1402
1403	if (c->use16 == on || b->chan->unfram)
1404		return;
1405
1406	use[0] = b->chan[0].use16;
1407	use[1] = b->chan[1].use16;
1408
1409	/* Correct value */
1410	use[c->num] = on;
1411
1412	if (b->ddk.Interfaces == 1) {
1413		cfg[0] |= on ? TAU32_framed_cas_set : TAU32_framed_no_cas;
1414	} else {
1415		if (use[0] == 0 && use[1] == 0) {
1416			cfg[0] |= TAU32_framed_cas_cross;
1417			cfg[1] |= TAU32_framed_cas_cross;
1418		} else if (use[0] == 0) {
1419			cfg[0] |= TAU32_framed_cas_set;
1420			cfg[1] |= TAU32_framed_no_cas;
1421		} else if (use[1] == 0) {
1422			cfg[0] |= TAU32_framed_no_cas;
1423			cfg[1] |= TAU32_framed_cas_set;
1424		} else {
1425			cfg[0] |= TAU32_framed_no_cas;
1426			cfg[1] |= TAU32_framed_no_cas;
1427		}
1428	}
1429
1430	c->use16 = on;
1431
1432	for (x = b->chan; !on && x < b->chan + NCHAN; x++) {
1433		if (x->dir == c->num && x->ts & (1ul<<16)) {
1434			ce_set_ts (x, x->ts);
1435			break;
1436		}
1437	}
1438
1439	if (cfg[0] != b->chan[0].config) {
1440		b->chan[0].config = cfg[0];
1441		_ce_submit_configure_e1 (b->chan + 0, "use16");
1442	}
1443
1444	if (cfg[1] != b->chan[1].config) {
1445		b->chan[1].config = cfg[1];
1446		_ce_submit_configure_e1 (b->chan + 1, "use16");
1447	}
1448}
1449
1450void ce_set_crc4 (ce_chan_t *c, unsigned char on)
1451{
1452	TAU32_UserRequest *req;
1453	unsigned long cfg = c->config & ~TAU32_crc4_mf;
1454	ce_board_t *b = c->board;
1455
1456	if (c->num >= b->ddk.Interfaces || b->cr.pending >= CONFREQSZ)
1457		return;
1458	on = on ? 1 : 0;
1459	if (on == c->crc4 || b->chan->unfram)
1460		return;
1461
1462	cfg |= on ? TAU32_crc4_mf : 0;
1463	CE_PREREQUEST (b, c, b->cr.queue, req);
1464	if (!req)
1465		return;
1466	req->Command = TAU32_Configure_E1;
1467	req->Io.InterfaceConfig.Interface = c->num ? TAU32_E1_B : TAU32_E1_A;
1468	req->Io.InterfaceConfig.Config = cfg;
1469	req->Io.InterfaceConfig.UnframedTsMask = c->ts;
1470	CE_DDK_DEBUG (b, c, ("Submit crc4\n"));
1471	if (ce_cfg_submit (b)) {
1472		c->crc4 = on ? 1 : 0;
1473		c->config = cfg;
1474	}
1475}
1476
1477void ce_set_gsyn (ce_chan_t *c, int syn)
1478{
1479	ce_board_t *b = c->board;
1480	unsigned int mode;
1481
1482	if (c->num >= b->ddk.Interfaces)
1483		return;
1484
1485	if (syn == GSYN_RCV)
1486		syn = c->num ? GSYN_RCV1 : GSYN_RCV0;
1487
1488	switch (syn) {
1489	default:	mode = TAU32_SYNC_INTERNAL;	break;
1490	case GSYN_RCV0:	mode = TAU32_SYNC_RCV_A;	break;
1491	case GSYN_RCV1:	mode = TAU32_SYNC_RCV_B;	break;
1492	}
1493
1494	CE_DDK_DEBUG (b, c, ("Set Sync Mode\n"));
1495	if (TAU32_SetSyncMode (b->ddk.pControllerObject, mode)) {
1496		b->chan->gsyn = syn;
1497		if (b->ddk.Interfaces > 1)
1498			(b->chan + 1)->gsyn = syn;
1499	}
1500}
1501
1502int ce_get_cable (ce_chan_t *c)
1503{
1504	ce_board_t *b = c->board;
1505	if (c->num >= b->ddk.Interfaces)
1506		return 0;
1507
1508	return CABLE_TP;
1509}
1510
1511void ce_set_dir (ce_chan_t *c, int dir)
1512{
1513	ce_board_t *b = c->board;
1514	unsigned long ts;
1515	if (b->cr.pending + 1>= CONFREQSZ || c->dir == dir)
1516		return;
1517
1518	ts = c->ts;
1519	ce_set_ts (c, 0);
1520	c->dir = dir;
1521	ce_set_ts (c, ts);
1522}
1523