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