xref: /dragonfly/sys/dev/misc/musycc/musycc.c (revision fb1dde20d596d2938b7c0e3b7c31acf4a7cb4d0a)
1 /*
2  * ----------------------------------------------------------------------------
3  * "THE BEER-WARE LICENSE" (Revision 42):
4  * <phk@FreeBSD.org> wrote this file.  As long as you retain this notice you
5  * can do whatever you want with this stuff. If we meet some day, and you think
6  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
7  * ----------------------------------------------------------------------------
8  *
9  * $FreeBSD: src/sys/dev/musycc/musycc.c,v 1.17.2.3 2001/03/13 22:05:36 phk Exp $
10  *
11  *
12  *
13  * Card state machine:
14  * -------------------
15  *
16  * This is the state engine which drives the card "as such" which in reality
17  * means the MUSYCC chip.
18  *
19  *  State Description
20  *
21  *  IDLE  The card is in this state when no channels are configured.
22  *                  This is the state we leave the card in after _attach()
23  *
24  *  INIT  The card is being initialized
25  *
26  *  RUNNING         The card is running
27  *
28  *  FAULT The card is hosed and being reset
29  *
30  *      ------------------
31  *     /                  \
32  *    v                    |
33  *  IDLE ---> INIT ---> RUNNING
34  *                       ^   |
35  *                       |   |
36  *                       |   v
37  *                       FAULT
38  *
39  */
40 
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/conf.h>
44 #include <sys/kernel.h>
45 #include <sys/sysctl.h>
46 #include <sys/malloc.h>
47 #include <sys/bus.h>
48 #include <sys/mbuf.h>
49 #include <sys/queue.h>
50 #include <sys/rman.h>
51 
52 #include <machine/clock.h>
53 
54 #include <bus/pci/pcireg.h>
55 #include <bus/pci/pcivar.h>
56 
57 #include "pci_if.h"
58 
59 #include <netgraph/ng_message.h>
60 #include <netgraph/netgraph.h>
61 
62 #include <vm/vm.h>
63 #include <vm/pmap.h>
64 
65 static MALLOC_DEFINE(M_MUSYCC, "musycc", "MUSYCC related");
66 
67 static int maxlatency = 250;
68 SYSCTL_INT(_debug, OID_AUTO, musycc_maxlatency, CTLFLAG_RW, &maxlatency, 0,
69           "The number of milliseconds a packet is allowed to spend in the output queue.  "
70           "If the output queue is longer than this number of milliseconds when the packet "
71           "arrives for output, the packet will be dropped."
72 );
73 
74 static int debug = 0;
75 SYSCTL_INT(_debug, OID_AUTO, musycc_debug, CTLFLAG_RW, &debug, 0, "");
76 
77 struct softc;
78 static void init_8370(struct softc *sc);
79 static    u_int32_t parse_ts(const char *s, int *nbit);
80 
81 /*
82  * Device driver initialization stuff
83  */
84 
85 static devclass_t musycc_devclass;
86 
87 /* XXX: Notice, these babies must be aligned to 2k boundaries [5-7] */
88 struct groupr {
89           u_int32_t thp[32];   /* Transmit Head Pointer [5-29]             */
90           u_int32_t tmp[32];   /* Transmit Message Pointer [5-30]          */
91           u_int32_t rhp[32];   /* Receive Head Pointer [5-29]              */
92           u_int32_t rmp[32];   /* Receive Message Pointer [5-30]           */
93           u_int8_t  ttsm[128]; /* Time Slot Map [5-22]                     */
94           u_int8_t  tscm[256]; /* Subchannel Map [5-24]                    */
95           u_int32_t tcct[32];  /* Channel Configuration [5-26]             */
96           u_int8_t  rtsm[128]; /* Time Slot Map [5-22]                     */
97           u_int8_t  rscm[256]; /* Subchannel Map [5-24]                    */
98           u_int32_t rcct[32];  /* Channel Configuration [5-26]             */
99           u_int32_t __glcd;      /* Global Configuration Descriptor [5-10] */
100           u_int32_t __iqp;       /* Interrupt Queue Pointer [5-36]         */
101           u_int32_t __iql;       /* Interrupt Queue Length [5-36]          */
102           u_int32_t grcd;        /* Group Configuration Descriptor [5-16]  */
103           u_int32_t mpd;         /* Memory Protection Descriptor [5-18]    */
104           u_int32_t mld;         /* Message Length Descriptor [5-20]       */
105           u_int32_t pcd;         /* Port Configuration Descriptor [5-19]   */
106           u_int32_t __rbist;   /* Receive BIST status [5-4]                */
107           u_int32_t __tbist;   /* Receive BIST status [5-4]                */
108 };
109 
110 struct globalr {
111           u_int32_t gbp;         /* Group Base Pointer */
112           u_int32_t dacbp;       /* Dual Address Cycle Base Pointer */
113           u_int32_t srd;         /* Service Request Descriptor */
114           u_int32_t isd;         /* Interrupt Service Descriptor */
115           u_int32_t __thp[28];   /* Transmit Head Pointer [5-29]           */
116           u_int32_t __tmp[32];   /* Transmit Message Pointer [5-30]        */
117           u_int32_t __rhp[32];   /* Receive Head Pointer [5-29]            */
118           u_int32_t __rmp[32];   /* Receive Message Pointer [5-30]         */
119           u_int8_t  ttsm[128]; /* Time Slot Map [5-22]                     */
120           u_int8_t  tscm[256]; /* Subchannel Map [5-24]                    */
121           u_int32_t tcct[32];  /* Channel Configuration [5-26]             */
122           u_int8_t  rtsm[128]; /* Time Slot Map [5-22]                     */
123           u_int8_t  rscm[256]; /* Subchannel Map [5-24]                    */
124           u_int32_t rcct[32];  /* Channel Configuration [5-26]             */
125           u_int32_t glcd;        /* Global Configuration Descriptor [5-10] */
126           u_int32_t iqp;         /* Interrupt Queue Pointer [5-36]         */
127           u_int32_t iql;         /* Interrupt Queue Length [5-36]          */
128           u_int32_t grcd;        /* Group Configuration Descriptor [5-16]  */
129           u_int32_t mpd;         /* Memory Protection Descriptor [5-18]    */
130           u_int32_t mld;         /* Message Length Descriptor [5-20]       */
131           u_int32_t pcd;         /* Port Configuration Descriptor [5-19]   */
132           u_int32_t rbist;   /* Receive BIST status [5-4]                  */
133           u_int32_t tbist;   /* Receive BIST status [5-4]                  */
134 };
135 
136 /*
137  * Because the chan_group must be 2k aligned we create this super
138  * structure so we can use the remaining 476 bytes for something useful
139  */
140 
141 struct mycg {
142           struct groupr       cg;
143 };
144 
145 struct mdesc {
146           u_int32_t status;
147           u_int32_t data;
148           u_int32_t next;
149           /* Software only */
150           struct mbuf         *m;
151           struct mdesc        *snext;
152 };
153 
154 #define NPORT       8
155 
156 #define NHDLC       32
157 
158 #define NIQD        32
159 
160 struct softc;
161 
162 struct schan {
163           enum {DOWN, UP} state;
164           struct softc        *sc;
165           int                 chan;
166           u_int32_t ts;
167           char                hookname[8];
168 
169           hook_p              hook;
170 
171           u_long              rx_drop;  /* mbuf allocation failures */
172           u_long              tx_limit;
173           u_long              tx_pending;
174           struct mdesc        *tx_next_md;        /* next MD */
175           struct mdesc        *tx_last_md;        /* last MD */
176           int                 rx_last_md;         /* index to next MD */
177           int                 nmd;                /* count of MD's. */
178 
179           time_t              last_recv;
180           time_t              last_rdrop;
181           time_t              last_rxerr;
182           u_long              crc_error;
183           u_long              dribble_error;
184           u_long              long_error;
185           u_long              abort_error;
186           u_long              short_error;
187           u_long              txn, rxn;
188 
189           time_t              last_xmit;
190           time_t              last_txerr;
191 
192           time_t              last_txdrop;
193           u_long              tx_drop;
194 
195 #if 0
196 
197 
198           u_long              rx_error;
199 
200           u_long              overflow_error;
201 
202           int                 last_error;
203           int                 prev_error;
204 
205 #endif
206 };
207 
208 enum framing {WHOKNOWS, E1, E1U, T1, T1U};
209 enum clocksource {EXT, INT};
210 
211 struct softc {
212           enum framing framing;
213           enum clocksource clocksource;
214           int nhooks;
215           u_int32_t last;
216           struct csoftc *csc;
217           u_int32_t *ds8370;
218           void      *ds847x;
219           struct globalr *reg;
220           struct groupr *ram;
221           struct mycg *mycg;
222           struct mdesc *mdt[NHDLC];
223           struct mdesc *mdr[NHDLC];
224           node_p node;                            /* NG node */
225           char nodename[NG_NODESIZ];    /* NG nodename */
226           struct schan *chan[NHDLC];
227           u_long              cnt_ferr;
228           u_long              cnt_cerr;
229           u_long              cnt_lcv;
230           u_long              cnt_febe;
231           u_long              cnt_berr;
232           u_long              cnt_fred;
233           u_long              cnt_cofa;
234           u_long              cnt_sef;
235 };
236 
237 /*
238  * SoftC for the entire card.
239  */
240 
241 struct csoftc {
242           enum { C_IDLE, C_INIT, C_RUNNING, C_FAULT } state;
243 
244           int       unit, bus, slot;
245           LIST_ENTRY(csoftc) list;
246 
247           device_t f[2];
248           struct resource *irq[2];
249           void *intrhand[2];
250           vm_offset_t physbase[2];
251           u_char *virbase[2];
252 
253           u_int creg, *cregp;
254           int nchan;
255           struct softc serial[NPORT];
256 
257           struct globalr *reg;
258           struct globalr *ram;
259           u_int32_t iqd[NIQD];
260 };
261 
262 /*
263  *
264  */
265 
266 #define NG_NODETYPE "lmc1504"
267 
268 static  ng_constructor_t musycc_constructor;
269 static  ng_rcvmsg_t musycc_rcvmsg;
270 static  ng_shutdown_t musycc_shutdown;
271 static  ng_newhook_t musycc_newhook;
272 static  ng_connect_t musycc_connect;
273 static  ng_rcvdata_t musycc_rcvdata;
274 static  ng_disconnect_t musycc_disconnect;
275 
276 static struct ng_type ngtypestruct = {
277           NG_VERSION,
278           NG_NODETYPE,
279           NULL,
280           musycc_constructor,
281           musycc_rcvmsg,
282           musycc_shutdown,
283           musycc_newhook,
284           NULL,
285           musycc_connect,
286           musycc_rcvdata,
287           musycc_rcvdata,
288           musycc_disconnect,
289           NULL
290 };
291 
292 /*
293  *
294  */
295 
296 static u_int32_t
parse_ts(const char * s,int * nbit)297 parse_ts(const char *s, int *nbit)
298 {
299           unsigned r;
300           int i, j;
301           char *p;
302 
303           r = 0;
304           j = -1;
305           *nbit = 0;
306           while(*s) {
307                     i = strtol(s, &p, 0);
308                     if (i < 0 || i > 31)
309                               return (0);
310                     while (j != -1 && j < i) {
311                               r |= 1 << j++;
312                               (*nbit)++;
313                     }
314                     j = -1;
315                     r |= 1 << i;
316                     (*nbit)++;
317                     if (*p == ',') {
318                               s = p + 1;
319                               continue;
320                     } else if (*p == '-') {
321                               j = i + 1;
322                               s = p + 1;
323                               continue;
324                     } else if (!*p) {
325                               break;
326                     } else {
327                               return (0);
328                     }
329           }
330           return (r);
331 }
332 
333 /*
334  *
335  */
336 
337 
338 static LIST_HEAD(, csoftc) sc_list = LIST_HEAD_INITIALIZER(&sc_list);
339 
340 #if 0
341 static void
342 poke_847x(void *dummy)
343 {
344           static int count;
345           int i;
346           struct csoftc *csc;
347 
348           timeout(poke_847x, NULL, 1);
349           LIST_FOREACH(csc, &sc_list, list)  {
350                     count++;
351                     i = (csc->creg >> 24 & 0xf);
352                     csc->creg &= ~0xf000000;
353                     i++;
354                     csc->creg |= (i & 0xf) << 24;
355                     *csc->cregp = csc->creg;
356 #if 0
357                     for (i = 0; i < sc->nchan; i++) {
358                               if (sc->serial[i].last == 0xffffffff) {
359                                         sc->serial[i].reg->srd = 0;
360                                         sc->serial[i].last = 0;
361                                         return;
362                               }
363                     }
364 #endif
365           }
366 }
367 #endif
368 
369 static void
init_card(struct csoftc * csc)370 init_card(struct csoftc *csc)
371 {
372 
373           kprintf("init_card(%p)\n", csc);
374 
375           csc->state = C_INIT;
376           csc->reg->srd = 0x100;
377           tsleep(csc, PCATCH, "icard", hz / 10);
378           csc->reg->gbp = vtophys(csc->ram);
379           csc->ram->glcd = 0x3f30;      /* XXX: designer magic */
380 
381           csc->ram->iqp = vtophys(csc->iqd);
382           csc->ram->iql = NIQD - 1;
383           csc->ram->dacbp = 0;                    /* 32bit only */
384 
385           csc->reg->srd = csc->serial[0].last = 0x400;
386           tsleep(&csc->serial[0].last, PCATCH, "con1", hz);
387 /*
388           timeout(poke_847x, NULL, 1);
389 */
390 #if 0
391           DELAY(20000);
392 #endif
393           csc->state = C_RUNNING;
394 }
395 
396 static void
init_ctrl(struct softc * sc)397 init_ctrl(struct softc *sc)
398 {
399           int i;
400 
401           kprintf("init_ctrl(%p) [%s] [%08x]\n", sc, sc->nodename, sc->csc->reg->glcd);
402           init_8370(sc);
403           tsleep(sc, PCATCH, "ds8370", hz);
404           kprintf("%s: glcd: [%08x]\n", sc->nodename, sc->csc->reg->glcd);
405           sc->reg->gbp = vtophys(sc->ram);
406           sc->ram->grcd =  0x00000001;  /* RXENBL */
407           sc->ram->grcd |= 0x00000002;  /* TXENBL */
408           sc->ram->grcd |= 0x00000004;  /* SUBDSBL */
409           if (sc->framing == E1 || sc->framing == T1)
410                     sc->ram->grcd |= 0x00000008;  /* OOFABT */
411           else
412                     sc->ram->grcd |= 0x00000000;  /* !OOFABT */
413 
414           sc->ram->grcd |= 0x00000020;  /* MSKCOFA */
415 
416           sc->ram->grcd |= 0x00000440;  /* POLLTH=1 */
417 
418           sc->ram->mpd = 0;             /* Memory Protection NI [5-18] */
419 
420           sc->ram->pcd =  0x0000001;    /* PORTMD=1 (E1/32ts) */
421           sc->ram->pcd |= 1 << 5;                 /* TSYNC_EDGE */
422           sc->ram->pcd |= 1 << 9;                 /* TRITX */
423 
424           /* Message length descriptor */
425           /* XXX: MTU */
426           sc->ram->mld = 1600;
427           sc->ram->mld |= (1600 << 16);
428 
429           for (i = 0; i < NHDLC; i++) {
430                     sc->ram->ttsm[i] = 0;
431                     sc->ram->rtsm[i] = 0;
432           }
433           sc->reg->srd = sc->last = 0x500;
434           tsleep(&sc->last, PCATCH, "con1", hz);
435           sc->reg->srd = sc->last = 0x520;
436           tsleep(&sc->last, PCATCH, "con1", hz);
437 }
438 
439 /*
440  *
441  */
442 
443 static void
status_chans(struct softc * sc,char * s)444 status_chans(struct softc *sc, char *s)
445 {
446           int i;
447           struct schan *scp;
448 
449           s += strlen(s);
450           for (i = 0; i < NHDLC; i++) {
451                     scp = sc->chan[i];
452                     if (scp == NULL)
453                               continue;
454                     ksprintf(s + strlen(s), "c%2d:", i);
455                     ksprintf(s + strlen(s), " ts %08x", scp->ts);
456                     ksprintf(s + strlen(s), " RX %lus/%lus",
457                         time_uptime - scp->last_recv, time_uptime - scp->last_rxerr);
458                     ksprintf(s + strlen(s), " TX %lus/%lus/%lus",
459                         time_uptime - scp->last_xmit,
460                         time_uptime - scp->last_txerr,
461                         time_uptime - scp->last_txdrop);
462                     ksprintf(s + strlen(s), " TXdrop %lu Pend %lu",
463                         scp->tx_drop,
464                         scp->tx_pending);
465                     ksprintf(s + strlen(s), " CRC %lu Dribble %lu Long %lu Short %lu Abort %lu",
466                         scp->crc_error,
467                         scp->dribble_error,
468                         scp->long_error,
469                         scp->short_error,
470                         scp->abort_error);
471                     ksprintf(s + strlen(s), "\n TX: %lu RX: %lu\n",
472                         scp->txn, scp->rxn);
473           }
474 }
475 
476 
477 /*
478  *
479  */
480 
481 static void
status_8370(struct softc * sc,char * s)482 status_8370(struct softc *sc, char *s)
483 {
484           u_int32_t *p = sc->ds8370;
485 
486           s += strlen(s);
487           ksprintf(s, "Framer: "); s += strlen(s);
488           switch (sc->framing) {
489                     case WHOKNOWS: ksprintf(s, "(unconfigured)\n"); break;
490                     case E1: ksprintf(s, "(e1)\n"); break;
491                     case E1U: ksprintf(s, "(e1u)\n"); break;
492                     case T1: ksprintf(s, "(t1)\n"); break;
493                     case T1U: ksprintf(s, "(t1u)\n"); break;
494                     default: ksprintf(s, "(mode %d XXX?)\n", sc->framing); break;
495           }
496           s += strlen(s);
497           ksprintf(s, "    Red alarms:"); s += strlen(s);
498           if (p[0x47] & 0x08) { ksprintf(s, " ALOS"); s += strlen(s); }
499           if (p[0x47] & 0x04) { ksprintf(s, " LOS"); s += strlen(s); }
500           if (sc->framing == E1 || sc->framing == T1) {
501                     if (p[0x47] & 0x02) { ksprintf(s, " LOF"); s += strlen(s); }
502           }
503           ksprintf(s, "\n    Yellow alarms:"); s += strlen(s);
504           if (p[0x47] & 0x80) { ksprintf(s, " RMYEL"); s += strlen(s); }
505           if (p[0x47] & 0x40) { ksprintf(s, " RYEL"); s += strlen(s); }
506           ksprintf(s, "\n    Blue alarms:"); s += strlen(s);
507           if (p[0x47] & 0x10) { ksprintf(s, " AIS"); s += strlen(s); }
508           ksprintf(s, "\n"); s += strlen(s);
509           ksprintf(s, "\n    Various alarms:"); s += strlen(s);
510           if (p[0x48] & 0x10) { ksprintf(s, " TSHORT"); s += strlen(s); }
511           ksprintf(s, "\n    Counters:"); s += strlen(s);
512           if (sc->framing == E1) {
513                     ksprintf(s, " FERR=%lu", sc->cnt_ferr); s += strlen(s);
514           }
515           ksprintf(s, " CERR=%lu", sc->cnt_cerr); s += strlen(s);
516           ksprintf(s, " LCV=%lu",  sc->cnt_lcv); s += strlen(s);
517           ksprintf(s, " FEBE=%lu", sc->cnt_febe); s += strlen(s);
518           ksprintf(s, " BERR=%lu", sc->cnt_berr); s += strlen(s);
519           ksprintf(s, " FRED=%lu", sc->cnt_fred); s += strlen(s);
520           ksprintf(s, " COFA=%lu", sc->cnt_cofa); s += strlen(s);
521           ksprintf(s, " SEF=%lu", sc->cnt_sef); s += strlen(s);
522           ksprintf(s, "\n"); s += strlen(s);
523 }
524 
525 static void
dump_8370(struct softc * sc,char * s,int offset)526 dump_8370(struct softc *sc, char *s, int offset)
527 {
528           int i, j;
529           u_int32_t *p = sc->ds8370;
530 
531           s += strlen(s);
532           for (i = 0; i < 0x100; i += 16) {
533                     ksprintf(s, "%03x: ", i + offset);
534                     s += strlen(s);
535                     for (j = 0; j < 0x10; j ++) {
536                               ksprintf(s, " %02x", p[i + j + offset] & 0xff);
537                               s += strlen(s);
538                     }
539                     ksprintf(s, "\n");
540                     s += strlen(s);
541           }
542 }
543 
544 static void
init_8370(struct softc * sc)545 init_8370(struct softc *sc)
546 {
547           int i;
548           u_int32_t *p = sc->ds8370;
549 
550           p[0x001] = 0x80; /* CR0 - Reset */
551           DELAY(20);
552           p[0x001] = 0x00; /* CR0 - E1, RFRAME: FAS only */
553           DELAY(20);
554           if (sc->clocksource == INT)
555                     p[0x002] = 0x40; /* JAT_CR - XXX */
556           else
557                     p[0x002] = 0x20; /* JAT_CR - XXX */
558           p[0x00D] = 0x01; /* IER6 - ONESEC */
559           p[0x014] = 0x00; /* LOOP - */
560           p[0x015] = 0x00; /* DL3_TS - */
561           p[0x016] = 0x00; /* DL3_BIT - */
562           p[0x017] = 0x00; /* DL3_BIT - */
563           p[0x018] = 0xFF; /* PIO - XXX */
564           p[0x019] = 0x3c; /* POE - CLADO_OE|RCKO_OE */
565           if (sc->clocksource == INT)
566                     p[0x01A] = 0x37; /* CMUX - RSBCKI(RSBCKI), TSBCKI(CLADO), CLADO(RCKO), TCKI(CLADO) */
567           else
568                     p[0x01A] = 0x37; /* CMUX - RSBCKI(RSBCKI), TSBCKI(RSBCKI), CLADO(RCKO), TCKI(RCKO) */
569 
570           /* I.431/G.775 */
571           p[0x020] = 0x41; /* LIU_CR - SQUELCH */
572           p[0x022] = 0xb1; /* RLIU_CR - */
573           p[0x024] = 0x1d; /* VGA_MAX - */
574           p[0x027] = 0xba; /* DSLICE - */
575           p[0x028] = 0xda; /* EQ_OUT - */
576           p[0x02a] = 0xa6; /* PRE_EQ - */
577 
578           if (sc->framing == E1U || sc->framing == T1U)
579                     p[0x040] = 0x49; /* RCRO - XXX */
580           else
581                     p[0x040] = 0x09; /* RCRO - XXX */
582 
583           p[0x041] = 0x00; /* RPATT - XXX */
584           p[0x045] = 0x00; /* RALM - XXX */
585           p[0x046] = 0x05; /* LATCH - LATCH_CNT|LATCH_ALM */
586 
587           p[0x068] = 0x4c; /* TLIU_CR - TERM|Pulse=6 */
588           p[0x070] = 0x04; /* TCR0 - TFRAME=4 */
589 
590           if (sc->framing == E1U || sc->framing == T1U)
591                     p[0x071] = 0x41; /* TCR1 - TZCS */
592           else
593                     p[0x071] = 0x51; /* TCR1 - TZCS */
594 
595           if (sc->framing == E1U || sc->framing == T1U)
596                     p[0x072] = 0x00;
597           else
598                     p[0x072] = 0x1b; /* TCR1 - INS_YEL|INS_MF|INS_CRC|INS_FBIT */
599 
600           p[0x073] = 0x00; /* TERROR */
601           p[0x074] = 0x00; /* TMAN */
602 
603           if (sc->framing == E1U || sc->framing == T1U)
604                     p[0x075] = 0x0; /* TALM */
605           else
606                     p[0x075] = 0x10; /* TALM - AUTO_YEL */
607 
608           p[0x076] = 0x00; /* TPATT */
609           p[0x077] = 0x00; /* TLP */
610 
611           p[0x090] = 0x05; /* CLAD_CR - XXX */
612           p[0x091] = 0x01; /* CSEL - 2048kHz */
613 
614           if (sc->framing == E1U || sc->framing == T1U) {
615                     p[0x0a0] = 0x00;
616                     p[0x0a6] = 0x00;
617                     p[0x0b1] = 0x00;
618           }
619 
620           p[0x0d0] = 0x46; /* SBI_CR - SBI=6 */
621           p[0x0d1] = 0x70; /* RSB_CR - XXX */
622           p[0x0d2] = 0x00; /* RSYNC_BIT - 0 */
623           p[0x0d3] = 0x00; /* RSYNC_TS - 0 */
624           p[0x0d4] = 0x30; /* TSB_CR - XXX */
625           p[0x0d5] = 0x00; /* TSYNC_BIT - 0 */
626           p[0x0d6] = 0x00; /* TSYNC_TS - 0 */
627           if (sc->framing == E1U || sc->framing == T1U)
628                     p[0x0d7] = 0x05; /* RSIG_CR - 0  | FRZ_OFF*/
629           else
630                     p[0x0d7] = 0x01; /* RSIG_CR - 0 */
631           p[0x0d8] = 0x00; /* RSIG_FRM - 0 */
632           for (i = 0; i < 32; i ++) {
633                     p[0x0e0 + i] = 0x0d; /* SBC$i - RINDO|TINDO|ASSIGN */
634                     p[0x100 + i] = 0x00; /* TPC$i - 0 */
635                     p[0x180 + i] = 0x00; /* RPC$i - 0 */
636           }
637 }
638 
639 /*
640  * Interrupts
641  */
642 
643 static void
musycc_intr0_tx_eom(struct softc * sc,int ch)644 musycc_intr0_tx_eom(struct softc *sc, int ch)
645 {
646           struct schan *sch;
647           struct mdesc *md;
648 
649           sch = sc->chan[ch];
650           if (sch == NULL || sch->state != UP) {
651                     /* XXX: this should not happen once the driver is done */
652                     kprintf("Xmit packet on uninitialized channel %d\n", ch);
653           }
654           if (sc->mdt[ch] == NULL)
655                     return;   /* XXX: can this happen ? */
656           for (;;) {
657                     md = sch->tx_last_md;
658                     if (md->status == 0)
659                               break;
660                     if (md->status & 0x80000000)
661                               break;              /* Not our mdesc, done */
662                     sch->tx_last_md = md->snext;
663                     md->data = 0;
664                     if (md->m != NULL) {
665                               sch->tx_pending -= md->m->m_pkthdr.len;
666                               m_freem(md->m);
667                               md->m = NULL;
668                     }
669                     md->status = 0;
670           }
671 }
672 
673 /*
674  * Receive interrupt on controller *sc, channel ch
675  *
676  * We perambulate the Rx descriptor ring until we hit
677  * a mdesc which isn't ours to take.
678  */
679 
680 static void
musycc_intr0_rx_eom(struct softc * sc,int ch)681 musycc_intr0_rx_eom(struct softc *sc, int ch)
682 {
683           u_int32_t status, error;
684           struct schan *sch;
685           struct mbuf *m, *m2;
686           struct mdesc *md;
687 
688           sch = sc->chan[ch];
689           if (sch == NULL || sch->state != UP) {
690                     /* XXX: this should not happen once the driver is done */
691                     kprintf("Received packet on uninitialized channel %d\n", ch);
692                     return;
693           }
694           if (sc->mdr[ch] == NULL)
695                     return;   /* XXX: can this happen ? */
696           for (;;) {
697                     md = &sc->mdr[ch][sch->rx_last_md];
698                     status = md->status;
699                     if (!(status & 0x80000000))
700                               break;              /* Not our mdesc, done */
701                     m = md->m;
702                     m->m_len = m->m_pkthdr.len = status & 0x3fff;
703                     error = (status >> 16) & 0xf;
704                     if (error == 0) {
705                               MGETHDR(m2, M_NOWAIT, MT_DATA);
706                               if (m2 != NULL) {
707                                         MCLGET(m2, M_NOWAIT);
708                                         if((m2->m_flags & M_EXT) != 0) {
709                                                   /* Substitute the mbuf+cluster. */
710                                                   md->m = m2;
711                                                   md->data = vtophys(m2->m_data);
712                                                   /* Pass the received mbuf upwards. */
713                                                   sch->last_recv = time_uptime;
714                                                   ng_queue_data(sch->hook, m, NULL);
715                                         } else {
716                                                   /*
717                                                    * We didn't get a mbuf cluster,
718                                                    * drop received packet, free the
719                                                    * mbuf we cannot use and recycle
720                                                    * the mbuf+cluster we already had.
721                                                    */
722                                                   m_freem(m2);
723                                                   sch->last_rdrop = time_uptime;
724                                                   sch->rx_drop++;
725                                         }
726                               } else {
727                                         /*
728                                          * We didn't get a mbuf, drop received packet
729                                          * and recycle the "old" mbuf+cluster.
730                                          */
731                                         sch->last_rdrop = time_uptime;
732                                         sch->rx_drop++;
733                               }
734                     } else if (error == 9) {
735                               sch->last_rxerr = time_uptime;
736                               sch->crc_error++;
737                     } else if (error == 10) {
738                               sch->last_rxerr = time_uptime;
739                               sch->dribble_error++;
740                     } else if (error == 11) {
741                               sch->last_rxerr = time_uptime;
742                               sch->abort_error++;
743                     } else if (error == 12) {
744                               sch->last_rxerr = time_uptime;
745                               sch->long_error++;
746                     } else {
747                               sch->last_rxerr = time_uptime;
748                               /* Receive error, print some useful info */
749                               kprintf("%s %s: RX 0x%08x ", sch->sc->nodename,
750                                   sch->hookname, status);
751                               /* Don't print a lot, just the begining will do */
752                               if (m->m_len > 16)
753                                         m->m_len = m->m_pkthdr.len = 16;
754                               m_print(m);
755                               kprintf("\n");
756                     }
757                     md->status = 1600;  /* XXX: MTU */
758                     /* Check next mdesc in the ring */
759                     if (++sch->rx_last_md >= sch->nmd)
760                               sch->rx_last_md = 0;
761           }
762 }
763 
764 static void
musycc_intr0(void * arg)765 musycc_intr0(void *arg)
766 {
767           int i, j, g, ch, ev, er;
768           struct csoftc *csc;
769           u_int32_t u, u1, n, c;
770           struct softc *sc;
771 
772           csc = arg;
773 
774           for (;;) {
775                     u = csc->reg->isd;
776                     c = u & 0x7fff;
777                     n = u >> 16;
778                     if (c == 0)
779                               return;
780                     if (debug & 1)
781                               kprintf("%s: IRQ: %08x n = %d c = %d\n", csc->serial[0].nodename, u, n, c);
782                     for (i = 0; i < c; i++) {
783                               j = (n + i) % NIQD;
784                               u1 = csc->iqd[j];
785                               g = (u1 >> 29) & 0x3;
786                               g |= (u1 >> (14-2)) & 0x4;
787                               ch = (u1 >> 24) & 0x1f;
788                               ev = (u1 >> 20) & 0xf;
789                               er = (u1 >> 16) & 0xf;
790                               sc = &csc->serial[g];
791                               if ((debug & 2) || er) {
792                                         kprintf("%08x %d", u1, g);
793                                         kprintf("/%s", u1 & 0x80000000 ? "T" : "R");
794                                         kprintf("/%02d", ch);
795                                         kprintf(" %02d", ev);
796                                         kprintf(":%02d", er);
797                                         kprintf("\n");
798                               }
799                               switch (ev) {
800                               case 1: /* SACK               Service Request Acknowledge       */
801 #if 0
802                                         kprintf("%s: SACK: %08x group=%d", sc->nodename, csc->iqd[j], g);
803                                         kprintf("/%s", csc->iqd[j] & 0x80000000 ? "T" : "R");
804                                         kprintf(" cmd %08x (%08x) \n", sc->last, sc->reg->srd);
805 #endif
806                                         sc->last = 0xffffffff;
807                                         wakeup(&sc->last);
808                                         break;
809                               case 5: /* CHABT    Change To Abort Code (0x7e -> 0xff) */
810                               case 6: /* CHIC               Change To Idle Code (0xff -> 0x7e)  */
811                                         break;
812                               case 3: /* EOM                End Of Message                              */
813                                         if (csc->iqd[j] & 0x80000000)
814                                                   musycc_intr0_tx_eom(sc, ch);
815                                         else
816                                                   musycc_intr0_rx_eom(sc, ch);
817                                         break;
818                               case 0:
819                                         if (er == 13) {     /* SHT */
820                                                   sc->chan[ch]->last_rxerr = time_uptime;
821                                                   sc->chan[ch]->short_error++;
822                                                   break;
823                                         }
824                               default:
825                                         musycc_intr0_tx_eom(sc, ch);
826                                         musycc_intr0_rx_eom(sc, ch);
827 #if 1
828                                         kprintf("huh ? %08x %d", u1, g);
829                                         kprintf("/%s", u1 & 0x80000000 ? "T" : "R");
830                                         kprintf("/%02d", ch);
831                                         kprintf(" %02d", ev);
832                                         kprintf(":%02d", er);
833                                         kprintf("\n");
834 #endif
835                               }
836                               csc->iqd[j] = 0xffffffff;
837                               j++;
838                               j %= NIQD;
839                               csc->reg->isd = j << 16;
840                     }
841           }
842 }
843 
844 static void
musycc_intr1(void * arg)845 musycc_intr1(void *arg)
846 {
847           int i;
848           struct csoftc *csc;
849           struct softc *sc;
850           u_int32_t *u;
851           u_int8_t irr;
852 
853           csc = arg;
854 
855           for (i = 0; i < csc->nchan; i++) {
856                     sc = &csc->serial[i];
857                     u = sc->ds8370;
858                     irr = u[3];
859                     if (irr == 0)
860                               continue;
861                     if (u[0x5] & 1) { /* ONESEC */
862                               sc->cnt_ferr +=  u[0x50] & 0xff;
863                               sc->cnt_ferr += (u[0x51] & 0xff) << 8;
864                               sc->cnt_cerr +=  u[0x52] & 0xff;
865                               sc->cnt_cerr += (u[0x53] & 0xff) << 8;
866                               sc->cnt_lcv  +=  u[0x54] & 0xff;
867                               sc->cnt_lcv  += (u[0x55] & 0xff) << 8;
868                               sc->cnt_febe +=  u[0x56] & 0xff;
869                               sc->cnt_febe += (u[0x57] & 0xff) << 8;
870                               sc->cnt_berr +=  u[0x58] & 0xff;
871                               sc->cnt_berr += (u[0x59] & 0xff) << 8;
872                               sc->cnt_fred += (u[0x5a] & 0xf0) >> 4;
873                               sc->cnt_cofa += (u[0x5a] & 0x0c) >> 2;
874                               sc->cnt_sef  +=  u[0x5a] & 0x03;
875                     }
876                     if (debug & 4) {
877                               int j;
878 
879                               kprintf("musycc_intr1:%d %02x", i, irr);
880                               for (j = 4; j < 0x14; j++)
881                                         kprintf(" %02x", u[j] & 0xff);
882                               kprintf("\n");
883                     }
884           }
885 }
886 
887 /*
888  * NetGraph Stuff
889  */
890 
891 static int
musycc_constructor(node_p * nodep)892 musycc_constructor(node_p *nodep)
893 {
894 
895           return (EINVAL);
896 }
897 
898 static int
musycc_shutdown(node_p nodep)899 musycc_shutdown(node_p nodep)
900 {
901 
902           return (EINVAL);
903 }
904 
905 static void
musycc_config(node_p node,char * set,char * ret)906 musycc_config(node_p node, char *set, char *ret)
907 {
908           struct softc *sc;
909           struct csoftc *csc;
910           enum framing wframing;
911           int i;
912 
913           sc = node->private;
914           csc = sc->csc;
915           if (csc->state == C_IDLE)
916                     init_card(csc);
917           while (csc->state != C_RUNNING)
918                     tsleep(&csc->state, PCATCH, "crun", hz/10);
919           if (set != NULL) {
920                     if (!strncmp(set, "line ", 5)) {
921                               wframing = sc->framing;
922                               if (!strcmp(set, "line e1")) {
923                                         wframing = E1;
924                               } else if (!strcmp(set, "line e1u")) {
925                                         wframing = E1U;
926                               } else {
927                                         strcat(ret, "ENOGROK\n");
928                                         return;
929                               }
930                               if (wframing == sc->framing)
931                                         return;
932                               if (sc->nhooks > 0) {
933                                         ksprintf(ret, "Cannot change line when %d hooks open\n", sc->nhooks);
934                                         return;
935                               }
936                               sc->framing = wframing;
937                               init_ctrl(sc);
938                               return;
939                     }
940                     if (!strcmp(set, "clock source internal")) {
941                               sc->clocksource = INT;
942                               init_ctrl(sc);
943                     } else if (!strcmp(set, "clock source line")) {
944                               sc->clocksource = EXT;
945                               init_ctrl(sc);
946                     } else if (!strcmp(set, "show 8370 0")) {
947                               dump_8370(sc, ret, 0);
948                     } else if (!strcmp(set, "show 8370 1")) {
949                               dump_8370(sc, ret, 0x100);
950                     } else if (!strncmp(set, "creg", 4)) {
951                               i = strtol(set + 5, 0, 0);
952                               kprintf("set creg %d\n", i);
953                               csc->creg = 0xfe | (i << 24);
954                               *csc->cregp = csc->creg;
955 /*
956                     } else if (!strcmp(set, "reset")) {
957                               reset_group(sc, ret);
958                     } else if (!strcmp(set, "reset all")) {
959                               reset_card(sc, ret);
960 */
961                     } else {
962                               kprintf("%s CONFIG SET [%s]\n", sc->nodename, set);
963                               goto barf;
964                     }
965 
966                     return;
967           }
968           if (sc->framing == E1)
969                     strcat(ret, "line e1\n");
970           else if (sc->framing == E1U)
971                     strcat(ret, "line e1u\n");
972           if (sc->clocksource == INT)
973                     strcat(ret, "clock source internal\n");
974           else
975                     strcat(ret, "clock source line\n");
976           return;
977 barf:
978           strcpy(ret, "Syntax Error\n");
979           strcat(ret, "\tline {e1|e1u}\n");
980           strcat(ret, "\tshow 8370 {0|1}\n");
981           return;
982 }
983 
984 /*
985  * Handle status and config enquiries.
986  * Respond with a synchronous response.
987  */
988 static int
musycc_rcvmsg(node_p node,struct ng_mesg * msg,const char * retaddr,struct ng_mesg ** resp)989 musycc_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr, struct ng_mesg **resp)
990 {
991           struct softc *sc;
992           char *s, *r;
993 
994           sc = node->private;
995 
996           if (msg->header.typecookie != NGM_GENERIC_COOKIE)
997                     goto out;
998 
999           if (msg->header.cmd == NGM_TEXT_STATUS) {
1000                     NG_MKRESPONSE(*resp, msg,
1001                         sizeof(struct ng_mesg) + NG_TEXTRESPONSE, M_NOWAIT);
1002                     if (*resp == NULL) {
1003                               kfree(msg, M_NETGRAPH);
1004                               return (ENOMEM);
1005                     }
1006                     s = (char *)(*resp)->data;
1007                     status_8370(sc, s);
1008                     status_chans(sc,s);
1009                     (*resp)->header.arglen = strlen(s) + 1;
1010                     kfree(msg, M_NETGRAPH);
1011                     return (0);
1012           } else if (msg->header.cmd == NGM_TEXT_CONFIG) {
1013                     if (msg->header.arglen) {
1014                               s = (char *)msg->data;
1015                     } else {
1016                               s = NULL;
1017                     }
1018 
1019                     NG_MKRESPONSE(*resp, msg,
1020                         sizeof(struct ng_mesg) + NG_TEXTRESPONSE, M_NOWAIT);
1021                     if (*resp == NULL) {
1022                               kfree(msg, M_NETGRAPH);
1023                               return (ENOMEM);
1024                     }
1025                     r = (char *)(*resp)->data;
1026                     *r = '\0';
1027                     musycc_config(node, s, r);
1028                     (*resp)->header.arglen = strlen(r) + 1;
1029                     kfree(msg, M_NETGRAPH);
1030                     return (0);
1031           }
1032 
1033 out:
1034           if (resp)
1035                     *resp = NULL;
1036           kfree(msg, M_NETGRAPH);
1037           return (EINVAL);
1038 }
1039 
1040 static int
musycc_newhook(node_p node,hook_p hook,const char * name)1041 musycc_newhook(node_p node, hook_p hook, const char *name)
1042 {
1043           struct softc *sc;
1044           struct csoftc *csc;
1045           struct schan *sch;
1046           u_int32_t ts, chan;
1047           int nbit;
1048 
1049           sc = node->private;
1050           csc = sc->csc;
1051 
1052           while (csc->state != C_RUNNING)
1053                     tsleep(&csc->state, PCATCH, "crun", hz/10);
1054 
1055           if (sc->framing == WHOKNOWS)
1056                     return (EINVAL);
1057 
1058           if (name[0] != 't' || name[1] != 's')
1059                     return (EINVAL);
1060           ts = parse_ts(name + 2, &nbit);
1061           if (ts == 0)
1062                     return (EINVAL);
1063           chan = ffs(ts) - 1;
1064 
1065           if (sc->framing == E1U && nbit == 32)
1066                     ;
1067           else if (sc->framing == T1U && nbit == 24)
1068                     ;
1069           else if (ts & 1)
1070                     return (EINVAL);
1071 
1072           if (sc->chan[chan] == NULL) {
1073                     sch = kmalloc(sizeof(*sch), M_MUSYCC, M_WAITOK | M_ZERO);
1074                     sch->sc = sc;
1075                     sch->state = DOWN;
1076                     sch->chan = chan;
1077                     ksprintf(sch->hookname, name);          /* XXX overflow ? */
1078                     sc->chan[chan] = sch;
1079           } else if (sc->chan[chan]->state == UP) {
1080                     return (EBUSY);
1081           }
1082           sc->nhooks++;
1083           sch = sc->chan[chan];
1084           sch->ts = ts;
1085           sch->hook = hook;
1086           sch->tx_limit = nbit * 8;
1087           hook->private = sch;
1088           return(0);
1089 }
1090 
1091 static int
musycc_rcvdata(hook_p hook,struct mbuf * m,meta_p meta)1092 musycc_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
1093 {
1094 
1095           struct softc *sc;
1096           struct csoftc *csc;
1097           struct schan *sch;
1098           struct mdesc *md, *md0;
1099           u_int32_t ch, u, u0, len;
1100           struct mbuf *m2;
1101 
1102           sch = hook->private;
1103           sc = sch->sc;
1104           csc = sc->csc;
1105           ch = sch->chan;
1106 
1107           if (csc->state != C_RUNNING) {
1108                     kprintf("csc->state = %d\n", csc->state);
1109                     NG_FREE_DATA(m, meta);
1110                     return (0);
1111           }
1112 
1113           NG_FREE_META(meta);
1114           meta = NULL;
1115 
1116           if (sch->state != UP) {
1117                     kprintf("sch->state = %d\n", sch->state);
1118                     NG_FREE_DATA(m, meta);
1119                     return (0);
1120           }
1121           if (sch->tx_pending + m->m_pkthdr.len > sch->tx_limit * maxlatency) {
1122                     sch->tx_drop++;
1123                     sch->last_txdrop = time_uptime;
1124                     NG_FREE_DATA(m, meta);
1125                     return (0);
1126           }
1127 
1128           /* find out if we have enough txmd's */
1129           m2 = m;
1130           md = sch->tx_next_md;
1131           for (len = m2->m_pkthdr.len; len; m2 = m2->m_next) {
1132                     if (m2->m_len == 0)
1133                               continue;
1134                     if (md->status != 0) {
1135                               sch->tx_drop++;
1136                               sch->last_txdrop = time_uptime;
1137                               NG_FREE_DATA(m, meta);
1138                               return (0);
1139                     }
1140                     len -= m2->m_len;
1141                     md = md->snext;
1142           }
1143 
1144           m2 = m;
1145           md = md0 = sch->tx_next_md;
1146           u0 = 0;
1147           for (len = m->m_pkthdr.len; len > 0; m = m->m_next) {
1148                     if (m->m_len == 0)
1149                               continue;
1150                     if (md->status != 0) {
1151                               kprintf("Out of tx md(2)\n");
1152                               sch->last_txerr = time_uptime;
1153                               sch->tx_drop++;
1154                               sch->last_txdrop = time_uptime;
1155                               NG_FREE_DATA(m, meta);
1156                               break;
1157                     }
1158 
1159                     md->data = vtophys(m->m_data);
1160                     if (md == md0)
1161                               u = 0x00000000;     /* OWNER = CPU */
1162                     else
1163                               u = 0x80000000;     /* OWNER = MUSYCC */
1164                     u |= m->m_len;
1165                     len -= m->m_len;
1166                     if (len > 0) {
1167                               md->m = NULL;
1168                               if (md == md0)
1169                                         u0 = u;
1170                               else
1171                                         md->status = u;
1172                               md = md->snext;
1173                               continue;
1174                     }
1175                     u |= 0x20000000;    /* EOM */
1176                     md->m = m2;
1177                     sch->tx_pending += m2->m_pkthdr.len;
1178                     if (md == md0) {
1179                               u |= 0x80000000;    /* OWNER = MUSYCC */
1180                               md->status = u;
1181                     } else {
1182                               md->status = u;
1183                               md0->status = u0 | 0x80000000; /* OWNER = MUSYCC */
1184                     }
1185                     sch->last_xmit = time_uptime;
1186                     sch->tx_next_md = md->snext;
1187           }
1188           sch->txn++;
1189           return (0);
1190 }
1191 
1192 static int
musycc_connect(hook_p hook)1193 musycc_connect(hook_p hook)
1194 {
1195           struct softc *sc;
1196           struct csoftc *csc;
1197           struct schan *sch;
1198           int nts, nbuf, i, nmd, ch;
1199           struct mbuf *m;
1200 
1201           sch = hook->private;
1202           sc = sch->sc;
1203           csc = sc->csc;
1204           ch = sch->chan;
1205 
1206           while (csc->state != C_RUNNING)
1207                     tsleep(&csc->state, PCATCH, "crun", hz/10);
1208 
1209           if (sch->state == UP)
1210                     return (0);
1211           sch->state = UP;
1212 
1213           /* Setup the Time Slot Map */
1214           nts = 0;
1215           for (i = ch; i < 32; i++) {
1216                     if (sch->ts & (1 << i)) {
1217                               sc->ram->rtsm[i] = ch | (4 << 5);
1218                               sc->ram->ttsm[i] = ch | (4 << 5);
1219                               nts++;
1220                     }
1221           }
1222 
1223           /*
1224            * Find the length of the first run of timeslots.
1225            * XXX: find the longest instead.
1226            */
1227           nbuf = 0;
1228           for (i = ch; i < 32; i++) {
1229                     if (sch->ts & (1 << i))
1230                               nbuf++;
1231                     else
1232                               break;
1233           }
1234 
1235           kprintf("Connect ch= %d ts= %08x nts= %d nbuf = %d\n",
1236               ch, sch->ts, nts, nbuf);
1237 
1238           /* Reread the Time Slot Map */
1239           sc->reg->srd = sc->last = 0x1800;
1240           tsleep(&sc->last, PCATCH, "con1", hz);
1241           sc->reg->srd = sc->last = 0x1820;
1242           tsleep(&sc->last, PCATCH, "con2", hz);
1243 
1244           /* Set the channel mode */
1245           sc->ram->tcct[ch] = 0x2800; /* HDLC-FCS16 | MAXSEL[2] */
1246           sc->ram->rcct[ch] = 0x2800; /* HDLC-FCS16 | MAXSEL[2] */
1247 
1248           /*
1249            * Allocate the FIFO space
1250            * We don't do subchanneling so we can use 128 dwords [4-13]
1251            */
1252           sc->ram->tcct[ch] |= (1 + 2 * (nbuf - 1)) << 16; /* BUFFLEN */
1253           sc->ram->rcct[ch] |= (1 + 2 * (nbuf - 1)) << 16; /* BUFFLEN */
1254           sc->ram->tcct[ch] |= ((ch * 2) << 24);   /* BUFFLOC */
1255           sc->ram->rcct[ch] |= ((ch * 2) << 24);   /* BUFFLOC */
1256 
1257           /* Reread the Channel Configuration Descriptor for this channel */
1258           sc->reg->srd = sc->last = 0x0b00 + ch;
1259           tsleep(&sc->last, PCATCH, "con3", hz);
1260           sc->reg->srd = sc->last = 0x0b20 + ch;
1261           tsleep(&sc->last, PCATCH, "con4", hz);
1262 
1263           /*
1264            * Figure out how many receive buffers we want:  10 + nts * 2
1265            *  1 timeslot,  50 bytes packets -> 68msec
1266            * 31 timeslots, 50 bytes packets -> 14msec
1267            */
1268           sch->nmd = nmd = 200 + nts * 4;
1269           sch->rx_last_md = 0;
1270           sc->mdt[ch] = kmalloc(sizeof(struct mdesc) * nmd, M_MUSYCC, M_WAITOK);
1271           sc->mdr[ch] = kmalloc(sizeof(struct mdesc) * nmd, M_MUSYCC, M_WAITOK);
1272           for (i = 0; i < nmd; i++) {
1273                     if (i == nmd - 1) {
1274                               sc->mdt[ch][i].snext = &sc->mdt[ch][0];
1275                               sc->mdt[ch][i].next = vtophys(sc->mdt[ch][i].snext);
1276                               sc->mdr[ch][i].snext = &sc->mdr[ch][0];
1277                               sc->mdr[ch][i].next = vtophys(sc->mdr[ch][i].snext);
1278                     } else {
1279                               sc->mdt[ch][i].snext = &sc->mdt[ch][i + 1];
1280                               sc->mdt[ch][i].next = vtophys(sc->mdt[ch][i].snext);
1281                               sc->mdr[ch][i].snext = &sc->mdr[ch][i + 1];
1282                               sc->mdr[ch][i].next = vtophys(sc->mdr[ch][i].snext);
1283                     }
1284                     sc->mdt[ch][i].status = 0;
1285                     sc->mdt[ch][i].m = NULL;
1286                     sc->mdt[ch][i].data = 0;
1287 
1288                     MGETHDR(m, M_WAITOK, MT_DATA);
1289                     MCLGET(m, M_WAITOK);
1290                     sc->mdr[ch][i].m = m;
1291                     sc->mdr[ch][i].data = vtophys(m->m_data);
1292                     sc->mdr[ch][i].status = 1600; /* MTU */
1293           }
1294           sch->tx_last_md = sch->tx_next_md = &sc->mdt[ch][0];
1295 
1296           /* Configure it into the chip */
1297           sc->ram->thp[ch] = vtophys(&sc->mdt[ch][0]);
1298           sc->ram->tmp[ch] = vtophys(&sc->mdt[ch][0]);
1299           sc->ram->rhp[ch] = vtophys(&sc->mdr[ch][0]);
1300           sc->ram->rmp[ch] = vtophys(&sc->mdr[ch][0]);
1301 
1302           /* Activate the Channel */
1303           sc->reg->srd = sc->last = 0x0800 + ch;
1304           tsleep(&sc->last, PCATCH, "con4", hz);
1305           sc->reg->srd = sc->last = 0x0820 + ch;
1306           tsleep(&sc->last, PCATCH, "con3", hz);
1307 
1308           return (0);
1309 }
1310 
1311 static int
musycc_disconnect(hook_p hook)1312 musycc_disconnect(hook_p hook)
1313 {
1314           struct softc *sc;
1315           struct csoftc *csc;
1316           struct schan *sch;
1317           int i, ch;
1318 
1319           sch = hook->private;
1320           sc = sch->sc;
1321           csc = sc->csc;
1322           ch = sch->chan;
1323 
1324           while (csc->state != C_RUNNING)
1325                     tsleep(&csc->state, PCATCH, "crun", hz/10);
1326 
1327           /* Deactivate the channel */
1328           sc->reg->srd = sc->last = 0x0900 + sch->chan;
1329           tsleep(&sc->last, PCATCH, "con3", hz);
1330           sc->reg->srd = sc->last = 0x0920 + sch->chan;
1331           tsleep(&sc->last, PCATCH, "con4", hz);
1332 
1333           if (sch->state == DOWN)
1334                     return (0);
1335           sch->state = DOWN;
1336 
1337           sc->ram->thp[ch] = 0;
1338           sc->ram->tmp[ch] = 0;
1339           sc->ram->rhp[ch] = 0;
1340           sc->ram->rmp[ch] = 0;
1341           for (i = 0; i < sch->nmd; i++) {
1342                     if (sc->mdt[ch][i].m != NULL)
1343                               m_freem(sc->mdt[ch][i].m);
1344                     if (sc->mdr[ch][i].m != NULL)
1345                               m_freem(sc->mdr[ch][i].m);
1346           }
1347           kfree(sc->mdt[ch], M_MUSYCC);
1348           sc->mdt[ch] = NULL;
1349           kfree(sc->mdr[ch], M_MUSYCC);
1350           sc->mdr[ch] = NULL;
1351 
1352           for (i = 0; i < 32; i++) {
1353                     if (sch->ts & (1 << i)) {
1354                               sc->ram->rtsm[i] = 0;
1355                               sc->ram->ttsm[i] = 0;
1356                     }
1357           }
1358           sc->nhooks--;
1359           sch->tx_pending = 0;
1360 
1361           return (0);
1362 }
1363 
1364 
1365 
1366 /*
1367  * PCI initialization stuff
1368  */
1369 
1370 static int
musycc_probe(device_t self)1371 musycc_probe(device_t self)
1372 {
1373           char desc[40];
1374 
1375           if (sizeof(struct groupr) != 1572) {
1376                     kprintf("sizeof(struct groupr) = %zu, should be 1572\n",
1377                         sizeof(struct groupr));
1378                     return(ENXIO);
1379           }
1380 
1381           if (sizeof(struct globalr) != 1572) {
1382                     kprintf("sizeof(struct globalr) = %zu, should be 1572\n",
1383                         sizeof(struct globalr));
1384                     return(ENXIO);
1385           }
1386 
1387           if (sizeof(struct mycg) > 2048) {
1388                     kprintf("sizeof(struct mycg) = %zu, should be <= 2048\n",
1389                         sizeof(struct mycg));
1390                     return(ENXIO);
1391           }
1392 
1393           switch (pci_get_devid(self)) {
1394           case 0x8471109e: strcpy(desc, "CN8471 MUSYCC"); break;
1395           case 0x8472109e: strcpy(desc, "CN8472 MUSYCC"); break;
1396           case 0x8474109e: strcpy(desc, "CN8474 MUSYCC"); break;
1397           case 0x8478109e: strcpy(desc, "CN8478 MUSYCC"); break;
1398           default:
1399                     return (ENXIO);
1400           }
1401 
1402           switch (pci_get_function(self)) {
1403           case 0: strcat(desc, " Network controller"); break;
1404           case 1: strcat(desc, " Ebus bridge"); break;
1405           default:
1406                     return (ENXIO);
1407           }
1408 
1409           device_set_desc_copy(self, desc);
1410           return 0;
1411 }
1412 
1413 static int
musycc_attach(device_t self)1414 musycc_attach(device_t self)
1415 {
1416           struct csoftc *csc;
1417           struct resource *res;
1418           struct softc *sc;
1419           int rid, i, error;
1420           int f;
1421           u_int32_t *u32p, u;
1422           static int once;
1423 
1424           if (!once) {
1425                     once++;
1426                     error = ng_newtype(&ngtypestruct);
1427                     if (error != 0)
1428                               kprintf("ng_newtype() failed %d\n", error);
1429           }
1430           kprintf("We have %zu pad bytes in mycg\n", 2048 - sizeof(struct mycg));
1431 
1432           f = pci_get_function(self);
1433           /* For function zero allocate a csoftc */
1434           if (f == 0) {
1435                     csc = kmalloc(sizeof(*csc), M_MUSYCC, M_WAITOK | M_ZERO);
1436                     csc->bus = pci_get_bus(self);
1437                     csc->slot = pci_get_slot(self);
1438                     LIST_INSERT_HEAD(&sc_list, csc, list);
1439           } else {
1440                     LIST_FOREACH(csc, &sc_list, list) {
1441                               if (csc->bus != pci_get_bus(self))
1442                                         continue;
1443                               if (csc->slot != pci_get_slot(self))
1444                                         continue;
1445                               break;
1446                     }
1447           }
1448           csc->f[f] = self;
1449           device_set_softc(self, csc);
1450           rid = PCIR_MAPS;
1451           res = bus_alloc_resource(self, SYS_RES_MEMORY, &rid,
1452               0, ~0, 1, RF_ACTIVE);
1453           if (res == NULL) {
1454                     device_printf(self, "Could not map memory\n");
1455                     return ENXIO;
1456           }
1457           csc->virbase[f] = (u_char *)rman_get_virtual(res);
1458           csc->physbase[f] = rman_get_start(res);
1459 
1460           /* Allocate interrupt */
1461           rid = 0;
1462           csc->irq[f] = bus_alloc_resource(self, SYS_RES_IRQ, &rid, 0, ~0,
1463               1, RF_SHAREABLE | RF_ACTIVE);
1464 
1465           if (csc->irq[f] == NULL) {
1466                     kprintf("couldn't map interrupt\n");
1467                     return(ENXIO);
1468           }
1469 
1470           error = bus_setup_intr(self, csc->irq[f], 0,
1471                                      (f == 0 ? musycc_intr0 : musycc_intr1), csc,
1472                                      &csc->intrhand[f], NULL);
1473 
1474           if (error) {
1475                     kprintf("couldn't set up irq\n");
1476                     return(ENXIO);
1477           }
1478 
1479           if (f == 0)
1480                     return (0);
1481 
1482           for (i = 0; i < 2; i++)
1483                     kprintf("f%d: device %p virtual %p physical %08lx\n",
1484                         i, csc->f[i], csc->virbase[i], csc->physbase[i]);
1485 
1486           csc->reg = (struct globalr *)csc->virbase[0];
1487           csc->reg->glcd = 0x3f30;      /* XXX: designer magic */
1488           u32p = (u_int32_t *)csc->virbase[1];
1489           u = u32p[0x1200];
1490           if ((u & 0xffff0000) != 0x13760000) {
1491                     kprintf("Not a LMC1504 (ID is 0x%08x).  Bailing out.\n", u);
1492                     return(ENXIO);
1493           }
1494           csc->nchan = (u >> 8) & 0xf;
1495           kprintf("Found <LanMedia LMC1504 Rev %d Chan %d>\n", (u >> 12) & 0xf, csc->nchan);
1496 
1497           csc->creg = 0xfe;
1498           csc->cregp = &u32p[0x1000];
1499           *csc->cregp = csc->creg;
1500           for (i = 0; i < csc->nchan; i++) {
1501                     sc = &csc->serial[i];
1502                     sc->csc = csc;
1503                     sc->last = 0xffffffff;
1504                     sc->ds8370 = (u_int32_t *)
1505                         (csc->virbase[1] + i * 0x800);
1506                     sc->ds847x = csc->virbase[0] + i * 0x800;
1507                     sc->reg = (struct globalr *)
1508                         (csc->virbase[0] + i * 0x800);
1509                     sc->mycg = kmalloc(sizeof(struct mycg), M_MUSYCC,
1510                                            M_WAITOK | M_ZERO);
1511                     sc->ram = &sc->mycg->cg;
1512 
1513                     error = ng_make_node_common(&ngtypestruct, &sc->node);
1514                     if (error) {
1515                               kprintf("ng_make_node_common() failed %d\n", error);
1516                               continue;
1517                     }
1518                     sc->node->private = sc;
1519                     ksprintf(sc->nodename, "sync-%d-%d-%d",
1520                               csc->bus,
1521                               csc->slot,
1522                               i);
1523                     error = ng_name_node(sc->node, sc->nodename);
1524                     /* XXX Apparently failure isn't a problem */
1525           }
1526           csc->ram = (struct globalr *)&csc->serial[0].mycg->cg;
1527           sc = &csc->serial[0];
1528           sc->reg->srd = sc->last = 0x100;
1529           csc->state = C_IDLE;
1530 
1531           return 0;
1532 }
1533 
1534 static device_method_t musycc_methods[] = {
1535           /* Device interface */
1536           DEVMETHOD(device_probe,                 musycc_probe),
1537           DEVMETHOD(device_attach,      musycc_attach),
1538           DEVMETHOD(device_suspend,     bus_generic_suspend),
1539           DEVMETHOD(device_resume,      bus_generic_resume),
1540           DEVMETHOD(device_shutdown,    bus_generic_shutdown),
1541 
1542           DEVMETHOD_END
1543 };
1544 
1545 static driver_t musycc_driver = {
1546           "musycc",
1547           musycc_methods,
1548           0
1549 };
1550 
1551 DRIVER_MODULE(musycc, pci, musycc_driver, musycc_devclass, NULL, NULL);
1552