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