]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/dev/ce/ceddk.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / dev / ce / ceddk.c
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
142 static void _ce_set_ts (ce_chan_t *c, unsigned long ts);
143 static void _ce_submit_configure_e1 (ce_chan_t *c, char *rname);
144
145 #ifdef CE_DDK_DEBUG_ENABLED
146 static 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
201 void ce_set_dtr (ce_chan_t *c, int on)
202 {
203         c->dtr = on?1:0;
204 }
205
206 void ce_set_rts (ce_chan_t *c, int on)
207 {
208         c->rts = on?1:0;
209 }
210
211 static 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
272 static 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
311 int ce_transmit_space (ce_chan_t *c)
312 {
313         return c->tx_pending < (TAU32_IO_QUEUE);
314 }
315
316 int 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
356 static 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
368 static 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
406 static 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
431 void 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
527 void 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
618 void 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 realy
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
650 void ce_register_transmit (ce_chan_t *c,
651         void (*func) (ce_chan_t*, void*, int))
652 {
653         c->transmit = func;
654 }
655
656 void ce_register_receive (ce_chan_t *c,
657         void (*func) (ce_chan_t*, unsigned char*, int))
658 {
659         c->receive = func;
660 }
661
662 void ce_register_error (ce_chan_t *c,
663         void (*func) (ce_chan_t*, int))
664 {
665         c->error = func;
666 }
667
668 void 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
718 void 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
735 int 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
742 int ce_get_cts (ce_chan_t *c)
743 {
744         return 0;
745 }
746
747 int ce_get_dsr (ce_chan_t *c)
748 {
749         return 0;
750 }
751
752 void 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
935 void 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
983 void 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
1010 void 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
1037 void 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
1064 static 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
1176 void 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
1198 void 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
1264 void 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
1314 void 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
1341 void 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
1368 static 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
1388 void 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
1450 void 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
1477 void 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
1502 int 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
1511 void 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 }