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