The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/misc/musycc/musycc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 18f5859a4238de19620fdb06fed3cc5a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.