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