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