]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/cxt1e1/pmcc4_drv.c
Merge branch 'uprobes/core' of git://git.kernel.org/pub/scm/linux/kernel/git/oleg...
[karo-tx-linux.git] / drivers / staging / cxt1e1 / pmcc4_drv.c
1 /*-----------------------------------------------------------------------------
2  * pmcc4_drv.c -
3  *
4  * Copyright (C) 2007  One Stop Systems, Inc.
5  * Copyright (C) 2002-2006  SBE, Inc.
6  *
7  *   This program is free software; you can redistribute it and/or modify
8  *   it under the terms of the GNU General Public License as published by
9  *   the Free Software Foundation; either version 2 of the License, or
10  *   (at your option) any later version.
11  *
12  *   This program is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  * For further information, contact via email: support@onestopsystems.com
18  * One Stop Systems, Inc.  Escondido, California  U.S.A.
19  *-----------------------------------------------------------------------------
20  */
21
22 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23
24 #include <linux/types.h>
25 #include "pmcc4_sysdep.h"
26 #include <linux/errno.h>
27 #include <linux/kernel.h>
28 #include <linux/sched.h>        /* include for timer */
29 #include <linux/timer.h>        /* include for timer */
30 #include <linux/hdlc.h>
31 #include <linux/io.h>
32
33 #include "sbecom_inline_linux.h"
34 #include "libsbew.h"
35 #include "pmcc4_private.h"
36 #include "pmcc4.h"
37 #include "pmcc4_ioctls.h"
38 #include "musycc.h"
39 #include "comet.h"
40 #include "sbe_bid.h"
41
42 #define KERN_WARN KERN_WARNING
43
44 /* forward references */
45 status_t    c4_wk_chan_init (mpi_t *, mch_t *);
46 void        c4_wq_port_cleanup (mpi_t *);
47 status_t    c4_wq_port_init (mpi_t *);
48
49 int         c4_loop_port (ci_t *, int, u_int8_t);
50 status_t    c4_set_port (ci_t *, int);
51 status_t    musycc_chan_down (ci_t *, int);
52
53 u_int32_t musycc_chan_proto (int);
54 status_t    musycc_dump_ring (ci_t *, unsigned int);
55 status_t __init musycc_init (ci_t *);
56 void        musycc_init_mdt (mpi_t *);
57 void        musycc_serv_req (mpi_t *, u_int32_t);
58 void        musycc_update_timeslots (mpi_t *);
59
60 extern void musycc_update_tx_thp (mch_t *);
61 extern int  cxt1e1_log_level;
62 extern int  cxt1e1_max_mru;
63 extern int  cxt1e1_max_mtu;
64 extern int  max_rxdesc_used, max_rxdesc_default;
65 extern int  max_txdesc_used, max_txdesc_default;
66
67 #if defined (__powerpc__)
68 extern void *memset (void *s, int c, size_t n);
69
70 #endif
71
72 int         drvr_state = SBE_DRVR_INIT;
73 ci_t       *c4_list = NULL;
74 ci_t       *CI;                 /* dummy pointer to board ZEROE's data -
75                                  * DEBUG USAGE */
76
77
78 void
79 sbecom_set_loglevel (int d)
80 {
81     /*
82      * The code within the following -if- clause is a backdoor debug facility
83      * which can be used to display the state of a board's channel.
84      */
85     if (d > LOG_DEBUG)
86     {
87         unsigned int channum = d - (LOG_DEBUG + 1);     /* convert to ZERO
88                                                          * relativity */
89
90         (void) musycc_dump_ring ((ci_t *) CI, channum); /* CI implies support
91                                                          * for card 0 only */
92     } else
93     {
94         if (cxt1e1_log_level != d)
95         {
96             pr_info("log level changed from %d to %d\n", cxt1e1_log_level, d);
97             cxt1e1_log_level = d;          /* set new */
98         } else
99             pr_info("log level is %d\n", cxt1e1_log_level);
100     }
101 }
102
103
104 mch_t      *
105 c4_find_chan (int channum)
106 {
107     ci_t       *ci;
108     mch_t      *ch;
109     int         portnum, gchan;
110
111     for (ci = c4_list; ci; ci = ci->next)
112         for (portnum = 0; portnum < ci->max_port; portnum++)
113             for (gchan = 0; gchan < MUSYCC_NCHANS; gchan++)
114             {
115                 ch = ci->port[portnum].chan[gchan];
116                 if (ch) {
117                         if ((ch->state != UNASSIGNED) &&
118                            (ch->channum == channum))
119                                 return ch;
120                 }
121             }
122     return NULL;
123 }
124
125
126 ci_t       *__init
127 c4_new (void *hi)
128 {
129     ci_t       *ci;
130
131 #ifdef SBE_MAP_DEBUG
132     pr_warning("c4_new() entered, ci needs %u.\n",
133                (unsigned int) sizeof (ci_t));
134 #endif
135
136     ci = (ci_t *) OS_kmalloc (sizeof (ci_t));
137     if (ci)
138     {
139         ci->hdw_info = hi;
140         ci->state = C_INIT;         /* mark as hardware not available */
141         ci->next = c4_list;
142         c4_list = ci;
143         ci->brdno = ci->next ? ci->next->brdno + 1 : 0;
144     } else
145         pr_warning("failed CI malloc, size %u.\n",
146                    (unsigned int) sizeof (ci_t));
147
148     if (!CI)
149         CI = ci;                    /* DEBUG, only board 0 usage */
150     return ci;
151 }
152
153
154 /***
155  * Check port state and set LED states using watchdog or ioctl...
156  * also check for in-band SF loopback commands (& cause results if they are there)
157  *
158  * Alarm function depends on comet bits indicating change in
159  * link status (linkMask) to keep the link status indication straight.
160  *
161  * Indications are only LED and system log -- except when ioctl is invoked.
162  *
163  * "alarmed" record (a.k.a. copyVal, in some cases below) decodes as:
164  *
165  *   RMAI  (E1 only) 0x100
166  *   alarm LED on    0x80
167  *   link LED on     0x40
168  *   link returned   0x20 (link was down, now it's back and 'port get' hasn't run)
169  *   change in LED   0x10 (update LED register because value has changed)
170  *   link is down    0x08
171  *   YelAlm(RAI)     0x04
172  *   RedAlm          0x02
173  *   AIS(blue)Alm    0x01
174  *
175  * note "link has returned" indication is reset on read
176  * (e.g. by use of the c4_control port get command)
177  */
178
179 #define sbeLinkMask       0x41  /* change in signal status (lost/recovered) +
180                                  * state */
181 #define sbeLinkChange     0x40
182 #define sbeLinkDown       0x01
183 #define sbeAlarmsMask     0x07  /* red / yellow / blue alarm conditions */
184 #define sbeE1AlarmsMask   0x107 /* alarm conditions */
185
186 #define COMET_LBCMD_READ  0x80  /* read only (do not set, return read value) */
187
188 void
189 checkPorts (ci_t *ci)
190 {
191 #ifndef CONFIG_SBE_PMCC4_NCOMM
192     /*
193      * PORT POINT - NCOMM needs to avoid this code since the polling of
194      * alarms conflicts with NCOMM's interrupt servicing implementation.
195      */
196
197     struct s_comet_reg    *comet;
198     volatile u_int32_t value;
199     u_int32_t   copyVal, LEDval;
200
201     u_int8_t portnum;
202
203     LEDval = 0;
204     for (portnum = 0; portnum < ci->max_port; portnum++)
205     {
206         copyVal = 0x12f & (ci->alarmed[portnum]);       /* port's alarm record */
207         comet = ci->port[portnum].cometbase;
208         value = pci_read_32 ((u_int32_t *) &comet->cdrc_ists) & sbeLinkMask;    /* link loss reg */
209
210         if (value & sbeLinkChange)  /* is there a change in the link stuff */
211         {
212             /* if there's been a change (above) and yet it's the same (below) */
213             if (!(((copyVal >> 3) & sbeLinkDown) ^ (value & sbeLinkDown)))
214             {
215                 if (value & sbeLinkDown)
216                     pr_warning("%s: Port %d momentarily recovered.\n",
217                                ci->devname, portnum);
218                 else
219                     pr_warning("%s: Warning: Port %d link was briefly down.\n",
220                                ci->devname, portnum);
221             } else if (value & sbeLinkDown)
222                 pr_warning("%s: Warning: Port %d link is down.\n",
223                            ci->devname, portnum);
224             else
225             {
226                 pr_warning("%s: Port %d link has recovered.\n",
227                            ci->devname, portnum);
228                 copyVal |= 0x20;    /* record link transition to up */
229             }
230             copyVal |= 0x10;        /* change (link) --> update LEDs  */
231         }
232         copyVal &= 0x137;           /* clear LED & link old history bits &
233                                      * save others */
234         if (value & sbeLinkDown)
235             copyVal |= 0x08;        /* record link status (now) */
236         else
237         {                           /* if link is up, do this */
238             copyVal |= 0x40;        /* LED indicate link is up    */
239             /* Alarm things & the like ... first if E1, then if T1 */
240             if (IS_FRAME_ANY_E1 (ci->port[portnum].p.port_mode))
241             {
242                 /*
243                  * first check Codeword (SaX) changes & CRC and
244                  * sub-multi-frame errors
245                  */
246                 /*
247                  * note these errors are printed every time they are detected
248                  * vs. alarms
249                  */
250                 value = pci_read_32 ((u_int32_t *) &comet->e1_frmr_nat_ists);   /* codeword */
251                 if (value & 0x1f)
252                 {                   /* if errors (crc or smf only) */
253                     if (value & 0x10)
254                         pr_warning("%s: E1 Port %d Codeword Sa4 change detected.\n",
255                                    ci->devname, portnum);
256                     if (value & 0x08)
257                         pr_warning("%s: E1 Port %d Codeword Sa5 change detected.\n",
258                                    ci->devname, portnum);
259                     if (value & 0x04)
260                         pr_warning("%s: E1 Port %d Codeword Sa6 change detected.\n",
261                                    ci->devname, portnum);
262                     if (value & 0x02)
263                         pr_warning("%s: E1 Port %d Codeword Sa7 change detected.\n",
264                                    ci->devname, portnum);
265                     if (value & 0x01)
266                         pr_warning("%s: E1 Port %d Codeword Sa8 change detected.\n",
267                                    ci->devname, portnum);
268                 }
269                 value = pci_read_32 ((u_int32_t *) &comet->e1_frmr_mists);      /* crc & smf */
270                 if (value & 0x3)
271                 {                   /* if errors (crc or smf only) */
272                     if (value & sbeE1CRC)
273                         pr_warning("%s: E1 Port %d CRC-4 error(s) detected.\n",
274                                    ci->devname, portnum);
275                     if (value & sbeE1errSMF)    /* error in sub-multiframe */
276                         pr_warning("%s: E1 Port %d received errored SMF.\n",
277                                    ci->devname, portnum);
278                 }
279                 value = pci_read_32 ((u_int32_t *) &comet->e1_frmr_masts) & 0xcc; /* alarms */
280                 /*
281                  * pack alarms together (bitmiser), and construct similar to
282                  * T1
283                  */
284                 /* RAI,RMAI,.,.,LOF,AIS,.,. ==>  RMAI,.,.,.,.,.,RAI,LOF,AIS */
285                 /* see 0x97 */
286                 value = (value >> 2);
287                 if (value & 0x30)
288                 {
289                     if (value & 0x20)
290                         value |= 0x40;  /* RAI */
291                     if (value & 0x10)
292                         value |= 0x100; /* RMAI */
293                     value &= ~0x30;
294                 }                   /* finished packing alarm in handy order */
295                 if (value != (copyVal & sbeE1AlarmsMask))
296                 {                   /* if alarms changed */
297                     copyVal |= 0x10;/* change LED status   */
298                     if ((copyVal & sbeRedAlm) && !(value & sbeRedAlm))
299                     {
300                         copyVal &= ~sbeRedAlm;
301                         pr_warning("%s: E1 Port %d LOF alarm ended.\n",
302                                    ci->devname, portnum);
303                     } else if (!(copyVal & sbeRedAlm) && (value & sbeRedAlm))
304                     {
305                         copyVal |= sbeRedAlm;
306                         pr_warning("%s: E1 Warning: Port %d LOF alarm.\n",
307                                    ci->devname, portnum);
308                     } else if ((copyVal & sbeYelAlm) && !(value & sbeYelAlm))
309                     {
310                         copyVal &= ~sbeYelAlm;
311                         pr_warning("%s: E1 Port %d RAI alarm ended.\n",
312                                    ci->devname, portnum);
313                     } else if (!(copyVal & sbeYelAlm) && (value & sbeYelAlm))
314                     {
315                         copyVal |= sbeYelAlm;
316                         pr_warning("%s: E1 Warning: Port %d RAI alarm.\n",
317                                    ci->devname, portnum);
318                     } else if ((copyVal & sbeE1RMAI) && !(value & sbeE1RMAI))
319                     {
320                         copyVal &= ~sbeE1RMAI;
321                         pr_warning("%s: E1 Port %d RMAI alarm ended.\n",
322                                    ci->devname, portnum);
323                     } else if (!(copyVal & sbeE1RMAI) && (value & sbeE1RMAI))
324                     {
325                         copyVal |= sbeE1RMAI;
326                         pr_warning("%s: E1 Warning: Port %d RMAI alarm.\n",
327                                    ci->devname, portnum);
328                     } else if ((copyVal & sbeAISAlm) && !(value & sbeAISAlm))
329                     {
330                         copyVal &= ~sbeAISAlm;
331                         pr_warning("%s: E1 Port %d AIS alarm ended.\n",
332                                    ci->devname, portnum);
333                     } else if (!(copyVal & sbeAISAlm) && (value & sbeAISAlm))
334                     {
335                         copyVal |= sbeAISAlm;
336                         pr_warning("%s: E1 Warning: Port %d AIS alarm.\n",
337                                    ci->devname, portnum);
338                     }
339                 }
340                 /* end of E1 alarm code */
341             } else
342             {                       /* if a T1 mode */
343                 value = pci_read_32 ((u_int32_t *) &comet->t1_almi_ists);       /* alarms */
344                 value &= sbeAlarmsMask;
345                 if (value != (copyVal & sbeAlarmsMask))
346                 {                   /* if alarms changed */
347                     copyVal |= 0x10;/* change LED status   */
348                     if ((copyVal & sbeRedAlm) && !(value & sbeRedAlm))
349                     {
350                         copyVal &= ~sbeRedAlm;
351                         pr_warning("%s: Port %d red alarm ended.\n",
352                                    ci->devname, portnum);
353                     } else if (!(copyVal & sbeRedAlm) && (value & sbeRedAlm))
354                     {
355                         copyVal |= sbeRedAlm;
356                         pr_warning("%s: Warning: Port %d red alarm.\n",
357                                    ci->devname, portnum);
358                     } else if ((copyVal & sbeYelAlm) && !(value & sbeYelAlm))
359                     {
360                         copyVal &= ~sbeYelAlm;
361                         pr_warning("%s: Port %d yellow (RAI) alarm ended.\n",
362                                    ci->devname, portnum);
363                     } else if (!(copyVal & sbeYelAlm) && (value & sbeYelAlm))
364                     {
365                         copyVal |= sbeYelAlm;
366                         pr_warning("%s: Warning: Port %d yellow (RAI) alarm.\n",
367                                    ci->devname, portnum);
368                     } else if ((copyVal & sbeAISAlm) && !(value & sbeAISAlm))
369                     {
370                         copyVal &= ~sbeAISAlm;
371                         pr_warning("%s: Port %d blue (AIS) alarm ended.\n",
372                                    ci->devname, portnum);
373                     } else if (!(copyVal & sbeAISAlm) && (value & sbeAISAlm))
374                     {
375                         copyVal |= sbeAISAlm;
376                         pr_warning("%s: Warning: Port %d blue (AIS) alarm.\n",
377                                    ci->devname, portnum);
378                     }
379                 }
380             }                       /* end T1 mode alarm checks */
381         }
382         if (copyVal & sbeAlarmsMask)
383             copyVal |= 0x80;        /* if alarm turn yel LED on */
384         if (copyVal & 0x10)
385             LEDval |= 0x100;        /* tag if LED values have changed  */
386         LEDval |= ((copyVal & 0xc0) >> (6 - (portnum * 2)));
387
388         ci->alarmed[portnum] &= 0xfffff000;     /* out with the old (it's fff
389                                                  * ... foo) */
390         ci->alarmed[portnum] |= (copyVal);      /* in with the new */
391
392         /*
393          * enough with the alarms and LED's, now let's check for loopback
394          * requests
395          */
396
397         if (IS_FRAME_ANY_T1 (ci->port[portnum].p.port_mode))
398         {                           /* if a T1 mode  */
399             /*
400              * begin in-band (SF) loopback code detection -- start by reading
401              * command
402              */
403             value = pci_read_32 ((u_int32_t *) &comet->ibcd_ies);       /* detect reg. */
404             value &= 0x3;           /* trim to handy bits */
405             if (value & 0x2)
406             {                       /* activate loopback (sets for deactivate
407                                      * code length) */
408                 copyVal = c4_loop_port (ci, portnum, COMET_LBCMD_READ); /* read line loopback
409                                                                          * mode */
410                 if (copyVal != COMET_MDIAG_LINELB)      /* don't do it again if
411                                                          * already in that mode */
412                     c4_loop_port (ci, portnum, COMET_MDIAG_LINELB);     /* put port in line
413                                                                          * loopback mode */
414             }
415             if (value & 0x1)
416             {                       /* deactivate loopback (sets for activate
417                                      * code length) */
418                 copyVal = c4_loop_port (ci, portnum, COMET_LBCMD_READ); /* read line loopback
419                                                                          * mode */
420                 if (copyVal != COMET_MDIAG_LBOFF)       /* don't do it again if
421                                                          * already in that mode */
422                     c4_loop_port (ci, portnum, COMET_MDIAG_LBOFF);      /* take port out of any
423                                                                          * loopback mode */
424             }
425         }
426         if (IS_FRAME_ANY_T1ESF (ci->port[portnum].p.port_mode))
427         {                           /* if a T1 ESF mode  */
428             /* begin ESF loopback code */
429             value = pci_read_32 ((u_int32_t *) &comet->t1_rboc_sts) & 0x3f;     /* read command */
430             if (value == 0x07)
431                 c4_loop_port (ci, portnum, COMET_MDIAG_LINELB); /* put port in line
432                                                                  * loopback mode */
433             if (value == 0x0a)
434                 c4_loop_port (ci, portnum, COMET_MDIAG_PAYLB);  /* put port in payload
435                                                                  * loopbk mode */
436             if ((value == 0x1c) || (value == 0x19) || (value == 0x12))
437                 c4_loop_port (ci, portnum, COMET_MDIAG_LBOFF);  /* take port out of any
438                                                                  * loopbk mode */
439             if (cxt1e1_log_level >= LOG_DEBUG)
440                 if (value != 0x3f)
441                     pr_warning("%s: BOC value = %x on Port %d\n",
442                                ci->devname, value, portnum);
443             /* end ESF loopback code */
444         }
445     }
446
447     /* if something is new, update LED's */
448     if (LEDval & 0x100)
449         pci_write_32 ((u_int32_t *) &ci->cpldbase->leds, LEDval & 0xff);
450 #endif                              /*** CONFIG_SBE_PMCC4_NCOMM ***/
451 }
452
453
454 static void
455 c4_watchdog (ci_t *ci)
456 {
457     if (drvr_state != SBE_DRVR_AVAILABLE)
458     {
459         if (cxt1e1_log_level >= LOG_MONITOR)
460             pr_info("drvr not available (%x)\n", drvr_state);
461         return;
462     }
463     ci->wdcount++;
464     checkPorts (ci);
465     ci->wd_notify = 0;
466 }
467
468
469 void
470 c4_cleanup (void)
471 {
472     ci_t       *ci, *next;
473     mpi_t      *pi;
474     int         portnum, j;
475
476     ci = c4_list;
477     while (ci)
478     {
479         next = ci->next;            /* protect <next> from upcoming <free> */
480         pci_write_32 ((u_int32_t *) &ci->cpldbase->leds, PMCC4_CPLD_LED_OFF);
481         for (portnum = 0; portnum < ci->max_port; portnum++)
482         {
483             pi = &ci->port[portnum];
484             c4_wq_port_cleanup (pi);
485             for (j = 0; j < MUSYCC_NCHANS; j++)
486             {
487                 if (pi->chan[j])
488                     OS_kfree (pi->chan[j]);     /* free mch_t struct */
489             }
490             OS_kfree (pi->regram_saved);
491         }
492         OS_kfree (ci->iqd_p_saved);
493         OS_kfree (ci);
494         ci = next;                  /* cleanup next board, if any */
495     }
496 }
497
498
499 /*
500  * This function issues a write to all comet chips and expects the same data
501  * to be returned from the subsequent read.  This determines the board build
502  * to be a 1-port, 2-port, or 4-port build.  The value returned represents a
503  * bit-mask of the found ports.  Only certain configurations are considered
504  * VALID or LEGAL builds.
505  */
506
507 int
508 c4_get_portcfg (ci_t *ci)
509 {
510     struct s_comet_reg    *comet;
511     int         portnum, mask;
512     u_int32_t   wdata, rdata;
513
514     wdata = COMET_MDIAG_LBOFF;      /* take port out of any loopback mode */
515
516     mask = 0;
517     for (portnum = 0; portnum < MUSYCC_NPORTS; portnum++)
518     {
519         comet = ci->port[portnum].cometbase;
520         pci_write_32 ((u_int32_t *) &comet->mdiag, wdata);
521         rdata = pci_read_32 ((u_int32_t *) &comet->mdiag) & COMET_MDIAG_LBMASK;
522         if (wdata == rdata)
523             mask |= 1 << portnum;
524     }
525     return mask;
526 }
527
528
529 /* nothing herein should generate interrupts */
530
531 status_t    __init
532 c4_init (ci_t *ci, u_char *func0, u_char *func1)
533 {
534     mpi_t      *pi;
535     mch_t      *ch;
536     static u_int32_t count = 0;
537     int         portnum, j;
538
539     ci->state = C_INIT;
540     ci->brdno = count++;
541     ci->intlog.this_status_new = 0;
542     atomic_set (&ci->bh_pending, 0);
543
544     ci->reg = (struct musycc_globalr *) func0;
545     ci->eeprombase = (u_int32_t *) (func1 + EEPROM_OFFSET);
546     ci->cpldbase = (c4cpld_t *) ((u_int32_t *) (func1 + ISPLD_OFFSET));
547
548     /*** PORT POINT - the following is the first access of any type to the hardware ***/
549 #ifdef CONFIG_SBE_PMCC4_NCOMM
550     /* NCOMM driver uses INTB interrupt to monitor CPLD register */
551     pci_write_32 ((u_int32_t *) &ci->reg->glcd, GCD_MAGIC);
552 #else
553     /* standard driver POLLS for INTB via CPLD register */
554     pci_write_32 ((u_int32_t *) &ci->reg->glcd, GCD_MAGIC | MUSYCC_GCD_INTB_DISABLE);
555 #endif
556
557     {
558         int         pmsk;
559
560         /* need comet addresses available for determination of hardware build */
561         for (portnum = 0; portnum < MUSYCC_NPORTS; portnum++)
562         {
563             pi = &ci->port[portnum];
564             pi->cometbase = (struct s_comet_reg *) ((u_int32_t *) (func1 + COMET_OFFSET (portnum)));
565             pi->reg = (struct musycc_globalr *) ((u_char *) ci->reg + (portnum * 0x800));
566             pi->portnum = portnum;
567             pi->p.portnum = portnum;
568             pi->openchans = 0;
569 #ifdef SBE_MAP_DEBUG
570             pr_info("Comet-%d: addr = %p\n", portnum, pi->cometbase);
571 #endif
572         }
573         pmsk = c4_get_portcfg (ci);
574         switch (pmsk)
575         {
576         case 0x1:
577             ci->max_port = 1;
578             break;
579         case 0x3:
580             ci->max_port = 2;
581             break;
582 #if 0
583         case 0x7:                   /* not built, but could be... */
584             ci->max_port = 3;
585             break;
586 #endif
587         case 0xf:
588             ci->max_port = 4;
589             break;
590         default:
591             ci->max_port = 0;
592             pr_warning("%s: illegal port configuration (%x)\n",
593                        ci->devname, pmsk);
594             return SBE_DRVR_FAIL;
595         }
596 #ifdef SBE_MAP_DEBUG
597         pr_info(">> %s: c4_get_build - pmsk %x max_port %x\n",
598                 ci->devname, pmsk, ci->max_port);
599 #endif
600     }
601
602     for (portnum = 0; portnum < ci->max_port; portnum++)
603     {
604         pi = &ci->port[portnum];
605         pi->up = ci;
606         pi->sr_last = 0xffffffff;
607         pi->p.port_mode = CFG_FRAME_SF; /* T1 B8ZS, the default */
608         pi->p.portP = (CFG_CLK_PORT_EXTERNAL | CFG_LBO_LH0);    /* T1 defaults */
609
610         OS_sem_init (&pi->sr_sem_busy, SEM_AVAILABLE);
611         OS_sem_init (&pi->sr_sem_wait, SEM_TAKEN);
612
613         for (j = 0; j < 32; j++)
614         {
615             pi->fifomap[j] = -1;
616             pi->tsm[j] = 0;         /* no assignments, all available */
617         }
618
619         /* allocate channel structures for this port */
620         for (j = 0; j < MUSYCC_NCHANS; j++)
621         {
622             ch = OS_kmalloc (sizeof (mch_t));
623             if (ch)
624             {
625                 pi->chan[j] = ch;
626                 ch->state = UNASSIGNED;
627                 ch->up = pi;
628                 ch->gchan = (-1);   /* channel assignment not yet known */
629                 ch->channum = (-1); /* channel assignment not yet known */
630                 ch->p.card = ci->brdno;
631                 ch->p.port = portnum;
632                 ch->p.channum = (-1);   /* channel assignment not yet known */
633                 ch->p.mode_56k = 0; /* default is 64kbps mode */
634             } else
635             {
636                 pr_warning("failed mch_t malloc, port %d channel %d size %u.\n",
637                            portnum, j, (unsigned int) sizeof (mch_t));
638                 break;
639             }
640         }
641     }
642
643
644     {
645         /*
646          * Set LEDs through their paces to supply visual proof that LEDs are
647          * functional and not burnt out nor broken.
648          *
649          * YELLOW + GREEN -> OFF.
650          */
651
652         pci_write_32 ((u_int32_t *) &ci->cpldbase->leds,
653                       PMCC4_CPLD_LED_GREEN | PMCC4_CPLD_LED_YELLOW);
654         OS_uwait (750000, "leds");
655         pci_write_32 ((u_int32_t *) &ci->cpldbase->leds, PMCC4_CPLD_LED_OFF);
656     }
657
658     OS_init_watchdog (&ci->wd, (void (*) (void *)) c4_watchdog, ci, WATCHDOG_TIMEOUT);
659     return SBE_DRVR_SUCCESS;
660 }
661
662
663 /* better be fully setup to handle interrupts when you call this */
664
665 status_t    __init
666 c4_init2 (ci_t *ci)
667 {
668     status_t    ret;
669
670     /* PORT POINT: this routine generates first interrupt */
671         ret = musycc_init(ci);
672         if (ret != SBE_DRVR_SUCCESS)
673                 return ret;
674
675 #if 0
676     ci->p.framing_type = FRAMING_CBP;
677     ci->p.h110enable = 1;
678 #if 0
679     ci->p.hypersize = 0;
680 #else
681     hyperdummy = 0;
682 #endif
683     ci->p.clock = 0;                /* Use internal clocking until set to
684                                      * external */
685     c4_card_set_params (ci, &ci->p);
686 #endif
687     OS_start_watchdog (&ci->wd);
688     return SBE_DRVR_SUCCESS;
689 }
690
691
692 /* This function sets the loopback mode (or clears it, as the case may be). */
693
694 int
695 c4_loop_port (ci_t *ci, int portnum, u_int8_t cmd)
696 {
697     struct s_comet_reg    *comet;
698     volatile u_int32_t loopValue;
699
700     comet = ci->port[portnum].cometbase;
701     loopValue = pci_read_32 ((u_int32_t *) &comet->mdiag) & COMET_MDIAG_LBMASK;
702
703     if (cmd & COMET_LBCMD_READ)
704         return loopValue;           /* return the read value */
705
706     if (loopValue != cmd)
707     {
708         switch (cmd)
709         {
710         case COMET_MDIAG_LINELB:
711             /* set(SF)loopback down (turn off) code length to 6 bits */
712             pci_write_32 ((u_int32_t *) &comet->ibcd_cfg, 0x05);
713             break;
714         case COMET_MDIAG_LBOFF:
715             /* set (SF) loopback up (turn on) code length to 5 bits */
716             pci_write_32 ((u_int32_t *) &comet->ibcd_cfg, 0x00);
717             break;
718         }
719
720         pci_write_32 ((u_int32_t *) &comet->mdiag, cmd);
721         if (cxt1e1_log_level >= LOG_WARN)
722             pr_info("%s: loopback mode changed to %2x from %2x on Port %d\n",
723                     ci->devname, cmd, loopValue, portnum);
724         loopValue = pci_read_32 ((u_int32_t *) &comet->mdiag) & COMET_MDIAG_LBMASK;
725         if (loopValue != cmd)
726         {
727             if (cxt1e1_log_level >= LOG_ERROR)
728                 pr_info("%s: write to loop register failed, unknown state for Port %d\n",
729                         ci->devname, portnum);
730         }
731     } else
732     {
733         if (cxt1e1_log_level >= LOG_WARN)
734             pr_info("%s: loopback already in that mode (%2x)\n",
735                     ci->devname, loopValue);
736     }
737     return 0;
738 }
739
740
741 /* c4_frame_rw: read or write the comet register specified
742  * (modifies use of port_param to non-standard use of struct)
743  * Specifically:
744  *   pp.portnum     (one guess)
745  *   pp.port_mode   offset of register
746  *   pp.portP       write (or not, i.e. read)
747  *   pp.portStatus  write value
748  * BTW:
749  *   pp.portStatus  also used to return read value
750  *   pp.portP       also used during write, to return old reg value
751  */
752
753 status_t
754 c4_frame_rw (ci_t *ci, struct sbecom_port_param *pp)
755 {
756     struct s_comet_reg    *comet;
757     volatile u_int32_t data;
758
759     if (pp->portnum >= ci->max_port)/* sanity check */
760         return -ENXIO;
761
762     comet = ci->port[pp->portnum].cometbase;
763     data = pci_read_32 ((u_int32_t *) comet + pp->port_mode) & 0xff;
764
765     if (pp->portP)
766     {                               /* control says this is a register
767                                      * _write_ */
768         if (pp->portStatus == data)
769             pr_info("%s: Port %d already that value!  Writing again anyhow.\n",
770                     ci->devname, pp->portnum);
771         pp->portP = (u_int8_t) data;
772         pci_write_32 ((u_int32_t *) comet + pp->port_mode,
773                       pp->portStatus);
774         data = pci_read_32 ((u_int32_t *) comet + pp->port_mode) & 0xff;
775     }
776     pp->portStatus = (u_int8_t) data;
777     return 0;
778 }
779
780
781 /* c4_pld_rw: read or write the pld register specified
782  * (modifies use of port_param to non-standard use of struct)
783  * Specifically:
784  *   pp.port_mode   offset of register
785  *   pp.portP       write (or not, i.e. read)
786  *   pp.portStatus  write value
787  * BTW:
788  *   pp.portStatus  also used to return read value
789  *   pp.portP       also used during write, to return old reg value
790  */
791
792 status_t
793 c4_pld_rw (ci_t *ci, struct sbecom_port_param *pp)
794 {
795     volatile u_int32_t *regaddr;
796     volatile u_int32_t data;
797     int         regnum = pp->port_mode;
798
799     regaddr = (u_int32_t *) ci->cpldbase + regnum;
800     data = pci_read_32 ((u_int32_t *) regaddr) & 0xff;
801
802     if (pp->portP)
803     {                               /* control says this is a register
804                                      * _write_ */
805         pp->portP = (u_int8_t) data;
806         pci_write_32 ((u_int32_t *) regaddr, pp->portStatus);
807         data = pci_read_32 ((u_int32_t *) regaddr) & 0xff;
808     }
809     pp->portStatus = (u_int8_t) data;
810     return 0;
811 }
812
813 /* c4_musycc_rw: read or write the musycc register specified
814  * (modifies use of port_param to non-standard use of struct)
815  * Specifically:
816  *    mcp.RWportnum   port number and write indication bit (0x80)
817  *    mcp.offset      offset of register
818  *    mcp.value       write value going in and read value returning
819  */
820
821 /* PORT POINT: TX Subchannel Map registers are write-only
822  * areas within the MUSYCC and always return FF */
823 /* PORT POINT: regram and reg structures are minorly different and <offset> ioctl
824  * settings are aligned with the <reg> struct musycc_globalr{} usage.
825  * Also, regram is separately allocated shared memory, allocated for each port.
826  * PORT POINT: access offsets of 0x6000 for Msg Cfg Desc Tbl are for 4-port MUSYCC
827  * only.  (An 8-port MUSYCC has 0x16000 offsets for accessing its upper 4 tables.)
828  */
829
830 status_t
831 c4_musycc_rw (ci_t *ci, struct c4_musycc_param *mcp)
832 {
833     mpi_t      *pi;
834     volatile u_int32_t *dph;    /* hardware implemented register */
835     u_int32_t *dpr = NULL;      /* RAM image of registers for group command
836                                  * usage */
837     int         offset = mcp->offset % 0x800;   /* group relative address
838                                                  * offset, mcp->portnum is
839                                                  * not used */
840     int         portnum, ramread = 0;
841     volatile u_int32_t data;
842
843     /*
844      * Sanity check hardware accessibility.  The 0x6000 portion handles port
845      * numbers associated with Msg Descr Tbl decoding.
846      */
847     portnum = (mcp->offset % 0x6000) / 0x800;
848     if (portnum >= ci->max_port)
849         return -ENXIO;
850     pi = &ci->port[portnum];
851     if (mcp->offset >= 0x6000)
852         offset += 0x6000;           /* put back in MsgCfgDesc address offset */
853     dph = (u_int32_t *) ((u_long) pi->reg + offset);
854
855     /* read of TX are from RAM image, since hardware returns FF */
856     dpr = (u_int32_t *) ((u_long) pi->regram + offset);
857     if (mcp->offset < 0x6000)       /* non MsgDesc Tbl accesses might require
858                                      * RAM access */
859     {
860         if (offset >= 0x200 && offset < 0x380)
861             ramread = 1;
862         if (offset >= 0x10 && offset < 0x200)
863             ramread = 1;
864     }
865     /* read register from RAM or hardware, depending... */
866     if (ramread)
867     {
868         data = *dpr;
869         //pr_info("c4_musycc_rw: RAM addr %p  read data %x (portno %x offset %x RAM ramread %x)\n", dpr, data, portnum, offset, ramread); /* RLD DEBUG */
870     } else
871     {
872         data = pci_read_32 ((u_int32_t *) dph);
873         //pr_info("c4_musycc_rw: REG addr %p  read data %x (portno %x offset %x RAM ramread %x)\n", dph, data, portnum, offset, ramread); /* RLD DEBUG */
874     }
875
876
877     if (mcp->RWportnum & 0x80)
878     {                               /* control says this is a register
879                                      * _write_ */
880         if (mcp->value == data)
881             pr_info("%s: musycc grp%d already that value! writing again anyhow.\n",
882                     ci->devname, (mcp->RWportnum & 0x7));
883         /* write register RAM */
884         if (ramread)
885             *dpr = mcp->value;
886         /* write hardware register */
887         pci_write_32 ((u_int32_t *) dph, mcp->value);
888     }
889     mcp->value = data;              /* return the read value (or the 'old
890                                      * value', if is write) */
891     return 0;
892 }
893
894 status_t
895 c4_get_port (ci_t *ci, int portnum)
896 {
897     if (portnum >= ci->max_port)    /* sanity check */
898         return -ENXIO;
899
900     SD_SEM_TAKE (&ci->sem_wdbusy, "_wd_");      /* only 1 thru here, per
901                                                  * board */
902     checkPorts (ci);
903     ci->port[portnum].p.portStatus = (u_int8_t) ci->alarmed[portnum];
904     ci->alarmed[portnum] &= 0xdf;
905     SD_SEM_GIVE (&ci->sem_wdbusy);  /* release per-board hold */
906     return 0;
907 }
908
909 status_t
910 c4_set_port (ci_t *ci, int portnum)
911 {
912     mpi_t      *pi;
913     struct sbecom_port_param *pp;
914     int         e1mode;
915     u_int8_t    clck;
916     int         i;
917
918     if (portnum >= ci->max_port)    /* sanity check */
919         return -ENXIO;
920
921     pi = &ci->port[portnum];
922     pp = &ci->port[portnum].p;
923     e1mode = IS_FRAME_ANY_E1 (pp->port_mode);
924     if (cxt1e1_log_level >= LOG_MONITOR2)
925     {
926         pr_info("%s: c4_set_port[%d]:  entered, e1mode = %x, openchans %d.\n",
927                 ci->devname,
928                 portnum, e1mode, pi->openchans);
929     }
930     if (pi->openchans)
931         return -EBUSY;               /* group needs initialization only for
932                                      * first channel of a group */
933
934     {
935         status_t    ret;
936
937         ret = c4_wq_port_init(pi);
938         if (ret)       /* create/init workqueue_struct */
939                 return ret;
940     }
941
942     init_comet (ci, pi->cometbase, pp->port_mode, 1 /* clockmaster == true */ , pp->portP);
943     clck = pci_read_32 ((u_int32_t *) &ci->cpldbase->mclk) & PMCC4_CPLD_MCLK_MASK;
944     if (e1mode)
945         clck |= 1 << portnum;
946     else
947         clck &= 0xf ^ (1 << portnum);
948
949     pci_write_32 ((u_int32_t *) &ci->cpldbase->mclk, clck);
950     pci_write_32 ((u_int32_t *) &ci->cpldbase->mcsr, PMCC4_CPLD_MCSR_IND);
951     pci_write_32 ((u_int32_t *) &pi->reg->gbp, OS_vtophys (pi->regram));
952
953     /*********************************************************************/
954     /* ERRATA: If transparent mode is used, do not set OOFMP_DISABLE bit */
955     /*********************************************************************/
956
957     pi->regram->grcd =
958         __constant_cpu_to_le32 (MUSYCC_GRCD_RX_ENABLE |
959                                 MUSYCC_GRCD_TX_ENABLE |
960                                 MUSYCC_GRCD_OOFMP_DISABLE |
961                                 MUSYCC_GRCD_SF_ALIGN |  /* per MUSYCC ERRATA,
962                                                          * for T1 * fix */
963                                 MUSYCC_GRCD_COFAIRQ_DISABLE |
964                                 MUSYCC_GRCD_MC_ENABLE |
965                        (MUSYCC_GRCD_POLLTH_32 << MUSYCC_GRCD_POLLTH_SHIFT));
966
967     pi->regram->pcd =
968         __constant_cpu_to_le32 ((e1mode ? 1 : 0) |
969                                 MUSYCC_PCD_TXSYNC_RISING |
970                                 MUSYCC_PCD_RXSYNC_RISING |
971                                 MUSYCC_PCD_RXDATA_RISING);
972
973     /* Message length descriptor */
974        pi->regram->mld = __constant_cpu_to_le32 (cxt1e1_max_mru | (cxt1e1_max_mru << 16));
975
976     /* tsm algorithm */
977     for (i = 0; i < 32; i++)
978     {
979
980         /*** ASSIGNMENT NOTES:                             ***/
981         /*** Group's channel  ZERO  unavailable if E1.     ***/
982         /*** Group's channel  16    unavailable if E1 CAS. ***/
983         /*** Group's channels 24-31 unavailable if T1.     ***/
984
985         if (((i == 0) && e1mode) ||
986             ((i == 16) && ((pp->port_mode == CFG_FRAME_E1CRC_CAS) || (pp->port_mode == CFG_FRAME_E1CRC_CAS_AMI)))
987             || ((i > 23) && (!e1mode)))
988         {
989             pi->tsm[i] = 0xff;      /* make tslot unavailable for this mode */
990         } else
991         {
992             pi->tsm[i] = 0x00;      /* make tslot available for assignment */
993         }
994     }
995     for (i = 0; i < MUSYCC_NCHANS; i++)
996     {
997         pi->regram->ttsm[i] = 0;
998         pi->regram->rtsm[i] = 0;
999     }
1000     FLUSH_MEM_WRITE ();
1001     musycc_serv_req (pi, SR_GROUP_INIT | SR_RX_DIRECTION);
1002     musycc_serv_req (pi, SR_GROUP_INIT | SR_TX_DIRECTION);
1003
1004     musycc_init_mdt (pi);
1005
1006     pi->group_is_set = 1;
1007     pi->p = *pp;
1008     return 0;
1009 }
1010
1011
1012 unsigned int max_int = 0;
1013
1014 status_t
1015 c4_new_chan (ci_t *ci, int portnum, int channum, void *user)
1016 {
1017     mpi_t      *pi;
1018     mch_t      *ch;
1019     int         gchan;
1020
1021     if (c4_find_chan (channum))     /* a new channel shouldn't already exist */
1022         return -EEXIST;
1023
1024     if (portnum >= ci->max_port)    /* sanity check */
1025         return -ENXIO;
1026
1027     pi = &(ci->port[portnum]);
1028     /* find any available channel within this port */
1029     for (gchan = 0; gchan < MUSYCC_NCHANS; gchan++)
1030     {
1031         ch = pi->chan[gchan];
1032         if (ch && ch->state == UNASSIGNED)      /* no assignment is good! */
1033             break;
1034     }
1035     if (gchan == MUSYCC_NCHANS)     /* exhausted table, all were assigned */
1036         return -ENFILE;
1037
1038     ch->up = pi;
1039
1040     /* NOTE: mch_t already cleared during OS_kmalloc() */
1041     ch->state = DOWN;
1042     ch->user = user;
1043     ch->gchan = gchan;
1044     ch->channum = channum;          /* mark our channel assignment */
1045     ch->p.channum = channum;
1046 #if 1
1047     ch->p.card = ci->brdno;
1048     ch->p.port = portnum;
1049 #endif
1050     ch->p.chan_mode = CFG_CH_PROTO_HDLC_FCS16;
1051     ch->p.idlecode = CFG_CH_FLAG_7E;
1052     ch->p.pad_fill_count = 2;
1053     spin_lock_init (&ch->ch_rxlock);
1054     spin_lock_init (&ch->ch_txlock);
1055
1056     {
1057         status_t    ret;
1058
1059         ret = c4_wk_chan_init(pi, ch);
1060         if (ret)
1061                 return ret;
1062     }
1063
1064     /* save off interface assignments which bound a board */
1065     if (!ci->first_if)          /* first channel registered is assumed to
1066                                      * be the lowest channel */
1067     {
1068         ci->first_if = ci->last_if = user;
1069         ci->first_channum = ci->last_channum = channum;
1070     } else
1071     {
1072         ci->last_if = user;
1073         if (ci->last_channum < channum) /* higher number channel found */
1074             ci->last_channum = channum;
1075     }
1076     return 0;
1077 }
1078
1079 status_t
1080 c4_del_chan (int channum)
1081 {
1082     mch_t      *ch;
1083
1084         ch = c4_find_chan(channum);
1085         if (!ch)
1086                 return -ENOENT;
1087
1088     if (ch->state == UP)
1089         musycc_chan_down ((ci_t *) 0, channum);
1090     ch->state = UNASSIGNED;
1091     ch->gchan = (-1);
1092     ch->channum = (-1);
1093     ch->p.channum = (-1);
1094     return 0;
1095 }
1096
1097 status_t
1098 c4_del_chan_stats (int channum)
1099 {
1100     mch_t      *ch;
1101
1102         ch = c4_find_chan(channum);
1103         if (!ch)
1104                 return -ENOENT;
1105
1106     memset (&ch->s, 0, sizeof (struct sbecom_chan_stats));
1107     return 0;
1108 }
1109
1110
1111 status_t
1112 c4_set_chan (int channum, struct sbecom_chan_param *p)
1113 {
1114     mch_t      *ch;
1115     int         i, x = 0;
1116
1117         ch = c4_find_chan(channum);
1118         if (!ch)
1119                 return -ENOENT;
1120
1121 #if 1
1122     if (ch->p.card != p->card ||
1123         ch->p.port != p->port ||
1124         ch->p.channum != p->channum)
1125         return -EINVAL;
1126 #endif
1127
1128     if (!(ch->up->group_is_set))
1129     {
1130         return -EIO;                 /* out of order, SET_PORT command
1131                                      * required prior to first group's
1132                                      * SET_CHAN command */
1133     }
1134     /*
1135      * Check for change of parameter settings in order to invoke closing of
1136      * channel prior to hardware poking.
1137      */
1138
1139     if (ch->p.status != p->status || ch->p.chan_mode != p->chan_mode ||
1140         ch->p.data_inv != p->data_inv || ch->p.intr_mask != p->intr_mask ||
1141         ch->txd_free < ch->txd_num) /* to clear out queued messages */
1142         x = 1;                      /* we have a change requested */
1143     for (i = 0; i < 32; i++)        /* check for timeslot mapping changes */
1144         if (ch->p.bitmask[i] != p->bitmask[i])
1145             x = 1;                  /* we have a change requested */
1146     ch->p = *p;
1147     if (x && (ch->state == UP))     /* if change request and channel is
1148                                      * open... */
1149     {
1150         status_t    ret;
1151
1152         ret = musycc_chan_down((ci_t *)0, channum);
1153         if (ret)
1154                 return ret;
1155         ret = c4_chan_up(ch->up->up, channum);
1156         if (ret)
1157                 return ret;
1158         sd_enable_xmit (ch->user);  /* re-enable to catch flow controlled
1159                                      * channel */
1160     }
1161     return 0;
1162 }
1163
1164
1165 status_t
1166 c4_get_chan (int channum, struct sbecom_chan_param *p)
1167 {
1168     mch_t      *ch;
1169
1170         ch = c4_find_chan(channum);
1171         if (!ch)
1172                 return -ENOENT;
1173
1174     *p = ch->p;
1175     return 0;
1176 }
1177
1178 status_t
1179 c4_get_chan_stats (int channum, struct sbecom_chan_stats *p)
1180 {
1181     mch_t      *ch;
1182
1183         ch = c4_find_chan(channum);
1184         if (!ch)
1185                 return -ENOENT;
1186
1187     *p = ch->s;
1188     p->tx_pending = atomic_read (&ch->tx_pending);
1189     return 0;
1190 }
1191
1192 static int
1193 c4_fifo_alloc (mpi_t *pi, int chan, int *len)
1194 {
1195     int         i, l = 0, start = 0, max = 0, maxstart = 0;
1196
1197     for (i = 0; i < 32; i++)
1198     {
1199         if (pi->fifomap[i] != -1)
1200         {
1201             l = 0;
1202             start = i + 1;
1203             continue;
1204         }
1205         ++l;
1206         if (l > max)
1207         {
1208             max = l;
1209             maxstart = start;
1210         }
1211         if (max == *len)
1212             break;
1213     }
1214     if (max != *len)
1215     {
1216         if (cxt1e1_log_level >= LOG_WARN)
1217             pr_info("%s: wanted to allocate %d fifo space, but got only %d\n",
1218                     pi->up->devname, *len, max);
1219         *len = max;
1220     }
1221     if (cxt1e1_log_level >= LOG_DEBUG)
1222         pr_info("%s: allocated %d fifo at %d for channel %d/%d\n",
1223                 pi->up->devname, max, start, chan, pi->p.portnum);
1224     for (i = maxstart; i < (maxstart + max); i++)
1225         pi->fifomap[i] = chan;
1226     return start;
1227 }
1228
1229 void
1230 c4_fifo_free (mpi_t *pi, int chan)
1231 {
1232     int         i;
1233
1234     if (cxt1e1_log_level >= LOG_DEBUG)
1235         pr_info("%s: deallocated fifo for channel %d/%d\n",
1236                 pi->up->devname, chan, pi->p.portnum);
1237     for (i = 0; i < 32; i++)
1238         if (pi->fifomap[i] == chan)
1239             pi->fifomap[i] = -1;
1240 }
1241
1242
1243 status_t
1244 c4_chan_up (ci_t *ci, int channum)
1245 {
1246     mpi_t      *pi;
1247     mch_t      *ch;
1248     struct mbuf *m;
1249     struct mdesc *md;
1250     int         nts, nbuf, txnum, rxnum;
1251     int         addr, i, j, gchan;
1252     u_int32_t   tmp;            /* for optimizing conversion across BE
1253                                  * platform */
1254
1255         ch = c4_find_chan(channum);
1256         if (!ch)
1257                 return -ENOENT;
1258
1259     if (ch->state == UP)
1260     {
1261         if (cxt1e1_log_level >= LOG_MONITOR)
1262             pr_info("%s: channel already UP, graceful early exit\n",
1263                     ci->devname);
1264         return 0;
1265     }
1266     pi = ch->up;
1267     gchan = ch->gchan;
1268     /* find nts ('number of timeslots') */
1269     nts = 0;
1270     for (i = 0; i < 32; i++)
1271     {
1272         if (ch->p.bitmask[i] & pi->tsm[i])
1273         {
1274             if (1 || cxt1e1_log_level >= LOG_WARN)
1275             {
1276                 pr_info("%s: c4_chan_up[%d] EINVAL (attempt to cfg in-use or unavailable TimeSlot[%d])\n",
1277                         ci->devname, channum, i);
1278                 pr_info("+ ask4 %x, currently %x\n",
1279                         ch->p.bitmask[i], pi->tsm[i]);
1280             }
1281             return -EINVAL;
1282         }
1283         for (j = 0; j < 8; j++)
1284             if (ch->p.bitmask[i] & (1 << j))
1285                 nts++;
1286     }
1287
1288     nbuf = nts / 8 ? nts / 8 : 1;
1289     if (!nbuf)
1290     {
1291         /* if( cxt1e1_log_level >= LOG_WARN)  */
1292         pr_info("%s: c4_chan_up[%d] ENOBUFS (no TimeSlots assigned)\n",
1293                 ci->devname, channum);
1294         return -ENOBUFS;             /* this should not happen */
1295     }
1296     addr = c4_fifo_alloc (pi, gchan, &nbuf);
1297     ch->state = UP;
1298
1299     /* Setup the Time Slot Map */
1300     musycc_update_timeslots (pi);
1301
1302     /* ch->tx_limit = nts; */
1303     ch->s.tx_pending = 0;
1304
1305     /* Set Channel Configuration Descriptors */
1306     {
1307         u_int32_t   ccd;
1308
1309         ccd = musycc_chan_proto (ch->p.chan_mode) << MUSYCC_CCD_PROTO_SHIFT;
1310         if ((ch->p.chan_mode == CFG_CH_PROTO_ISLP_MODE) ||
1311             (ch->p.chan_mode == CFG_CH_PROTO_TRANS))
1312         {
1313             ccd |= MUSYCC_CCD_FCS_XFER; /* Non FSC Mode */
1314         }
1315         ccd |= 2 << MUSYCC_CCD_MAX_LENGTH;      /* Select second MTU */
1316         ccd |= ch->p.intr_mask;
1317         ccd |= addr << MUSYCC_CCD_BUFFER_LOC;
1318         if (ch->p.chan_mode == CFG_CH_PROTO_TRANS)
1319             ccd |= (nbuf) << MUSYCC_CCD_BUFFER_LENGTH;
1320         else
1321             ccd |= (nbuf - 1) << MUSYCC_CCD_BUFFER_LENGTH;
1322
1323         if (ch->p.data_inv & CFG_CH_DINV_TX)
1324             ccd |= MUSYCC_CCD_INVERT_DATA;      /* Invert data */
1325         pi->regram->tcct[gchan] = cpu_to_le32 (ccd);
1326
1327         if (ch->p.data_inv & CFG_CH_DINV_RX)
1328             ccd |= MUSYCC_CCD_INVERT_DATA;      /* Invert data */
1329         else
1330             ccd &= ~MUSYCC_CCD_INVERT_DATA;     /* take away data inversion */
1331         pi->regram->rcct[gchan] = cpu_to_le32 (ccd);
1332         FLUSH_MEM_WRITE ();
1333     }
1334
1335     /* Reread the Channel Configuration Descriptor for this channel */
1336     musycc_serv_req (pi, SR_CHANNEL_CONFIG | SR_RX_DIRECTION | gchan);
1337     musycc_serv_req (pi, SR_CHANNEL_CONFIG | SR_TX_DIRECTION | gchan);
1338
1339     /*
1340      * Figure out how many buffers we want.  If the customer has changed from
1341      * the defaults, then use the changed values.  Otherwise, use Transparent
1342      * mode's specific minimum default settings.
1343      */
1344     if (ch->p.chan_mode == CFG_CH_PROTO_TRANS)
1345     {
1346         if (max_rxdesc_used == max_rxdesc_default)      /* use default setting */
1347             max_rxdesc_used = MUSYCC_RXDESC_TRANS;
1348         if (max_txdesc_used == max_txdesc_default)      /* use default setting */
1349             max_txdesc_used = MUSYCC_TXDESC_TRANS;
1350     }
1351     /*
1352      * Increase counts when hyperchanneling, since this implies an increase
1353      * in throughput per channel
1354      */
1355     rxnum = max_rxdesc_used + (nts / 4);
1356     txnum = max_txdesc_used + (nts / 4);
1357
1358 #if 0
1359     /* DEBUG INFO */
1360     if (cxt1e1_log_level >= LOG_MONITOR)
1361         pr_info("%s: mode %x rxnum %d (rxused %d def %d) txnum %d (txused %d def %d)\n",
1362                 ci->devname, ch->p.chan_mode,
1363                 rxnum, max_rxdesc_used, max_rxdesc_default,
1364                 txnum, max_txdesc_used, max_txdesc_default);
1365 #endif
1366
1367     ch->rxd_num = rxnum;
1368     ch->txd_num = txnum;
1369     ch->rxix_irq_srv = 0;
1370
1371     ch->mdr = OS_kmalloc (sizeof (struct mdesc) * rxnum);
1372     ch->mdt = OS_kmalloc (sizeof (struct mdesc) * txnum);
1373     if (ch->p.chan_mode == CFG_CH_PROTO_TRANS)
1374                tmp = __constant_cpu_to_le32 (cxt1e1_max_mru | EOBIRQ_ENABLE);
1375     else
1376                tmp = __constant_cpu_to_le32 (cxt1e1_max_mru);
1377
1378     for (i = 0, md = ch->mdr; i < rxnum; i++, md++)
1379     {
1380         if (i == (rxnum - 1))
1381         {
1382             md->snext = &ch->mdr[0];/* wrapness */
1383         } else
1384         {
1385             md->snext = &ch->mdr[i + 1];
1386         }
1387         md->next = cpu_to_le32 (OS_vtophys (md->snext));
1388
1389         m = OS_mem_token_alloc(cxt1e1_max_mru);
1390         if (!m) {
1391                 if (cxt1e1_log_level >= LOG_MONITOR)
1392                         pr_info(
1393                         "%s: c4_chan_up[%d] - token alloc failure, size = %d.\n",
1394                         ci->devname, channum, cxt1e1_max_mru);
1395                 goto errfree;
1396         }
1397         md->mem_token = m;
1398         md->data = cpu_to_le32 (OS_vtophys (OS_mem_token_data (m)));
1399         md->status = tmp | MUSYCC_RX_OWNED;     /* MUSYCC owns RX descriptor **
1400                                                  * CODING NOTE:
1401                                                  * MUSYCC_RX_OWNED = 0 so no
1402                                                  * need to byteSwap */
1403     }
1404
1405     for (i = 0, md = ch->mdt; i < txnum; i++, md++)
1406     {
1407         md->status = HOST_TX_OWNED; /* Host owns TX descriptor ** CODING
1408                                      * NOTE: HOST_TX_OWNED = 0 so no need to
1409                                      * byteSwap */
1410         md->mem_token = NULL;
1411         md->data = 0;
1412         if (i == (txnum - 1))
1413         {
1414             md->snext = &ch->mdt[0];/* wrapness */
1415         } else
1416         {
1417             md->snext = &ch->mdt[i + 1];
1418         }
1419         md->next = cpu_to_le32 (OS_vtophys (md->snext));
1420     }
1421     ch->txd_irq_srv = ch->txd_usr_add = &ch->mdt[0];
1422     ch->txd_free = txnum;
1423     ch->tx_full = 0;
1424     ch->txd_required = 0;
1425
1426     /* Configure it into the chip */
1427     tmp = cpu_to_le32 (OS_vtophys (&ch->mdt[0]));
1428     pi->regram->thp[gchan] = tmp;
1429     pi->regram->tmp[gchan] = tmp;
1430
1431     tmp = cpu_to_le32 (OS_vtophys (&ch->mdr[0]));
1432     pi->regram->rhp[gchan] = tmp;
1433     pi->regram->rmp[gchan] = tmp;
1434
1435     /* Activate the Channel */
1436     FLUSH_MEM_WRITE ();
1437     if (ch->p.status & RX_ENABLED)
1438     {
1439 #ifdef RLD_TRANS_DEBUG
1440         pr_info("++ c4_chan_up() CHAN RX ACTIVATE: chan %d\n", ch->channum);
1441 #endif
1442         ch->ch_start_rx = 0;        /* we are restarting RX... */
1443         musycc_serv_req (pi, SR_CHANNEL_ACTIVATE | SR_RX_DIRECTION | gchan);
1444     }
1445     if (ch->p.status & TX_ENABLED)
1446     {
1447 #ifdef RLD_TRANS_DEBUG
1448         pr_info("++ c4_chan_up() CHAN TX ACTIVATE: chan %d <delayed>\n", ch->channum);
1449 #endif
1450         ch->ch_start_tx = CH_START_TX_1ST;      /* we are delaying start
1451                                                  * until receipt from user of
1452                                                  * first packet to transmit. */
1453     }
1454     ch->status = ch->p.status;
1455     pi->openchans++;
1456     return 0;
1457
1458 errfree:
1459     while (i > 0)
1460     {
1461         /* Don't leak all the previously allocated mbufs in this loop */
1462         i--;
1463         OS_mem_token_free (ch->mdr[i].mem_token);
1464     }
1465     OS_kfree (ch->mdt);
1466     ch->mdt = NULL;
1467     ch->txd_num = 0;
1468     OS_kfree (ch->mdr);
1469     ch->mdr = NULL;
1470     ch->rxd_num = 0;
1471     ch->state = DOWN;
1472     return -ENOBUFS;
1473 }
1474
1475 /* stop the hardware from servicing & interrupting */
1476
1477 void
1478 c4_stopwd (ci_t *ci)
1479 {
1480     OS_stop_watchdog (&ci->wd);
1481     SD_SEM_TAKE (&ci->sem_wdbusy, "_stop_");    /* ensure WD not running */
1482     SD_SEM_GIVE (&ci->sem_wdbusy);
1483 }
1484
1485
1486 void
1487 sbecom_get_brdinfo (ci_t *ci, struct sbe_brd_info *bip, u_int8_t *bsn)
1488 {
1489     char       *np;
1490     u_int32_t   sn = 0;
1491     int         i;
1492
1493     bip->brdno = ci->brdno;         /* our board number */
1494     bip->brd_id = ci->brd_id;
1495     bip->brd_hdw_id = ci->hdw_bid;
1496     bip->brd_chan_cnt = MUSYCC_NCHANS *ci->max_port;   /* number of channels
1497                                                          * being used */
1498     bip->brd_port_cnt = ci->max_port;   /* number of ports being used */
1499     bip->brd_pci_speed = BINFO_PCI_SPEED_unk;   /* PCI speed not yet
1500                                                  * determinable */
1501
1502     if (ci->first_if)
1503     {
1504         {
1505             struct net_device *dev;
1506
1507             dev = (struct net_device *) ci->first_if;
1508             np = (char *) dev->name;
1509         }
1510         strncpy (bip->first_iname, np, CHNM_STRLEN - 1);
1511     } else
1512         strcpy (bip->first_iname, "<NULL>");
1513     if (ci->last_if)
1514     {
1515         {
1516             struct net_device *dev;
1517
1518             dev = (struct net_device *) ci->last_if;
1519             np = (char *) dev->name;
1520         }
1521         strncpy (bip->last_iname, np, CHNM_STRLEN - 1);
1522     } else
1523         strcpy (bip->last_iname, "<NULL>");
1524
1525     if (bsn)
1526     {
1527         for (i = 0; i < 3; i++)
1528         {
1529             bip->brd_mac_addr[i] = *bsn++;
1530         }
1531         for (; i < 6; i++)
1532         {
1533             bip->brd_mac_addr[i] = *bsn;
1534             sn = (sn << 8) | *bsn++;
1535         }
1536     } else
1537     {
1538         for (i = 0; i < 6; i++)
1539             bip->brd_mac_addr[i] = 0;
1540     }
1541     bip->brd_sn = sn;
1542 }
1543
1544
1545 status_t
1546 c4_get_iidinfo (ci_t *ci, struct sbe_iid_info *iip)
1547 {
1548     struct net_device *dev;
1549     char       *np;
1550
1551         dev = getuserbychan(iip->channum);
1552         if (!dev)
1553                 return -ENOENT;
1554
1555     np = dev->name;
1556     strncpy (iip->iname, np, CHNM_STRLEN - 1);
1557     iip->iname[CHNM_STRLEN - 1] = '\0';
1558     return 0;
1559 }
1560
1561
1562 #ifdef CONFIG_SBE_PMCC4_NCOMM
1563 void        (*nciInterrupt[MAX_BOARDS][4]) (void);
1564 extern void wanpmcC4T1E1_hookInterrupt (int cardID, int deviceID, void *handler);
1565
1566 void
1567 wanpmcC4T1E1_hookInterrupt (int cardID, int deviceID, void *handler)
1568 {
1569     if (cardID < MAX_BOARDS)    /* sanity check */
1570         nciInterrupt[cardID][deviceID] = handler;
1571 }
1572
1573 irqreturn_t
1574 c4_ebus_intr_th_handler (void *devp)
1575 {
1576     ci_t       *ci = (ci_t *) devp;
1577     volatile u_int32_t ists;
1578     int         handled = 0;
1579     int         brdno;
1580
1581     /* which COMET caused the interrupt */
1582     brdno = ci->brdno;
1583     ists = pci_read_32 ((u_int32_t *) &ci->cpldbase->intr);
1584     if (ists & PMCC4_CPLD_INTR_CMT_1)
1585     {
1586         handled = 0x1;
1587         if (nciInterrupt[brdno][0] != NULL)
1588             (*nciInterrupt[brdno][0]) ();
1589     }
1590     if (ists & PMCC4_CPLD_INTR_CMT_2)
1591     {
1592         handled |= 0x2;
1593         if (nciInterrupt[brdno][1] != NULL)
1594             (*nciInterrupt[brdno][1]) ();
1595     }
1596     if (ists & PMCC4_CPLD_INTR_CMT_3)
1597     {
1598         handled |= 0x4;
1599         if (nciInterrupt[brdno][2] != NULL)
1600             (*nciInterrupt[brdno][2]) ();
1601     }
1602     if (ists & PMCC4_CPLD_INTR_CMT_4)
1603     {
1604         handled |= 0x8;
1605         if (nciInterrupt[brdno][3] != NULL)
1606             (*nciInterrupt[brdno][3]) ();
1607     }
1608 #if 0
1609     /*** Test code just de-implements the asserted interrupt.  Alternate
1610     vendor will supply COMET interrupt handling code herein or such.
1611     ***/
1612     pci_write_32 ((u_int32_t *) &ci->reg->glcd, GCD_MAGIC | MUSYCC_GCD_INTB_DISABLE);
1613 #endif
1614
1615     return IRQ_RETVAL (handled);
1616 }
1617
1618
1619 unsigned long
1620 wanpmcC4T1E1_getBaseAddress (int cardID, int deviceID)
1621 {
1622     ci_t       *ci;
1623     unsigned long base = 0;
1624
1625     ci = c4_list;
1626     while (ci)
1627     {
1628         if (ci->brdno == cardID)    /* found valid device */
1629         {
1630             if (deviceID < ci->max_port)        /* comet is supported */
1631                 base = ((unsigned long) ci->port[deviceID].cometbase);
1632             break;
1633         }
1634         ci = ci->next;              /* next board, if any */
1635     }
1636     return base;
1637 }
1638
1639 #endif                          /*** CONFIG_SBE_PMCC4_NCOMM ***/
1640
1641
1642 /***  End-of-File  ***/