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.3 (Berkeley) 08/04/88 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 = ifrw->ifrw_info & 0x3ffff; 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 = ifxp->ifw_info & 0x3ffff; 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 = sc->sc_ubinfo & 0x3ffff; 345 dmcload(sc, DMC_BASEI, 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, w0, w1; 424 { 425 register struct dmcdevice *addr; 426 register int unit, sps; 427 register struct dmc_command *qp; 428 429 unit = sc - dmc_softc; 430 addr = (struct dmcdevice *)dmcinfo[unit]->ui_addr; 431 sps = spl5(); 432 433 /* grab a command buffer from the free list */ 434 if ((qp = sc->sc_qfreeh) == (struct dmc_command *)0) 435 panic("dmc command queue overflow"); 436 DEQUEUE(sc->sc_qfreeh, sc->sc_qfreet); 437 438 /* fill in requested info */ 439 qp->qp_cmd = (type | DMC_RQI); 440 qp->qp_ubaddr = w0; 441 qp->qp_cc = w1; 442 443 if (sc->sc_qactive) { /* command in progress */ 444 if (type == DMC_READ) { 445 QUEUE_AT_HEAD(qp, sc->sc_qhead, sc->sc_qtail); 446 } else { 447 QUEUE_AT_TAIL(qp, sc->sc_qhead, sc->sc_qtail); 448 } 449 } else { /* command port free */ 450 sc->sc_qactive = qp; 451 addr->bsel0 = qp->qp_cmd; 452 dmcrint(unit); 453 } 454 splx(sps); 455 } 456 457 /* 458 * DMC interface receiver interrupt. 459 * Ready to accept another command, 460 * pull one off the command queue. 461 */ 462 dmcrint(unit) 463 int unit; 464 { 465 register struct dmc_softc *sc; 466 register struct dmcdevice *addr; 467 register struct dmc_command *qp; 468 register int n; 469 470 addr = (struct dmcdevice *)dmcinfo[unit]->ui_addr; 471 sc = &dmc_softc[unit]; 472 if ((qp = sc->sc_qactive) == (struct dmc_command *) 0) { 473 printf("dmc%d: dmcrint no command\n", unit); 474 return; 475 } 476 while (addr->bsel0&DMC_RDYI) { 477 addr->sel4 = qp->qp_ubaddr; 478 addr->sel6 = qp->qp_cc; 479 addr->bsel0 &= ~(DMC_IEI|DMC_RQI); 480 /* free command buffer */ 481 QUEUE_AT_HEAD(qp, sc->sc_qfreeh, sc->sc_qfreet); 482 while (addr->bsel0 & DMC_RDYI) { 483 /* 484 * Can't check for RDYO here 'cause 485 * this routine isn't reentrant! 486 */ 487 DELAY(5); 488 } 489 /* move on to next command */ 490 if ((sc->sc_qactive = sc->sc_qhead) == (struct dmc_command *)0) 491 break; /* all done */ 492 /* more commands to do, start the next one */ 493 qp = sc->sc_qactive; 494 DEQUEUE(sc->sc_qhead, sc->sc_qtail); 495 addr->bsel0 = qp->qp_cmd; 496 n = RDYSCAN; 497 while (n-- > 0) 498 if ((addr->bsel0&DMC_RDYI) || (addr->bsel2&DMC_RDYO)) 499 break; 500 } 501 if (sc->sc_qactive) { 502 addr->bsel0 |= DMC_IEI|DMC_RQI; 503 /* VMS does it twice !*$%@# */ 504 addr->bsel0 |= DMC_IEI|DMC_RQI; 505 } 506 507 } 508 509 /* 510 * DMC interface transmitter interrupt. 511 * A transfer may have completed, check for errors. 512 * If it was a read, notify appropriate protocol. 513 * If it was a write, pull the next one off the queue. 514 */ 515 dmcxint(unit) 516 int unit; 517 { 518 register struct dmc_softc *sc; 519 register struct ifnet *ifp; 520 struct uba_device *ui = dmcinfo[unit]; 521 struct dmcdevice *addr; 522 struct mbuf *m; 523 struct ifqueue *inq; 524 int arg, pkaddr, cmd, len, s; 525 register struct ifrw *ifrw; 526 register struct dmcbufs *rp; 527 register struct ifxmt *ifxp; 528 struct dmc_header *dh; 529 int off, resid; 530 531 addr = (struct dmcdevice *)ui->ui_addr; 532 sc = &dmc_softc[unit]; 533 ifp = &sc->sc_if; 534 535 while (addr->bsel2 & DMC_RDYO) { 536 537 cmd = addr->bsel2 & 0xff; 538 arg = addr->sel6 & 0xffff; 539 /* reconstruct UNIBUS address of buffer returned to us */ 540 pkaddr = ((arg&DMC_XMEM)<<2) | (addr->sel4 & 0xffff); 541 /* release port */ 542 addr->bsel2 &= ~DMC_RDYO; 543 switch (cmd & 07) { 544 545 case DMC_OUR: 546 /* 547 * A read has completed. 548 * Pass packet to type specific 549 * higher-level input routine. 550 */ 551 ifp->if_ipackets++; 552 /* find location in dmcuba struct */ 553 ifrw= &sc->sc_ifr[0]; 554 for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) { 555 if(rp->ubinfo == pkaddr) 556 break; 557 ifrw++; 558 } 559 if (rp >= &sc->sc_rbufs[NRCV]) 560 panic("dmc rcv"); 561 if ((rp->flags & DBUF_DMCS) == 0) 562 printf("dmc%d: done unalloc rbuf\n", unit); 563 564 len = (arg & DMC_CCOUNT) - sizeof (struct dmc_header); 565 if (len < 0 || len > DMCMTU) { 566 ifp->if_ierrors++; 567 printd("dmc%d: bad rcv pkt addr 0x%x len 0x%x\n", 568 unit, pkaddr, len); 569 goto setup; 570 } 571 /* 572 * Deal with trailer protocol: if type is trailer 573 * get true type from first 16-bit word past data. 574 * Remember that type was trailer by setting off. 575 */ 576 dh = (struct dmc_header *)ifrw->ifrw_addr; 577 dh->dmc_type = ntohs((u_short)dh->dmc_type); 578 #define dmcdataaddr(dh, off, type) ((type)(((caddr_t)((dh)+1)+(off)))) 579 if (dh->dmc_type >= DMC_TRAILER && 580 dh->dmc_type < DMC_TRAILER+DMC_NTRAILER) { 581 off = (dh->dmc_type - DMC_TRAILER) * 512; 582 if (off >= DMCMTU) 583 goto setup; /* sanity */ 584 dh->dmc_type = ntohs(*dmcdataaddr(dh, off, u_short *)); 585 resid = ntohs(*(dmcdataaddr(dh, off+2, u_short *))); 586 if (off + resid > len) 587 goto setup; /* sanity */ 588 len = off + resid; 589 } else 590 off = 0; 591 if (len == 0) 592 goto setup; 593 594 /* 595 * Pull packet off interface. Off is nonzero if 596 * packet has trailing header; dmc_get will then 597 * force this header information to be at the front, 598 * but we still have to drop the type and length 599 * which are at the front of any trailer data. 600 */ 601 m = if_ubaget(&sc->sc_ifuba, ifrw, len, off, ifp); 602 if (m == 0) 603 goto setup; 604 if (off) { 605 ifp = *(mtod(m, struct ifnet **)); 606 m->m_off += 2 * sizeof (u_short); 607 m->m_len -= 2 * sizeof (u_short); 608 *(mtod(m, struct ifnet **)) = ifp; 609 } 610 switch (dh->dmc_type) { 611 612 #ifdef INET 613 case DMC_IPTYPE: 614 schednetisr(NETISR_IP); 615 inq = &ipintrq; 616 break; 617 #endif 618 default: 619 m_freem(m); 620 goto setup; 621 } 622 623 s = splimp(); 624 if (IF_QFULL(inq)) { 625 IF_DROP(inq); 626 m_freem(m); 627 } else 628 IF_ENQUEUE(inq, m); 629 splx(s); 630 631 setup: 632 /* is this needed? */ 633 rp->ubinfo = ifrw->ifrw_info & 0x3ffff; 634 635 dmcload(sc, DMC_READ, rp->ubinfo, 636 ((rp->ubinfo >> 2) & DMC_XMEM) | rp->cc); 637 break; 638 639 case DMC_OUX: 640 /* 641 * A write has completed, start another 642 * transfer if there is more data to send. 643 */ 644 ifp->if_opackets++; 645 /* find associated dmcbuf structure */ 646 ifxp = &sc->sc_ifw[0]; 647 for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[NXMT]; rp++) { 648 if(rp->ubinfo == pkaddr) 649 break; 650 ifxp++; 651 } 652 if (rp >= &sc->sc_xbufs[NXMT]) { 653 printf("dmc%d: bad packet address 0x%x\n", 654 unit, pkaddr); 655 break; 656 } 657 if ((rp->flags & DBUF_DMCS) == 0) 658 printf("dmc%d: unallocated packet 0x%x\n", 659 unit, pkaddr); 660 /* mark buffer free */ 661 if (ifxp->ifw_xtofree) { 662 (void)m_freem(ifxp->ifw_xtofree); 663 ifxp->ifw_xtofree = 0; 664 } 665 rp->flags &= ~DBUF_DMCS; 666 if (--sc->sc_oused == 0) 667 sc->sc_if.if_timer = 0; 668 else 669 sc->sc_if.if_timer = dmc_timeout; 670 if ((sc->sc_flag & DMC_ONLINE) == 0) { 671 extern int ifqmaxlen; 672 673 /* 674 * We're on the air. 675 * Open the queue to the usual value. 676 */ 677 sc->sc_flag |= DMC_ONLINE; 678 ifp->if_snd.ifq_maxlen = ifqmaxlen; 679 } 680 break; 681 682 case DMC_CNTLO: 683 arg &= DMC_CNTMASK; 684 if (arg & DMC_FATAL) { 685 if (arg != DMC_START) 686 log(LOG_ERR, 687 "dmc%d: fatal error, flags=%b\n", 688 unit, arg, CNTLO_BITS); 689 dmcrestart(unit); 690 break; 691 } 692 /* ACCUMULATE STATISTICS */ 693 switch(arg) { 694 case DMC_NOBUFS: 695 ifp->if_ierrors++; 696 if ((sc->sc_nobuf++ % DMC_RPNBFS) == 0) 697 goto report; 698 break; 699 case DMC_DISCONN: 700 if ((sc->sc_disc++ % DMC_RPDSC) == 0) 701 goto report; 702 break; 703 case DMC_TIMEOUT: 704 if ((sc->sc_timeo++ % DMC_RPTMO) == 0) 705 goto report; 706 break; 707 case DMC_DATACK: 708 ifp->if_oerrors++; 709 if ((sc->sc_datck++ % DMC_RPDCK) == 0) 710 goto report; 711 break; 712 default: 713 goto report; 714 } 715 break; 716 report: 717 printd("dmc%d: soft error, flags=%b\n", unit, 718 arg, CNTLO_BITS); 719 if ((sc->sc_flag & DMC_RESTART) == 0) { 720 /* 721 * kill off the dmc to get things 722 * going again by generating a 723 * procedure error 724 */ 725 sc->sc_flag |= DMC_RESTART; 726 arg = sc->sc_ubinfo & 0x3ffff; 727 dmcload(sc, DMC_BASEI, arg, (arg>>2)&DMC_XMEM); 728 } 729 break; 730 731 default: 732 printf("dmc%d: bad control %o\n", unit, cmd); 733 break; 734 } 735 } 736 dmcstart(unit); 737 return; 738 } 739 740 /* 741 * DMC output routine. 742 * Encapsulate a packet of type family for the dmc. 743 * Use trailer local net encapsulation if enough data in first 744 * packet leaves a multiple of 512 bytes of data in remainder. 745 */ 746 dmcoutput(ifp, m0, dst) 747 register struct ifnet *ifp; 748 register struct mbuf *m0; 749 struct sockaddr *dst; 750 { 751 int type, error, s; 752 register struct mbuf *m = m0; 753 register struct dmc_header *dh; 754 register int off; 755 756 if ((ifp->if_flags & IFF_UP) == 0) { 757 error = ENETDOWN; 758 goto bad; 759 } 760 761 switch (dst->sa_family) { 762 #ifdef INET 763 case AF_INET: 764 off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; 765 if ((ifp->if_flags & IFF_NOTRAILERS) == 0) 766 if (off > 0 && (off & 0x1ff) == 0 && 767 m->m_off >= MMINOFF + 2 * sizeof (u_short)) { 768 type = DMC_TRAILER + (off>>9); 769 m->m_off -= 2 * sizeof (u_short); 770 m->m_len += 2 * sizeof (u_short); 771 *mtod(m, u_short *) = htons((u_short)DMC_IPTYPE); 772 *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); 773 goto gottrailertype; 774 } 775 type = DMC_IPTYPE; 776 off = 0; 777 goto gottype; 778 #endif 779 780 case AF_UNSPEC: 781 dh = (struct dmc_header *)dst->sa_data; 782 type = dh->dmc_type; 783 goto gottype; 784 785 default: 786 printf("dmc%d: can't handle af%d\n", ifp->if_unit, 787 dst->sa_family); 788 error = EAFNOSUPPORT; 789 goto bad; 790 } 791 792 gottrailertype: 793 /* 794 * Packet to be sent as a trailer; move first packet 795 * (control information) to end of chain. 796 */ 797 while (m->m_next) 798 m = m->m_next; 799 m->m_next = m0; 800 m = m0->m_next; 801 m0->m_next = 0; 802 m0 = m; 803 804 gottype: 805 /* 806 * Add local network header 807 * (there is space for a uba on a vax to step on) 808 */ 809 if (m->m_off > MMAXOFF || 810 MMINOFF + sizeof(struct dmc_header) > m->m_off) { 811 m = m_get(M_DONTWAIT, MT_HEADER); 812 if (m == 0) { 813 error = ENOBUFS; 814 goto bad; 815 } 816 m->m_next = m0; 817 m->m_off = MMINOFF; 818 m->m_len = sizeof (struct dmc_header); 819 } else { 820 m->m_off -= sizeof (struct dmc_header); 821 m->m_len += sizeof (struct dmc_header); 822 } 823 dh = mtod(m, struct dmc_header *); 824 dh->dmc_type = htons((u_short)type); 825 826 /* 827 * Queue message on interface, and start output if interface 828 * not yet active. 829 */ 830 s = splimp(); 831 if (IF_QFULL(&ifp->if_snd)) { 832 IF_DROP(&ifp->if_snd); 833 m_freem(m); 834 splx(s); 835 return (ENOBUFS); 836 } 837 IF_ENQUEUE(&ifp->if_snd, m); 838 dmcstart(ifp->if_unit); 839 splx(s); 840 return (0); 841 842 bad: 843 m_freem(m0); 844 return (error); 845 } 846 847 848 /* 849 * Process an ioctl request. 850 */ 851 /* ARGSUSED */ 852 dmcioctl(ifp, cmd, data) 853 register struct ifnet *ifp; 854 int cmd; 855 caddr_t data; 856 { 857 int s = splimp(), error = 0; 858 register struct dmc_softc *sc = &dmc_softc[ifp->if_unit]; 859 860 switch (cmd) { 861 862 case SIOCSIFADDR: 863 ifp->if_flags |= IFF_UP; 864 if ((ifp->if_flags & IFF_RUNNING) == 0) 865 dmcinit(ifp->if_unit); 866 break; 867 868 case SIOCSIFDSTADDR: 869 if ((ifp->if_flags & IFF_RUNNING) == 0) 870 dmcinit(ifp->if_unit); 871 break; 872 873 case SIOCSIFFLAGS: 874 if ((ifp->if_flags & IFF_UP) == 0 && 875 sc->sc_flag & DMC_RUNNING) 876 dmcdown(ifp->if_unit); 877 else if (ifp->if_flags & IFF_UP && 878 (sc->sc_flag & DMC_RUNNING) == 0) 879 dmcrestart(ifp->if_unit); 880 break; 881 882 default: 883 error = EINVAL; 884 } 885 splx(s); 886 return (error); 887 } 888 889 /* 890 * Restart after a fatal error. 891 * Clear device and reinitialize. 892 */ 893 dmcrestart(unit) 894 int unit; 895 { 896 register struct dmc_softc *sc = &dmc_softc[unit]; 897 register struct dmcdevice *addr; 898 register int i; 899 int s; 900 901 #ifdef DEBUG 902 /* dump base table */ 903 printf("dmc%d base table:\n", unit); 904 for (i = 0; i < sizeof (struct dmc_base); i++) 905 printf("%o\n" ,dmc_base[unit].d_base[i]); 906 #endif 907 908 dmcdown(unit); 909 910 /* 911 * Let the DMR finish the MCLR. At 1 Mbit, it should do so 912 * in about a max of 6.4 milliseconds with diagnostics enabled. 913 */ 914 addr = (struct dmcdevice *)(dmcinfo[unit]->ui_addr); 915 for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--) 916 ; 917 /* Did the timer expire or did the DMR finish? */ 918 if ((addr->bsel1 & DMC_RUN) == 0) { 919 log(LOG_ERR, "dmc%d: M820 Test Failed\n", unit); 920 return; 921 } 922 923 /* restart DMC */ 924 dmcinit(unit); 925 sc->sc_flag &= ~DMC_RESTART; 926 s = spl5(); 927 dmcstart(unit); 928 splx(s); 929 sc->sc_if.if_collisions++; /* why not? */ 930 } 931 932 /* 933 * Reset a device and mark down. 934 * Flush output queue and drop queue limit. 935 */ 936 dmcdown(unit) 937 int unit; 938 { 939 register struct dmc_softc *sc = &dmc_softc[unit]; 940 register struct ifxmt *ifxp; 941 942 ((struct dmcdevice *)(dmcinfo[unit]->ui_addr))->bsel1 = DMC_MCLR; 943 sc->sc_flag &= ~(DMC_RUNNING | DMC_ONLINE); 944 945 for (ifxp = sc->sc_ifw; ifxp < &sc->sc_ifw[NXMT]; ifxp++) { 946 if (ifxp->ifw_xtofree) { 947 (void) m_freem(ifxp->ifw_xtofree); 948 ifxp->ifw_xtofree = 0; 949 } 950 } 951 if_qflush(&sc->sc_if.if_snd); 952 } 953 954 /* 955 * Watchdog timeout to see that transmitted packets don't 956 * lose interrupts. The device has to be online (the first 957 * transmission may block until the other side comes up). 958 */ 959 dmctimeout(unit) 960 int unit; 961 { 962 register struct dmc_softc *sc; 963 struct dmcdevice *addr; 964 965 sc = &dmc_softc[unit]; 966 if (sc->sc_flag & DMC_ONLINE) { 967 addr = (struct dmcdevice *)(dmcinfo[unit]->ui_addr); 968 log(LOG_ERR, "dmc%d: output timeout, bsel0=%b bsel2=%b\n", 969 unit, addr->bsel0 & 0xff, DMC0BITS, 970 addr->bsel2 & 0xff, DMC2BITS); 971 dmcrestart(unit); 972 } 973 } 974 #endif 975