]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/cxt1e1/pmcc4_drv.c
Merge remote-tracking branch 'asoc/fix/core' into asoc-linus
[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 = 0;
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                 if ((ch = ci->port[portnum].chan[gchan]))
116                 {
117                     if ((ch->state != UNASSIGNED) &&
118                         (ch->channum == channum))
119                         return ch;
120                 }
121             }
122     return 0;
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 == 0)
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     comet_t    *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     comet_t    *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 = (comet_t *) ((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     if ((ret = musycc_init (ci)) != SBE_DRVR_SUCCESS)
672         return ret;
673
674 #if 0
675     ci->p.framing_type = FRAMING_CBP;
676     ci->p.h110enable = 1;
677 #if 0
678     ci->p.hypersize = 0;
679 #else
680     hyperdummy = 0;
681 #endif
682     ci->p.clock = 0;                /* Use internal clocking until set to
683                                      * external */
684     c4_card_set_params (ci, &ci->p);
685 #endif
686     OS_start_watchdog (&ci->wd);
687     return SBE_DRVR_SUCCESS;
688 }
689
690
691 /* This function sets the loopback mode (or clears it, as the case may be). */
692
693 int
694 c4_loop_port (ci_t *ci, int portnum, u_int8_t cmd)
695 {
696     comet_t    *comet;
697     volatile u_int32_t loopValue;
698
699     comet = ci->port[portnum].cometbase;
700     loopValue = pci_read_32 ((u_int32_t *) &comet->mdiag) & COMET_MDIAG_LBMASK;
701
702     if (cmd & COMET_LBCMD_READ)
703         return loopValue;           /* return the read value */
704
705     if (loopValue != cmd)
706     {
707         switch (cmd)
708         {
709         case COMET_MDIAG_LINELB:
710             /* set(SF)loopback down (turn off) code length to 6 bits */
711             pci_write_32 ((u_int32_t *) &comet->ibcd_cfg, 0x05);
712             break;
713         case COMET_MDIAG_LBOFF:
714             /* set (SF) loopback up (turn on) code length to 5 bits */
715             pci_write_32 ((u_int32_t *) &comet->ibcd_cfg, 0x00);
716             break;
717         }
718
719         pci_write_32 ((u_int32_t *) &comet->mdiag, cmd);
720         if (cxt1e1_log_level >= LOG_WARN)
721             pr_info("%s: loopback mode changed to %2x from %2x on Port %d\n",
722                     ci->devname, cmd, loopValue, portnum);
723         loopValue = pci_read_32 ((u_int32_t *) &comet->mdiag) & COMET_MDIAG_LBMASK;
724         if (loopValue != cmd)
725         {
726             if (cxt1e1_log_level >= LOG_ERROR)
727                 pr_info("%s: write to loop register failed, unknown state for Port %d\n",
728                         ci->devname, portnum);
729         }
730     } else
731     {
732         if (cxt1e1_log_level >= LOG_WARN)
733             pr_info("%s: loopback already in that mode (%2x)\n",
734                     ci->devname, loopValue);
735     }
736     return 0;
737 }
738
739
740 /* c4_frame_rw: read or write the comet register specified
741  * (modifies use of port_param to non-standard use of struct)
742  * Specifically:
743  *   pp.portnum     (one guess)
744  *   pp.port_mode   offset of register
745  *   pp.portP       write (or not, i.e. read)
746  *   pp.portStatus  write value
747  * BTW:
748  *   pp.portStatus  also used to return read value
749  *   pp.portP       also used during write, to return old reg value
750  */
751
752 status_t
753 c4_frame_rw (ci_t *ci, struct sbecom_port_param *pp)
754 {
755     comet_t    *comet;
756     volatile u_int32_t data;
757
758     if (pp->portnum >= ci->max_port)/* sanity check */
759         return ENXIO;
760
761     comet = ci->port[pp->portnum].cometbase;
762     data = pci_read_32 ((u_int32_t *) comet + pp->port_mode) & 0xff;
763
764     if (pp->portP)
765     {                               /* control says this is a register
766                                      * _write_ */
767         if (pp->portStatus == data)
768             pr_info("%s: Port %d already that value!  Writing again anyhow.\n",
769                     ci->devname, pp->portnum);
770         pp->portP = (u_int8_t) data;
771         pci_write_32 ((u_int32_t *) comet + pp->port_mode,
772                       pp->portStatus);
773         data = pci_read_32 ((u_int32_t *) comet + pp->port_mode) & 0xff;
774     }
775     pp->portStatus = (u_int8_t) data;
776     return 0;
777 }
778
779
780 /* c4_pld_rw: read or write the pld register specified
781  * (modifies use of port_param to non-standard use of struct)
782  * Specifically:
783  *   pp.port_mode   offset of register
784  *   pp.portP       write (or not, i.e. read)
785  *   pp.portStatus  write value
786  * BTW:
787  *   pp.portStatus  also used to return read value
788  *   pp.portP       also used during write, to return old reg value
789  */
790
791 status_t
792 c4_pld_rw (ci_t *ci, struct sbecom_port_param *pp)
793 {
794     volatile u_int32_t *regaddr;
795     volatile u_int32_t data;
796     int         regnum = pp->port_mode;
797
798     regaddr = (u_int32_t *) ci->cpldbase + regnum;
799     data = pci_read_32 ((u_int32_t *) regaddr) & 0xff;
800
801     if (pp->portP)
802     {                               /* control says this is a register
803                                      * _write_ */
804         pp->portP = (u_int8_t) data;
805         pci_write_32 ((u_int32_t *) regaddr, pp->portStatus);
806         data = pci_read_32 ((u_int32_t *) regaddr) & 0xff;
807     }
808     pp->portStatus = (u_int8_t) data;
809     return 0;
810 }
811
812 /* c4_musycc_rw: read or write the musycc register specified
813  * (modifies use of port_param to non-standard use of struct)
814  * Specifically:
815  *    mcp.RWportnum   port number and write indication bit (0x80)
816  *    mcp.offset      offset of register
817  *    mcp.value       write value going in and read value returning
818  */
819
820 /* PORT POINT: TX Subchannel Map registers are write-only
821  * areas within the MUSYCC and always return FF */
822 /* PORT POINT: regram and reg structures are minorly different and <offset> ioctl
823  * settings are aligned with the <reg> struct musycc_globalr{} usage.
824  * Also, regram is separately allocated shared memory, allocated for each port.
825  * PORT POINT: access offsets of 0x6000 for Msg Cfg Desc Tbl are for 4-port MUSYCC
826  * only.  (An 8-port MUSYCC has 0x16000 offsets for accessing its upper 4 tables.)
827  */
828
829 status_t
830 c4_musycc_rw (ci_t *ci, struct c4_musycc_param *mcp)
831 {
832     mpi_t      *pi;
833     volatile u_int32_t *dph;    /* hardware implemented register */
834     u_int32_t  *dpr = 0;        /* RAM image of registers for group command
835                                  * usage */
836     int         offset = mcp->offset % 0x800;   /* group relative address
837                                                  * offset, mcp->portnum is
838                                                  * not used */
839     int         portnum, ramread = 0;
840     volatile u_int32_t data;
841
842     /*
843      * Sanity check hardware accessibility.  The 0x6000 portion handles port
844      * numbers associated with Msg Descr Tbl decoding.
845      */
846     portnum = (mcp->offset % 0x6000) / 0x800;
847     if (portnum >= ci->max_port)
848         return ENXIO;
849     pi = &ci->port[portnum];
850     if (mcp->offset >= 0x6000)
851         offset += 0x6000;           /* put back in MsgCfgDesc address offset */
852     dph = (u_int32_t *) ((u_long) pi->reg + offset);
853
854     /* read of TX are from RAM image, since hardware returns FF */
855     dpr = (u_int32_t *) ((u_long) pi->regram + offset);
856     if (mcp->offset < 0x6000)       /* non MsgDesc Tbl accesses might require
857                                      * RAM access */
858     {
859         if (offset >= 0x200 && offset < 0x380)
860             ramread = 1;
861         if (offset >= 0x10 && offset < 0x200)
862             ramread = 1;
863     }
864     /* read register from RAM or hardware, depending... */
865     if (ramread)
866     {
867         data = *dpr;
868         //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 */
869     } else
870     {
871         data = pci_read_32 ((u_int32_t *) dph);
872         //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 */
873     }
874
875
876     if (mcp->RWportnum & 0x80)
877     {                               /* control says this is a register
878                                      * _write_ */
879         if (mcp->value == data)
880             pr_info("%s: musycc grp%d already that value! writing again anyhow.\n",
881                     ci->devname, (mcp->RWportnum & 0x7));
882         /* write register RAM */
883         if (ramread)
884             *dpr = mcp->value;
885         /* write hardware register */
886         pci_write_32 ((u_int32_t *) dph, mcp->value);
887     }
888     mcp->value = data;              /* return the read value (or the 'old
889                                      * value', if is write) */
890     return 0;
891 }
892
893 status_t
894 c4_get_port (ci_t *ci, int portnum)
895 {
896     if (portnum >= ci->max_port)    /* sanity check */
897         return ENXIO;
898
899     SD_SEM_TAKE (&ci->sem_wdbusy, "_wd_");      /* only 1 thru here, per
900                                                  * board */
901     checkPorts (ci);
902     ci->port[portnum].p.portStatus = (u_int8_t) ci->alarmed[portnum];
903     ci->alarmed[portnum] &= 0xdf;
904     SD_SEM_GIVE (&ci->sem_wdbusy);  /* release per-board hold */
905     return 0;
906 }
907
908 status_t
909 c4_set_port (ci_t *ci, int portnum)
910 {
911     mpi_t      *pi;
912     struct sbecom_port_param *pp;
913     int         e1mode;
914     u_int8_t    clck;
915     int         i;
916
917     if (portnum >= ci->max_port)    /* sanity check */
918         return ENXIO;
919
920     pi = &ci->port[portnum];
921     pp = &ci->port[portnum].p;
922     e1mode = IS_FRAME_ANY_E1 (pp->port_mode);
923     if (cxt1e1_log_level >= LOG_MONITOR2)
924     {
925         pr_info("%s: c4_set_port[%d]:  entered, e1mode = %x, openchans %d.\n",
926                 ci->devname,
927                 portnum, e1mode, pi->openchans);
928     }
929     if (pi->openchans)
930         return EBUSY;               /* group needs initialization only for
931                                      * first channel of a group */
932
933     {
934         status_t    ret;
935
936         if ((ret = c4_wq_port_init (pi)))       /* create/init
937                                                  * workqueue_struct */
938             return ret;
939     }
940
941     init_comet (ci, pi->cometbase, pp->port_mode, 1 /* clockmaster == true */ , pp->portP);
942     clck = pci_read_32 ((u_int32_t *) &ci->cpldbase->mclk) & PMCC4_CPLD_MCLK_MASK;
943     if (e1mode)
944         clck |= 1 << portnum;
945     else
946         clck &= 0xf ^ (1 << portnum);
947
948     pci_write_32 ((u_int32_t *) &ci->cpldbase->mclk, clck);
949     pci_write_32 ((u_int32_t *) &ci->cpldbase->mcsr, PMCC4_CPLD_MCSR_IND);
950     pci_write_32 ((u_int32_t *) &pi->reg->gbp, OS_vtophys (pi->regram));
951
952     /*********************************************************************/
953     /* ERRATA: If transparent mode is used, do not set OOFMP_DISABLE bit */
954     /*********************************************************************/
955
956     pi->regram->grcd =
957         __constant_cpu_to_le32 (MUSYCC_GRCD_RX_ENABLE |
958                                 MUSYCC_GRCD_TX_ENABLE |
959                                 MUSYCC_GRCD_OOFMP_DISABLE |
960                                 MUSYCC_GRCD_SF_ALIGN |  /* per MUSYCC ERRATA,
961                                                          * for T1 * fix */
962                                 MUSYCC_GRCD_COFAIRQ_DISABLE |
963                                 MUSYCC_GRCD_MC_ENABLE |
964                        (MUSYCC_GRCD_POLLTH_32 << MUSYCC_GRCD_POLLTH_SHIFT));
965
966     pi->regram->pcd =
967         __constant_cpu_to_le32 ((e1mode ? 1 : 0) |
968                                 MUSYCC_PCD_TXSYNC_RISING |
969                                 MUSYCC_PCD_RXSYNC_RISING |
970                                 MUSYCC_PCD_RXDATA_RISING);
971
972     /* Message length descriptor */
973        pi->regram->mld = __constant_cpu_to_le32 (cxt1e1_max_mru | (cxt1e1_max_mru << 16));
974
975     /* tsm algorithm */
976     for (i = 0; i < 32; i++)
977     {
978
979         /*** ASSIGNMENT NOTES:                             ***/
980         /*** Group's channel  ZERO  unavailable if E1.     ***/
981         /*** Group's channel  16    unavailable if E1 CAS. ***/
982         /*** Group's channels 24-31 unavailable if T1.     ***/
983
984         if (((i == 0) && e1mode) ||
985             ((i == 16) && ((pp->port_mode == CFG_FRAME_E1CRC_CAS) || (pp->port_mode == CFG_FRAME_E1CRC_CAS_AMI)))
986             || ((i > 23) && (!e1mode)))
987         {
988             pi->tsm[i] = 0xff;      /* make tslot unavailable for this mode */
989         } else
990         {
991             pi->tsm[i] = 0x00;      /* make tslot available for assignment */
992         }
993     }
994     for (i = 0; i < MUSYCC_NCHANS; i++)
995     {
996         pi->regram->ttsm[i] = 0;
997         pi->regram->rtsm[i] = 0;
998     }
999     FLUSH_MEM_WRITE ();
1000     musycc_serv_req (pi, SR_GROUP_INIT | SR_RX_DIRECTION);
1001     musycc_serv_req (pi, SR_GROUP_INIT | SR_TX_DIRECTION);
1002
1003     musycc_init_mdt (pi);
1004
1005     pi->group_is_set = 1;
1006     pi->p = *pp;
1007     return 0;
1008 }
1009
1010
1011 unsigned int max_int = 0;
1012
1013 status_t
1014 c4_new_chan (ci_t *ci, int portnum, int channum, void *user)
1015 {
1016     mpi_t      *pi;
1017     mch_t      *ch;
1018     int         gchan;
1019
1020     if (c4_find_chan (channum))     /* a new channel shouldn't already exist */
1021         return EEXIST;
1022
1023     if (portnum >= ci->max_port)    /* sanity check */
1024         return ENXIO;
1025
1026     pi = &(ci->port[portnum]);
1027     /* find any available channel within this port */
1028     for (gchan = 0; gchan < MUSYCC_NCHANS; gchan++)
1029     {
1030         ch = pi->chan[gchan];
1031         if (ch && ch->state == UNASSIGNED)      /* no assignment is good! */
1032             break;
1033     }
1034     if (gchan == MUSYCC_NCHANS)     /* exhausted table, all were assigned */
1035         return ENFILE;
1036
1037     ch->up = pi;
1038
1039     /* NOTE: mch_t already cleared during OS_kmalloc() */
1040     ch->state = DOWN;
1041     ch->user = user;
1042     ch->gchan = gchan;
1043     ch->channum = channum;          /* mark our channel assignment */
1044     ch->p.channum = channum;
1045 #if 1
1046     ch->p.card = ci->brdno;
1047     ch->p.port = portnum;
1048 #endif
1049     ch->p.chan_mode = CFG_CH_PROTO_HDLC_FCS16;
1050     ch->p.idlecode = CFG_CH_FLAG_7E;
1051     ch->p.pad_fill_count = 2;
1052     spin_lock_init (&ch->ch_rxlock);
1053     spin_lock_init (&ch->ch_txlock);
1054
1055     {
1056         status_t    ret;
1057
1058         if ((ret = c4_wk_chan_init (pi, ch)))
1059             return ret;
1060     }
1061
1062     /* save off interface assignments which bound a board */
1063     if (ci->first_if == 0)          /* first channel registered is assumed to
1064                                      * be the lowest channel */
1065     {
1066         ci->first_if = ci->last_if = user;
1067         ci->first_channum = ci->last_channum = channum;
1068     } else
1069     {
1070         ci->last_if = user;
1071         if (ci->last_channum < channum) /* higher number channel found */
1072             ci->last_channum = channum;
1073     }
1074     return 0;
1075 }
1076
1077 status_t
1078 c4_del_chan (int channum)
1079 {
1080     mch_t      *ch;
1081
1082     if (!(ch = c4_find_chan (channum)))
1083         return ENOENT;
1084     if (ch->state == UP)
1085         musycc_chan_down ((ci_t *) 0, channum);
1086     ch->state = UNASSIGNED;
1087     ch->gchan = (-1);
1088     ch->channum = (-1);
1089     ch->p.channum = (-1);
1090     return 0;
1091 }
1092
1093 status_t
1094 c4_del_chan_stats (int channum)
1095 {
1096     mch_t      *ch;
1097
1098     if (!(ch = c4_find_chan (channum)))
1099         return ENOENT;
1100
1101     memset (&ch->s, 0, sizeof (struct sbecom_chan_stats));
1102     return 0;
1103 }
1104
1105
1106 status_t
1107 c4_set_chan (int channum, struct sbecom_chan_param *p)
1108 {
1109     mch_t      *ch;
1110     int         i, x = 0;
1111
1112     if (!(ch = c4_find_chan (channum)))
1113         return ENOENT;
1114
1115 #if 1
1116     if (ch->p.card != p->card ||
1117         ch->p.port != p->port ||
1118         ch->p.channum != p->channum)
1119         return EINVAL;
1120 #endif
1121
1122     if (!(ch->up->group_is_set))
1123     {
1124         return EIO;                 /* out of order, SET_PORT command
1125                                      * required prior to first group's
1126                                      * SET_CHAN command */
1127     }
1128     /*
1129      * Check for change of parameter settings in order to invoke closing of
1130      * channel prior to hardware poking.
1131      */
1132
1133     if (ch->p.status != p->status || ch->p.chan_mode != p->chan_mode ||
1134         ch->p.data_inv != p->data_inv || ch->p.intr_mask != p->intr_mask ||
1135         ch->txd_free < ch->txd_num) /* to clear out queued messages */
1136         x = 1;                      /* we have a change requested */
1137     for (i = 0; i < 32; i++)        /* check for timeslot mapping changes */
1138         if (ch->p.bitmask[i] != p->bitmask[i])
1139             x = 1;                  /* we have a change requested */
1140     ch->p = *p;
1141     if (x && (ch->state == UP))     /* if change request and channel is
1142                                      * open... */
1143     {
1144         status_t    ret;
1145
1146         if ((ret = musycc_chan_down ((ci_t *) 0, channum)))
1147             return ret;
1148         if ((ret = c4_chan_up (ch->up->up, channum)))
1149             return ret;
1150         sd_enable_xmit (ch->user);  /* re-enable to catch flow controlled
1151                                      * channel */
1152     }
1153     return 0;
1154 }
1155
1156
1157 status_t
1158 c4_get_chan (int channum, struct sbecom_chan_param *p)
1159 {
1160     mch_t      *ch;
1161
1162     if (!(ch = c4_find_chan (channum)))
1163         return ENOENT;
1164     *p = ch->p;
1165     return 0;
1166 }
1167
1168 status_t
1169 c4_get_chan_stats (int channum, struct sbecom_chan_stats *p)
1170 {
1171     mch_t      *ch;
1172
1173     if (!(ch = c4_find_chan (channum)))
1174         return ENOENT;
1175     *p = ch->s;
1176     p->tx_pending = atomic_read (&ch->tx_pending);
1177     return 0;
1178 }
1179
1180 static int
1181 c4_fifo_alloc (mpi_t *pi, int chan, int *len)
1182 {
1183     int         i, l = 0, start = 0, max = 0, maxstart = 0;
1184
1185     for (i = 0; i < 32; i++)
1186     {
1187         if (pi->fifomap[i] != -1)
1188         {
1189             l = 0;
1190             start = i + 1;
1191             continue;
1192         }
1193         ++l;
1194         if (l > max)
1195         {
1196             max = l;
1197             maxstart = start;
1198         }
1199         if (max == *len)
1200             break;
1201     }
1202     if (max != *len)
1203     {
1204         if (cxt1e1_log_level >= LOG_WARN)
1205             pr_info("%s: wanted to allocate %d fifo space, but got only %d\n",
1206                     pi->up->devname, *len, max);
1207         *len = max;
1208     }
1209     if (cxt1e1_log_level >= LOG_DEBUG)
1210         pr_info("%s: allocated %d fifo at %d for channel %d/%d\n",
1211                 pi->up->devname, max, start, chan, pi->p.portnum);
1212     for (i = maxstart; i < (maxstart + max); i++)
1213         pi->fifomap[i] = chan;
1214     return start;
1215 }
1216
1217 void
1218 c4_fifo_free (mpi_t *pi, int chan)
1219 {
1220     int         i;
1221
1222     if (cxt1e1_log_level >= LOG_DEBUG)
1223         pr_info("%s: deallocated fifo for channel %d/%d\n",
1224                 pi->up->devname, chan, pi->p.portnum);
1225     for (i = 0; i < 32; i++)
1226         if (pi->fifomap[i] == chan)
1227             pi->fifomap[i] = -1;
1228 }
1229
1230
1231 status_t
1232 c4_chan_up (ci_t *ci, int channum)
1233 {
1234     mpi_t      *pi;
1235     mch_t      *ch;
1236     struct mbuf *m;
1237     struct mdesc *md;
1238     int         nts, nbuf, txnum, rxnum;
1239     int         addr, i, j, gchan;
1240     u_int32_t   tmp;            /* for optimizing conversion across BE
1241                                  * platform */
1242
1243     if (!(ch = c4_find_chan (channum)))
1244         return ENOENT;
1245     if (ch->state == UP)
1246     {
1247         if (cxt1e1_log_level >= LOG_MONITOR)
1248             pr_info("%s: channel already UP, graceful early exit\n",
1249                     ci->devname);
1250         return 0;
1251     }
1252     pi = ch->up;
1253     gchan = ch->gchan;
1254     /* find nts ('number of timeslots') */
1255     nts = 0;
1256     for (i = 0; i < 32; i++)
1257     {
1258         if (ch->p.bitmask[i] & pi->tsm[i])
1259         {
1260             if (1 || cxt1e1_log_level >= LOG_WARN)
1261             {
1262                 pr_info("%s: c4_chan_up[%d] EINVAL (attempt to cfg in-use or unavailable TimeSlot[%d])\n",
1263                         ci->devname, channum, i);
1264                 pr_info("+ ask4 %x, currently %x\n",
1265                         ch->p.bitmask[i], pi->tsm[i]);
1266             }
1267             return EINVAL;
1268         }
1269         for (j = 0; j < 8; j++)
1270             if (ch->p.bitmask[i] & (1 << j))
1271                 nts++;
1272     }
1273
1274     nbuf = nts / 8 ? nts / 8 : 1;
1275     if (!nbuf)
1276     {
1277         /* if( cxt1e1_log_level >= LOG_WARN)  */
1278         pr_info("%s: c4_chan_up[%d] ENOBUFS (no TimeSlots assigned)\n",
1279                 ci->devname, channum);
1280         return ENOBUFS;             /* this should not happen */
1281     }
1282     addr = c4_fifo_alloc (pi, gchan, &nbuf);
1283     ch->state = UP;
1284
1285     /* Setup the Time Slot Map */
1286     musycc_update_timeslots (pi);
1287
1288     /* ch->tx_limit = nts; */
1289     ch->s.tx_pending = 0;
1290
1291     /* Set Channel Configuration Descriptors */
1292     {
1293         u_int32_t   ccd;
1294
1295         ccd = musycc_chan_proto (ch->p.chan_mode) << MUSYCC_CCD_PROTO_SHIFT;
1296         if ((ch->p.chan_mode == CFG_CH_PROTO_ISLP_MODE) ||
1297             (ch->p.chan_mode == CFG_CH_PROTO_TRANS))
1298         {
1299             ccd |= MUSYCC_CCD_FCS_XFER; /* Non FSC Mode */
1300         }
1301         ccd |= 2 << MUSYCC_CCD_MAX_LENGTH;      /* Select second MTU */
1302         ccd |= ch->p.intr_mask;
1303         ccd |= addr << MUSYCC_CCD_BUFFER_LOC;
1304         if (ch->p.chan_mode == CFG_CH_PROTO_TRANS)
1305             ccd |= (nbuf) << MUSYCC_CCD_BUFFER_LENGTH;
1306         else
1307             ccd |= (nbuf - 1) << MUSYCC_CCD_BUFFER_LENGTH;
1308
1309         if (ch->p.data_inv & CFG_CH_DINV_TX)
1310             ccd |= MUSYCC_CCD_INVERT_DATA;      /* Invert data */
1311         pi->regram->tcct[gchan] = cpu_to_le32 (ccd);
1312
1313         if (ch->p.data_inv & CFG_CH_DINV_RX)
1314             ccd |= MUSYCC_CCD_INVERT_DATA;      /* Invert data */
1315         else
1316             ccd &= ~MUSYCC_CCD_INVERT_DATA;     /* take away data inversion */
1317         pi->regram->rcct[gchan] = cpu_to_le32 (ccd);
1318         FLUSH_MEM_WRITE ();
1319     }
1320
1321     /* Reread the Channel Configuration Descriptor for this channel */
1322     musycc_serv_req (pi, SR_CHANNEL_CONFIG | SR_RX_DIRECTION | gchan);
1323     musycc_serv_req (pi, SR_CHANNEL_CONFIG | SR_TX_DIRECTION | gchan);
1324
1325     /*
1326      * Figure out how many buffers we want.  If the customer has changed from
1327      * the defaults, then use the changed values.  Otherwise, use Transparent
1328      * mode's specific minimum default settings.
1329      */
1330     if (ch->p.chan_mode == CFG_CH_PROTO_TRANS)
1331     {
1332         if (max_rxdesc_used == max_rxdesc_default)      /* use default setting */
1333             max_rxdesc_used = MUSYCC_RXDESC_TRANS;
1334         if (max_txdesc_used == max_txdesc_default)      /* use default setting */
1335             max_txdesc_used = MUSYCC_TXDESC_TRANS;
1336     }
1337     /*
1338      * Increase counts when hyperchanneling, since this implies an increase
1339      * in throughput per channel
1340      */
1341     rxnum = max_rxdesc_used + (nts / 4);
1342     txnum = max_txdesc_used + (nts / 4);
1343
1344 #if 0
1345     /* DEBUG INFO */
1346     if (cxt1e1_log_level >= LOG_MONITOR)
1347         pr_info("%s: mode %x rxnum %d (rxused %d def %d) txnum %d (txused %d def %d)\n",
1348                 ci->devname, ch->p.chan_mode,
1349                 rxnum, max_rxdesc_used, max_rxdesc_default,
1350                 txnum, max_txdesc_used, max_txdesc_default);
1351 #endif
1352
1353     ch->rxd_num = rxnum;
1354     ch->txd_num = txnum;
1355     ch->rxix_irq_srv = 0;
1356
1357     ch->mdr = OS_kmalloc (sizeof (struct mdesc) * rxnum);
1358     ch->mdt = OS_kmalloc (sizeof (struct mdesc) * txnum);
1359     if (ch->p.chan_mode == CFG_CH_PROTO_TRANS)
1360                tmp = __constant_cpu_to_le32 (cxt1e1_max_mru | EOBIRQ_ENABLE);
1361     else
1362                tmp = __constant_cpu_to_le32 (cxt1e1_max_mru);
1363
1364     for (i = 0, md = ch->mdr; i < rxnum; i++, md++)
1365     {
1366         if (i == (rxnum - 1))
1367         {
1368             md->snext = &ch->mdr[0];/* wrapness */
1369         } else
1370         {
1371             md->snext = &ch->mdr[i + 1];
1372         }
1373         md->next = cpu_to_le32 (OS_vtophys (md->snext));
1374
1375                if (!(m = OS_mem_token_alloc (cxt1e1_max_mru)))
1376         {
1377             if (cxt1e1_log_level >= LOG_MONITOR)
1378                 pr_info("%s: c4_chan_up[%d] - token alloc failure, size = %d.\n",
1379                                                ci->devname, channum, cxt1e1_max_mru);
1380             goto errfree;
1381         }
1382         md->mem_token = m;
1383         md->data = cpu_to_le32 (OS_vtophys (OS_mem_token_data (m)));
1384         md->status = tmp | MUSYCC_RX_OWNED;     /* MUSYCC owns RX descriptor **
1385                                                  * CODING NOTE:
1386                                                  * MUSYCC_RX_OWNED = 0 so no
1387                                                  * need to byteSwap */
1388     }
1389
1390     for (i = 0, md = ch->mdt; i < txnum; i++, md++)
1391     {
1392         md->status = HOST_TX_OWNED; /* Host owns TX descriptor ** CODING
1393                                      * NOTE: HOST_TX_OWNED = 0 so no need to
1394                                      * byteSwap */
1395         md->mem_token = 0;
1396         md->data = 0;
1397         if (i == (txnum - 1))
1398         {
1399             md->snext = &ch->mdt[0];/* wrapness */
1400         } else
1401         {
1402             md->snext = &ch->mdt[i + 1];
1403         }
1404         md->next = cpu_to_le32 (OS_vtophys (md->snext));
1405     }
1406     ch->txd_irq_srv = ch->txd_usr_add = &ch->mdt[0];
1407     ch->txd_free = txnum;
1408     ch->tx_full = 0;
1409     ch->txd_required = 0;
1410
1411     /* Configure it into the chip */
1412     tmp = cpu_to_le32 (OS_vtophys (&ch->mdt[0]));
1413     pi->regram->thp[gchan] = tmp;
1414     pi->regram->tmp[gchan] = tmp;
1415
1416     tmp = cpu_to_le32 (OS_vtophys (&ch->mdr[0]));
1417     pi->regram->rhp[gchan] = tmp;
1418     pi->regram->rmp[gchan] = tmp;
1419
1420     /* Activate the Channel */
1421     FLUSH_MEM_WRITE ();
1422     if (ch->p.status & RX_ENABLED)
1423     {
1424 #ifdef RLD_TRANS_DEBUG
1425         pr_info("++ c4_chan_up() CHAN RX ACTIVATE: chan %d\n", ch->channum);
1426 #endif
1427         ch->ch_start_rx = 0;        /* we are restarting RX... */
1428         musycc_serv_req (pi, SR_CHANNEL_ACTIVATE | SR_RX_DIRECTION | gchan);
1429     }
1430     if (ch->p.status & TX_ENABLED)
1431     {
1432 #ifdef RLD_TRANS_DEBUG
1433         pr_info("++ c4_chan_up() CHAN TX ACTIVATE: chan %d <delayed>\n", ch->channum);
1434 #endif
1435         ch->ch_start_tx = CH_START_TX_1ST;      /* we are delaying start
1436                                                  * until receipt from user of
1437                                                  * first packet to transmit. */
1438     }
1439     ch->status = ch->p.status;
1440     pi->openchans++;
1441     return 0;
1442
1443 errfree:
1444     while (i > 0)
1445     {
1446         /* Don't leak all the previously allocated mbufs in this loop */
1447         i--;
1448         OS_mem_token_free (ch->mdr[i].mem_token);
1449     }
1450     OS_kfree (ch->mdt);
1451     ch->mdt = 0;
1452     ch->txd_num = 0;
1453     OS_kfree (ch->mdr);
1454     ch->mdr = 0;
1455     ch->rxd_num = 0;
1456     ch->state = DOWN;
1457     return ENOBUFS;
1458 }
1459
1460 /* stop the hardware from servicing & interrupting */
1461
1462 void
1463 c4_stopwd (ci_t *ci)
1464 {
1465     OS_stop_watchdog (&ci->wd);
1466     SD_SEM_TAKE (&ci->sem_wdbusy, "_stop_");    /* ensure WD not running */
1467     SD_SEM_GIVE (&ci->sem_wdbusy);
1468 }
1469
1470
1471 void
1472 sbecom_get_brdinfo (ci_t *ci, struct sbe_brd_info *bip, u_int8_t *bsn)
1473 {
1474     char       *np;
1475     u_int32_t   sn = 0;
1476     int         i;
1477
1478     bip->brdno = ci->brdno;         /* our board number */
1479     bip->brd_id = ci->brd_id;
1480     bip->brd_hdw_id = ci->hdw_bid;
1481     bip->brd_chan_cnt = MUSYCC_NCHANS *ci->max_port;   /* number of channels
1482                                                          * being used */
1483     bip->brd_port_cnt = ci->max_port;   /* number of ports being used */
1484     bip->brd_pci_speed = BINFO_PCI_SPEED_unk;   /* PCI speed not yet
1485                                                  * determinable */
1486
1487     if (ci->first_if)
1488     {
1489         {
1490             struct net_device *dev;
1491
1492             dev = (struct net_device *) ci->first_if;
1493             np = (char *) dev->name;
1494         }
1495         strncpy (bip->first_iname, np, CHNM_STRLEN - 1);
1496     } else
1497         strcpy (bip->first_iname, "<NULL>");
1498     if (ci->last_if)
1499     {
1500         {
1501             struct net_device *dev;
1502
1503             dev = (struct net_device *) ci->last_if;
1504             np = (char *) dev->name;
1505         }
1506         strncpy (bip->last_iname, np, CHNM_STRLEN - 1);
1507     } else
1508         strcpy (bip->last_iname, "<NULL>");
1509
1510     if (bsn)
1511     {
1512         for (i = 0; i < 3; i++)
1513         {
1514             bip->brd_mac_addr[i] = *bsn++;
1515         }
1516         for (; i < 6; i++)
1517         {
1518             bip->brd_mac_addr[i] = *bsn;
1519             sn = (sn << 8) | *bsn++;
1520         }
1521     } else
1522     {
1523         for (i = 0; i < 6; i++)
1524             bip->brd_mac_addr[i] = 0;
1525     }
1526     bip->brd_sn = sn;
1527 }
1528
1529
1530 status_t
1531 c4_get_iidinfo (ci_t *ci, struct sbe_iid_info *iip)
1532 {
1533     struct net_device *dev;
1534     char       *np;
1535
1536     if (!(dev = getuserbychan (iip->channum)))
1537         return ENOENT;
1538
1539     np = dev->name;
1540     strncpy (iip->iname, np, CHNM_STRLEN - 1);
1541     iip->iname[CHNM_STRLEN - 1] = '\0';
1542     return 0;
1543 }
1544
1545
1546 #ifdef CONFIG_SBE_PMCC4_NCOMM
1547 void        (*nciInterrupt[MAX_BOARDS][4]) (void);
1548 extern void wanpmcC4T1E1_hookInterrupt (int cardID, int deviceID, void *handler);
1549
1550 void
1551 wanpmcC4T1E1_hookInterrupt (int cardID, int deviceID, void *handler)
1552 {
1553     if (cardID < MAX_BOARDS)    /* sanity check */
1554         nciInterrupt[cardID][deviceID] = handler;
1555 }
1556
1557 irqreturn_t
1558 c4_ebus_intr_th_handler (void *devp)
1559 {
1560     ci_t       *ci = (ci_t *) devp;
1561     volatile u_int32_t ists;
1562     int         handled = 0;
1563     int         brdno;
1564
1565     /* which COMET caused the interrupt */
1566     brdno = ci->brdno;
1567     ists = pci_read_32 ((u_int32_t *) &ci->cpldbase->intr);
1568     if (ists & PMCC4_CPLD_INTR_CMT_1)
1569     {
1570         handled = 0x1;
1571         if (nciInterrupt[brdno][0] != NULL)
1572             (*nciInterrupt[brdno][0]) ();
1573     }
1574     if (ists & PMCC4_CPLD_INTR_CMT_2)
1575     {
1576         handled |= 0x2;
1577         if (nciInterrupt[brdno][1] != NULL)
1578             (*nciInterrupt[brdno][1]) ();
1579     }
1580     if (ists & PMCC4_CPLD_INTR_CMT_3)
1581     {
1582         handled |= 0x4;
1583         if (nciInterrupt[brdno][2] != NULL)
1584             (*nciInterrupt[brdno][2]) ();
1585     }
1586     if (ists & PMCC4_CPLD_INTR_CMT_4)
1587     {
1588         handled |= 0x8;
1589         if (nciInterrupt[brdno][3] != NULL)
1590             (*nciInterrupt[brdno][3]) ();
1591     }
1592 #if 0
1593     /*** Test code just de-implements the asserted interrupt.  Alternate
1594     vendor will supply COMET interrupt handling code herein or such.
1595     ***/
1596     pci_write_32 ((u_int32_t *) &ci->reg->glcd, GCD_MAGIC | MUSYCC_GCD_INTB_DISABLE);
1597 #endif
1598
1599     return IRQ_RETVAL (handled);
1600 }
1601
1602
1603 unsigned long
1604 wanpmcC4T1E1_getBaseAddress (int cardID, int deviceID)
1605 {
1606     ci_t       *ci;
1607     unsigned long base = 0;
1608
1609     ci = c4_list;
1610     while (ci)
1611     {
1612         if (ci->brdno == cardID)    /* found valid device */
1613         {
1614             if (deviceID < ci->max_port)        /* comet is supported */
1615                 base = ((unsigned long) ci->port[deviceID].cometbase);
1616             break;
1617         }
1618         ci = ci->next;              /* next board, if any */
1619     }
1620     return base;
1621 }
1622
1623 #endif                          /*** CONFIG_SBE_PMCC4_NCOMM ***/
1624
1625
1626 /***  End-of-File  ***/