]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/ce/ceddk.c
Merge bmake-20210206
[FreeBSD/FreeBSD.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/ce/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 completeness, but for now I
625          * don't use it. I just started to write and haven't finished it yet.
626          * It is VERY BUGGY!!! Do not use it. If you really need
627          * it ask me to fix it or rewrite it by yourself.
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 void ce_register_transmit (ce_chan_t *c,
650         void (*func) (ce_chan_t*, void*, int))
651 {
652         c->transmit = func;
653 }
654
655 void ce_register_receive (ce_chan_t *c,
656         void (*func) (ce_chan_t*, unsigned char*, int))
657 {
658         c->receive = func;
659 }
660
661 void ce_register_error (ce_chan_t *c,
662         void (*func) (ce_chan_t*, int))
663 {
664         c->error = func;
665 }
666
667 void TAU32_CALLBACK_TYPE ce_error_callback (TAU32_UserContext *pContext,
668                                                 int Item, unsigned NotifyBits)
669 {
670         ce_board_t *b = (ce_board_t *) pContext;
671         ENTER ();
672         if (NotifyBits & (TAU32_ERROR_FAIL | TAU32_ERROR_TIMEOUT
673                 | TAU32_ERROR_INT_OVER_TX | TAU32_ERROR_INT_OVER_RX
674                 | TAU32_ERROR_INT_STORM)) {
675                 /* Fatal: adapter failure, need reset & restart */
676                 /* RIKXXX: probably I should add CE_FAILURE for ce_error */
677                 CE_DDK_DEBUG (b, (ce_chan_t *)0, ("Err, disable interrupts: %s\n",
678                                 ce_err2str (NotifyBits)));
679 /*              TAU32_DisableInterrupts (b->ddk.pControllerObject);*/
680                 EXIT ();
681         }
682         if (Item >= 0) {
683                 /* channel error */
684                 ce_chan_t *c = b->chan + Item;
685                 if (NotifyBits & TAU32_ERROR_TX_UNDERFLOW) {
686                         c->underrun++;
687                         if (c->error)
688                                 c->error (c, CE_UNDERRUN);
689                 }
690                 if (NotifyBits & TAU32_ERROR_RX_OVERFLOW) {
691                         c->overrun++;
692                         if (c->error)
693                                 c->error (c, CE_OVERFLOW);
694                 }
695                 if (NotifyBits & (TAU32_ERROR_RX_FRAME | TAU32_ERROR_RX_ABORT |
696                     TAU32_ERROR_RX_SHORT | TAU32_ERROR_RX_LONG |
697                     TAU32_ERROR_RX_SYNC | TAU32_ERROR_RX_SPLIT |
698                     TAU32_ERROR_RX_UNFIT)) {
699                         c->frame++;
700                         CE_DDK_DEBUG (b, c, ("Frame error: %x\n", NotifyBits));
701                         if (c->error)
702                                 c->error (c, CE_FRAME);
703                 }
704                 if(NotifyBits & TAU32_ERROR_RX_CRC) {
705                         c->crc++;
706                         if (c->error)
707                                 c->error (c, CE_CRC);
708                 }
709         } else {
710                 CE_DDK_DEBUG (b, (ce_chan_t *)0, ("Another error: %x\n",
711                               NotifyBits));
712                 /* Adapter error, do smth */
713         }
714         EXIT ();
715 }
716
717 void TAU32_CALLBACK_TYPE ce_status_callback(TAU32_UserContext *pContext,
718                                                 int Item, unsigned NotifyBits)
719 {
720         ce_board_t *b = (ce_board_t *) pContext;
721         ENTER ();
722         if(Item >= 0) {
723                 /* e1 status */
724                 ce_chan_t *c = b->chan + Item;
725                 c->acc_status |= b->ddk.InterfacesInfo[Item].Status;
726 /*              CE_DDK_DEBUG (b, c, ("Current status: %x\n", c->acc_status));*/
727         } else {
728                 CE_DDK_DEBUG (b, (ce_chan_t *)0, ("Another status: %x\n", NotifyBits));
729                 /* Adapter status, do smth. */
730         }
731         EXIT ();
732 }
733
734 int ce_get_cd (ce_chan_t *c)
735 {
736         unsigned int e1status = c->board->ddk.InterfacesInfo[c->dir].Status;
737
738         return (c->ts && !(e1status & (TAU32_RCL | TAU32_E1OFF)));
739 }
740
741 int ce_get_cts (ce_chan_t *c)
742 {
743         return 0;
744 }
745
746 int ce_get_dsr (ce_chan_t *c)
747 {
748         return 0;
749 }
750
751 void ce_e1_timer (ce_chan_t *c)
752 {
753         unsigned bpv, fas, crc4, ebit, pcv, oof, css;
754         unsigned int acc_status;
755         ce_board_t *b = c->board;
756         TAU32_E1_State  *state;
757
758         if (c->num >= b->ddk.Interfaces)
759                 return;
760
761         state = &b->ddk.InterfacesInfo[c->num];
762         acc_status = c->acc_status;
763
764         /* Clear acc_status */
765         c->acc_status = b->ddk.InterfacesInfo[c->num].Status;
766
767         /* Count seconds.
768          * During the first second after the channel startup
769          * the status registers are not stable yet,
770          * we will so skip the first second. */
771         ++c->cursec;
772         if (! c->totsec && c->cursec <= 1)
773                 return;
774
775         c->status = 0;
776
777         /* Compute the SNMP-compatible channel status. */
778         oof = 0;
779
780         if (acc_status & TAU32_RCL)
781                 c->status |= ESTS_LOS;          /* loss of signal */
782         if (acc_status & TAU32_RUA1)
783                 c->status |= ESTS_AIS;          /* receiving all ones */
784
785         /* Get error counters. */
786         bpv = state->RxViolations;
787         fas = 0;
788         crc4 = 0;
789         ebit = 0;
790         css = 0;
791
792         if (! c->unfram) {
793                 if (! c->use16 && (acc_status & TAU32_RSA1))
794                         c->status |= ESTS_AIS16;        /* signaling all ones */
795                 if (! c->use16 && (acc_status & TAU32_RDMA))
796                         c->status |= ESTS_FARLOMF;      /* alarm in timeslot 16 */
797                 if (acc_status & TAU32_RRA)
798                         c->status |= ESTS_FARLOF;       /* far loss of framing */
799
800                 if (acc_status & TAU32_RFAS) {
801                         c->status |= ESTS_LOF;          /* loss of framing */
802                         ++oof;                          /* out of framing */
803                 }
804                 if ((! c->use16 && (acc_status & TAU32_RCAS)) ||
805                     (c->crc4 && (acc_status & TAU32_RCRC4))) {
806                         c->status |= ESTS_LOMF;         /* loss of multiframing */
807                         ++oof;                          /* out of framing */
808                 }
809                 fas = state->FasErrors;
810                 crc4 = state->Crc4Errors;
811                 ebit = state->FarEndBlockErrors;
812
813                 /* Controlled slip second -- any slip event. */
814                 css = state->TransmitSlips + state->ReceiveSlips;
815         }
816
817         /* Clear state */
818         state->RxViolations             = 0;
819         state->FasErrors                = 0;
820         state->Crc4Errors               = 0;
821         state->FarEndBlockErrors        = 0;
822         state->TransmitSlips            = 0;
823         state->ReceiveSlips             = 0;
824
825         if (c->status & ESTS_LOS)
826                 c->status = ESTS_LOS;
827         else if (c->status & ESTS_AIS)
828                 c->status = ESTS_AIS;
829         else if (c->status & ESTS_LOF)
830                 c->status = ESTS_LOF;
831         else if (c->status & ESTS_LOMF)
832                 c->status &= ~(ESTS_FARLOMF | ESTS_AIS16);
833
834         if (! c->status)
835                 c->status = ESTS_NOALARM;
836
837         c->currnt.bpv += bpv;
838         c->currnt.fse += fas;
839         if (c->crc4) {
840                 c->currnt.crce += crc4;
841                 c->currnt.rcrce += ebit;
842         }
843
844         /* Path code violation is frame sync error if CRC4 disabled,
845          * or CRC error if CRC4 enabled. */
846         pcv = fas;
847         if (c->crc4)
848                 pcv += crc4;
849
850         /* Unavaiable second -- receiving all ones, or
851          * loss of carrier, or loss of signal. */
852         if (acc_status & (TAU32_RUA1 | TAU32_RCL))
853                 /* Unavailable second -- no other counters. */
854                 ++c->currnt.uas;
855         else {
856                 /* Line errored second -- any BPV. */
857                 if (bpv)
858                         ++c->currnt.les;
859
860                 /* Errored second -- any PCV, or out of frame sync,
861                  * or any slip events. */
862                 if (pcv || oof || css)
863                         ++c->currnt.es;
864
865                 /* Severely errored framing second -- out of frame sync. */
866                 if (oof)
867                         ++c->currnt.oofs;
868
869                 /* Severely errored seconds --
870                  * 832 or more PCVs, or 2048 or more BPVs. */
871                 if (bpv >= 2048 || pcv >= 832)
872                         ++c->currnt.ses;
873                 else {
874                         /* Bursty errored seconds --
875                          * no SES and more than 1 PCV. */
876                         if (pcv > 1)
877                                 ++c->currnt.bes;
878
879                         /* Collect data for computing
880                          * degraded minutes. */
881                         ++c->degsec;
882                         c->degerr += bpv + pcv;
883                 }
884         }
885
886         /* Degraded minutes -- having error rate more than 10e-6,
887          * not counting unavailable and severely errored seconds. */
888         if (c->cursec % 60 == 0) {
889                 if (c->degerr > c->degsec * 2048 / 1000)
890                         ++c->currnt.dm;
891                 c->degsec = 0;
892                 c->degerr = 0;
893         }
894
895         /* Rotate statistics every 15 minutes. */
896         if (c->cursec > 15*60) {
897                 int i;
898
899                 for (i=47; i>0; --i)
900                         c->interval[i] = c->interval[i-1];
901                 c->interval[0] = c->currnt;
902
903                 /* Accumulate total statistics. */
904                 c->total.bpv   += c->currnt.bpv;
905                 c->total.fse   += c->currnt.fse;
906                 c->total.crce  += c->currnt.crce;
907                 c->total.rcrce += c->currnt.rcrce;
908                 c->total.uas   += c->currnt.uas;
909                 c->total.les   += c->currnt.les;
910                 c->total.es    += c->currnt.es;
911                 c->total.bes   += c->currnt.bes;
912                 c->total.ses   += c->currnt.ses;
913                 c->total.oofs  += c->currnt.oofs;
914                 c->total.css   += c->currnt.css;
915                 c->total.dm    += c->currnt.dm;
916                 c->currnt.bpv   = 0;
917                 c->currnt.fse   = 0;
918                 c->currnt.crce  = 0;
919                 c->currnt.rcrce = 0;
920                 c->currnt.uas   = 0;
921                 c->currnt.les   = 0;
922                 c->currnt.es    = 0;
923                 c->currnt.bes   = 0;
924                 c->currnt.ses   = 0;
925                 c->currnt.oofs  = 0;
926                 c->currnt.css   = 0;
927                 c->currnt.dm    = 0;
928
929                 c->totsec += c->cursec;
930                 c->cursec = 0;
931         }
932 }
933
934 void ce_set_baud (ce_chan_t *c, unsigned long baud)
935 {
936         TAU32_UserRequest *req;
937         ce_board_t *b = c->board;
938         unsigned long cfg = c->config & ~TAU32_framing_mode_mask;
939         unsigned long ts;
940         unsigned long kbps = (baud + 32000) / 64000 * 64;
941
942         if (!c->unfram || c->num != 0 ||
943                 baud == c->baud || b->cr.pending >= CONFREQSZ)
944                 return;
945
946         if (!kbps || kbps > 1024) {
947                 ts = 0xffffffffUL;
948                 cfg |= TAU32_unframed_2048;
949         } else if (kbps > 512) {
950                 ts = 0x0000ffffUL;
951                 cfg |= TAU32_unframed_1024;
952         } else if (kbps > 256) {
953                 ts = 0x000000ffUL;
954                 cfg |= TAU32_unframed_512;
955         } else if (kbps > 128) {
956                 ts = 0x0000000fUL;
957                 cfg |= TAU32_unframed_256;
958         } else if (kbps > 64) {
959                 ts = 0x00000003UL;
960                 cfg |= TAU32_unframed_128;
961         } else {
962                 ts = 0x00000001UL;
963                 cfg |= TAU32_unframed_64;
964         }
965
966         /* _ce_set_ts () will set proper baud */
967         _ce_set_ts (c, ts);
968         CE_PREREQUEST (b, c, b->cr.queue, req);
969         if (!req)
970                 return;
971         req->Command = TAU32_Configure_E1;
972         req->Io.InterfaceConfig.Interface = TAU32_E1_A;
973         req->Io.InterfaceConfig.Config = cfg;
974         req->Io.InterfaceConfig.UnframedTsMask = ts;
975         if (ce_cfg_submit (b)) {
976                 c->baud = baud;
977                 c->ts = ts;
978                 c->config = cfg;
979         }
980 }
981
982 void ce_set_lloop (ce_chan_t *c, unsigned char on)
983 {
984         TAU32_UserRequest *req;
985         unsigned long cfg = c->config & ~(TAU32_line_mode_mask | TAU32_ais_on_loss);
986         ce_board_t *b = c->board;
987
988         if (c->num >= b->ddk.Interfaces || b->cr.pending >= CONFREQSZ)
989                 return;
990         on = on ? 1 : 0;
991         if (on == c->lloop)
992                 return;
993
994         cfg |= on ? TAU32_LineLoopInt : (TAU32_LineNormal | TAU32_ais_on_loss);
995         CE_PREREQUEST (b, c, b->cr.queue, req);
996         if (!req)
997                 return;
998         req->Command = TAU32_Configure_E1;
999         req->Io.InterfaceConfig.Interface = c->num ? TAU32_E1_B : TAU32_E1_A;
1000         req->Io.InterfaceConfig.Config = cfg;
1001         req->Io.InterfaceConfig.UnframedTsMask = c->ts;
1002         CE_DDK_DEBUG (b, c, ("Submit lloop\n"));
1003         if (ce_cfg_submit (b)) {
1004                 c->lloop = on ? 1 : 0;
1005                 c->config = cfg;
1006         } 
1007 }
1008
1009 void ce_set_rloop (ce_chan_t *c, unsigned char on)
1010 {
1011         TAU32_UserRequest *req;
1012         unsigned long cfg = c->config & ~TAU32_line_mode_mask;
1013         ce_board_t *b = c->board;
1014
1015         if (c->num >= b->ddk.Interfaces || b->cr.pending >= CONFREQSZ)
1016                 return;
1017         on = on ? 1 : 0;
1018         if (on == c->rloop)
1019                 return;
1020
1021         cfg |= on ? TAU32_LineLoopExt : TAU32_LineNormal;
1022         CE_PREREQUEST (b, c, b->cr.queue, req);
1023         if (!req)
1024                 return;
1025         req->Command = TAU32_Configure_E1;
1026         req->Io.InterfaceConfig.Interface = c->num ? TAU32_E1_B : TAU32_E1_A;
1027         req->Io.InterfaceConfig.Config = cfg;
1028         req->Io.InterfaceConfig.UnframedTsMask = c->ts;
1029         CE_DDK_DEBUG (b, c, ("Submit rloop\n"));
1030         if (ce_cfg_submit (b)) {
1031                 c->rloop = on ? 1 : 0;
1032                 c->config = cfg;
1033         }
1034 }
1035
1036 void ce_set_higain (ce_chan_t *c, unsigned char on)
1037 {
1038         TAU32_UserRequest *req;
1039         unsigned long cfg = c->config & ~TAU32_higain;
1040         ce_board_t *b = c->board;
1041
1042         if (c->num >= b->ddk.Interfaces || b->cr.pending >= CONFREQSZ)
1043                 return;
1044         on = on ? 1 : 0;
1045         if (on == c->higain)
1046                 return;
1047
1048         cfg |= on ? TAU32_higain : 0;
1049         CE_PREREQUEST (b, c, b->cr.queue, req);
1050         if (!req)
1051                 return;
1052         req->Command = TAU32_Configure_E1;
1053         req->Io.InterfaceConfig.Interface = c->num ? TAU32_E1_B : TAU32_E1_A;
1054         req->Io.InterfaceConfig.Config = cfg;
1055         req->Io.InterfaceConfig.UnframedTsMask = c->ts;
1056         CE_DDK_DEBUG (b, c, ("Submit higain\n"));
1057         if (ce_cfg_submit (b)) {
1058                 c->higain = on ? 1 : 0;
1059                 c->config = cfg;
1060         }
1061 }
1062
1063 static void _ce_set_ts (ce_chan_t *c, unsigned long ts)
1064 {
1065         TAU32_UserRequest *req;
1066         ce_board_t *b = c->board;
1067         unsigned long mask = 0, omask = 0;
1068         int nts = 0, ots = 0, pts = 0;
1069         int i, k;
1070
1071         if (b->cr.pending >= CONFREQSZ)
1072                 return;
1073
1074         /*
1075          * pts - number of busy "peb" ts
1076          * ots - current (old) busy ts
1077          * nts - new busy ts
1078          */
1079         for (i = 0; i < 32; i++) {
1080                 if (c->ts & (1ul << i))
1081                         ots++;
1082                 if (ts & (1ul << i))
1083                         nts++;
1084                 if (b->dxc[i] != TAU32_CROSS_OFF)
1085                         pts++;
1086         }
1087
1088         CE_DDK_DEBUG (b, c, ("pts: %d ots: %d nts: %d ts: %lx\n", pts, ots, nts,
1089                       ts));
1090         /* 32 - all busy + my old busy == free */
1091         if (32 - pts + ots - nts < 0)
1092                 return;
1093                 
1094         /* Ok. We have enougth "peb" ts. Clean old. */
1095         /* We start from zero, cause this is peb cells */
1096         for (i = 0; i < 32; i++) {
1097                 int tin = b->dxc[i];
1098                 int t = tin % 32;
1099                 if (tin < (c->dir?64:32) || tin > (c->dir?95:63))
1100                         continue;
1101                 if (c->ts & (1ul << t)) {
1102                         b->dxc[tin] = TAU32_CROSS_OFF;
1103                         b->dxc[i] = TAU32_CROSS_OFF;
1104                         if (b->dxc[t + 32] == TAU32_CROSS_OFF &&
1105                             b->dxc[t + 64] == TAU32_CROSS_OFF) {
1106                                 b->dxc[t + 32] = t + 64;
1107                                 b->dxc[t + 64] = t + 32;
1108                         }
1109                         omask |= (1ul << t);
1110                 }
1111         }
1112
1113         k = 0;
1114         /* Set */
1115         for (i = 0; i < 32; i++) {
1116                 if ((ts & (1ul << i)) == 0)
1117                         continue;
1118                 while (b->dxc[k] != TAU32_CROSS_OFF) {
1119                         k++;
1120                         /* Paranoic */
1121                         if (k >= 32) {
1122                                 CE_DDK_DEBUG (b, c, ("TS count overflow\n"));
1123                                 return;
1124                         }
1125                 }
1126                 b->dxc[k] = (c->dir?64:32) + i;
1127                 b->dxc[(c->dir?64:32) + i] = k;
1128                 if (b->dxc[(c->dir?32:64) + i] == (c->dir?64:32) + i)
1129                         b->dxc[(c->dir?32:64) + i] = TAU32_CROSS_OFF;
1130                 mask |= (1ul << k);
1131         }
1132
1133         c->ts = ts;
1134         c->baud = nts*64000;
1135
1136         CE_PREREQUEST (b, c, b->cr.queue, req);
1137         if (!req)
1138                 return;
1139
1140         req->Command = TAU32_Timeslots_Channel | TAU32_Configure_Commit;
1141         req->Io.ChannelNumber = c->num;
1142         req->Io.ChannelConfig.AssignedTsMask = mask;    
1143
1144         if (c->phony) {
1145                 b->pmask &= ~omask;
1146                 b->pmask |= mask;
1147         }
1148
1149         CE_DDK_DEBUG (b, c, ("ts=%lx mask=%lx omask=%lx pmask=%lx\n", c->ts,
1150                       mask, omask, b->pmask));
1151         CE_DDK_DEBUG (b, c, ("Crossmatrix table:\n"));
1152
1153 #ifdef CE_DDK_DEBUG_ENABLED
1154         for (i = 0; i < 32*3; i++) {
1155                 printf ("%3d\t%s", b->dxc[i], (i%8==7)?"\n":"");
1156                 printf ("%s",(i%32==31)?"\n":"");
1157         }
1158 #endif
1159
1160         CE_DDK_DEBUG (b, c, ("Submit tsmask\n"));
1161         if (!ce_cfg_submit (b)) {
1162                 CE_DDK_DEBUG (b, c, ("Fail to submit tsmask\n"));
1163                 /* Do some error processing */
1164                 return;
1165         }
1166
1167         CE_DDK_DEBUG (b, c, ("SetCrossMatrix\n"));
1168         if (!TAU32_SetCrossMatrix(b->ddk.pControllerObject, b->dxc, b->pmask)) {
1169                 CE_DDK_DEBUG (b, c, ("Faild to SetCrossMatrix\n"));
1170                 /* Do some error processing */
1171                 return;
1172         }
1173 }
1174
1175 void ce_set_ts (ce_chan_t *c, unsigned long ts)
1176 {
1177         ce_board_t *b = c->board;
1178         ce_chan_t *x;
1179
1180         if (c->ts == ts || b->chan->unfram)
1181                 return;
1182
1183         ts &= ~(1ul);
1184
1185         if (!b->chan[c->dir].use16)
1186                 ts &= ~(1ul << 16);
1187                 
1188         for (x = b->chan; x < b->chan + NCHAN; x++) {
1189                 if (x == c || x->dir != c->dir)
1190                         continue;
1191                 ts &= ~x->ts;
1192         }
1193
1194         _ce_set_ts (c, ts);
1195 }
1196
1197 void ce_set_unfram (ce_chan_t *c, unsigned char on)
1198 {
1199         TAU32_UserRequest *req;
1200         ce_board_t *b = c->board;
1201         unsigned long cfg = c->config & ~TAU32_framing_mode_mask;
1202         unsigned long i;
1203
1204         if (c->num != 0 || b->cr.pending + 2*32 + 3>= CONFREQSZ)
1205                 return;
1206
1207         on = on ? 1 : 0;
1208
1209         if (on == c->unfram)
1210                 return;
1211                 
1212         if (on) {
1213                 ce_set_dir (c, 0);
1214                 for (i = 1; i < TAU32_CHANNELS; i++) {
1215                         ce_set_ts (b->chan + i, 0);
1216                         ce_set_phony (b->chan + i, 0);
1217                 }
1218                 ce_set_use16 (b->chan + 0, 0);
1219                 ce_set_use16 (b->chan + 1, 0);
1220                 /* Get current value, previous ce_set request may change it */
1221                 cfg = c->config & ~TAU32_framing_mode_mask;
1222                 cfg |= TAU32_unframed_2048;
1223                 c->unfram = on;
1224                 _ce_set_ts (b->chan, ~0ul);
1225                 c->config = cfg;
1226                 /* XXXRIK: Do extra checks on config queue size*/
1227                 if (b->ddk.Interfaces) {
1228                         CE_PREREQUEST (b, c, b->cr.queue, req);
1229                         if (!req)
1230                                 return;
1231                         req->Command = TAU32_Configure_E1;
1232                         req->Io.InterfaceConfig.Interface = TAU32_E1_B;
1233                         req->Io.InterfaceConfig.Config = TAU32_LineOff;
1234                         req->Io.InterfaceConfig.UnframedTsMask = 0;
1235                         CE_DDK_DEBUG (b, c, ("unfram: B line off\n"));
1236                         ce_cfg_submit (b);
1237                 }
1238                 CE_PREREQUEST (b, c, b->cr.queue, req);
1239                 if (!req)
1240                         return;
1241                 req->Command = TAU32_Configure_E1;
1242                 req->Io.InterfaceConfig.Interface = TAU32_E1_A;
1243                 req->Io.InterfaceConfig.Config = cfg;
1244                 req->Io.InterfaceConfig.UnframedTsMask = c->ts;
1245                 CE_DDK_DEBUG (b, c, ("Submit unfram\n"));
1246                 ce_cfg_submit (b);
1247         } else {
1248                 cfg |= TAU32_framed_cas_cross;
1249                 CE_PREREQUEST (b, c, b->cr.queue, req);
1250                 if (!req)
1251                         return;
1252                 req->Command = TAU32_Configure_E1;
1253                 req->Io.InterfaceConfig.Interface = TAU32_E1_ALL;
1254                 req->Io.InterfaceConfig.Config = cfg;
1255                 req->Io.InterfaceConfig.UnframedTsMask = 0;
1256                 CE_DDK_DEBUG (b, c, ("Submit framed\n"));
1257                 ce_cfg_submit (b);
1258                 ce_set_ts (c, 0);
1259         }
1260         c->unfram = on;
1261 }
1262
1263 void ce_set_phony (ce_chan_t *c, unsigned char on)
1264 {
1265         TAU32_UserRequest *req;
1266         ce_board_t *b = c->board;
1267         unsigned long mask = 0;
1268         int i;
1269
1270         if ((c->phony && on) || (c->phony == 0 && on == 0) ||
1271             b->cr.pending >= CONFREQSZ)
1272                 return;
1273
1274         CE_PREREQUEST (b, c, b->cr.queue, req);
1275         if (!req)
1276                 return;
1277
1278         req->Command = TAU32_Configure_Channel;
1279         req->Io.InterfaceConfig.Config = on ? TAU32_TMA :
1280                 (TAU32_HDLC | TAU32_fr_rx_splitcheck | TAU32_fr_rx_fitcheck);
1281         req->Io.ChannelNumber = c->num;
1282         CE_DDK_DEBUG (b, c, ("Submit phony\n"));
1283         if (!ce_cfg_submit (b)) {
1284                 /* Do some error processing */
1285                 return;
1286         }
1287
1288         for (i = 0; i < 32; i++) {
1289                 int t = b->dxc[i] % 32;
1290                 if (b->dxc[i] < (c->dir?64:32) || b->dxc[i] > (c->dir?95:63))
1291                         continue;
1292                 if (c->ts & (1ul << t))
1293                         mask |= (1ul << t);
1294         }
1295
1296         CE_DDK_DEBUG (b, c, ("phony mask:%lx\n", mask));
1297
1298         if (on) {
1299                 b->pmask |= mask;
1300         } else {
1301                 b->pmask &= ~mask;
1302         }
1303
1304         c->phony = on ? 1 : 0;
1305
1306         CE_DDK_DEBUG (b, c, ("Submit (setcrosmatrix) phony\n"));
1307         if (!TAU32_SetCrossMatrix(b->ddk.pControllerObject, b->dxc, b->pmask)) {
1308                 /* Do some error processing */
1309                 return;
1310         }
1311 }
1312
1313 void ce_set_scrambler (ce_chan_t *c, unsigned char on)
1314 {
1315         TAU32_UserRequest *req;
1316         unsigned long cfg = c->config & ~TAU32_scrambler;
1317         ce_board_t *b = c->board;
1318
1319         if (c->num != 0 || c->unfram == 0 || b->cr.pending >= CONFREQSZ)
1320                 return;
1321         on = on ? 1 : 0;
1322         if (on == c->scrambler)
1323                 return;
1324
1325         cfg |= on ? TAU32_scrambler : 0;
1326         CE_PREREQUEST (b, c, b->cr.queue, req);
1327         if (!req)
1328                 return;
1329         req->Command = TAU32_Configure_E1;
1330         req->Io.InterfaceConfig.Interface = c->num ? TAU32_E1_B : TAU32_E1_A;
1331         req->Io.InterfaceConfig.Config = cfg;
1332         req->Io.InterfaceConfig.UnframedTsMask = c->ts;
1333         CE_DDK_DEBUG (b, c, ("Submit scrambler\n"));
1334         if (ce_cfg_submit (b)) {
1335                 c->scrambler = on ? 1 : 0;
1336                 c->config = cfg;
1337         }
1338 }
1339
1340 void ce_set_monitor (ce_chan_t *c, unsigned char on)
1341 {
1342         TAU32_UserRequest *req;
1343         unsigned long cfg = c->config & ~TAU32_monitor;
1344         ce_board_t *b = c->board;
1345
1346         if (c->num >= b->ddk.Interfaces || b->cr.pending >= CONFREQSZ)
1347                 return;
1348         on = on ? 1 : 0;
1349         if (on == c->monitor)
1350                 return;
1351
1352         cfg |= on ? TAU32_monitor : 0;
1353         CE_PREREQUEST (b, c, b->cr.queue, req);
1354         if (!req)
1355                 return;
1356         req->Command = TAU32_Configure_E1;
1357         req->Io.InterfaceConfig.Interface = c->num ? TAU32_E1_B : TAU32_E1_A;
1358         req->Io.InterfaceConfig.Config = cfg;
1359         req->Io.InterfaceConfig.UnframedTsMask = c->ts;
1360         CE_DDK_DEBUG (b, c, ("Submit monitor\n"));
1361         if (ce_cfg_submit (b)) {
1362                 c->monitor = on ? 1 : 0;
1363                 c->config = cfg;
1364         }
1365 }
1366
1367 static void _ce_submit_configure_e1 (ce_chan_t *c, char *rname)
1368 {
1369         TAU32_UserRequest *req;
1370         ce_board_t *b = c->board;
1371
1372         CE_PREREQUEST (b, c, b->cr.queue, req);
1373         if (!req)
1374                 return;
1375         req->Command = TAU32_Configure_E1;
1376         req->Io.InterfaceConfig.Interface = c->num == 0 ? TAU32_E1_A : TAU32_E1_B;
1377         req->Io.InterfaceConfig.Config = c->config;
1378         req->Io.InterfaceConfig.UnframedTsMask = c->ts;
1379         CE_DDK_DEBUG (b, c, ("Submit %s\n", rname ? rname : ""));
1380         if (!ce_cfg_submit (b)) {
1381                 CE_DDK_DEBUG (b, c, ("Fail to submit %s\n", rname?rname:""));
1382                 /* Do some error processing */
1383                 return; 
1384         }
1385 }
1386
1387 void ce_set_use16 (ce_chan_t *c, unsigned char on)
1388 {
1389         ce_board_t *b = c->board;
1390         ce_chan_t *x;
1391         unsigned long cfg[2];
1392         int use[2];
1393
1394         if (c->num >= b->ddk.Interfaces || b->cr.pending + 2 >= CONFREQSZ)
1395                 return;
1396
1397         cfg[0] = b->chan[0].config & ~TAU32_framing_mode_mask;
1398         cfg[1] = b->chan[1].config & ~TAU32_framing_mode_mask;
1399
1400         on = on ? 1 : 0;
1401
1402         if (c->use16 == on || b->chan->unfram)
1403                 return;
1404                 
1405         use[0] = b->chan[0].use16;
1406         use[1] = b->chan[1].use16;
1407
1408         /* Correct value */
1409         use[c->num] = on;
1410
1411         if (b->ddk.Interfaces == 1) {
1412                 cfg[0] |= on ? TAU32_framed_cas_set : TAU32_framed_no_cas;
1413         } else {
1414                 if (use[0] == 0 && use[1] == 0) {
1415                         cfg[0] |= TAU32_framed_cas_cross;
1416                         cfg[1] |= TAU32_framed_cas_cross;
1417                 } else if (use[0] == 0) {
1418                         cfg[0] |= TAU32_framed_cas_set;
1419                         cfg[1] |= TAU32_framed_no_cas;
1420                 } else if (use[1] == 0) {
1421                         cfg[0] |= TAU32_framed_no_cas;
1422                         cfg[1] |= TAU32_framed_cas_set;
1423                 } else {
1424                         cfg[0] |= TAU32_framed_no_cas;
1425                         cfg[1] |= TAU32_framed_no_cas;
1426                 }
1427         }
1428
1429         c->use16 = on;
1430
1431         for (x = b->chan; !on && x < b->chan + NCHAN; x++) {
1432                 if (x->dir == c->num && x->ts & (1ul<<16)) {
1433                         ce_set_ts (x, x->ts);
1434                         break;
1435                 }
1436         }
1437
1438         if (cfg[0] != b->chan[0].config) {
1439                 b->chan[0].config = cfg[0];
1440                 _ce_submit_configure_e1 (b->chan + 0, "use16");
1441         }
1442
1443         if (cfg[1] != b->chan[1].config) {
1444                 b->chan[1].config = cfg[1];
1445                 _ce_submit_configure_e1 (b->chan + 1, "use16");
1446         }
1447 }
1448
1449 void ce_set_crc4 (ce_chan_t *c, unsigned char on)
1450 {
1451         TAU32_UserRequest *req;
1452         unsigned long cfg = c->config & ~TAU32_crc4_mf;
1453         ce_board_t *b = c->board;
1454
1455         if (c->num >= b->ddk.Interfaces || b->cr.pending >= CONFREQSZ)
1456                 return;
1457         on = on ? 1 : 0;
1458         if (on == c->crc4 || b->chan->unfram)
1459                 return;
1460
1461         cfg |= on ? TAU32_crc4_mf : 0;
1462         CE_PREREQUEST (b, c, b->cr.queue, req);
1463         if (!req)
1464                 return;
1465         req->Command = TAU32_Configure_E1;
1466         req->Io.InterfaceConfig.Interface = c->num ? TAU32_E1_B : TAU32_E1_A;
1467         req->Io.InterfaceConfig.Config = cfg;
1468         req->Io.InterfaceConfig.UnframedTsMask = c->ts;
1469         CE_DDK_DEBUG (b, c, ("Submit crc4\n"));
1470         if (ce_cfg_submit (b)) {
1471                 c->crc4 = on ? 1 : 0;
1472                 c->config = cfg;
1473         }
1474 }
1475
1476 void ce_set_gsyn (ce_chan_t *c, int syn)
1477 {
1478         ce_board_t *b = c->board;
1479         unsigned int mode;
1480
1481         if (c->num >= b->ddk.Interfaces)
1482                 return;
1483
1484         if (syn == GSYN_RCV)
1485                 syn = c->num ? GSYN_RCV1 : GSYN_RCV0;
1486
1487         switch (syn) {
1488         default:        mode = TAU32_SYNC_INTERNAL;     break;
1489         case GSYN_RCV0: mode = TAU32_SYNC_RCV_A;        break;
1490         case GSYN_RCV1: mode = TAU32_SYNC_RCV_B;        break;
1491         }
1492
1493         CE_DDK_DEBUG (b, c, ("Set Sync Mode\n"));
1494         if (TAU32_SetSyncMode (b->ddk.pControllerObject, mode)) {
1495                 b->chan->gsyn = syn;
1496                 if (b->ddk.Interfaces > 1)
1497                         (b->chan + 1)->gsyn = syn;
1498         }
1499 }
1500
1501 int ce_get_cable (ce_chan_t *c)
1502 {
1503         ce_board_t *b = c->board;
1504         if (c->num >= b->ddk.Interfaces)
1505                 return 0;
1506
1507         return CABLE_TP;
1508 }
1509
1510 void ce_set_dir (ce_chan_t *c, int dir)
1511 {
1512         ce_board_t *b = c->board;
1513         unsigned long ts;
1514         if (b->cr.pending + 1>= CONFREQSZ || c->dir == dir)
1515                 return;
1516
1517         ts = c->ts;
1518         ce_set_ts (c, 0);
1519         c->dir = dir;
1520         ce_set_ts (c, ts);
1521 }