1: /* 2: * Copyright (c) 1982, 1986 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: * 6: * @(#)if_dmc.c 7.1 (Berkeley) 6/5/86 7: */ 8: 9: #include "dmc.h" 10: #if NDMC > 0 11: 12: /* 13: * DMC11 device driver, internet version 14: * 15: * Bill Nesheim 16: * Cornell University 17: * 18: * Lou Salkind 19: * New York University 20: */ 21: 22: /* #define DEBUG /* for base table dump on fatal error */ 23: 24: #include "../machine/pte.h" 25: 26: #include "param.h" 27: #include "systm.h" 28: #include "mbuf.h" 29: #include "buf.h" 30: #include "ioctl.h" /* must precede tty.h */ 31: #include "tty.h" 32: #include "protosw.h" 33: #include "socket.h" 34: #include "syslog.h" 35: #include "vmmac.h" 36: #include "errno.h" 37: 38: #include "../net/if.h" 39: #include "../net/netisr.h" 40: #include "../net/route.h" 41: 42: #ifdef INET 43: #include "../netinet/in.h" 44: #include "../netinet/in_systm.h" 45: #include "../netinet/in_var.h" 46: #include "../netinet/ip.h" 47: #endif 48: 49: #include "../vax/cpu.h" 50: #include "../vax/mtpr.h" 51: #include "if_uba.h" 52: #include "if_dmc.h" 53: #include "../vaxuba/ubareg.h" 54: #include "../vaxuba/ubavar.h" 55: 56: #include "../h/time.h" 57: #include "../h/kernel.h" 58: 59: int dmctimer; /* timer started? */ 60: int dmc_timeout = 8; /* timeout value */ 61: int dmcwatch(); 62: 63: /* 64: * Driver information for auto-configuration stuff. 65: */ 66: int dmcprobe(), dmcattach(), dmcinit(), dmcioctl(); 67: int dmcoutput(), dmcreset(); 68: struct uba_device *dmcinfo[NDMC]; 69: u_short dmcstd[] = { 0 }; 70: struct uba_driver dmcdriver = 71: { dmcprobe, 0, dmcattach, 0, dmcstd, "dmc", dmcinfo }; 72: 73: #define NRCV 7 74: #define NXMT 3 75: #define NCMDS (NRCV+NXMT+4) /* size of command queue */ 76: 77: #define printd if(dmcdebug)printf 78: int dmcdebug = 0; 79: 80: /* error reporting intervals */ 81: #define DMC_RPNBFS 50 82: #define DMC_RPDSC 1 83: #define DMC_RPTMO 10 84: #define DMC_RPDCK 10 85: 86: struct dmc_command { 87: char qp_cmd; /* command */ 88: short qp_ubaddr; /* buffer address */ 89: short qp_cc; /* character count || XMEM */ 90: struct dmc_command *qp_next; /* next command on queue */ 91: }; 92: 93: struct dmcbufs { 94: int ubinfo; /* from uballoc */ 95: short cc; /* buffer size */ 96: short flags; /* access control */ 97: }; 98: #define DBUF_OURS 0 /* buffer is available */ 99: #define DBUF_DMCS 1 /* buffer claimed by somebody */ 100: #define DBUF_XMIT 4 /* transmit buffer */ 101: #define DBUF_RCV 8 /* receive buffer */ 102: 103: 104: /* 105: * DMC software status per interface. 106: * 107: * Each interface is referenced by a network interface structure, 108: * sc_if, which the routing code uses to locate the interface. 109: * This structure contains the output queue for the interface, its address, ... 110: * We also have, for each interface, a set of 7 UBA interface structures 111: * for each, which 112: * contain information about the UNIBUS resources held by the interface: 113: * map registers, buffered data paths, etc. Information is cached in this 114: * structure for use by the if_uba.c routines in running the interface 115: * efficiently. 116: */ 117: struct dmc_softc { 118: struct ifnet sc_if; /* network-visible interface */ 119: struct dmcbufs sc_rbufs[NRCV]; /* receive buffer info */ 120: struct dmcbufs sc_xbufs[NXMT]; /* transmit buffer info */ 121: struct ifubinfo sc_ifuba; /* UNIBUS resources */ 122: struct ifrw sc_ifr[NRCV]; /* UNIBUS receive buffer maps */ 123: struct ifxmt sc_ifw[NXMT]; /* UNIBUS receive buffer maps */ 124: short sc_oused; /* output buffers currently in use */ 125: short sc_iused; /* input buffers given to DMC */ 126: short sc_flag; /* flags */ 127: int sc_nticks; /* seconds since last interrupt */ 128: int sc_ubinfo; /* UBA mapping info for base table */ 129: int sc_errors[4]; /* non-fatal error counters */ 130: #define sc_datck sc_errors[0] 131: #define sc_timeo sc_errors[1] 132: #define sc_nobuf sc_errors[2] 133: #define sc_disc sc_errors[3] 134: /* command queue stuff */ 135: struct dmc_command sc_cmdbuf[NCMDS]; 136: struct dmc_command *sc_qhead; /* head of command queue */ 137: struct dmc_command *sc_qtail; /* tail of command queue */ 138: struct dmc_command *sc_qactive; /* command in progress */ 139: struct dmc_command *sc_qfreeh; /* head of list of free cmd buffers */ 140: struct dmc_command *sc_qfreet; /* tail of list of free cmd buffers */ 141: /* end command queue stuff */ 142: } dmc_softc[NDMC]; 143: 144: /* flags */ 145: #define DMC_ALLOC 0x01 /* unibus resources allocated */ 146: #define DMC_BMAPPED 0x02 /* base table mapped */ 147: #define DMC_RESTART 0x04 /* software restart in progress */ 148: #define DMC_ACTIVE 0x08 /* device active */ 149: #define DMC_RUNNING 0x20 /* device initialized */ 150: 151: struct dmc_base { 152: short d_base[128]; /* DMC base table */ 153: } dmc_base[NDMC]; 154: 155: /* queue manipulation macros */ 156: #define QUEUE_AT_HEAD(qp, head, tail) \ 157: (qp)->qp_next = (head); \ 158: (head) = (qp); \ 159: if ((tail) == (struct dmc_command *) 0) \ 160: (tail) = (head) 161: 162: #define QUEUE_AT_TAIL(qp, head, tail) \ 163: if ((tail)) \ 164: (tail)->qp_next = (qp); \ 165: else \ 166: (head) = (qp); \ 167: (qp)->qp_next = (struct dmc_command *) 0; \ 168: (tail) = (qp) 169: 170: #define DEQUEUE(head, tail) \ 171: (head) = (head)->qp_next;\ 172: if ((head) == (struct dmc_command *) 0)\ 173: (tail) = (head) 174: 175: dmcprobe(reg) 176: caddr_t reg; 177: { 178: register int br, cvec; 179: register struct dmcdevice *addr = (struct dmcdevice *)reg; 180: register int i; 181: 182: #ifdef lint 183: br = 0; cvec = br; br = cvec; 184: dmcrint(0); dmcxint(0); 185: #endif 186: addr->bsel1 = DMC_MCLR; 187: for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--) 188: ; 189: if ((addr->bsel1 & DMC_RUN) == 0) { 190: printf("dmcprobe: can't start device\n" ); 191: return (0); 192: } 193: addr->bsel0 = DMC_RQI|DMC_IEI; 194: /* let's be paranoid */ 195: addr->bsel0 |= DMC_RQI|DMC_IEI; 196: DELAY(1000000); 197: addr->bsel1 = DMC_MCLR; 198: for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--) 199: ; 200: return (1); 201: } 202: 203: /* 204: * Interface exists: make available by filling in network interface 205: * record. System will initialize the interface when it is ready 206: * to accept packets. 207: */ 208: dmcattach(ui) 209: register struct uba_device *ui; 210: { 211: register struct dmc_softc *sc = &dmc_softc[ui->ui_unit]; 212: 213: sc->sc_if.if_unit = ui->ui_unit; 214: sc->sc_if.if_name = "dmc"; 215: sc->sc_if.if_mtu = DMCMTU; 216: sc->sc_if.if_init = dmcinit; 217: sc->sc_if.if_output = dmcoutput; 218: sc->sc_if.if_ioctl = dmcioctl; 219: sc->sc_if.if_reset = dmcreset; 220: sc->sc_if.if_flags = IFF_POINTOPOINT; 221: sc->sc_ifuba.iff_flags = UBA_CANTWAIT; 222: 223: if (dmctimer == 0) { 224: dmctimer = 1; 225: timeout(dmcwatch, (caddr_t) 0, hz); 226: } 227: if_attach(&sc->sc_if); 228: } 229: 230: /* 231: * Reset of interface after UNIBUS reset. 232: * If interface is on specified UBA, reset its state. 233: */ 234: dmcreset(unit, uban) 235: int unit, uban; 236: { 237: register struct uba_device *ui; 238: register struct dmc_softc *sc = &dmc_softc[unit]; 239: 240: if (unit >= NDMC || (ui = dmcinfo[unit]) == 0 || ui->ui_alive == 0 || 241: ui->ui_ubanum != uban) 242: return; 243: printf(" dmc%d", unit); 244: sc->sc_flag = 0; 245: sc->sc_if.if_flags &= ~IFF_RUNNING; 246: dmcinit(unit); 247: } 248: 249: /* 250: * Initialization of interface; reinitialize UNIBUS usage. 251: */ 252: dmcinit(unit) 253: int unit; 254: { 255: register struct dmc_softc *sc = &dmc_softc[unit]; 256: register struct uba_device *ui = dmcinfo[unit]; 257: register struct dmcdevice *addr; 258: register struct ifnet *ifp = &sc->sc_if; 259: register struct ifrw *ifrw; 260: register struct ifxmt *ifxp; 261: register struct dmcbufs *rp; 262: register struct dmc_command *qp; 263: struct ifaddr *ifa; 264: int base; 265: int s; 266: 267: addr = (struct dmcdevice *)ui->ui_addr; 268: 269: /* 270: * Check to see that an address has been set 271: * (both local and destination for an address family). 272: */ 273: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 274: if (ifa->ifa_addr.sa_family && ifa->ifa_dstaddr.sa_family) 275: break; 276: if (ifa == (struct ifaddr *) 0) 277: return; 278: 279: if ((addr->bsel1&DMC_RUN) == 0) { 280: printf("dmcinit: DMC not running\n"); 281: ifp->if_flags &= ~IFF_UP; 282: return; 283: } 284: /* map base table */ 285: if ((sc->sc_flag & DMC_BMAPPED) == 0) { 286: sc->sc_ubinfo = uballoc(ui->ui_ubanum, 287: (caddr_t)&dmc_base[unit], sizeof (struct dmc_base), 0); 288: sc->sc_flag |= DMC_BMAPPED; 289: } 290: /* initialize UNIBUS resources */ 291: sc->sc_iused = sc->sc_oused = 0; 292: if ((ifp->if_flags & IFF_RUNNING) == 0) { 293: if (if_ubaminit(&sc->sc_ifuba, ui->ui_ubanum, 294: sizeof(struct dmc_header), (int)btoc(DMCMTU), 295: sc->sc_ifr, NRCV, sc->sc_ifw, NXMT) == 0) { 296: printf("dmc%d: can't allocate uba resources\n", unit); 297: ifp->if_flags &= ~IFF_UP; 298: return; 299: } 300: ifp->if_flags |= IFF_RUNNING; 301: } 302: sc->sc_flag |= DMC_RUNNING; 303: 304: /* initialize buffer pool */ 305: /* receives */ 306: ifrw = &sc->sc_ifr[0]; 307: for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) { 308: rp->ubinfo = ifrw->ifrw_info & 0x3ffff; 309: rp->cc = DMCMTU + sizeof (struct dmc_header); 310: rp->flags = DBUF_OURS|DBUF_RCV; 311: ifrw++; 312: } 313: /* transmits */ 314: ifxp = &sc->sc_ifw[0]; 315: for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[NXMT]; rp++) { 316: rp->ubinfo = ifxp->ifw_info & 0x3ffff; 317: rp->cc = 0; 318: rp->flags = DBUF_OURS|DBUF_XMIT; 319: ifxp++; 320: } 321: 322: /* set up command queues */ 323: sc->sc_qfreeh = sc->sc_qfreet 324: = sc->sc_qhead = sc->sc_qtail = sc->sc_qactive = 325: (struct dmc_command *)0; 326: /* set up free command buffer list */ 327: for (qp = &sc->sc_cmdbuf[0]; qp < &sc->sc_cmdbuf[NCMDS]; qp++) { 328: QUEUE_AT_HEAD(qp, sc->sc_qfreeh, sc->sc_qfreet); 329: } 330: 331: /* base in */ 332: base = sc->sc_ubinfo & 0x3ffff; 333: dmcload(sc, DMC_BASEI, base, (base>>2) & DMC_XMEM); 334: /* specify half duplex operation, flags tell if primary */ 335: /* or secondary station */ 336: if (ui->ui_flags == 0) 337: /* use DDCMP mode in full duplex */ 338: dmcload(sc, DMC_CNTLI, 0, 0); 339: else if (ui->ui_flags == 1) 340: /* use MAINTENENCE mode */ 341: dmcload(sc, DMC_CNTLI, 0, DMC_MAINT ); 342: else if (ui->ui_flags == 2) 343: /* use DDCMP half duplex as primary station */ 344: dmcload(sc, DMC_CNTLI, 0, DMC_HDPLX); 345: else if (ui->ui_flags == 3) 346: /* use DDCMP half duplex as secondary station */ 347: dmcload(sc, DMC_CNTLI, 0, DMC_HDPLX | DMC_SEC); 348: 349: /* enable operation done interrupts */ 350: sc->sc_flag &= ~DMC_ACTIVE; 351: while ((addr->bsel2 & DMC_IEO) == 0) 352: addr->bsel2 |= DMC_IEO; 353: s = spl5(); 354: /* queue first NRCV buffers for DMC to fill */ 355: for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) { 356: rp->flags |= DBUF_DMCS; 357: dmcload(sc, DMC_READ, rp->ubinfo, 358: (((rp->ubinfo>>2)&DMC_XMEM) | rp->cc)); 359: sc->sc_iused++; 360: } 361: splx(s); 362: } 363: 364: /* 365: * Start output on interface. Get another datagram 366: * to send from the interface queue and map it to 367: * the interface before starting output. 368: * 369: * Must be called at spl 5 370: */ 371: dmcstart(dev) 372: dev_t dev; 373: { 374: int unit = minor(dev); 375: register struct dmc_softc *sc = &dmc_softc[unit]; 376: struct mbuf *m; 377: register struct dmcbufs *rp; 378: register int n; 379: 380: /* 381: * Dequeue up to NXMT requests and map them to the UNIBUS. 382: * If no more requests, or no dmc buffers available, just return. 383: */ 384: n = 0; 385: for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[NXMT]; rp++ ) { 386: /* find an available buffer */ 387: if ((rp->flags & DBUF_DMCS) == 0) { 388: IF_DEQUEUE(&sc->sc_if.if_snd, m); 389: if (m == 0) 390: return; 391: /* mark it dmcs */ 392: rp->flags |= (DBUF_DMCS); 393: /* 394: * Have request mapped to UNIBUS for transmission 395: * and start the output. 396: */ 397: rp->cc = if_ubaput(&sc->sc_ifuba, &sc->sc_ifw[n], m); 398: rp->cc &= DMC_CCOUNT; 399: sc->sc_oused++; 400: dmcload(sc, DMC_WRITE, rp->ubinfo, 401: rp->cc | ((rp->ubinfo>>2)&DMC_XMEM)); 402: } 403: n++; 404: } 405: } 406: 407: /* 408: * Utility routine to load the DMC device registers. 409: */ 410: dmcload(sc, type, w0, w1) 411: register struct dmc_softc *sc; 412: int type, w0, w1; 413: { 414: register struct dmcdevice *addr; 415: register int unit, sps; 416: register struct dmc_command *qp; 417: 418: unit = sc - dmc_softc; 419: addr = (struct dmcdevice *)dmcinfo[unit]->ui_addr; 420: sps = spl5(); 421: 422: /* grab a command buffer from the free list */ 423: if ((qp = sc->sc_qfreeh) == (struct dmc_command *)0) 424: panic("dmc command queue overflow"); 425: DEQUEUE(sc->sc_qfreeh, sc->sc_qfreet); 426: 427: /* fill in requested info */ 428: qp->qp_cmd = (type | DMC_RQI); 429: qp->qp_ubaddr = w0; 430: qp->qp_cc = w1; 431: 432: if (sc->sc_qactive) { /* command in progress */ 433: if (type == DMC_READ) { 434: QUEUE_AT_HEAD(qp, sc->sc_qhead, sc->sc_qtail); 435: } else { 436: QUEUE_AT_TAIL(qp, sc->sc_qhead, sc->sc_qtail); 437: } 438: } else { /* command port free */ 439: sc->sc_qactive = qp; 440: addr->bsel0 = qp->qp_cmd; 441: dmcrint(unit); 442: } 443: splx(sps); 444: } 445: 446: /* 447: * DMC interface receiver interrupt. 448: * Ready to accept another command, 449: * pull one off the command queue. 450: */ 451: dmcrint(unit) 452: int unit; 453: { 454: register struct dmc_softc *sc; 455: register struct dmcdevice *addr; 456: register struct dmc_command *qp; 457: register int n; 458: 459: addr = (struct dmcdevice *)dmcinfo[unit]->ui_addr; 460: sc = &dmc_softc[unit]; 461: if ((qp = sc->sc_qactive) == (struct dmc_command *) 0) { 462: printf("dmc%d: dmcrint no command\n", unit); 463: return; 464: } 465: while (addr->bsel0&DMC_RDYI) { 466: addr->sel4 = qp->qp_ubaddr; 467: addr->sel6 = qp->qp_cc; 468: addr->bsel0 &= ~(DMC_IEI|DMC_RQI); 469: /* free command buffer */ 470: QUEUE_AT_HEAD(qp, sc->sc_qfreeh, sc->sc_qfreet); 471: while (addr->bsel0 & DMC_RDYI) { 472: /* 473: * Can't check for RDYO here 'cause 474: * this routine isn't reentrant! 475: */ 476: DELAY(5); 477: } 478: /* move on to next command */ 479: if ((sc->sc_qactive = sc->sc_qhead) == (struct dmc_command *)0) 480: break; /* all done */ 481: /* more commands to do, start the next one */ 482: qp = sc->sc_qactive; 483: DEQUEUE(sc->sc_qhead, sc->sc_qtail); 484: addr->bsel0 = qp->qp_cmd; 485: n = RDYSCAN; 486: while (n-- > 0) 487: if ((addr->bsel0&DMC_RDYI) || (addr->bsel2&DMC_RDYO)) 488: break; 489: } 490: if (sc->sc_qactive) { 491: addr->bsel0 |= DMC_IEI|DMC_RQI; 492: /* VMS does it twice !*$%@# */ 493: addr->bsel0 |= DMC_IEI|DMC_RQI; 494: } 495: 496: } 497: 498: /* 499: * DMC interface transmitter interrupt. 500: * A transfer may have completed, check for errors. 501: * If it was a read, notify appropriate protocol. 502: * If it was a write, pull the next one off the queue. 503: */ 504: dmcxint(unit) 505: int unit; 506: { 507: register struct dmc_softc *sc; 508: register struct ifnet *ifp; 509: struct uba_device *ui = dmcinfo[unit]; 510: struct dmcdevice *addr; 511: struct mbuf *m; 512: struct ifqueue *inq; 513: int arg, pkaddr, cmd, len, s; 514: register struct ifrw *ifrw; 515: register struct dmcbufs *rp; 516: register struct ifxmt *ifxp; 517: struct dmc_header *dh; 518: int off, resid; 519: 520: addr = (struct dmcdevice *)ui->ui_addr; 521: sc = &dmc_softc[unit]; 522: ifp = &sc->sc_if; 523: 524: while (addr->bsel2 & DMC_RDYO) { 525: 526: cmd = addr->bsel2 & 0xff; 527: arg = addr->sel6 & 0xffff; 528: /* reconstruct UNIBUS address of buffer returned to us */ 529: pkaddr = ((arg&DMC_XMEM)<<2) | (addr->sel4 & 0xffff); 530: /* release port */ 531: addr->bsel2 &= ~DMC_RDYO; 532: switch (cmd & 07) { 533: 534: case DMC_OUR: 535: /* 536: * A read has completed. 537: * Pass packet to type specific 538: * higher-level input routine. 539: */ 540: ifp->if_ipackets++; 541: /* find location in dmcuba struct */ 542: ifrw= &sc->sc_ifr[0]; 543: for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) { 544: if(rp->ubinfo == pkaddr) 545: break; 546: ifrw++; 547: } 548: if (rp >= &sc->sc_rbufs[NRCV]) 549: panic("dmc rcv"); 550: if ((rp->flags & DBUF_DMCS) == 0) 551: printf("dmc%d: done unalloc rbuf\n", unit); 552: 553: len = (arg & DMC_CCOUNT) - sizeof (struct dmc_header); 554: if (len < 0 || len > DMCMTU) { 555: ifp->if_ierrors++; 556: printd("dmc%d: bad rcv pkt addr 0x%x len 0x%x\n", 557: unit, pkaddr, len); 558: goto setup; 559: } 560: /* 561: * Deal with trailer protocol: if type is trailer 562: * get true type from first 16-bit word past data. 563: * Remember that type was trailer by setting off. 564: */ 565: dh = (struct dmc_header *)ifrw->ifrw_addr; 566: dh->dmc_type = ntohs((u_short)dh->dmc_type); 567: #define dmcdataaddr(dh, off, type) ((type)(((caddr_t)((dh)+1)+(off)))) 568: if (dh->dmc_type >= DMC_TRAILER && 569: dh->dmc_type < DMC_TRAILER+DMC_NTRAILER) { 570: off = (dh->dmc_type - DMC_TRAILER) * 512; 571: if (off >= DMCMTU) 572: goto setup; /* sanity */ 573: dh->dmc_type = ntohs(*dmcdataaddr(dh, off, u_short *)); 574: resid = ntohs(*(dmcdataaddr(dh, off+2, u_short *))); 575: if (off + resid > len) 576: goto setup; /* sanity */ 577: len = off + resid; 578: } else 579: off = 0; 580: if (len == 0) 581: goto setup; 582: 583: /* 584: * Pull packet off interface. Off is nonzero if 585: * packet has trailing header; dmc_get will then 586: * force this header information to be at the front, 587: * but we still have to drop the type and length 588: * which are at the front of any trailer data. 589: */ 590: m = if_ubaget(&sc->sc_ifuba, ifrw, len, off, ifp); 591: if (m == 0) 592: goto setup; 593: if (off) { 594: ifp = *(mtod(m, struct ifnet **)); 595: m->m_off += 2 * sizeof (u_short); 596: m->m_len -= 2 * sizeof (u_short); 597: *(mtod(m, struct ifnet **)) = ifp; 598: } 599: switch (dh->dmc_type) { 600: 601: #ifdef INET 602: case DMC_IPTYPE: 603: schednetisr(NETISR_IP); 604: inq = &ipintrq; 605: break; 606: #endif 607: default: 608: m_freem(m); 609: goto setup; 610: } 611: 612: s = splimp(); 613: if (IF_QFULL(inq)) { 614: IF_DROP(inq); 615: m_freem(m); 616: } else 617: IF_ENQUEUE(inq, m); 618: splx(s); 619: 620: setup: 621: /* is this needed? */ 622: rp->ubinfo = ifrw->ifrw_info & 0x3ffff; 623: 624: dmcload(sc, DMC_READ, rp->ubinfo, 625: ((rp->ubinfo >> 2) & DMC_XMEM) | rp->cc); 626: break; 627: 628: case DMC_OUX: 629: /* 630: * A write has completed, start another 631: * transfer if there is more data to send. 632: */ 633: ifp->if_opackets++; 634: /* find associated dmcbuf structure */ 635: ifxp = &sc->sc_ifw[0]; 636: for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[NXMT]; rp++) { 637: if(rp->ubinfo == pkaddr) 638: break; 639: ifxp++; 640: } 641: if (rp >= &sc->sc_xbufs[NXMT]) { 642: printf("dmc%d: bad packet address 0x%x\n", 643: unit, pkaddr); 644: break; 645: } 646: if ((rp->flags & DBUF_DMCS) == 0) 647: printf("dmc%d: unallocated packet 0x%x\n", 648: unit, pkaddr); 649: /* mark buffer free */ 650: if (ifxp->ifw_xtofree) { 651: (void)m_freem(ifxp->ifw_xtofree); 652: ifxp->ifw_xtofree = 0; 653: } 654: rp->flags &= ~DBUF_DMCS; 655: sc->sc_oused--; 656: sc->sc_nticks = 0; 657: sc->sc_flag |= DMC_ACTIVE; 658: break; 659: 660: case DMC_CNTLO: 661: arg &= DMC_CNTMASK; 662: if (arg & DMC_FATAL) { 663: log(LOG_ERR, "dmc%d: fatal error, flags=%b\n", 664: unit, arg, CNTLO_BITS); 665: dmcrestart(unit); 666: break; 667: } 668: /* ACCUMULATE STATISTICS */ 669: switch(arg) { 670: case DMC_NOBUFS: 671: ifp->if_ierrors++; 672: if ((sc->sc_nobuf++ % DMC_RPNBFS) == 0) 673: goto report; 674: break; 675: case DMC_DISCONN: 676: if ((sc->sc_disc++ % DMC_RPDSC) == 0) 677: goto report; 678: break; 679: case DMC_TIMEOUT: 680: if ((sc->sc_timeo++ % DMC_RPTMO) == 0) 681: goto report; 682: break; 683: case DMC_DATACK: 684: ifp->if_oerrors++; 685: if ((sc->sc_datck++ % DMC_RPDCK) == 0) 686: goto report; 687: break; 688: default: 689: goto report; 690: } 691: break; 692: report: 693: printd("dmc%d: soft error, flags=%b\n", unit, 694: arg, CNTLO_BITS); 695: if ((sc->sc_flag & DMC_RESTART) == 0) { 696: /* 697: * kill off the dmc to get things 698: * going again by generating a 699: * procedure error 700: */ 701: sc->sc_flag |= DMC_RESTART; 702: arg = sc->sc_ubinfo & 0x3ffff; 703: dmcload(sc, DMC_BASEI, arg, (arg>>2)&DMC_XMEM); 704: } 705: break; 706: 707: default: 708: printf("dmc%d: bad control %o\n", unit, cmd); 709: break; 710: } 711: } 712: dmcstart(unit); 713: return; 714: } 715: 716: /* 717: * DMC output routine. 718: * Encapsulate a packet of type family for the dmc. 719: * Use trailer local net encapsulation if enough data in first 720: * packet leaves a multiple of 512 bytes of data in remainder. 721: */ 722: dmcoutput(ifp, m0, dst) 723: register struct ifnet *ifp; 724: register struct mbuf *m0; 725: struct sockaddr *dst; 726: { 727: int type, error, s; 728: register struct mbuf *m = m0; 729: register struct dmc_header *dh; 730: register int off; 731: 732: switch (dst->sa_family) { 733: #ifdef INET 734: case AF_INET: 735: off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; 736: if ((ifp->if_flags & IFF_NOTRAILERS) == 0) 737: if (off > 0 && (off & 0x1ff) == 0 && 738: m->m_off >= MMINOFF + 2 * sizeof (u_short)) { 739: type = DMC_TRAILER + (off>>9); 740: m->m_off -= 2 * sizeof (u_short); 741: m->m_len += 2 * sizeof (u_short); 742: *mtod(m, u_short *) = htons((u_short)DMC_IPTYPE); 743: *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); 744: goto gottrailertype; 745: } 746: type = DMC_IPTYPE; 747: off = 0; 748: goto gottype; 749: #endif 750: 751: case AF_UNSPEC: 752: dh = (struct dmc_header *)dst->sa_data; 753: type = dh->dmc_type; 754: goto gottype; 755: 756: default: 757: printf("dmc%d: can't handle af%d\n", ifp->if_unit, 758: dst->sa_family); 759: error = EAFNOSUPPORT; 760: goto bad; 761: } 762: 763: gottrailertype: 764: /* 765: * Packet to be sent as a trailer; move first packet 766: * (control information) to end of chain. 767: */ 768: while (m->m_next) 769: m = m->m_next; 770: m->m_next = m0; 771: m = m0->m_next; 772: m0->m_next = 0; 773: m0 = m; 774: 775: gottype: 776: /* 777: * Add local network header 778: * (there is space for a uba on a vax to step on) 779: */ 780: if (m->m_off > MMAXOFF || 781: MMINOFF + sizeof(struct dmc_header) > m->m_off) { 782: m = m_get(M_DONTWAIT, MT_HEADER); 783: if (m == 0) { 784: error = ENOBUFS; 785: goto bad; 786: } 787: m->m_next = m0; 788: m->m_off = MMINOFF; 789: m->m_len = sizeof (struct dmc_header); 790: } else { 791: m->m_off -= sizeof (struct dmc_header); 792: m->m_len += sizeof (struct dmc_header); 793: } 794: dh = mtod(m, struct dmc_header *); 795: dh->dmc_type = htons((u_short)type); 796: 797: /* 798: * Queue message on interface, and start output if interface 799: * not yet active. 800: */ 801: s = splimp(); 802: if (IF_QFULL(&ifp->if_snd)) { 803: IF_DROP(&ifp->if_snd); 804: m_freem(m); 805: splx(s); 806: return (ENOBUFS); 807: } 808: IF_ENQUEUE(&ifp->if_snd, m); 809: dmcstart(ifp->if_unit); 810: splx(s); 811: return (0); 812: 813: bad: 814: m_freem(m0); 815: return (error); 816: } 817: 818: 819: /* 820: * Process an ioctl request. 821: */ 822: /* ARGSUSED */ 823: dmcioctl(ifp, cmd, data) 824: register struct ifnet *ifp; 825: int cmd; 826: caddr_t data; 827: { 828: int s = splimp(), error = 0; 829: register struct dmc_softc *sc = &dmc_softc[ifp->if_unit]; 830: 831: switch (cmd) { 832: 833: case SIOCSIFADDR: 834: ifp->if_flags |= IFF_UP; 835: if ((ifp->if_flags & IFF_RUNNING) == 0) 836: dmcinit(ifp->if_unit); 837: break; 838: 839: case SIOCSIFDSTADDR: 840: if ((ifp->if_flags & IFF_RUNNING) == 0) 841: dmcinit(ifp->if_unit); 842: break; 843: 844: case SIOCSIFFLAGS: 845: if ((ifp->if_flags & IFF_UP) == 0 && 846: sc->sc_flag & DMC_RUNNING) { 847: ((struct dmcdevice *) 848: (dmcinfo[ifp->if_unit]->ui_addr))->bsel1 = DMC_MCLR; 849: sc->sc_flag &= ~DMC_RUNNING; 850: } else if (ifp->if_flags & IFF_UP && 851: (sc->sc_flag & DMC_RUNNING) == 0) 852: dmcrestart(ifp->if_unit); 853: break; 854: 855: default: 856: error = EINVAL; 857: } 858: splx(s); 859: return (error); 860: } 861: 862: /* 863: * Restart after a fatal error. 864: * Clear device and reinitialize. 865: */ 866: dmcrestart(unit) 867: int unit; 868: { 869: register struct dmc_softc *sc = &dmc_softc[unit]; 870: register struct uba_device *ui = dmcinfo[unit]; 871: register struct dmcdevice *addr; 872: register struct ifxmt *ifxp; 873: register int i; 874: 875: addr = (struct dmcdevice *)ui->ui_addr; 876: #ifdef DEBUG 877: /* dump base table */ 878: printf("dmc%d base table:\n", unit); 879: for (i = 0; i < sizeof (struct dmc_base); i++) 880: printf("%o\n" ,dmc_base[unit].d_base[i]); 881: #endif 882: /* 883: * Let the DMR finish the MCLR. At 1 Mbit, it should do so 884: * in about a max of 6.4 milliseconds with diagnostics enabled. 885: */ 886: addr->bsel1 = DMC_MCLR; 887: for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--) 888: ; 889: /* Did the timer expire or did the DMR finish? */ 890: if ((addr->bsel1 & DMC_RUN) == 0) { 891: log(LOG_ERR, "dmc%d: M820 Test Failed\n", unit); 892: return; 893: } 894: 895: for (ifxp = sc->sc_ifw; ifxp < &sc->sc_ifw[NXMT]; ifxp++) { 896: if (ifxp->ifw_xtofree) { 897: (void) m_freem(ifxp->ifw_xtofree); 898: ifxp->ifw_xtofree = 0; 899: } 900: } 901: 902: /* restart DMC */ 903: dmcinit(unit); 904: sc->sc_flag &= ~DMC_RESTART; 905: sc->sc_if.if_collisions++; /* why not? */ 906: } 907: 908: /* 909: * Check to see that transmitted packets don't 910: * lose interrupts. The device has to be active. 911: */ 912: dmcwatch() 913: { 914: register struct uba_device *ui; 915: register struct dmc_softc *sc; 916: struct dmcdevice *addr; 917: register int i; 918: 919: for (i = 0; i < NDMC; i++) { 920: sc = &dmc_softc[i]; 921: if ((sc->sc_flag & DMC_ACTIVE) == 0) 922: continue; 923: if ((ui = dmcinfo[i]) == 0 || ui->ui_alive == 0) 924: continue; 925: if (sc->sc_oused) { 926: sc->sc_nticks++; 927: if (sc->sc_nticks > dmc_timeout) { 928: sc->sc_nticks = 0; 929: addr = (struct dmcdevice *)ui->ui_addr; 930: log(LOG_ERR, "dmc%d hung: bsel0=%b bsel2=%b\n", 931: i, addr->bsel0 & 0xff, DMC0BITS, 932: addr->bsel2 & 0xff, DMC2BITS); 933: dmcrestart(i); 934: } 935: } 936: } 937: timeout(dmcwatch, (caddr_t) 0, hz); 938: } 939: #endif