1 /* 2 * @(#)if_dmv.c 7.3 (Berkeley) 05/27/88 3 * DMV-11 Driver 4 * 5 * Qbus Sync DDCMP interface - DMV operated in full duplex, point to point mode 6 * 7 * Derived from 4.3 release if_dmv.c rev. 6.12 dated 4/23/86 8 * (which wasn't the 4.3 release!) 9 * 10 * Bob Kridle 11 * mt Xinu 12 */ 13 14 #include "dmv.h" 15 #if NDMV > 0 16 17 #include "param.h" 18 #include "systm.h" 19 #include "mbuf.h" 20 #include "buf.h" 21 #include "ioctl.h" /* must precede tty.h */ 22 #include "tty.h" 23 #include "protosw.h" 24 #include "socket.h" 25 #include "syslog.h" 26 #include "vmmac.h" 27 #include "errno.h" 28 #include "time.h" 29 #include "kernel.h" 30 31 #include "../net/if.h" 32 #include "../net/netisr.h" 33 #include "../net/route.h" 34 35 #ifdef INET 36 #include "../netinet/in.h" 37 #include "../netinet/in_systm.h" 38 #include "../netinet/in_var.h" 39 #include "../netinet/ip.h" 40 #endif 41 42 #include "../vax/cpu.h" 43 #include "../vax/mtpr.h" 44 #include "../vax/pte.h" 45 #include "../vaxuba/ubareg.h" 46 #include "../vaxuba/ubavar.h" 47 #include "if_uba.h" 48 #include "if_dmv.h" 49 50 int dmv_timeout = 8; /* timeout value */ 51 52 /* 53 * Driver information for auto-configuration stuff. 54 */ 55 int dmvprobe(), dmvattach(), dmvinit(), dmvioctl(); 56 int dmvoutput(), dmvreset(), dmvtimeout(); 57 struct uba_device *dmvinfo[NDMV]; 58 u_short dmvstd[] = { 0 }; 59 struct uba_driver dmvdriver = 60 { dmvprobe, 0, dmvattach, 0, dmvstd, "dmv", dmvinfo }; 61 62 /* 63 * Don't really know how many buffers/commands can be queued to a DMV-11. 64 * Manual doesn't say... Perhaps we can look at a DEC driver some day. 65 * These numbers ame from DMC/DMR driver. 66 */ 67 #define NRCV 5 68 #define NXMT 3 69 #define NCMDS (NRCV+NXMT+4) /* size of command queue */ 70 71 #ifdef DEBUG 72 #define printd(f) if (sc->sc_if.if_flags & IFF_DEBUG) \ 73 printf("DMVDEBUG: dmv%d: ", unit), printf(f) 74 #else 75 #define printd(f) /* nil */ 76 #endif 77 78 /* error reporting intervals */ 79 80 #define DMV_RPRTE 1 81 #define DMV_RPTTE 1 82 #define DMV_RPSTE 1 83 #define DMV_RPNXM 1 84 #define DMV_RPMODD 1 85 #define DMV_RPQOVF 1 86 #define DMV_RPCXRL 1 87 88 /* number of errors to accept before trying a reset */ 89 #define DMV_RPUNKNOWN 10 90 91 struct dmv_command { 92 u_char qp_mask; /* Which registers to set up */ 93 #define QP_TRIB 0x01 94 #define QP_SEL4 0x02 95 #define QP_SEL6 0x04 96 #define QP_SEL10 0x08 97 u_char qp_cmd; 98 u_char qp_tributary; 99 u_short qp_sel4; 100 u_short qp_sel6; 101 u_short qp_sel10; 102 struct dmv_command *qp_next; /* next command on queue */ 103 }; 104 105 #define qp_lowbufaddr qp_ 106 107 struct dmvbufs { 108 int ubinfo; /* from uballoc */ 109 short cc; /* buffer size */ 110 short flags; /* access control */ 111 }; 112 113 #define DBUF_OURS 0 /* buffer is available */ 114 #define DBUF_DMVS 1 /* buffer claimed by somebody */ 115 #define DBUF_XMIT 4 /* transmit buffer */ 116 #define DBUF_RCV 8 /* receive buffer */ 117 118 119 /* 120 * DMV software status per interface. 121 * 122 * Each interface is referenced by a network interface structure, 123 * sc_if, which the routing code uses to locate the interface. 124 * This structure contains the output queue for the interface, its address, ... 125 * We also have, for each interface, a set of 7 UBA interface structures 126 * for each, which 127 * contain information about the UNIBUS resources held by the interface: 128 * map registers, buffered data paths, etc. Information is cached in this 129 * structure for use by the if_uba.c routines in running the interface 130 * efficiently. 131 */ 132 struct dmv_softc { 133 struct ifnet sc_if; /* network-visible interface */ 134 short sc_oused; /* output buffers currently in use */ 135 short sc_iused; /* input buffers given to DMV */ 136 short sc_flag; /* flags */ 137 int sc_ubinfo; /* UBA mapping info for base table */ 138 int sc_errors[8]; /* error counters */ 139 #define sc_rte sc_errors[0] /* receive threshhold error */ 140 #define sc_xte sc_errors[1] /* xmit threshhold error */ 141 #define sc_ste sc_errors[2] /* select threshhold error */ 142 #define sc_nxm sc_errors[3] /* non-existant memory */ 143 #define sc_modd sc_errors[4] /* modem disconnect */ 144 #define sc_qovf sc_errors[5] /* command/response queue overflow */ 145 #define sc_cxrl sc_errors[6] /* carrier loss */ 146 #define sc_unknown sc_errors[7] /* other errors - look in DMV manual */ 147 struct dmvbufs sc_rbufs[NRCV]; /* receive buffer info */ 148 struct dmvbufs sc_xbufs[NXMT]; /* transmit buffer info */ 149 struct ifubinfo sc_ifuba; /* UNIBUS resources */ 150 struct ifrw sc_ifr[NRCV]; /* UNIBUS receive buffer maps */ 151 struct ifxmt sc_ifw[NXMT]; /* UNIBUS receive buffer maps */ 152 /* command queue stuff */ 153 struct dmv_command sc_cmdbuf[NCMDS]; 154 struct dmv_command *sc_qhead; /* head of command queue */ 155 struct dmv_command *sc_qtail; /* tail of command queue */ 156 struct dmv_command *sc_qactive; /* command in progress */ 157 struct dmv_command *sc_qfreeh; /* head of list of free cmd buffers */ 158 struct dmv_command *sc_qfreet; /* tail of list of free cmd buffers */ 159 /* end command queue stuff */ 160 } dmv_softc[NDMV]; 161 162 /* flags */ 163 #define DMV_RESTART 0x01 /* software restart in progress */ 164 #define DMV_ONLINE 0x02 /* device managed to transmit */ 165 #define DMV_RUNNING 0x04 /* device initialized */ 166 167 168 /* queue manipulation macros */ 169 #define QUEUE_AT_HEAD(qp, head, tail) \ 170 (qp)->qp_next = (head); \ 171 (head) = (qp); \ 172 if ((tail) == (struct dmv_command *) 0) \ 173 (tail) = (head) 174 175 #define QUEUE_AT_TAIL(qp, head, tail) \ 176 if ((tail)) \ 177 (tail)->qp_next = (qp); \ 178 else \ 179 (head) = (qp); \ 180 (qp)->qp_next = (struct dmv_command *) 0; \ 181 (tail) = (qp) 182 183 #define DEQUEUE(head, tail) \ 184 (head) = (head)->qp_next;\ 185 if ((head) == (struct dmv_command *) 0)\ 186 (tail) = (head) 187 188 dmvprobe(reg) 189 caddr_t reg; 190 { 191 register int br, cvec; 192 register struct dmvdevice *addr = (struct dmvdevice *)reg; 193 register int i; 194 195 #ifdef lint 196 br = 0; cvec = br; br = cvec; 197 dmvrint(0); dmvxint(0); 198 #endif 199 addr->bsel1 = DMV_MCLR; 200 for (i = 100000; i && (addr->bsel1 & DMV_RUN) == 0; i--) 201 ; 202 if ((addr->bsel1 & DMV_RUN) == 0) { 203 printf("dmvprobe: can't start device\n" ); 204 return (0); 205 } 206 if ((addr->bsel4 != 033) || (addr->bsel6 != 0305)) 207 { 208 printf("dmvprobe: device init failed, bsel4=%o, bsel6=%o\n", 209 addr->bsel4, addr->bsel6); 210 return (0); 211 } 212 addr->bsel0 = DMV_RQI|DMV_IEI|DMV_IEO; 213 DELAY(1000000); 214 addr->bsel1 = DMV_MCLR; 215 for (i = 100000; i && (addr->bsel1 & DMV_RUN) == 0; i--) 216 ; 217 br = 0x15; /* screwy interrupt structure */ 218 return (1); 219 } 220 221 /* 222 * Interface exists: make available by filling in network interface 223 * record. System will initialize the interface when it is ready 224 * to accept packets. 225 */ 226 dmvattach(ui) 227 register struct uba_device *ui; 228 { 229 register struct dmv_softc *sc = &dmv_softc[ui->ui_unit]; 230 231 sc->sc_if.if_unit = ui->ui_unit; 232 sc->sc_if.if_name = "dmv"; 233 sc->sc_if.if_mtu = DMVMTU; 234 sc->sc_if.if_init = dmvinit; 235 sc->sc_if.if_output = dmvoutput; 236 sc->sc_if.if_ioctl = dmvioctl; 237 sc->sc_if.if_reset = dmvreset; 238 sc->sc_if.if_watchdog = dmvtimeout; 239 sc->sc_if.if_flags = IFF_POINTOPOINT; 240 sc->sc_ifuba.iff_flags = UBA_CANTWAIT; 241 242 if_attach(&sc->sc_if); 243 } 244 245 /* 246 * Reset of interface after UNIBUS reset. 247 * If interface is on specified UBA, reset its state. 248 */ 249 dmvreset(unit, uban) 250 int unit, uban; 251 { 252 register struct uba_device *ui; 253 register struct dmv_softc *sc = &dmv_softc[unit]; 254 255 if (unit >= NDMV || (ui = dmvinfo[unit]) == 0 || ui->ui_alive == 0 || 256 ui->ui_ubanum != uban) 257 return; 258 printf(" dmv%d", unit); 259 sc->sc_flag = 0; 260 sc->sc_if.if_flags &= ~IFF_RUNNING; 261 dmvinit(unit); 262 } 263 264 /* 265 * Initialization of interface; reinitialize UNIBUS usage. 266 */ 267 dmvinit(unit) 268 int unit; 269 { 270 register struct dmv_softc *sc = &dmv_softc[unit]; 271 register struct uba_device *ui = dmvinfo[unit]; 272 register struct dmvdevice *addr; 273 register struct ifnet *ifp = &sc->sc_if; 274 register struct ifrw *ifrw; 275 register struct ifxmt *ifxp; 276 register struct dmvbufs *rp; 277 register struct dmv_command *qp; 278 struct ifaddr *ifa; 279 int base; 280 int s; 281 282 addr = (struct dmvdevice *)ui->ui_addr; 283 284 /* 285 * Check to see that an address has been set 286 * (both local and destination for an address family). 287 */ 288 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 289 if (ifa->ifa_addr.sa_family && ifa->ifa_dstaddr.sa_family) 290 break; 291 if (ifa == (struct ifaddr *) 0) 292 return; 293 294 if ((addr->bsel1&DMV_RUN) == 0) { 295 log(LOG_CRIT, "dmvinit: dmv%d not running\n", unit); 296 ifp->if_flags &= ~IFF_UP; 297 return; 298 } 299 printd(("dmvinit\n")); 300 /* initialize UNIBUS resources */ 301 sc->sc_iused = sc->sc_oused = 0; 302 if ((ifp->if_flags & IFF_RUNNING) == 0) { 303 if (if_ubaminit( 304 &sc->sc_ifuba, 305 ui->ui_ubanum, 306 sizeof(struct dmv_header), 307 (int)btoc(DMVMTU), 308 sc->sc_ifr, 309 NRCV, 310 sc->sc_ifw, 311 NXMT 312 ) == 0) { 313 log(LOG_CRIT, "dmvinit: dmv%d can't allocate uba resources\n", unit); 314 ifp->if_flags &= ~IFF_UP; 315 return; 316 } 317 ifp->if_flags |= IFF_RUNNING; 318 } 319 /* 320 * Limit packets enqueued until we see if we're on the air. 321 */ 322 ifp->if_snd.ifq_maxlen = 3; 323 324 325 /* initialize buffer pool */ 326 /* receives */ 327 ifrw = &sc->sc_ifr[0]; 328 for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) { 329 rp->ubinfo = ifrw->ifrw_info & 0x3ffff; 330 rp->cc = DMVMTU + sizeof (struct dmv_header); 331 rp->flags = DBUF_OURS|DBUF_RCV; 332 ifrw++; 333 } 334 /* transmits */ 335 ifxp = &sc->sc_ifw[0]; 336 for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[NXMT]; rp++) { 337 rp->ubinfo = ifxp->ifw_info & 0x3ffff; 338 rp->cc = 0; 339 rp->flags = DBUF_OURS|DBUF_XMIT; 340 ifxp++; 341 } 342 343 /* set up command queues */ 344 sc->sc_qfreeh = sc->sc_qfreet 345 = sc->sc_qhead = sc->sc_qtail = sc->sc_qactive = 346 (struct dmv_command *)0; 347 /* set up free command buffer list */ 348 for (qp = &sc->sc_cmdbuf[0]; qp < &sc->sc_cmdbuf[NCMDS]; qp++) { 349 QUEUE_AT_HEAD(qp, sc->sc_qfreeh, sc->sc_qfreet); 350 } 351 if(sc->sc_flag & DMV_RUNNING) 352 dmvload( sc, DMV_CNTRLI, (QP_TRIB|QP_SEL6), 1, 0, DMV_REQHS,0); 353 else 354 dmvload( sc, DMV_CNTRLI, (QP_TRIB|QP_SEL6), 1, 0, DMV_ESTTRIB,0); 355 dmvload( sc, DMV_CNTRLI, (QP_TRIB|QP_SEL6), 1, 0, DMV_REQSUS,0); 356 sc->sc_flag |= (DMV_RESTART|DMV_RUNNING); 357 sc->sc_flag &= ~DMV_ONLINE; 358 addr->bsel0 |= DMV_IEO; 359 } 360 361 /* 362 * Start output on interface. Get another datagram 363 * to send from the interface queue and map it to 364 * the interface before starting output. 365 * 366 * Must be called at spl 5 367 */ 368 dmvstart(dev) 369 dev_t dev; 370 { 371 int unit = minor(dev); 372 register struct dmv_softc *sc = &dmv_softc[unit]; 373 struct mbuf *m; 374 register struct dmvbufs *rp; 375 register int n; 376 377 /* 378 * Dequeue up to NXMT requests and map them to the UNIBUS. 379 * If no more requests, or no dmv buffers available, just return. 380 */ 381 printd(("dmvstart\n")); 382 n = 0; 383 for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[NXMT]; rp++ ) { 384 /* find an available buffer */ 385 if ((rp->flags & DBUF_DMVS) == 0) { 386 IF_DEQUEUE(&sc->sc_if.if_snd, m); 387 if (m == 0) 388 return; 389 /* mark it dmvs */ 390 rp->flags |= (DBUF_DMVS); 391 /* 392 * Have request mapped to UNIBUS for transmission 393 * and start the output. 394 */ 395 rp->cc = if_ubaput(&sc->sc_ifuba, &sc->sc_ifw[n], m); 396 if (++sc->sc_oused == 1) 397 sc->sc_if.if_timer = dmv_timeout; 398 dmvload( 399 sc, 400 DMV_BACCX, 401 QP_TRIB|QP_SEL4|QP_SEL6|QP_SEL10, 402 1, 403 rp->ubinfo, 404 (rp->ubinfo>>16)&0x3f, 405 rp->cc 406 ); 407 } 408 n++; 409 } 410 } 411 412 /* 413 * Utility routine to load the DMV device registers. 414 */ 415 dmvload(sc, cmd, mask, tributary, sel4, sel6, sel10) 416 register struct dmv_softc *sc; 417 u_char cmd, tributary, mask; 418 u_short sel4, sel6, sel10; 419 { 420 register struct dmvdevice *addr; 421 register int unit, sps; 422 register struct dmv_command *qp; 423 424 unit = sc - dmv_softc; 425 printd(("dmvload: cmd=%x mask=%x trib=%x sel4=%x sel6=%x sel10=%x\n", 426 (unsigned) cmd, 427 (unsigned) mask, 428 (unsigned) tributary, 429 (unsigned) sel4, 430 (unsigned) sel6, 431 (unsigned) sel10 432 )); 433 addr = (struct dmvdevice *)dmvinfo[unit]->ui_addr; 434 sps = spl5(); 435 436 /* grab a command buffer from the free list */ 437 if ((qp = sc->sc_qfreeh) == (struct dmv_command *)0) 438 panic("dmv command queue overflow"); 439 DEQUEUE(sc->sc_qfreeh, sc->sc_qfreet); 440 441 /* fill in requested info */ 442 qp->qp_cmd = cmd; 443 qp->qp_mask = mask; 444 qp->qp_tributary = tributary; 445 qp->qp_sel4 = sel4; 446 qp->qp_sel6 = sel6; 447 qp->qp_sel10 = sel10; 448 449 if (sc->sc_qactive) { /* command in progress */ 450 if (cmd == DMV_BACCR) { /* supply read buffers first */ 451 QUEUE_AT_HEAD(qp, sc->sc_qhead, sc->sc_qtail); 452 } else { 453 QUEUE_AT_TAIL(qp, sc->sc_qhead, sc->sc_qtail); 454 } 455 } else { /* command port free */ 456 sc->sc_qactive = qp; 457 addr->bsel0 = (DMV_RQI|DMV_IEI|DMV_IEO); 458 } 459 splx(sps); 460 } 461 /* 462 * DMV interface input interrupt. 463 * Ready to accept another command, 464 * pull one off the command queue. 465 */ 466 dmvrint(unit) 467 int unit; 468 { 469 register struct dmv_softc *sc; 470 register struct dmvdevice *addr; 471 register struct dmv_command *qp; 472 register int n; 473 474 addr = (struct dmvdevice *)dmvinfo[unit]->ui_addr; 475 sc = &dmv_softc[unit]; 476 printd(("dmvrint\n")); 477 if ((qp = sc->sc_qactive) == (struct dmv_command *) 0) { 478 log(LOG_WARNING, "dmvrint: dmv%d no command\n", unit); 479 return; 480 } 481 while (addr->bsel2&DMV_RDI) { 482 if(qp->qp_mask&QP_SEL4) 483 addr->wsel4 = qp->qp_sel4; 484 if(qp->qp_mask&QP_SEL6) 485 addr->wsel6 = qp->qp_sel6; 486 if(qp->qp_mask&QP_SEL10) { 487 addr->wsel10 = qp->qp_sel10; 488 qp->qp_cmd |= DMV_22BIT; 489 } 490 if(qp->qp_mask&QP_TRIB) 491 addr->wsel2 = qp->qp_cmd|(qp->qp_tributary << 8); 492 else 493 addr->bsel2 = qp->qp_cmd; 494 QUEUE_AT_HEAD(qp, sc->sc_qfreeh, sc->sc_qfreet); 495 if ((sc->sc_qactive = sc->sc_qhead) == (struct dmv_command *)0) 496 break; 497 qp = sc->sc_qactive; 498 DEQUEUE(sc->sc_qhead, sc->sc_qtail); 499 if (addr->bsel2&DMV_RDO) 500 break; 501 } 502 if (!sc->sc_qactive) { 503 if(addr->bsel2&DMV_RDI) { 504 /* clear RQI prior to last command per DMV manual */ 505 addr->bsel0 &= ~DMV_RQI; 506 addr->wsel6 = DMV_NOP; 507 addr->bsel2 = DMV_CNTRLI; 508 } 509 addr->bsel0 = DMV_IEO; 510 } 511 else /* RDO set or DMV still holding CSR */ 512 addr->bsel0 = (DMV_RQI|DMV_IEI|DMV_IEO); 513 514 } 515 516 /* 517 * DMV interface output interrupt. 518 * A transfer may have completed, check for errors. 519 * If it was a read, notify appropriate protocol. 520 * If it was a write, pull the next one off the queue. 521 */ 522 dmvxint(unit) 523 int unit; 524 { 525 register struct dmv_softc *sc; 526 register struct ifnet *ifp; 527 struct uba_device *ui = dmvinfo[unit]; 528 struct dmvdevice *addr; 529 struct mbuf *m; 530 struct ifqueue *inq; 531 int sel2, sel3, sel4, sel6, sel10, pkaddr, len, s; 532 register struct ifrw *ifrw; 533 register struct dmvbufs *rp; 534 register struct ifxmt *ifxp; 535 struct dmv_header *dh; 536 int off, resid; 537 538 addr = (struct dmvdevice *)ui->ui_addr; 539 sc = &dmv_softc[unit]; 540 ifp = &sc->sc_if; 541 542 while (addr->bsel2 & DMV_RDO) { 543 544 sel2 = addr->bsel2; 545 sel3 = addr->bsel3; 546 sel4 = addr->wsel4; /* release port */ 547 sel6 = addr->wsel6; 548 if(sel2 & DMV_22BIT) 549 sel10 = addr->wsel10; 550 addr->bsel2 &= ~DMV_RDO; 551 pkaddr = sel4 | ((sel6 & 0x3f) << 16); 552 printd(("dmvxint: sel2=%x sel4=%x sel6=%x sel10=%x pkaddr=%x\n", 553 (unsigned) sel2, 554 (unsigned) sel4, 555 (unsigned) sel6, 556 (unsigned) sel10, 557 (unsigned) pkaddr 558 )); 559 if((sc->sc_flag & DMV_RUNNING)==0) { 560 log(LOG_WARNING, "dmvxint: dmv%d xint while down\n", unit); 561 return; 562 } 563 switch (sel2 & 07) { 564 case DMV_BDRUS: 565 /* 566 * A read has completed. 567 * Pass packet to type specific 568 * higher-level input routine. 569 */ 570 ifp->if_ipackets++; 571 /* find location in dmvuba struct */ 572 ifrw= &sc->sc_ifr[0]; 573 for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) { 574 if(rp->ubinfo == pkaddr) 575 break; 576 ifrw++; 577 } 578 if (rp >= &sc->sc_rbufs[NRCV]) 579 panic("dmv rcv"); 580 if ((rp->flags & DBUF_DMVS) == 0) 581 log(LOG_WARNING, "dmvxint: dmv%d done unalloc rbuf\n", unit); 582 583 len = (sel10&0x3fff) - sizeof (struct dmv_header); 584 if (len < 0 || len > DMVMTU) { 585 ifp->if_ierrors++; 586 log(LOG_ERR, "dmvxint: dmv%d bad rcv pkt addr 0x%x len 0x%x\n", 587 unit, pkaddr, len); 588 goto setup; 589 } 590 /* 591 * Deal with trailer protocol: if type is trailer 592 * get true type from first 16-bit word past data. 593 * Remember that type was trailer by setting off. 594 */ 595 dh = (struct dmv_header *)ifrw->ifrw_addr; 596 dh->dmv_type = ntohs((u_short)dh->dmv_type); 597 #define dmvdataaddr(dh, off, type) ((type)(((caddr_t)((dh)+1)+(off)))) 598 if (dh->dmv_type >= DMV_TRAILER && 599 dh->dmv_type < DMV_TRAILER+DMV_NTRAILER) { 600 off = (dh->dmv_type - DMV_TRAILER) * 512; 601 if (off >= DMVMTU) 602 goto setup; /* sanity */ 603 dh->dmv_type = ntohs(*dmvdataaddr(dh, off, u_short *)); 604 resid = ntohs(*(dmvdataaddr(dh, off+2, u_short *))); 605 if (off + resid > len) 606 goto setup; /* sanity */ 607 len = off + resid; 608 } else 609 off = 0; 610 if (len == 0) 611 goto setup; 612 613 /* 614 * Pull packet off interface. Off is nonzero if 615 * packet has trailing header; dmv_get will then 616 * force this header information to be at the front, 617 * but we still have to drop the type and length 618 * which are at the front of any trailer data. 619 */ 620 m = if_ubaget(&sc->sc_ifuba, ifrw, len, off, ifp); 621 if (m == 0) 622 goto setup; 623 if (off) { 624 ifp = *(mtod(m, struct ifnet **)); 625 m->m_off += 2 * sizeof (u_short); 626 m->m_len -= 2 * sizeof (u_short); 627 *(mtod(m, struct ifnet **)) = ifp; 628 } 629 switch (dh->dmv_type) { 630 #ifdef INET 631 case DMV_IPTYPE: 632 schednetisr(NETISR_IP); 633 inq = &ipintrq; 634 break; 635 #endif 636 default: 637 m_freem(m); 638 goto setup; 639 } 640 641 s = splimp(); 642 if (IF_QFULL(inq)) { 643 IF_DROP(inq); 644 m_freem(m); 645 } else 646 IF_ENQUEUE(inq, m); 647 splx(s); 648 setup: 649 /* is this needed? */ 650 rp->ubinfo = ifrw->ifrw_info & 0x3ffff; 651 dmvload( 652 sc, 653 DMV_BACCR, 654 QP_SEL4|QP_SEL6|QP_SEL10, 655 0, 656 rp->ubinfo, 657 (rp->ubinfo>>16)&0x3f, 658 rp->cc 659 ); 660 break; 661 case DMV_BDXSA: 662 /* 663 * A write has completed, start another 664 * transfer if there is more data to send. 665 */ 666 ifp->if_opackets++; 667 /* find associated dmvbuf structure */ 668 ifxp = &sc->sc_ifw[0]; 669 for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[NXMT]; rp++) { 670 if(rp->ubinfo == pkaddr) 671 break; 672 ifxp++; 673 } 674 if (rp >= &sc->sc_xbufs[NXMT]) { 675 log(LOG_ERR, "dmv%d: bad packet address 0x%x\n", 676 unit, pkaddr); 677 break; 678 } 679 if ((rp->flags & DBUF_DMVS) == 0) 680 log(LOG_ERR, "dmvxint: dmv%d unallocated packet 0x%x\n", 681 unit, pkaddr); 682 /* mark buffer free */ 683 if (ifxp->ifw_xtofree) { 684 (void)m_freem(ifxp->ifw_xtofree); 685 ifxp->ifw_xtofree = 0; 686 } 687 rp->flags &= ~DBUF_DMVS; 688 if (--sc->sc_oused == 0) 689 sc->sc_if.if_timer = 0; 690 else 691 sc->sc_if.if_timer = dmv_timeout; 692 if ((sc->sc_flag & DMV_ONLINE) == 0) { 693 extern int ifqmaxlen; 694 695 /* 696 * We're on the air. 697 * Open the queue to the usual value. 698 */ 699 sc->sc_flag |= DMV_ONLINE; 700 ifp->if_snd.ifq_maxlen = ifqmaxlen; 701 } 702 break; 703 704 case DMV_CNTRLO: 705 /* ACCUMULATE STATISTICS */ 706 switch(sel6&DMV_EEC) { 707 case DMV_ORUN: 708 if(sc->sc_flag & DMV_RESTART) { 709 load_rec_bufs(sc); 710 sc->sc_flag &= ~DMV_RESTART; 711 log(LOG_INFO, 712 "dmv%d: far end on-line\n", unit); 713 } else { 714 log(LOG_WARNING, 715 "dmv%d: far end restart\n", unit); 716 goto restart; 717 } 718 break; 719 case DMV_RTE: 720 ifp->if_ierrors++; 721 if ((sc->sc_rte++ % DMV_RPRTE) == 0) 722 log(LOG_WARNING, 723 "dmv%d: receive threshold error\n", 724 unit); 725 break; 726 case DMV_TTE: 727 ifp->if_oerrors++; 728 if ((sc->sc_xte++ % DMV_RPTTE) == 0) 729 log(LOG_WARNING, 730 "dmv%d: transmit threshold error\n", 731 unit); 732 break; 733 case DMV_STE: 734 if ((sc->sc_ste++ % DMV_RPSTE) == 0) 735 log(LOG_WARNING, 736 "dmv%d: select threshold error\n", 737 unit); 738 break; 739 case DMV_NXM: 740 if ((sc->sc_nxm++ % DMV_RPNXM) == 0) 741 log(LOG_WARNING, 742 "dmv%d: nonexistent memory error\n", 743 unit); 744 break; 745 case DMV_MODD: 746 if ((sc->sc_modd++ % DMV_RPMODD) == 0) { 747 log(LOG_WARNING, 748 "dmv%d: modem disconnected error\n", 749 unit); 750 goto restart; 751 } 752 break; 753 case DMV_CXRL: 754 if ((sc->sc_cxrl++ % DMV_RPCXRL) == 0) 755 log(LOG_WARNING, 756 "dmv%d: carrier loss error\n", 757 unit); 758 break; 759 case DMV_QOVF: 760 log(LOG_WARNING, 761 "dmv%d: response queue overflow\n", 762 unit); 763 sc->sc_qovf++; 764 goto restart; 765 766 default: 767 log(LOG_WARNING, 768 "dmv%d: unknown error %o\n", 769 unit, sel6&DMV_EEC); 770 if ((sc->sc_unknown++ % DMV_RPUNKNOWN) == 0) 771 goto restart; 772 break; 773 } 774 break; 775 776 case DMV_BDRUNUS: 777 case DMV_BDXSN: 778 case DMV_BDXNS: 779 log(LOG_INFO, 780 "dmv%d: buffer disp for halted trib %o\n", 781 unit, sel2&0x7 782 ); 783 break; 784 785 case DMV_MDEFO: 786 if((sel6&0x1f) == 020) { 787 log(LOG_INFO, 788 "dmv%d: buffer return complete sel3=%x\n", 789 unit, sel3); 790 } else { 791 log(LOG_INFO, 792 "dmv%d: info resp sel3=%x sel4=%x sel6=%x\n", 793 unit, sel3, sel4, sel6 794 ); 795 } 796 break; 797 798 default: 799 log(LOG_WARNING, "dmv%d: bad control %o\n", 800 unit, sel2&0x7 801 ); 802 break; 803 } 804 } 805 dmvstart(unit); 806 return; 807 restart: 808 dmvrestart(unit); 809 } 810 811 load_rec_bufs(sc) 812 register struct dmv_softc *sc; 813 { 814 register struct dmvbufs *rp; 815 816 /* queue first NRCV buffers for DMV to fill */ 817 for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) { 818 rp->flags |= DBUF_DMVS; 819 dmvload( 820 sc, 821 DMV_BACCR, 822 QP_TRIB|QP_SEL4|QP_SEL6|QP_SEL10, 823 1, 824 rp->ubinfo, 825 (rp->ubinfo>>16)&0x3f, 826 rp->cc 827 ); 828 sc->sc_iused++; 829 } 830 } 831 832 /* 833 * DMV output routine. 834 * Encapsulate a packet of type family for the dmv. 835 * Use trailer local net encapsulation if enough data in first 836 * packet leaves a multiple of 512 bytes of data in remainder. 837 */ 838 dmvoutput(ifp, m0, dst) 839 register struct ifnet *ifp; 840 register struct mbuf *m0; 841 struct sockaddr *dst; 842 { 843 int type, error, s; 844 register struct mbuf *m = m0; 845 register struct dmv_header *dh; 846 register int off; 847 848 if ((ifp->if_flags & IFF_UP) == 0) { 849 error = ENETDOWN; 850 goto bad; 851 } 852 853 switch (dst->sa_family) { 854 #ifdef INET 855 case AF_INET: 856 off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; 857 if ((ifp->if_flags & IFF_NOTRAILERS) == 0) 858 if (off > 0 && (off & 0x1ff) == 0 && 859 m->m_off >= MMINOFF + 2 * sizeof (u_short)) { 860 type = DMV_TRAILER + (off>>9); 861 m->m_off -= 2 * sizeof (u_short); 862 m->m_len += 2 * sizeof (u_short); 863 *mtod(m, u_short *) = htons((u_short)DMV_IPTYPE); 864 *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); 865 goto gottrailertype; 866 } 867 type = DMV_IPTYPE; 868 off = 0; 869 goto gottype; 870 #endif 871 872 case AF_UNSPEC: 873 dh = (struct dmv_header *)dst->sa_data; 874 type = dh->dmv_type; 875 goto gottype; 876 877 default: 878 log(LOG_ERR, "dmvoutput, dmv%d can't handle af%d\n", 879 ifp->if_unit, dst->sa_family); 880 error = EAFNOSUPPORT; 881 goto bad; 882 } 883 884 gottrailertype: 885 /* 886 * Packet to be sent as a trailer; move first packet 887 * (control information) to end of chain. 888 */ 889 while (m->m_next) 890 m = m->m_next; 891 m->m_next = m0; 892 m = m0->m_next; 893 m0->m_next = 0; 894 m0 = m; 895 896 gottype: 897 /* 898 * Add local network header 899 * (there is space for a uba on a vax to step on) 900 */ 901 if (m->m_off > MMAXOFF || 902 MMINOFF + sizeof(struct dmv_header) > m->m_off) { 903 m = m_get(M_DONTWAIT, MT_HEADER); 904 if (m == 0) { 905 error = ENOBUFS; 906 goto bad; 907 } 908 m->m_next = m0; 909 m->m_off = MMINOFF; 910 m->m_len = sizeof (struct dmv_header); 911 } else { 912 m->m_off -= sizeof (struct dmv_header); 913 m->m_len += sizeof (struct dmv_header); 914 } 915 dh = mtod(m, struct dmv_header *); 916 dh->dmv_type = htons((u_short)type); 917 918 /* 919 * Queue message on interface, and start output if interface 920 * not yet active. 921 */ 922 s = splimp(); 923 if (IF_QFULL(&ifp->if_snd)) { 924 IF_DROP(&ifp->if_snd); 925 m_freem(m); 926 splx(s); 927 return (ENOBUFS); 928 } 929 IF_ENQUEUE(&ifp->if_snd, m); 930 dmvstart(ifp->if_unit); 931 splx(s); 932 return (0); 933 934 bad: 935 m_freem(m0); 936 return (error); 937 } 938 939 940 /* 941 * Process an ioctl request. 942 */ 943 /* ARGSUSED */ 944 dmvioctl(ifp, cmd, data) 945 register struct ifnet *ifp; 946 int cmd; 947 caddr_t data; 948 { 949 int s = splimp(), error = 0; 950 struct mbuf *m; 951 register struct dmv_softc *sc = &dmv_softc[ifp->if_unit]; 952 953 switch (cmd) { 954 955 case SIOCSIFADDR: 956 ifp->if_flags |= IFF_UP; 957 if ((ifp->if_flags & IFF_RUNNING) == 0) 958 dmvinit(ifp->if_unit); 959 break; 960 961 case SIOCSIFDSTADDR: 962 if ((ifp->if_flags & IFF_RUNNING) == 0) 963 dmvinit(ifp->if_unit); 964 break; 965 966 case SIOCSIFFLAGS: 967 if ((ifp->if_flags & IFF_UP) == 0 && 968 sc->sc_flag & DMV_RUNNING) 969 dmvdown(ifp->if_unit); 970 else if (ifp->if_flags & IFF_UP && 971 (sc->sc_flag & DMV_RUNNING) == 0) 972 dmvrestart(ifp->if_unit); 973 break; 974 975 default: 976 error = EINVAL; 977 } 978 splx(s); 979 return (error); 980 } 981 982 /* 983 * Restart after a fatal error. 984 * Clear device and reinitialize. 985 */ 986 dmvrestart(unit) 987 int unit; 988 { 989 register struct dmvdevice *addr; 990 register int i; 991 992 dmvdown(unit); 993 994 addr = (struct dmvdevice *)(dmvinfo[unit]->ui_addr); 995 /* 996 * Let the DMV finish the MCLR. 997 */ 998 for (i = 100000; i && (addr->bsel1 & DMV_RUN) == 0; i--) 999 ; 1000 if ((addr->bsel1 & DMV_RUN) == 0) { 1001 log(LOG_ERR, "dmvrestart: can't start device\n" ); 1002 return (0); 1003 } 1004 if ((addr->bsel4 != 033) || (addr->bsel6 != 0305)) 1005 { 1006 log(LOG_ERR, "dmv%d: device init failed, bsel4=%o, bsel6=%o\n", 1007 unit, addr->bsel4, addr->bsel6); 1008 return (0); 1009 } 1010 1011 /* restart DMV */ 1012 dmvinit(unit); 1013 dmv_softc[unit].sc_if.if_collisions++; /* why not? */ 1014 } 1015 1016 /* 1017 * Reset a device and mark down. 1018 * Flush output queue and drop queue limit. 1019 */ 1020 dmvdown(unit) 1021 int unit; 1022 { 1023 struct dmv_softc *sc = &dmv_softc[unit]; 1024 register struct ifxmt *ifxp; 1025 1026 ((struct dmvdevice *)(dmvinfo[unit]->ui_addr))->bsel1 = DMV_MCLR; 1027 sc->sc_flag &= ~(DMV_RUNNING | DMV_ONLINE); 1028 1029 for (ifxp = sc->sc_ifw; ifxp < &sc->sc_ifw[NXMT]; ifxp++) { 1030 if (ifxp->ifw_xtofree) { 1031 (void) m_freem(ifxp->ifw_xtofree); 1032 ifxp->ifw_xtofree = 0; 1033 } 1034 } 1035 sc->sc_oused = 0; 1036 if_qflush(&sc->sc_if.if_snd); 1037 1038 /* 1039 * Limit packets enqueued until we're back on the air. 1040 */ 1041 sc->sc_if.if_snd.ifq_maxlen = 3; 1042 } 1043 1044 /* 1045 * Watchdog timeout to see that transmitted packets don't 1046 * lose interrupts. The device has to be online. 1047 */ 1048 dmvtimeout(unit) 1049 int unit; 1050 { 1051 register struct dmv_softc *sc; 1052 struct dmvdevice *addr; 1053 1054 sc = &dmv_softc[unit]; 1055 if (sc->sc_flag & DMV_ONLINE) { 1056 addr = (struct dmvdevice *)(dmvinfo[unit]->ui_addr); 1057 log(LOG_ERR, "dmv%d: output timeout, bsel0=%b bsel2=%b\n", 1058 unit, addr->bsel0 & 0xff, DMV0BITS, 1059 addr->bsel2 & 0xff, DMV2BITS); 1060 dmvrestart(unit); 1061 } 1062 } 1063 #endif 1064