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