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.10 (Berkeley) 05/04/92 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 dpinput(ifp, len, buffer) 447 register struct ifnet *ifp; 448 caddr_t buffer; 449 { 450 register struct ifqueue *inq; 451 register struct mbuf *m; 452 extern struct ifqueue hdintrq, ipintrq; 453 int isr; 454 extern struct mbuf *m_devget(); 455 456 ifp->if_ipackets++; 457 if (dp_log) { 458 register u_char *p = (u_char *)buffer; 459 log(LOG_DEBUG, "dpinput(%d):%x %x %x %x %x\n", 460 len, p[0], p[1], p[2], p[3], p[4]); 461 } 462 463 { 464 register struct ifaddr *ifa = ifp->if_addrlist; 465 register u_char *cp = (u_char *)buffer; 466 467 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 468 if (ifa->ifa_addr->sa_family != AF_LINK) 469 break; 470 if (cp[0] == 0xff && cp[1] == 0x3) { 471 /* This is a UI HDLC Packet, so we'll assume PPP 472 protocol. for now, IP only. */ 473 buffer += 4; 474 len -= 4; 475 inq = &ipintrq; 476 isr = NETISR_IP; 477 } else { 478 inq = &hdintrq; 479 isr = NETISR_CCITT; 480 } 481 } 482 if (len <= 0) 483 return; 484 485 m = m_devget(buffer, len , 0, ifp, 0); 486 if (m == 0) 487 return; 488 489 if(IF_QFULL(inq)) { 490 IF_DROP(inq); 491 m_freem(m); 492 } else { 493 IF_ENQUEUE(inq, m); 494 schednetisr(isr); 495 } 496 } 497 498 /* 499 * Process an ioctl request. 500 */ 501 dpioctl(ifp, cmd, data) 502 register struct ifnet *ifp; 503 int cmd; 504 caddr_t data; 505 { 506 register struct ifaddr *ifa = (struct ifaddr *)data; 507 int s = splimp(), error = 0; 508 struct dp_softc *dp = &dp_softc[ifp->if_unit]; 509 510 dpstat.ioctl++; 511 switch (cmd) { 512 case SIOCSIFCONF_X25: 513 ifp->if_flags |= IFF_UP; 514 error = hd_ctlinput(PRC_IFUP, ifa->ifa_addr); 515 if (error == 0) 516 dpinit(ifp->if_unit); 517 break; 518 519 case SIOCSIFADDR: 520 ifa->ifa_rtrequest = x25_rtrequest; 521 break; 522 523 case SIOCSIFFLAGS: 524 if ((ifp->if_flags & IFF_UP) == 0 && 525 (ifp->if_flags & IFF_RUNNING)) 526 dpdown(ifp->if_unit); 527 else if (ifp->if_flags & IFF_UP && 528 (ifp->if_flags & IFF_RUNNING) == 0) 529 dpinit(ifp->if_unit); 530 break; 531 532 533 default: 534 error = EINVAL; 535 } 536 splx(s); 537 return (error); 538 } 539 /* 540 * Reset a device and mark down. 541 * Flush output queue and drop queue limit. 542 */ 543 dpdown(unit) 544 int unit; 545 { 546 547 register struct dp_softc *dp = &dp_softc[unit]; 548 register struct dpdevice *addr = dp->dp_addr; 549 550 dpstat.down++; 551 if_qflush(&dp->dp_if.if_snd); 552 dp->dp_flags = 0; 553 dp->dp_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 554 555 addr->dpclr = DP_CLR; 556 DELAY(1000); 557 addr->dpsar = 0; 558 addr->dprcsr = 0; 559 } 560 561 /* 562 * Watchdog timeout to see that transmitted packets don't 563 * lose interrupts. The device has to be online (the first 564 * transmission may block until the other side comes up). 565 */ 566 dptimeout(unit) 567 int unit; 568 { 569 register struct dp_softc *dp; 570 571 /* currently not armed */ 572 dpstat.timeout++; 573 dp = &dp_softc[unit]; 574 if (dp->dp_if.if_flags & IFF_OACTIVE) { 575 dpstart(&dp->dp_if); 576 } 577 } 578 /* 579 * For debugging loopback activity. 580 */ 581 static char pppheader[4] = { -1, 3, 0, 0x21 }; 582 int dp_louts; 583 584 dptestoutput(ifp, m, dst, rt) 585 register struct ifnet *ifp; 586 register struct mbuf *m; 587 struct sockaddr *dst; 588 struct rtentry *rt; 589 { 590 /* 591 * Queue message on interface, and start output if interface 592 * not yet active. 593 */ 594 int s = splimp(), error = 0; 595 dp_louts++; 596 M_PREPEND(m, sizeof pppheader, M_DONTWAIT); 597 if (m == 0) { 598 splx(s); 599 return ENOBUFS; 600 } 601 bcopy(pppheader, mtod(m, caddr_t), sizeof pppheader); 602 if (IF_QFULL(&ifp->if_snd)) { 603 IF_DROP(&ifp->if_snd); 604 /* printf("%s%d: HDLC says OK to send but queue full, may hang\n", 605 ifp->if_name, ifp->if_unit);*/ 606 m_freem(m); 607 error = ENOBUFS; 608 } else { 609 IF_ENQUEUE(&ifp->if_snd, m); 610 if ((ifp->if_flags & IFF_OACTIVE) == 0) 611 (*ifp->if_start)(ifp); 612 } 613 splx(s); 614 return (error); 615 } 616 617 #endif 618