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