1 /* 2 * Copyright (c) 1990 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)if_dp.c 7.3 (Berkeley) 09/12/90 8 */ 9 10 #include "dp.h" 11 #if NDP > 0 12 13 /* 14 * DPV-11 device driver, X.25 version 15 * 16 * Derived from dmc-11 driver: 17 * 18 * Bill Nesheim 19 * Cornell University 20 * 21 * Lou Salkind 22 * New York University 23 */ 24 25 /* #define DEBUG /* for base table dump on fatal error */ 26 27 #include "machine/pte.h" 28 29 #include "param.h" 30 #include "systm.h" 31 #include "mbuf.h" 32 #include "buf.h" 33 #include "ioctl.h" /* must precede tty.h */ 34 #include "protosw.h" 35 #include "socket.h" 36 #include "socketvar.h" 37 #include "syslog.h" 38 #include "vmmac.h" 39 #include "errno.h" 40 #include "time.h" 41 #include "kernel.h" 42 43 #include "../net/if.h" 44 #include "../net/netisr.h" 45 #include "../net/route.h" 46 47 #include "../vax/cpu.h" 48 #include "../vax/mtpr.h" 49 50 #define dzdevice dpdevice 51 #include "../vaxuba/pdma.h" 52 #include "../vaxuba/ubavar.h" 53 54 #include "../netccitt/x25.h" 55 #include "../netccitt/pk.h" 56 #include "../netccitt/pk_var.h" 57 58 #include "if_dpreg.h" 59 60 /* 61 * Driver information for auto-configuration stuff. 62 */ 63 int dpprobe(), dpattach(), dpinit(), dpioctl(), dprint(), dpxint(); 64 int dpoutput(), dpreset(), dptimeout(), dpstart(), x25_ifoutput(), dptestoutput(); 65 66 struct uba_device *dpinfo[NDP]; 67 68 u_short dpstd[] = { 0 }; 69 struct uba_driver dpdriver = 70 { dpprobe, 0, dpattach, 0, dpstd, "dp", dpinfo }; 71 72 /* 73 * debug info 74 */ 75 struct dpstat { 76 long start; 77 long nohdr; 78 long init; 79 long rint; 80 long xint; 81 long reset; 82 long ioctl; 83 long down; 84 long mchange; 85 long timeout; 86 } dpstat; 87 /* 88 * Pdma structures for fast interrupts. 89 */ 90 struct pdma dppdma[2*NDP]; 91 92 /* error reporting intervals */ 93 #define DPI_RPNBFS 50 94 #define DPI_RPDSC 1 95 #define DPI_RPTMO 10 96 #define DPI_RPDCK 10 97 98 99 /* 100 * DP software status per interface. 101 * 102 * Each interface is referenced by a network interface structure, 103 * dp_if, which the routing code uses to locate the interface. 104 * This structure contains the output queue for the interface, its address, ... 105 */ 106 struct dp_softc { 107 struct ifnet dp_if; /* network-visible interface */ 108 int dp_ipl; 109 short dp_iused; /* input buffers given to DP */ 110 short dp_flags; /* flags */ 111 #define DPF_RUNNING 0x01 /* device initialized */ 112 #define DPF_ONLINE 0x02 /* device running (had a RDYO) */ 113 #define DPF_RESTART 0x04 /* software restart in progress */ 114 #define DPF_FLUSH 0x08 /* had a ROVR, flush ipkt when done */ 115 short dp_ostate; /* restarting, etc. */ 116 short dp_istate; /* not sure this is necessary */ 117 #define DPS_IDLE 0 118 #define DPS_RESTART 1 119 #define DPS_ACTIVE 2 120 #define DPS_XEM 3 /* transmitting CRC, etc. */ 121 int dp_errors[4]; /* non-fatal error counters */ 122 #define dp_datck dp_errors[0] 123 #define dp_timeo dp_errors[1] 124 #define dp_nobuf dp_errors[2] 125 #define dp_disc dp_errors[3] 126 struct timeval dp_xt; /* start of last transmission */ 127 char dp_obuf[DP_MTU+8]; 128 char dp_ibuf[DP_MTU+8]; 129 } dp_softc[NDP]; 130 131 dpprobe(reg, ui) 132 caddr_t reg; 133 struct uba_device *ui; 134 { 135 register int br, cvec; 136 register struct dpdevice *addr = (struct dpdevice *)reg; 137 register int i; 138 139 #ifdef lint 140 br = 0; cvec = br; br = cvec; 141 dprint(0); dpxint(0); 142 #endif 143 (void) spl6(); 144 addr->dpclr = DP_CLR; 145 addr->dpclr = DP_XIE|DP_XE; 146 DELAY(100000); 147 dp_softc[ui->ui_unit].dp_ipl = br = qbgetpri(); 148 addr->dpclr = 0; 149 if (cvec && cvec != 0x200){ 150 cvec -= 4; 151 } 152 return (1); 153 } 154 155 /* 156 * Interface exists: make available by filling in network interface 157 * record. System will initialize the interface when it is ready 158 * to accept packets. 159 */ 160 dpattach(ui) 161 register struct uba_device *ui; 162 { 163 register struct dp_softc *dp = &dp_softc[ui->ui_unit]; 164 165 dp->dp_if.if_unit = ui->ui_unit; 166 dp->dp_if.if_name = "dp"; 167 dp->dp_if.if_mtu = DP_MTU; 168 dp->dp_if.if_init = dpinit; 169 dp->dp_if.if_output = x25_ifoutput; 170 dp->dp_if.if_start = dpstart; 171 dp->dp_if.if_ioctl = dpioctl; 172 dp->dp_if.if_reset = dpreset; 173 dp->dp_if.if_watchdog = dptimeout; 174 dp->dp_if.if_flags = 0; 175 if_attach(&dp->dp_if); 176 } 177 178 /* 179 * Reset of interface after UNIBUS reset. 180 * If interface is on specified UBA, reset its state. 181 */ 182 dpreset(unit, uban) 183 int unit, uban; 184 { 185 register struct uba_device *ui; 186 register struct dp_softc *dp = &dp_softc[unit]; 187 register struct dpdevice *addr; 188 189 dpstat.reset++; 190 if (unit >= NDP || (ui = dpinfo[unit]) == 0 || ui->ui_alive == 0 || 191 ui->ui_ubanum != uban) 192 return; 193 printf(" dp%d", unit); 194 dp->dp_flags = 0; 195 dp->dp_if.if_flags &= ~IFF_RUNNING; 196 addr = (struct dpdevice *)ui->ui_addr; 197 addr->dpclr = DP_CLR; 198 DELAY(1000); 199 addr->dpsar = 0; 200 addr->dprcsr = 0; 201 dpinit(unit); 202 } 203 204 /* 205 * Initialization of interface. 206 */ 207 dpinit(unit) 208 int unit; 209 { 210 register struct dp_softc *dp = &dp_softc[unit]; 211 register struct uba_device *ui = dpinfo[unit]; 212 register struct dpdevice *addr; 213 register struct ifaddr *ifa; 214 register struct pdma *pdp = &dppdma[unit*2]; 215 int base, s; 216 217 dpstat.init++; 218 /* 219 * Check to see that an address has been set. 220 */ 221 for (ifa = dp->dp_if.if_addrlist; ifa; ifa = ifa->ifa_next) 222 if (ifa->ifa_addr->sa_family != AF_LINK) 223 break; 224 if (ifa == (struct ifaddr *) 0) 225 return; 226 227 addr = (struct dpdevice *)ui->ui_addr; 228 s = splimp(); 229 dp->dp_iused = 0; 230 dp->dp_istate = dp->dp_ostate = DPS_IDLE; 231 dp->dp_if.if_flags |= IFF_RUNNING; 232 dp->dp_if.if_flags &= ~IFF_OACTIVE; 233 234 pdp->p_addr = addr; 235 pdp->p_fcn = dpxint; 236 pdp->p_mem = pdp->p_end = dp->dp_obuf; 237 pdp++; 238 pdp->p_addr = addr; 239 pdp->p_fcn = dprint; 240 /* force initial interrupt to come to dprint */ 241 pdp->p_mem = pdp->p_end = dp->dp_ibuf + DP_MTU + 8; 242 243 addr->dpclr = DP_CLR; 244 DELAY(1000); 245 addr->dpclr = 0; 246 DELAY(1000); 247 /* DP_ATA = 0, DP_CHRM = 0, 248 CRC = CCIIT, initially all ones, 2nd addr = 0 */ 249 addr->dpsar = 0; 250 /* enable receive interrupt */ 251 addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS; 252 dpstart(&dp->dp_if); 253 splx(s); 254 } 255 256 int dpMessy = 0; 257 /* 258 * Start output on interface. Get another datagram 259 * to send from the interface queue and map it to 260 * the interface before starting output. 261 * 262 */ 263 dpstart(ifp) 264 struct ifnet *ifp; 265 { 266 int s, unit = ifp->if_unit, error = 0, len; 267 register struct dp_softc *dp = &dp_softc[unit]; 268 register struct dpdevice *addr = 269 (struct dpdevice *)(dpinfo[unit]->ui_addr); 270 register struct mbuf *m; 271 register char *cp; 272 char *cplim; 273 274 /* 275 * If already doing output, go away and depend on transmit 276 * complete or error. 277 */ 278 dpstat.start++; 279 if (dp->dp_if.if_flags & IFF_OACTIVE) 280 goto out; 281 IF_DEQUEUE(&dp->dp_if.if_snd, m); 282 if (m == 0) 283 goto out; 284 dp->dp_if.if_collisions++; 285 if (m->m_flags & M_PKTHDR) 286 len = m->m_pkthdr.len; 287 else { 288 struct mbuf *m0 = m; 289 for (len = 0; m; m = m->m_next) 290 len += m->m_len; 291 m = m0; 292 dpstat.nohdr++; 293 } 294 if (len == 0) 295 goto out; 296 if (len > DP_MTU) { 297 error = EINVAL; 298 goto out; 299 } 300 cp = dp->dp_obuf; 301 dppdma[2*unit].p_mem = cp + 1; 302 while (m) { 303 struct mbuf *n; 304 bcopy(mtod(m, caddr_t), (caddr_t)cp, m->m_len); 305 cp += m->m_len; 306 MFREE(m, n); m = n; 307 } 308 dppdma[2*unit].p_end = cp; 309 if (dpMessy) 310 printf("dp: len %d, start %x, end %x, first %x, next %x", 311 len, dp->dp_obuf, cp, *(int *)dp->dp_obuf, 312 1[(int *)dp->dp_obuf]); 313 dp->dp_if.if_flags |= IFF_OACTIVE; 314 dp->dp_ostate = DPS_ACTIVE; 315 dp->dp_if.if_collisions--; 316 dp->dp_xt = time; 317 addr->dpclr = DP_XE | DP_XIE; 318 addr->dptdsr = DP_XSM | (0xff & dp->dp_obuf[0]); 319 out: 320 return (error); 321 } 322 /* 323 * Receive done or error interrupt 324 */ 325 dprint(unit, pdma, addr) 326 register struct pdma *pdma; 327 register struct dpdevice *addr; 328 { 329 register struct dp_softc *dp = &dp_softc[unit]; 330 short rdsr = addr->dprdsr, rcsr; 331 332 dpstat.rint++; 333 splx(dp->dp_ipl); 334 if (rdsr & DP_RSM) { /* Received Start of Message */ 335 dp->dp_ibuf[0] = rdsr & DP_RBUF; 336 pdma->p_mem = dp->dp_ibuf + 1; 337 dp->dp_flags &= ~DPF_FLUSH; 338 return; 339 } 340 if (rdsr & DP_REM) { /* Received End of Message */ 341 if (rdsr & DP_REC || dp->dp_flags & DPF_FLUSH) { 342 dp->dp_if.if_ierrors++; 343 } else 344 dpinput(&dp->dp_if, 345 pdma->p_mem - dp->dp_ibuf, dp->dp_ibuf); 346 pdma->p_mem = pdma->p_end; 347 dp->dp_flags &= ~ DPF_FLUSH; 348 return; 349 } 350 if (rdsr & DP_ROVR) { 351 dp->dp_flags |= DPF_FLUSH; 352 return; 353 } 354 rcsr = pdma->p_arg; 355 if (rcsr & DP_MSC) { 356 dpstat.mchange++; 357 if (0 == (rcsr & DP_DSR)) { 358 log(LOG_DEBUG, "dp%d: lost modem\n", unit); 359 dpdown(unit); 360 } 361 return; 362 } 363 dp->dp_flags |= DPF_FLUSH; 364 if (pdma->p_mem != pdma->p_end) 365 log("dp%d: unexplained receiver interrupt\n", unit); 366 } 367 struct timeval dp_xt; 368 369 /* 370 * Transmit complete or error interrupt 371 */ 372 dpxint(unit, pdma, addr) 373 register struct pdma *pdma; 374 register struct dpdevice *addr; 375 { 376 register struct dp_softc *dp = &dp_softc[unit]; 377 int s; 378 379 splx(dp->dp_ipl); 380 dpstat.xint++; 381 if (addr->dptdsr & DP_XERR) { 382 log("if_dp%d: data late\n", unit); 383 restart: 384 pdma->p_mem = dp->dp_obuf; 385 addr->dptdsr = DP_XSM; 386 dp->dp_if.if_oerrors++; 387 return; 388 } 389 switch (dp->dp_ostate) { 390 391 case DPS_ACTIVE: 392 if (pdma->p_mem != pdma->p_end) { 393 log("if_dp%d: misc error in dpxint\n", unit); 394 goto restart; 395 } 396 addr->dptdsr = DP_XEM; 397 dp->dp_ostate = DPS_XEM; 398 break; 399 400 case DPS_XEM: 401 dp->dp_if.if_opackets++; 402 dp->dp_if.if_flags &= ~IFF_OACTIVE; 403 s = splclock(); 404 dp_xt = time; 405 timevalsub(&dp_xt, &dp->dp_xt); 406 splx(s); 407 if (dp->dp_if.if_snd.ifq_len) 408 dpstart(&dp->dp_if); 409 else { 410 addr->dpclr = 0; 411 dp->dp_ostate = DPS_IDLE; 412 } 413 break; 414 415 default: 416 log("if_dp%d: impossible state in dpxint\n"); 417 } 418 } 419 /* 420 * Routine to copy from device buffer into mbufs. 421 * 422 * Warning: This makes the fairly safe assumption that 423 * mbufs have even lengths. 424 */ 425 struct mbuf * 426 dpget(rxbuf, totlen, off, ifp) 427 caddr_t rxbuf; 428 int totlen, off; 429 struct ifnet *ifp; 430 { 431 register caddr_t cp; 432 register struct mbuf *m; 433 struct mbuf *top = 0, **mp = ⊤ 434 int len; 435 caddr_t packet_end; 436 437 cp = rxbuf; 438 packet_end = cp + totlen; 439 if (off) { 440 off += 2 * sizeof(u_short); 441 totlen -= 2 *sizeof(u_short); 442 cp = rxbuf + off; 443 } 444 445 MGETHDR(m, M_DONTWAIT, MT_DATA); 446 if (m == 0) 447 return (0); 448 m->m_pkthdr.rcvif = ifp; 449 m->m_pkthdr.len = totlen; 450 m->m_len = MHLEN; 451 452 while (totlen > 0) { 453 if (top) { 454 MGET(m, M_DONTWAIT, MT_DATA); 455 if (m == 0) { 456 m_freem(top); 457 return (0); 458 } 459 m->m_len = MLEN; 460 } 461 len = min(totlen, (packet_end - cp)); 462 if (len >= MINCLSIZE) { 463 MCLGET(m, M_DONTWAIT); 464 if (m->m_flags & M_EXT) 465 m->m_len = len = min(len, MCLBYTES); 466 else 467 len = m->m_len; 468 } else { 469 /* 470 * Place initial small packet/header at end of mbuf. 471 */ 472 if (len < m->m_len) { 473 if (top == 0 && len + max_linkhdr <= m->m_len) 474 m->m_data += max_linkhdr; 475 m->m_len = len; 476 } else 477 len = m->m_len; 478 } 479 bcopy(cp, mtod(m, caddr_t), (u_int)len); 480 *mp = m; 481 mp = &m->m_next; 482 totlen -= len; 483 cp += len; 484 if (cp == packet_end) 485 cp = rxbuf; 486 } 487 return (top); 488 } 489 490 dpinput(ifp, len, buffer) 491 register struct ifnet *ifp; 492 caddr_t buffer; 493 { 494 register struct ifqueue *inq; 495 register struct mbuf *m; 496 extern struct ifqueue hdintrq, ipintrq; 497 int netisr; 498 499 ifp->if_ipackets++; 500 { 501 register struct ifaddr *ifa = ifp->if_addrlist; 502 register u_char *cp = (u_char *)buffer; 503 504 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 505 if (ifa->ifa_addr->sa_family != AF_LINK) 506 break; 507 if (cp[0] == 0xff && cp[1] == 0x3) { 508 /* This is a UI HDLC Packet, so we'll assume PPP 509 protocol. for now, IP only. */ 510 buffer += 4; 511 len -= 4; 512 inq = &ipintrq; 513 netisr = NETISR_IP; 514 } else { 515 inq = &hdintrq; 516 netisr = NETISR_CCITT; 517 } 518 } 519 if (len <= 0) 520 return; 521 522 m = dpget(buffer, len , 0, ifp); 523 if (m == 0) 524 return; 525 526 if(IF_QFULL(inq)) { 527 IF_DROP(inq); 528 m_freem(m); 529 } else { 530 IF_ENQUEUE(inq, m); 531 schednetisr(netisr); 532 } 533 } 534 535 /* 536 * Process an ioctl request. 537 */ 538 dpioctl(ifp, cmd, data) 539 register struct ifnet *ifp; 540 int cmd; 541 caddr_t data; 542 { 543 register struct ifaddr *ifa = (struct ifaddr *)data; 544 int s = splimp(), error = 0; 545 struct dp_softc *dp = &dp_softc[ifp->if_unit]; 546 547 dpstat.ioctl++; 548 switch (cmd) { 549 550 case SIOCSIFADDR: 551 ifp->if_flags |= IFF_UP; 552 switch (ifa->ifa_addr->sa_family) { 553 case AF_INET: 554 ifp->if_output = dptestoutput; 555 default: 556 dpinit(ifp->if_unit); 557 break; 558 } 559 break; 560 #ifdef CCITT 561 case SIOCSIFCONF_X25: 562 ifp->if_flags |= IFF_UP; 563 ifp->if_output = x25_ifoutput; 564 error = hd_ctlinput(PRC_IFUP, ifa->ifa_addr); 565 if (error == 0) 566 dpinit(ifp->if_unit); 567 break; 568 #endif 569 570 case SIOCSIFFLAGS: 571 if ((ifp->if_flags & IFF_UP) == 0 && 572 (ifp->if_flags & IFF_RUNNING)) 573 dpdown(ifp->if_unit); 574 else if (ifp->if_flags & IFF_UP && 575 (ifp->if_flags & IFF_RUNNING) == 0) 576 dpinit(ifp->if_unit); 577 break; 578 579 580 default: 581 error = EINVAL; 582 } 583 splx(s); 584 return (error); 585 } 586 /* 587 * Reset a device and mark down. 588 * Flush output queue and drop queue limit. 589 */ 590 dpdown(unit) 591 int unit; 592 { 593 register struct dp_softc *dp = &dp_softc[unit]; 594 595 dpstat.down++; 596 if_qflush(&dp->dp_if.if_snd); 597 dpreset(unit); 598 } 599 600 /* 601 * Watchdog timeout to see that transmitted packets don't 602 * lose interrupts. The device has to be online (the first 603 * transmission may block until the other side comes up). 604 */ 605 dptimeout(unit) 606 int unit; 607 { 608 register struct dp_softc *dp; 609 610 /* currently not armed */ 611 dpstat.timeout++; 612 dp = &dp_softc[unit]; 613 if (dp->dp_if.if_flags & IFF_OACTIVE) { 614 dpstart(&dp->dp_if); 615 } 616 } 617 /* 618 * For debugging loopback activity. 619 */ 620 static char pppheader[4] = { -1, 3, 0, 0x21 }; 621 int dp_louts; 622 623 dptestoutput(ifp, m, dst, rt) 624 register struct ifnet *ifp; 625 register struct mbuf *m; 626 struct sockaddr *dst; 627 struct rtentry *rt; 628 { 629 /* 630 * Queue message on interface, and start output if interface 631 * not yet active. 632 */ 633 int s = splimp(), error = 0; 634 dp_louts++; 635 M_PREPEND(m, sizeof pppheader, M_DONTWAIT); 636 if (m == 0) { 637 splx(s); 638 return ENOBUFS; 639 } 640 bcopy(pppheader, mtod(m, caddr_t), sizeof pppheader); 641 if (IF_QFULL(&ifp->if_snd)) { 642 IF_DROP(&ifp->if_snd); 643 /* printf("%s%d: HDLC says OK to send but queue full, may hang\n", 644 ifp->if_name, ifp->if_unit);*/ 645 m_freem(m); 646 error = ENOBUFS; 647 } else { 648 IF_ENQUEUE(&ifp->if_snd, m); 649 if ((ifp->if_flags & IFF_OACTIVE) == 0) 650 (*ifp->if_start)(ifp); 651 } 652 splx(s); 653 return (error); 654 } 655 656 #endif 657