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 * ----------------------------------------------------------------------------
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.8 2006/10/25 20:55:54 dillon Exp $
17 * This is the state engine which drives the card "as such" which in reality
18 * means the MUSYCC chip.
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()
25 * INIT The card is being initialized
27 * RUNNING The card is running
29 * FAULT The card is hosed and being reset
34 * IDLE ---> INIT ---> RUNNING
42 #include <sys/param.h>
43 #include <sys/systm.h>
45 #include <sys/kernel.h>
46 #include <sys/sysctl.h>
47 #include <sys/malloc.h>
50 #include <sys/queue.h>
53 #include <machine/clock.h>
55 #include <bus/pci/pcireg.h>
56 #include <bus/pci/pcivar.h>
60 #include <netgraph/ng_message.h>
61 #include <netgraph/netgraph.h>
66 static MALLOC_DEFINE(M_MUSYCC, "musycc", "MUSYCC related");
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."
76 SYSCTL_INT(_debug, OID_AUTO, musycc_debug, CTLFLAG_RW, &debug, 0, "");
79 static void init_8370(struct softc *sc);
80 static u_int32_t parse_ts(const char *s, int *nbit);
83 * Device driver initialization stuff
86 static devclass_t musycc_devclass;
88 /* XXX: Notice, these babies must be aligned to 2k boundaries [5-7] */
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] */
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] */
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
164 enum {DOWN, UP} state;
172 u_long rx_drop; /* mbuf allocation failures */
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. */
184 u_long dribble_error;
201 u_long overflow_error;
209 enum framing {WHOKNOWS, E1, E1U, T1, T1U};
210 enum clocksource {EXT, INT};
213 enum framing framing;
214 enum clocksource clocksource;
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];
239 * SoftC for the entire card.
243 enum { C_IDLE, C_INIT, C_RUNNING, C_FAULT } state;
246 LIST_ENTRY(csoftc) list;
249 struct resource *irq[2];
251 vm_offset_t physbase[2];
256 struct softc serial[NPORT];
267 #define NG_NODETYPE "lmc1504"
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;
277 static struct ng_type ngtypestruct = {
298 parse_ts(const char *s, int *nbit)
308 i = strtol(s, &p, 0);
311 while (j != -1 && j < i) {
321 } else if (*p == '-') {
339 static LIST_HEAD(, csoftc) sc_list = LIST_HEAD_INITIALIZER(&sc_list);
342 poke_847x(void *dummy)
348 timeout(poke_847x, NULL, 1);
349 LIST_FOREACH(csc, &sc_list, list) {
351 i = (csc->creg >> 24 & 0xf);
352 csc->creg &= ~0xf000000;
354 csc->creg |= (i & 0xf) << 24;
355 *csc->cregp = csc->creg;
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;
369 init_card(struct csoftc *csc)
372 printf("init_card(%p)\n", csc);
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 */
380 csc->ram->iqp = vtophys(csc->iqd);
381 csc->ram->iql = NIQD - 1;
382 csc->ram->dacbp = 0; /* 32bit only */
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;
391 init_ctrl(struct softc *sc)
395 printf("init_ctrl(%p) [%s] [%08x]\n", sc, sc->nodename, sc->csc->reg->glcd);
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 */
406 sc->ram->grcd |= 0x00000000; /* !OOFABT */
408 sc->ram->grcd |= 0x00000020; /* MSKCOFA */
410 sc->ram->grcd |= 0x00000440; /* POLLTH=1 */
412 sc->ram->mpd = 0; /* Memory Protection NI [5-18] */
414 sc->ram->pcd = 0x0000001; /* PORTMD=1 (E1/32ts) */
415 sc->ram->pcd |= 1 << 5; /* TSYNC_EDGE */
416 sc->ram->pcd |= 1 << 9; /* TRITX */
418 /* Message length descriptor */
421 sc->ram->mld |= (1600 << 16);
423 for (i = 0; i < NHDLC; i++) {
424 sc->ram->ttsm[i] = 0;
425 sc->ram->rtsm[i] = 0;
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);
438 status_chans(struct softc *sc, char *s)
444 for (i = 0; i < NHDLC; i++) {
448 sprintf(s + strlen(s), "c%2d:", i);
449 sprintf(s + strlen(s), " ts %08x", scp->ts);
450 sprintf(s + strlen(s), " RX %lus/%lus",
451 time_second - scp->last_recv, time_second - scp->last_rxerr);
452 sprintf(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 sprintf(s + strlen(s), " TXdrop %lu Pend %lu",
459 sprintf(s + strlen(s), " CRC %lu Dribble %lu Long %lu Short %lu Abort %lu",
465 sprintf(s + strlen(s), "\n TX: %lu RX: %lu\n",
476 status_8370(struct softc *sc, char *s)
478 u_int32_t *p = sc->ds8370;
481 sprintf(s, "Framer: "); s += strlen(s);
482 switch (sc->framing) {
483 case WHOKNOWS: sprintf(s, "(unconfigured)\n"); break;
484 case E1: sprintf(s, "(e1)\n"); break;
485 case E1U: sprintf(s, "(e1u)\n"); break;
486 case T1: sprintf(s, "(t1)\n"); break;
487 case T1U: sprintf(s, "(t1u)\n"); break;
488 default: sprintf(s, "(mode %d XXX?)\n", sc->framing); break;
491 sprintf(s, " Red alarms:"); s += strlen(s);
492 if (p[0x47] & 0x08) { sprintf(s, " ALOS"); s += strlen(s); }
493 if (p[0x47] & 0x04) { sprintf(s, " LOS"); s += strlen(s); }
494 if (sc->framing == E1 || sc->framing == T1) {
495 if (p[0x47] & 0x02) { sprintf(s, " LOF"); s += strlen(s); }
497 sprintf(s, "\n Yellow alarms:"); s += strlen(s);
498 if (p[0x47] & 0x80) { sprintf(s, " RMYEL"); s += strlen(s); }
499 if (p[0x47] & 0x40) { sprintf(s, " RYEL"); s += strlen(s); }
500 sprintf(s, "\n Blue alarms:"); s += strlen(s);
501 if (p[0x47] & 0x10) { sprintf(s, " AIS"); s += strlen(s); }
502 sprintf(s, "\n"); s += strlen(s);
503 sprintf(s, "\n Various alarms:"); s += strlen(s);
504 if (p[0x48] & 0x10) { sprintf(s, " TSHORT"); s += strlen(s); }
505 sprintf(s, "\n Counters:"); s += strlen(s);
506 if (sc->framing == E1) {
507 sprintf(s, " FERR=%lu", sc->cnt_ferr); s += strlen(s);
509 sprintf(s, " CERR=%lu", sc->cnt_cerr); s += strlen(s);
510 sprintf(s, " LCV=%lu", sc->cnt_lcv); s += strlen(s);
511 sprintf(s, " FEBE=%lu", sc->cnt_febe); s += strlen(s);
512 sprintf(s, " BERR=%lu", sc->cnt_berr); s += strlen(s);
513 sprintf(s, " FRED=%lu", sc->cnt_fred); s += strlen(s);
514 sprintf(s, " COFA=%lu", sc->cnt_cofa); s += strlen(s);
515 sprintf(s, " SEF=%lu", sc->cnt_sef); s += strlen(s);
516 sprintf(s, "\n"); s += strlen(s);
520 dump_8370(struct softc *sc, char *s, int offset)
523 u_int32_t *p = sc->ds8370;
526 for (i = 0; i < 0x100; i += 16) {
527 sprintf(s, "%03x: ", i + offset);
529 for (j = 0; j < 0x10; j ++) {
530 sprintf(s, " %02x", p[i + j + offset] & 0xff);
539 init_8370(struct softc *sc)
542 u_int32_t *p = sc->ds8370;
544 p[0x001] = 0x80; /* CR0 - Reset */
546 p[0x001] = 0x00; /* CR0 - E1, RFRAME: FAS only */
548 if (sc->clocksource == INT)
549 p[0x002] = 0x40; /* JAT_CR - XXX */
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) */
562 p[0x01A] = 0x37; /* CMUX - RSBCKI(RSBCKI), TSBCKI(RSBCKI), CLADO(RCKO), TCKI(RCKO) */
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 - */
572 if (sc->framing == E1U || sc->framing == T1U)
573 p[0x040] = 0x49; /* RCRO - XXX */
575 p[0x040] = 0x09; /* RCRO - XXX */
577 p[0x041] = 0x00; /* RPATT - XXX */
578 p[0x045] = 0x00; /* RALM - XXX */
579 p[0x046] = 0x05; /* LATCH - LATCH_CNT|LATCH_ALM */
581 p[0x068] = 0x4c; /* TLIU_CR - TERM|Pulse=6 */
582 p[0x070] = 0x04; /* TCR0 - TFRAME=4 */
584 if (sc->framing == E1U || sc->framing == T1U)
585 p[0x071] = 0x41; /* TCR1 - TZCS */
587 p[0x071] = 0x51; /* TCR1 - TZCS */
589 if (sc->framing == E1U || sc->framing == T1U)
592 p[0x072] = 0x1b; /* TCR1 - INS_YEL|INS_MF|INS_CRC|INS_FBIT */
594 p[0x073] = 0x00; /* TERROR */
595 p[0x074] = 0x00; /* TMAN */
597 if (sc->framing == E1U || sc->framing == T1U)
598 p[0x075] = 0x0; /* TALM */
600 p[0x075] = 0x10; /* TALM - AUTO_YEL */
602 p[0x076] = 0x00; /* TPATT */
603 p[0x077] = 0x00; /* TLP */
605 p[0x090] = 0x05; /* CLAD_CR - XXX */
606 p[0x091] = 0x01; /* CSEL - 2048kHz */
608 if (sc->framing == E1U || sc->framing == T1U) {
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*/
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 */
638 musycc_intr0_tx_eom(struct softc *sc, int 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);
648 if (sc->mdt[ch] == NULL)
649 return; /* XXX: can this happen ? */
651 md = sch->tx_last_md;
654 if (md->status & 0x80000000)
655 break; /* Not our mdesc, done */
656 sch->tx_last_md = md->snext;
659 sch->tx_pending -= md->m->m_pkthdr.len;
668 * Receive interrupt on controller *sc, channel ch
670 * We perambulate the Rx descriptor ring until we hit
671 * a mdesc which isn't ours to take.
675 musycc_intr0_rx_eom(struct softc *sc, int ch)
677 u_int32_t status, error;
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);
688 if (sc->mdr[ch] == NULL)
689 return; /* XXX: can this happen ? */
691 md = &sc->mdr[ch][sch->rx_last_md];
693 if (!(status & 0x80000000))
694 break; /* Not our mdesc, done */
696 m->m_len = m->m_pkthdr.len = status & 0x3fff;
697 error = (status >> 16) & 0xf;
699 MGETHDR(m2, MB_DONTWAIT, MT_DATA);
701 MCLGET(m2, MB_DONTWAIT);
702 if((m2->m_flags & M_EXT) != 0) {
703 /* Substitute the mbuf+cluster. */
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);
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.
717 sch->last_rdrop = time_second;
722 * We didn't get a mbuf, drop received packet
723 * and recycle the "old" mbuf+cluster.
725 sch->last_rdrop = time_second;
728 } else if (error == 9) {
729 sch->last_rxerr = time_second;
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;
737 } else if (error == 12) {
738 sch->last_rxerr = time_second;
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 */
747 m->m_len = m->m_pkthdr.len = 16;
751 md->status = 1600; /* XXX: MTU */
752 /* Check next mdesc in the ring */
753 if (++sch->rx_last_md >= sch->nmd)
759 musycc_intr0(void *arg)
761 int i, j, g, ch, ev, er;
763 u_int32_t u, u1, n, c;
775 printf("%s: IRQ: %08x n = %d c = %d\n", csc->serial[0].nodename, u, n, c);
776 for (i = 0; i < c; i++) {
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");
794 case 1: /* SACK Service Request Acknowledge */
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);
800 sc->last = 0xffffffff;
803 case 5: /* CHABT Change To Abort Code (0x7e -> 0xff) */
804 case 6: /* CHIC Change To Idle Code (0xff -> 0x7e) */
806 case 3: /* EOM End Of Message */
807 if (csc->iqd[j] & 0x80000000)
808 musycc_intr0_tx_eom(sc, ch);
810 musycc_intr0_rx_eom(sc, ch);
813 if (er == 13) { /* SHT */
814 sc->chan[ch]->last_rxerr = time_second;
815 sc->chan[ch]->short_error++;
819 musycc_intr0_tx_eom(sc, ch);
820 musycc_intr0_rx_eom(sc, ch);
822 printf("huh ? %08x %d", u1, g);
823 printf("/%s", u1 & 0x80000000 ? "T" : "R");
830 csc->iqd[j] = 0xffffffff;
833 csc->reg->isd = j << 16;
839 musycc_intr1(void *arg)
849 for (i = 0; i < csc->nchan; i++) {
850 sc = &csc->serial[i];
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;
873 printf("musycc_intr1:%d %02x", i, irr);
874 for (j = 4; j < 0x14; j++)
875 printf(" %02x", u[j] & 0xff);
886 musycc_constructor(node_p *nodep)
893 musycc_shutdown(node_p nodep)
900 musycc_config(node_p node, char *set, char *ret)
904 enum framing wframing;
909 if (csc->state == C_IDLE)
911 while (csc->state != C_RUNNING)
912 tsleep(&csc->state, PCATCH, "crun", hz/10);
914 if (!strncmp(set, "line ", 5)) {
915 wframing = sc->framing;
916 if (!strcmp(set, "line e1")) {
918 } else if (!strcmp(set, "line e1u")) {
921 strcat(ret, "ENOGROK\n");
924 if (wframing == sc->framing)
926 if (sc->nhooks > 0) {
927 sprintf(ret, "Cannot change line when %d hooks open\n", sc->nhooks);
930 sc->framing = wframing;
934 if (!strcmp(set, "clock source internal")) {
935 sc->clocksource = INT;
937 } else if (!strcmp(set, "clock source line")) {
938 sc->clocksource = EXT;
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;
950 } else if (!strcmp(set, "reset")) {
951 reset_group(sc, ret);
952 } else if (!strcmp(set, "reset all")) {
956 printf("%s CONFIG SET [%s]\n", sc->nodename, set);
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");
969 strcat(ret, "clock source line\n");
972 strcpy(ret, "Syntax Error\n");
973 strcat(ret, "\tline {e1|e1u}\n");
974 strcat(ret, "\tshow 8370 {0|1}\n");
979 * Handle status and config enquiries.
980 * Respond with a synchronous response.
983 musycc_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr, struct ng_mesg **resp)
990 if (msg->header.typecookie != NGM_GENERIC_COOKIE)
993 if (msg->header.cmd == NGM_TEXT_STATUS) {
994 NG_MKRESPONSE(*resp, msg,
995 sizeof(struct ng_mesg) + NG_TEXTRESPONSE, M_NOWAIT);
997 FREE(msg, M_NETGRAPH);
1000 s = (char *)(*resp)->data;
1003 (*resp)->header.arglen = strlen(s) + 1;
1004 FREE(msg, M_NETGRAPH);
1006 } else if (msg->header.cmd == NGM_TEXT_CONFIG) {
1007 if (msg->header.arglen) {
1008 s = (char *)msg->data;
1013 NG_MKRESPONSE(*resp, msg,
1014 sizeof(struct ng_mesg) + NG_TEXTRESPONSE, M_NOWAIT);
1015 if (*resp == NULL) {
1016 FREE(msg, M_NETGRAPH);
1019 r = (char *)(*resp)->data;
1021 musycc_config(node, s, r);
1022 (*resp)->header.arglen = strlen(r) + 1;
1023 FREE(msg, M_NETGRAPH);
1030 FREE(msg, M_NETGRAPH);
1035 musycc_newhook(node_p node, hook_p hook, const char *name)
1046 while (csc->state != C_RUNNING)
1047 tsleep(&csc->state, PCATCH, "crun", hz/10);
1049 if (sc->framing == WHOKNOWS)
1052 if (name[0] != 't' || name[1] != 's')
1054 ts = parse_ts(name + 2, &nbit);
1059 if (sc->framing == E1U && nbit == 32)
1061 else if (sc->framing == T1U && nbit == 24)
1066 if (sc->chan[chan] == NULL) {
1067 MALLOC(sch, struct schan *, sizeof(*sch), M_MUSYCC, M_WAITOK | M_ZERO);
1071 sprintf(sch->hookname, name); /* XXX overflow ? */
1072 sc->chan[chan] = sch;
1073 } else if (sc->chan[chan]->state == UP) {
1077 sch = sc->chan[chan];
1080 sch->tx_limit = nbit * 8;
1081 hook->private = sch;
1086 musycc_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
1092 struct mdesc *md, *md0;
1093 u_int32_t ch, u, u0, len;
1096 sch = hook->private;
1101 if (csc->state != C_RUNNING) {
1102 printf("csc->state = %d\n", csc->state);
1103 NG_FREE_DATA(m, meta);
1110 if (sch->state != UP) {
1111 printf("sch->state = %d\n", sch->state);
1112 NG_FREE_DATA(m, meta);
1115 if (sch->tx_pending + m->m_pkthdr.len > sch->tx_limit * maxlatency) {
1117 sch->last_txdrop = time_second;
1118 NG_FREE_DATA(m, meta);
1122 /* find out if we have enough txmd's */
1124 md = sch->tx_next_md;
1125 for (len = m2->m_pkthdr.len; len; m2 = m2->m_next) {
1128 if (md->status != 0) {
1130 sch->last_txdrop = time_second;
1131 NG_FREE_DATA(m, meta);
1139 md = md0 = sch->tx_next_md;
1141 for (len = m->m_pkthdr.len; len > 0; m = m->m_next) {
1144 if (md->status != 0) {
1145 printf("Out of tx md(2)\n");
1146 sch->last_txerr = time_second;
1148 sch->last_txdrop = time_second;
1149 NG_FREE_DATA(m, meta);
1153 md->data = vtophys(m->m_data);
1155 u = 0x00000000; /* OWNER = CPU */
1157 u = 0x80000000; /* OWNER = MUSYCC */
1169 u |= 0x20000000; /* EOM */
1171 sch->tx_pending += m2->m_pkthdr.len;
1173 u |= 0x80000000; /* OWNER = MUSYCC */
1177 md0->status = u0 | 0x80000000; /* OWNER = MUSYCC */
1179 sch->last_xmit = time_second;
1180 sch->tx_next_md = md->snext;
1187 musycc_connect(hook_p hook)
1192 int nts, nbuf, i, nmd, ch;
1195 sch = hook->private;
1200 while (csc->state != C_RUNNING)
1201 tsleep(&csc->state, PCATCH, "crun", hz/10);
1203 if (sch->state == UP)
1207 /* Setup the Time Slot Map */
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);
1218 * Find the length of the first run of timeslots.
1219 * XXX: find the longest instead.
1222 for (i = ch; i < 32; i++) {
1223 if (sch->ts & (1 << i))
1229 printf("Connect ch= %d ts= %08x nts= %d nbuf = %d\n",
1230 ch, sch->ts, nts, nbuf);
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);
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] */
1243 * Allocate the FIFO space
1244 * We don't do subchanneling so we can use 128 dwords [4-13]
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 */
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);
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
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++) {
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);
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);
1280 sc->mdt[ch][i].status = 0;
1281 sc->mdt[ch][i].m = NULL;
1282 sc->mdt[ch][i].data = 0;
1284 MGETHDR(m, MB_WAIT, MT_DATA);
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. */
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 */
1300 sch->tx_last_md = sch->tx_next_md = &sc->mdt[ch][0];
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]);
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);
1318 /* Don't leak all the previously allocated mbufs in this loop */
1320 m_free(sc->mdr[ch][i].m);
1322 FREE(sc->mdt[ch], M_MUSYCC);
1323 FREE(sc->mdr[ch], M_MUSYCC);
1328 musycc_disconnect(hook_p hook)
1335 sch = hook->private;
1340 while (csc->state != C_RUNNING)
1341 tsleep(&csc->state, PCATCH, "crun", hz/10);
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);
1349 if (sch->state == DOWN)
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);
1363 FREE(sc->mdt[ch], M_MUSYCC);
1365 FREE(sc->mdr[ch], M_MUSYCC);
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;
1375 sch->tx_pending = 0;
1383 * PCI initialization stuff
1387 musycc_probe(device_t self)
1391 if (sizeof(struct groupr) != 1572) {
1392 printf("sizeof(struct groupr) = %d, should be 1572\n",
1393 sizeof(struct groupr));
1397 if (sizeof(struct globalr) != 1572) {
1398 printf("sizeof(struct globalr) = %d, should be 1572\n",
1399 sizeof(struct globalr));
1403 if (sizeof(struct mycg) > 2048) {
1404 printf("sizeof(struct mycg) = %d, should be <= 2048\n",
1405 sizeof(struct mycg));
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;
1418 switch (pci_get_function(self)) {
1419 case 0: strcat(desc, " Network controller"); break;
1420 case 1: strcat(desc, " Ebus bridge"); break;
1425 device_set_desc_copy(self, desc);
1430 musycc_attach(device_t self)
1433 struct resource *res;
1442 error = ng_newtype(&ngtypestruct);
1444 printf("ng_newtype() failed %d\n", error);
1446 printf("We have %d pad bytes in mycg\n", 2048 - sizeof(struct mycg));
1448 f = pci_get_function(self);
1449 /* For function zero allocate a csoftc */
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);
1456 LIST_FOREACH(csc, &sc_list, list) {
1457 if (csc->bus != pci_get_bus(self))
1459 if (csc->slot != pci_get_slot(self))
1465 device_set_softc(self, csc);
1467 res = bus_alloc_resource(self, SYS_RES_MEMORY, &rid,
1468 0, ~0, 1, RF_ACTIVE);
1470 device_printf(self, "Could not map memory\n");
1473 csc->virbase[f] = (u_char *)rman_get_virtual(res);
1474 csc->physbase[f] = rman_get_start(res);
1476 /* Allocate interrupt */
1478 csc->irq[f] = bus_alloc_resource(self, SYS_RES_IRQ, &rid, 0, ~0,
1479 1, RF_SHAREABLE | RF_ACTIVE);
1481 if (csc->irq[f] == NULL) {
1482 printf("couldn't map interrupt\n");
1486 error = bus_setup_intr(self, csc->irq[f], 0,
1487 (f == 0 ? musycc_intr0 : musycc_intr1), csc,
1488 &csc->intrhand[f], NULL);
1491 printf("couldn't set up irq\n");
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]);
1502 csc->reg = (struct globalr *)csc->virbase[0];
1503 csc->reg->glcd = 0x3f30; /* XXX: designer magic */
1504 u32p = (u_int32_t *)csc->virbase[1];
1506 if ((u & 0xffff0000) != 0x13760000) {
1507 printf("Not a LMC1504 (ID is 0x%08x). Bailing out.\n", u);
1510 csc->nchan = (u >> 8) & 0xf;
1511 printf("Found <LanMedia LMC1504 Rev %d Chan %d>\n", (u >> 12) & 0xf, csc->nchan);
1514 csc->cregp = &u32p[0x1000];
1515 *csc->cregp = csc->creg;
1516 for (i = 0; i < csc->nchan; i++) {
1517 sc = &csc->serial[i];
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;
1529 error = ng_make_node_common(&ngtypestruct, &sc->node);
1531 printf("ng_make_node_common() failed %d\n", error);
1534 sc->node->private = sc;
1535 sprintf(sc->nodename, "sync-%d-%d-%d",
1539 error = ng_name_node(sc->node, sc->nodename);
1540 /* XXX Apparently failure isn't a problem */
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;
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),
1561 static driver_t musycc_driver = {
1567 DRIVER_MODULE(musycc, pci, musycc_driver, musycc_devclass, 0, 0);