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.11 (Berkeley) 10/02/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 && 298 ifa->ifa_addr->sa_family != AF_LINK && 299 ifa->ifa_dstaddr && ifa->ifa_dstaddr->sa_family) 300 break; 301 if (ifa == (struct ifaddr *) 0) 302 return; 303 304 if ((addr->bsel1&DMV_RUN) == 0) { 305 log(LOG_CRIT, "dmvinit: dmv%d not running\n", unit); 306 ifp->if_flags &= ~IFF_UP; 307 return; 308 } 309 printd(("dmvinit\n")); 310 /* initialize UNIBUS resources */ 311 sc->sc_iused = sc->sc_oused = 0; 312 if ((ifp->if_flags & IFF_RUNNING) == 0) { 313 if (if_ubaminit( 314 &sc->sc_ifuba, 315 ui->ui_ubanum, 316 sizeof(struct dmv_header), 317 (int)btoc(DMVMTU), 318 sc->sc_ifr, 319 NRCV, 320 sc->sc_ifw, 321 NXMT 322 ) == 0) { 323 log(LOG_CRIT, "dmvinit: dmv%d can't allocate uba resources\n", unit); 324 ifp->if_flags &= ~IFF_UP; 325 return; 326 } 327 ifp->if_flags |= IFF_RUNNING; 328 } 329 /* 330 * Limit packets enqueued until we see if we're on the air. 331 */ 332 ifp->if_snd.ifq_maxlen = 3; 333 334 335 /* initialize buffer pool */ 336 /* receives */ 337 ifrw = &sc->sc_ifr[0]; 338 for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) { 339 rp->ubinfo = UBAI_ADDR(ifrw->ifrw_info); 340 rp->cc = DMVMTU + sizeof (struct dmv_header); 341 rp->flags = DBUF_OURS|DBUF_RCV; 342 ifrw++; 343 } 344 /* transmits */ 345 ifxp = &sc->sc_ifw[0]; 346 for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[NXMT]; rp++) { 347 rp->ubinfo = UBAI_ADDR(ifxp->ifw_info); 348 rp->cc = 0; 349 rp->flags = DBUF_OURS|DBUF_XMIT; 350 ifxp++; 351 } 352 353 /* set up command queues */ 354 sc->sc_qfreeh = sc->sc_qfreet 355 = sc->sc_qhead = sc->sc_qtail = sc->sc_qactive = 356 (struct dmv_command *)0; 357 /* set up free command buffer list */ 358 for (qp = &sc->sc_cmdbuf[0]; qp < &sc->sc_cmdbuf[NCMDS]; qp++) { 359 QUEUE_AT_HEAD(qp, sc->sc_qfreeh, sc->sc_qfreet); 360 } 361 if(sc->sc_flag & DMV_RUNNING) 362 dmvload( sc, DMV_CNTRLI, (QP_TRIB|QP_SEL6), 1, 0, DMV_REQHS,0); 363 else 364 dmvload( sc, DMV_CNTRLI, (QP_TRIB|QP_SEL6), 1, 0, DMV_ESTTRIB,0); 365 dmvload( sc, DMV_CNTRLI, (QP_TRIB|QP_SEL6), 1, 0, DMV_REQSUS,0); 366 sc->sc_flag |= (DMV_RESTART|DMV_RUNNING); 367 sc->sc_flag &= ~DMV_ONLINE; 368 addr->bsel0 |= DMV_IEO; 369 } 370 371 /* 372 * Start output on interface. Get another datagram 373 * to send from the interface queue and map it to 374 * the interface before starting output. 375 * 376 * Must be called at spl 5 377 */ 378 dmvstart(dev) 379 dev_t dev; 380 { 381 int unit = minor(dev); 382 register struct dmv_softc *sc = &dmv_softc[unit]; 383 struct mbuf *m; 384 register struct dmvbufs *rp; 385 register int n; 386 387 /* 388 * Dequeue up to NXMT requests and map them to the UNIBUS. 389 * If no more requests, or no dmv buffers available, just return. 390 */ 391 printd(("dmvstart\n")); 392 n = 0; 393 for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[NXMT]; rp++ ) { 394 /* find an available buffer */ 395 if ((rp->flags & DBUF_DMVS) == 0) { 396 IF_DEQUEUE(&sc->sc_if.if_snd, m); 397 if (m == 0) 398 return; 399 /* mark it dmvs */ 400 rp->flags |= (DBUF_DMVS); 401 /* 402 * Have request mapped to UNIBUS for transmission 403 * and start the output. 404 */ 405 rp->cc = if_ubaput(&sc->sc_ifuba, &sc->sc_ifw[n], m); 406 if (++sc->sc_oused == 1) 407 sc->sc_if.if_timer = dmv_timeout; 408 dmvload( 409 sc, 410 DMV_BACCX, 411 QP_TRIB|QP_SEL4|QP_SEL6|QP_SEL10, 412 1, 413 rp->ubinfo, 414 (rp->ubinfo>>16)&0x3f, 415 rp->cc 416 ); 417 } 418 n++; 419 } 420 } 421 422 /* 423 * Utility routine to load the DMV device registers. 424 */ 425 dmvload(sc, cmd, mask, tributary, sel4, sel6, sel10) 426 register struct dmv_softc *sc; 427 u_char cmd, tributary, mask; 428 u_short sel4, sel6, sel10; 429 { 430 register struct dmvdevice *addr; 431 register int unit, sps; 432 register struct dmv_command *qp; 433 434 unit = sc - dmv_softc; 435 printd(("dmvload: cmd=%x mask=%x trib=%x sel4=%x sel6=%x sel10=%x\n", 436 (unsigned) cmd, 437 (unsigned) mask, 438 (unsigned) tributary, 439 (unsigned) sel4, 440 (unsigned) sel6, 441 (unsigned) sel10 442 )); 443 addr = (struct dmvdevice *)dmvinfo[unit]->ui_addr; 444 sps = spl5(); 445 446 /* grab a command buffer from the free list */ 447 if ((qp = sc->sc_qfreeh) == (struct dmv_command *)0) 448 panic("dmv command queue overflow"); 449 DEQUEUE(sc->sc_qfreeh, sc->sc_qfreet); 450 451 /* fill in requested info */ 452 qp->qp_cmd = cmd; 453 qp->qp_mask = mask; 454 qp->qp_tributary = tributary; 455 qp->qp_sel4 = sel4; 456 qp->qp_sel6 = sel6; 457 qp->qp_sel10 = sel10; 458 459 if (sc->sc_qactive) { /* command in progress */ 460 if (cmd == DMV_BACCR) { /* supply read buffers first */ 461 QUEUE_AT_HEAD(qp, sc->sc_qhead, sc->sc_qtail); 462 } else { 463 QUEUE_AT_TAIL(qp, sc->sc_qhead, sc->sc_qtail); 464 } 465 } else { /* command port free */ 466 sc->sc_qactive = qp; 467 addr->bsel0 = (DMV_RQI|DMV_IEI|DMV_IEO); 468 } 469 splx(sps); 470 } 471 /* 472 * DMV interface input interrupt. 473 * Ready to accept another command, 474 * pull one off the command queue. 475 */ 476 dmvrint(unit) 477 int unit; 478 { 479 register struct dmv_softc *sc; 480 register struct dmvdevice *addr; 481 register struct dmv_command *qp; 482 register int n; 483 484 addr = (struct dmvdevice *)dmvinfo[unit]->ui_addr; 485 sc = &dmv_softc[unit]; 486 splx(sc->sc_ipl); 487 printd(("dmvrint\n")); 488 if ((qp = sc->sc_qactive) == (struct dmv_command *) 0) { 489 log(LOG_WARNING, "dmvrint: dmv%d no command\n", unit); 490 return; 491 } 492 while (addr->bsel2&DMV_RDI) { 493 if(qp->qp_mask&QP_SEL4) 494 addr->wsel4 = qp->qp_sel4; 495 if(qp->qp_mask&QP_SEL6) 496 addr->wsel6 = qp->qp_sel6; 497 if(qp->qp_mask&QP_SEL10) { 498 addr->wsel10 = qp->qp_sel10; 499 qp->qp_cmd |= DMV_22BIT; 500 } 501 if(qp->qp_mask&QP_TRIB) 502 addr->wsel2 = qp->qp_cmd|(qp->qp_tributary << 8); 503 else 504 addr->bsel2 = qp->qp_cmd; 505 QUEUE_AT_HEAD(qp, sc->sc_qfreeh, sc->sc_qfreet); 506 if ((sc->sc_qactive = sc->sc_qhead) == (struct dmv_command *)0) 507 break; 508 qp = sc->sc_qactive; 509 DEQUEUE(sc->sc_qhead, sc->sc_qtail); 510 if (addr->bsel2&DMV_RDO) 511 break; 512 } 513 if (!sc->sc_qactive) { 514 if(addr->bsel2&DMV_RDI) { 515 /* clear RQI prior to last command per DMV manual */ 516 addr->bsel0 &= ~DMV_RQI; 517 addr->wsel6 = DMV_NOP; 518 addr->bsel2 = DMV_CNTRLI; 519 } 520 addr->bsel0 = DMV_IEO; 521 } 522 else /* RDO set or DMV still holding CSR */ 523 addr->bsel0 = (DMV_RQI|DMV_IEI|DMV_IEO); 524 525 } 526 527 /* 528 * DMV interface output interrupt. 529 * A transfer may have completed, check for errors. 530 * If it was a read, notify appropriate protocol. 531 * If it was a write, pull the next one off the queue. 532 */ 533 dmvxint(unit) 534 int unit; 535 { 536 register struct dmv_softc *sc; 537 register struct ifnet *ifp; 538 struct uba_device *ui = dmvinfo[unit]; 539 struct dmvdevice *addr; 540 struct mbuf *m; 541 struct ifqueue *inq; 542 int sel2, sel3, sel4, sel6, sel10, pkaddr, len, s; 543 register struct ifrw *ifrw; 544 register struct dmvbufs *rp; 545 register struct ifxmt *ifxp; 546 struct dmv_header *dh; 547 int off, resid; 548 549 addr = (struct dmvdevice *)ui->ui_addr; 550 sc = &dmv_softc[unit]; 551 splx(sc->sc_ipl); 552 ifp = &sc->sc_if; 553 554 while (addr->bsel2 & DMV_RDO) { 555 556 sel2 = addr->bsel2; 557 sel3 = addr->bsel3; 558 sel4 = addr->wsel4; /* release port */ 559 sel6 = addr->wsel6; 560 if(sel2 & DMV_22BIT) 561 sel10 = addr->wsel10; 562 addr->bsel2 &= ~DMV_RDO; 563 pkaddr = sel4 | ((sel6 & 0x3f) << 16); 564 printd(("dmvxint: sel2=%x sel4=%x sel6=%x sel10=%x pkaddr=%x\n", 565 (unsigned) sel2, 566 (unsigned) sel4, 567 (unsigned) sel6, 568 (unsigned) sel10, 569 (unsigned) pkaddr 570 )); 571 if((sc->sc_flag & DMV_RUNNING)==0) { 572 log(LOG_WARNING, "dmvxint: dmv%d xint while down\n", unit); 573 return; 574 } 575 switch (sel2 & 07) { 576 case DMV_BDRUS: 577 /* 578 * A read has completed. 579 * Pass packet to type specific 580 * higher-level input routine. 581 */ 582 ifp->if_ipackets++; 583 /* find location in dmvuba struct */ 584 ifrw= &sc->sc_ifr[0]; 585 for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) { 586 if(rp->ubinfo == pkaddr) 587 break; 588 ifrw++; 589 } 590 if (rp >= &sc->sc_rbufs[NRCV]) 591 panic("dmv rcv"); 592 if ((rp->flags & DBUF_DMVS) == 0) 593 log(LOG_WARNING, "dmvxint: dmv%d done unalloc rbuf\n", unit); 594 595 len = (sel10&0x3fff) - sizeof (struct dmv_header); 596 if (len < 0 || len > DMVMTU) { 597 ifp->if_ierrors++; 598 log(LOG_ERR, "dmvxint: dmv%d bad rcv pkt addr 0x%x len 0x%x\n", 599 unit, pkaddr, len); 600 goto setup; 601 } 602 /* 603 * Deal with trailer protocol: if type is trailer 604 * get true type from first 16-bit word past data. 605 * Remember that type was trailer by setting off. 606 */ 607 dh = (struct dmv_header *)ifrw->ifrw_addr; 608 dh->dmv_type = ntohs((u_short)dh->dmv_type); 609 #define dmvdataaddr(dh, off, type) ((type)(((caddr_t)((dh)+1)+(off)))) 610 if (dh->dmv_type >= DMV_TRAILER && 611 dh->dmv_type < DMV_TRAILER+DMV_NTRAILER) { 612 off = (dh->dmv_type - DMV_TRAILER) * 512; 613 if (off >= DMVMTU) 614 goto setup; /* sanity */ 615 dh->dmv_type = ntohs(*dmvdataaddr(dh, off, u_short *)); 616 resid = ntohs(*(dmvdataaddr(dh, off+2, u_short *))); 617 if (off + resid > len) 618 goto setup; /* sanity */ 619 len = off + resid; 620 } else 621 off = 0; 622 if (len == 0) 623 goto setup; 624 625 /* 626 * Pull packet off interface. Off is nonzero if 627 * packet has trailing header; dmv_get will then 628 * force this header information to be at the front, 629 * but we still have to drop the type and length 630 * which are at the front of any trailer data. 631 */ 632 m = if_ubaget(&sc->sc_ifuba, ifrw, len, off, ifp); 633 if (m == 0) 634 goto setup; 635 switch (dh->dmv_type) { 636 #ifdef INET 637 case DMV_IPTYPE: 638 schednetisr(NETISR_IP); 639 inq = &ipintrq; 640 break; 641 #endif 642 default: 643 m_freem(m); 644 goto setup; 645 } 646 647 s = splimp(); 648 if (IF_QFULL(inq)) { 649 IF_DROP(inq); 650 m_freem(m); 651 } else 652 IF_ENQUEUE(inq, m); 653 splx(s); 654 setup: 655 /* is this needed? */ 656 rp->ubinfo = UBAI_ADDR(ifrw->ifrw_info); 657 dmvload( 658 sc, 659 DMV_BACCR, 660 QP_SEL4|QP_SEL6|QP_SEL10, 661 0, 662 (u_short) rp->ubinfo, 663 (rp->ubinfo>>16)&0x3f, 664 rp->cc 665 ); 666 break; 667 case DMV_BDXSA: 668 /* 669 * A write has completed, start another 670 * transfer if there is more data to send. 671 */ 672 ifp->if_opackets++; 673 /* find associated dmvbuf structure */ 674 ifxp = &sc->sc_ifw[0]; 675 for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[NXMT]; rp++) { 676 if(rp->ubinfo == pkaddr) 677 break; 678 ifxp++; 679 } 680 if (rp >= &sc->sc_xbufs[NXMT]) { 681 log(LOG_ERR, "dmv%d: bad packet address 0x%x\n", 682 unit, pkaddr); 683 break; 684 } 685 if ((rp->flags & DBUF_DMVS) == 0) 686 log(LOG_ERR, "dmvxint: dmv%d unallocated packet 0x%x\n", 687 unit, pkaddr); 688 /* mark buffer free */ 689 if (ifxp->ifw_xtofree) { 690 (void)m_freem(ifxp->ifw_xtofree); 691 ifxp->ifw_xtofree = 0; 692 } 693 rp->flags &= ~DBUF_DMVS; 694 if (--sc->sc_oused == 0) 695 sc->sc_if.if_timer = 0; 696 else 697 sc->sc_if.if_timer = dmv_timeout; 698 if ((sc->sc_flag & DMV_ONLINE) == 0) { 699 extern int ifqmaxlen; 700 701 /* 702 * We're on the air. 703 * Open the queue to the usual value. 704 */ 705 sc->sc_flag |= DMV_ONLINE; 706 ifp->if_snd.ifq_maxlen = ifqmaxlen; 707 } 708 break; 709 710 case DMV_CNTRLO: 711 /* ACCUMULATE STATISTICS */ 712 switch(sel6&DMV_EEC) { 713 case DMV_ORUN: 714 if(sc->sc_flag & DMV_RESTART) { 715 load_rec_bufs(sc); 716 sc->sc_flag &= ~DMV_RESTART; 717 log(LOG_INFO, 718 "dmv%d: far end on-line\n", unit); 719 } else { 720 log(LOG_WARNING, 721 "dmv%d: far end restart\n", unit); 722 goto restart; 723 } 724 break; 725 case DMV_RTE: 726 ifp->if_ierrors++; 727 if ((sc->sc_rte++ % DMV_RPRTE) == 0) 728 log(LOG_WARNING, 729 "dmv%d: receive threshold error\n", 730 unit); 731 break; 732 case DMV_TTE: 733 ifp->if_oerrors++; 734 if ((sc->sc_xte++ % DMV_RPTTE) == 0) 735 log(LOG_WARNING, 736 "dmv%d: transmit threshold error\n", 737 unit); 738 break; 739 case DMV_STE: 740 if ((sc->sc_ste++ % DMV_RPSTE) == 0) 741 log(LOG_WARNING, 742 "dmv%d: select threshold error\n", 743 unit); 744 break; 745 case DMV_NXM: 746 if ((sc->sc_nxm++ % DMV_RPNXM) == 0) 747 log(LOG_WARNING, 748 "dmv%d: nonexistent memory error\n", 749 unit); 750 break; 751 case DMV_MODD: 752 if ((sc->sc_modd++ % DMV_RPMODD) == 0) { 753 log(LOG_WARNING, 754 "dmv%d: modem disconnected error\n", 755 unit); 756 goto restart; 757 } 758 break; 759 case DMV_CXRL: 760 if ((sc->sc_cxrl++ % DMV_RPCXRL) == 0) 761 log(LOG_WARNING, 762 "dmv%d: carrier loss error\n", 763 unit); 764 break; 765 case DMV_QOVF: 766 log(LOG_WARNING, 767 "dmv%d: response queue overflow\n", 768 unit); 769 sc->sc_qovf++; 770 goto restart; 771 772 default: 773 log(LOG_WARNING, 774 "dmv%d: unknown error %o\n", 775 unit, sel6&DMV_EEC); 776 if ((sc->sc_unknown++ % DMV_RPUNKNOWN) == 0) 777 goto restart; 778 break; 779 } 780 break; 781 782 case DMV_BDRUNUS: 783 case DMV_BDXSN: 784 case DMV_BDXNS: 785 log(LOG_INFO, 786 "dmv%d: buffer disp for halted trib %o\n", 787 unit, sel2&0x7 788 ); 789 break; 790 791 case DMV_MDEFO: 792 if((sel6&0x1f) == 020) { 793 log(LOG_INFO, 794 "dmv%d: buffer return complete sel3=%x\n", 795 unit, sel3); 796 } else { 797 log(LOG_INFO, 798 "dmv%d: info resp sel3=%x sel4=%x sel6=%x\n", 799 unit, sel3, sel4, sel6 800 ); 801 } 802 break; 803 804 default: 805 log(LOG_WARNING, "dmv%d: bad control %o\n", 806 unit, sel2&0x7 807 ); 808 break; 809 } 810 } 811 dmvstart(unit); 812 return; 813 restart: 814 dmvrestart(unit); 815 } 816 817 load_rec_bufs(sc) 818 register struct dmv_softc *sc; 819 { 820 register struct dmvbufs *rp; 821 822 /* queue first NRCV buffers for DMV to fill */ 823 for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) { 824 rp->flags |= DBUF_DMVS; 825 dmvload( 826 sc, 827 DMV_BACCR, 828 QP_TRIB|QP_SEL4|QP_SEL6|QP_SEL10, 829 1, 830 rp->ubinfo, 831 (rp->ubinfo>>16)&0x3f, 832 rp->cc 833 ); 834 sc->sc_iused++; 835 } 836 } 837 838 /* 839 * DMV output routine. 840 * Encapsulate a packet of type family for the dmv. 841 * Use trailer local net encapsulation if enough data in first 842 * packet leaves a multiple of 512 bytes of data in remainder. 843 */ 844 dmvoutput(ifp, m0, dst) 845 register struct ifnet *ifp; 846 register struct mbuf *m0; 847 struct sockaddr *dst; 848 { 849 int type, error, s; 850 register struct mbuf *m = m0; 851 register struct dmv_header *dh; 852 register int off; 853 854 if ((ifp->if_flags & IFF_UP) == 0) { 855 error = ENETDOWN; 856 goto bad; 857 } 858 859 switch (dst->sa_family) { 860 #ifdef INET 861 case AF_INET: 862 off = m->m_pkthdr.len - m->m_len; 863 if ((ifp->if_flags & IFF_NOTRAILERS) == 0) 864 if (off > 0 && (off & 0x1ff) == 0 && 865 (m->m_flags & M_EXT) == 0 && 866 m->m_data >= m->m_pktdat + 2 * sizeof (u_short)) { 867 type = DMV_TRAILER + (off>>9); 868 m->m_data -= 2 * sizeof (u_short); 869 m->m_len += 2 * sizeof (u_short); 870 *mtod(m, u_short *) = htons((u_short)DMV_IPTYPE); 871 *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); 872 goto gottrailertype; 873 } 874 type = DMV_IPTYPE; 875 off = 0; 876 goto gottype; 877 #endif 878 879 case AF_UNSPEC: 880 dh = (struct dmv_header *)dst->sa_data; 881 type = dh->dmv_type; 882 goto gottype; 883 884 default: 885 log(LOG_ERR, "dmvoutput, dmv%d can't handle af%d\n", 886 ifp->if_unit, dst->sa_family); 887 error = EAFNOSUPPORT; 888 goto bad; 889 } 890 891 gottrailertype: 892 /* 893 * Packet to be sent as a trailer; move first packet 894 * (control information) to end of chain. 895 */ 896 while (m->m_next) 897 m = m->m_next; 898 m->m_next = m0; 899 m = m0->m_next; 900 m0->m_next = 0; 901 m0 = m; 902 903 gottype: 904 /* 905 * Add local network header 906 * (there is space for a uba on a vax to step on) 907 */ 908 M_PREPEND(m, sizeof(struct dmv_header), M_DONTWAIT); 909 if (m == 0) { 910 error = ENOBUFS; 911 goto bad; 912 } 913 dh = mtod(m, struct dmv_header *); 914 dh->dmv_type = htons((u_short)type); 915 916 /* 917 * Queue message on interface, and start output if interface 918 * not yet active. 919 */ 920 s = splimp(); 921 if (IF_QFULL(&ifp->if_snd)) { 922 IF_DROP(&ifp->if_snd); 923 m_freem(m); 924 splx(s); 925 return (ENOBUFS); 926 } 927 IF_ENQUEUE(&ifp->if_snd, m); 928 dmvstart(ifp->if_unit); 929 splx(s); 930 return (0); 931 932 bad: 933 m_freem(m0); 934 return (error); 935 } 936 937 938 /* 939 * Process an ioctl request. 940 */ 941 /* ARGSUSED */ 942 dmvioctl(ifp, cmd, data) 943 register struct ifnet *ifp; 944 int cmd; 945 caddr_t data; 946 { 947 int s = splimp(), error = 0; 948 struct mbuf *m; 949 register struct dmv_softc *sc = &dmv_softc[ifp->if_unit]; 950 951 switch (cmd) { 952 953 case SIOCSIFADDR: 954 ifp->if_flags |= IFF_UP; 955 if ((ifp->if_flags & IFF_RUNNING) == 0) 956 dmvinit(ifp->if_unit); 957 break; 958 959 case SIOCSIFDSTADDR: 960 if ((ifp->if_flags & IFF_RUNNING) == 0) 961 dmvinit(ifp->if_unit); 962 break; 963 964 case SIOCSIFFLAGS: 965 if ((ifp->if_flags & IFF_UP) == 0 && 966 sc->sc_flag & DMV_RUNNING) 967 dmvdown(ifp->if_unit); 968 else if (ifp->if_flags & IFF_UP && 969 (sc->sc_flag & DMV_RUNNING) == 0) 970 dmvrestart(ifp->if_unit); 971 break; 972 973 default: 974 error = EINVAL; 975 } 976 splx(s); 977 return (error); 978 } 979 980 /* 981 * Restart after a fatal error. 982 * Clear device and reinitialize. 983 */ 984 dmvrestart(unit) 985 int unit; 986 { 987 register struct dmvdevice *addr; 988 register int i; 989 990 dmvdown(unit); 991 992 addr = (struct dmvdevice *)(dmvinfo[unit]->ui_addr); 993 /* 994 * Let the DMV finish the MCLR. 995 */ 996 for (i = 100000; i && (addr->bsel1 & DMV_RUN) == 0; i--) 997 ; 998 if ((addr->bsel1 & DMV_RUN) == 0) { 999 log(LOG_ERR, "dmvrestart: can't start device\n" ); 1000 return (0); 1001 } 1002 if ((addr->bsel4 != 033) || (addr->bsel6 != 0305)) 1003 { 1004 log(LOG_ERR, "dmv%d: device init failed, bsel4=%o, bsel6=%o\n", 1005 unit, addr->bsel4, addr->bsel6); 1006 return (0); 1007 } 1008 1009 /* restart DMV */ 1010 dmvinit(unit); 1011 dmv_softc[unit].sc_if.if_collisions++; /* why not? */ 1012 } 1013 1014 /* 1015 * Reset a device and mark down. 1016 * Flush output queue and drop queue limit. 1017 */ 1018 dmvdown(unit) 1019 int unit; 1020 { 1021 struct dmv_softc *sc = &dmv_softc[unit]; 1022 register struct ifxmt *ifxp; 1023 1024 ((struct dmvdevice *)(dmvinfo[unit]->ui_addr))->bsel1 = DMV_MCLR; 1025 sc->sc_flag &= ~(DMV_RUNNING | DMV_ONLINE); 1026 1027 for (ifxp = sc->sc_ifw; ifxp < &sc->sc_ifw[NXMT]; ifxp++) { 1028 if (ifxp->ifw_xtofree) { 1029 (void) m_freem(ifxp->ifw_xtofree); 1030 ifxp->ifw_xtofree = 0; 1031 } 1032 } 1033 sc->sc_oused = 0; 1034 if_qflush(&sc->sc_if.if_snd); 1035 1036 /* 1037 * Limit packets enqueued until we're back on the air. 1038 */ 1039 sc->sc_if.if_snd.ifq_maxlen = 3; 1040 } 1041 1042 /* 1043 * Watchdog timeout to see that transmitted packets don't 1044 * lose interrupts. The device has to be online. 1045 */ 1046 dmvtimeout(unit) 1047 int unit; 1048 { 1049 register struct dmv_softc *sc; 1050 struct dmvdevice *addr; 1051 1052 sc = &dmv_softc[unit]; 1053 if (sc->sc_flag & DMV_ONLINE) { 1054 addr = (struct dmvdevice *)(dmvinfo[unit]->ui_addr); 1055 log(LOG_ERR, "dmv%d: output timeout, bsel0=%b bsel2=%b\n", 1056 unit, addr->bsel0 & 0xff, DMV0BITS, 1057 addr->bsel2 & 0xff, DMV2BITS); 1058 dmvrestart(unit); 1059 } 1060 } 1061 #endif 1062