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