1 /* $NetBSD: if_plip.c,v 1.21 2008/04/18 14:56:40 cegger Exp $ */ 2 3 /*- 4 * Copyright (c) 1997 Poul-Henning Kamp 5 * Copyright (c) 2003, 2004 Gary Thorpe <gathorpe@users.sourceforge.net> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * From Id: lpt.c,v 1.55.2.1 1996/11/12 09:08:38 phk Exp 30 * FreeBSD: src/sys/dev/ppbus/if_plip.c,v 1.19.2.1 2000/05/24 00:20:57 n_hibma Exp 31 */ 32 33 #include <sys/cdefs.h> 34 __KERNEL_RCSID(0, "$NetBSD: if_plip.c,v 1.21 2008/04/18 14:56:40 cegger Exp $"); 35 36 /* 37 * Parallel port TCP/IP interfaces added. I looked at the driver from 38 * MACH but this is a complete rewrite, and btw. incompatible, and it 39 * should perform better too. I have never run the MACH driver though. 40 * 41 * This driver sends two bytes (0x08, 0x00) in front of each packet, 42 * to allow us to distinguish another format later. 43 * 44 * Now added an Linux/Crynwr compatibility mode which is enabled using 45 * IF_LINK0 - Tim Wilkinson. 46 * 47 * TODO: 48 * Make HDLC/PPP mode, use IF_LLC1 to enable. 49 * 50 * Connect the two computers using a Laplink parallel cable to use this 51 * feature: 52 * 53 * +----------------------------------------+ 54 * |A-name A-End B-End Descr. Port/Bit | 55 * +----------------------------------------+ 56 * |DATA0 2 15 Data 0/0x01 | 57 * |-ERROR 15 2 1/0x08 | 58 * +----------------------------------------+ 59 * |DATA1 3 13 Data 0/0x02 | 60 * |+SLCT 13 3 1/0x10 | 61 * +----------------------------------------+ 62 * |DATA2 4 12 Data 0/0x04 | 63 * |+PE 12 4 1/0x20 | 64 * +----------------------------------------+ 65 * |DATA3 5 10 Strobe 0/0x08 | 66 * |-ACK 10 5 1/0x40 | 67 * +----------------------------------------+ 68 * |DATA4 6 11 Data 0/0x10 | 69 * |BUSY 11 6 1/~0x80 | 70 * +----------------------------------------+ 71 * |GND 18-25 18-25 GND - | 72 * +----------------------------------------+ 73 * 74 * Expect transfer-rates up to 75 kbyte/sec. 75 * 76 * If GCC could correctly grok 77 * register int port __asm("edx") 78 * the code would be cleaner 79 * 80 * Poul-Henning Kamp <phk@freebsd.org> 81 */ 82 83 /* 84 * Update for ppbus, PLIP support only - Nicolas Souchu 85 */ 86 87 #include "opt_inet.h" 88 #include "opt_plip.h" 89 #include "bpfilter.h" 90 91 #include <sys/systm.h> 92 #include <sys/param.h> 93 #include <sys/proc.h> 94 #include <sys/types.h> 95 #include <sys/device.h> 96 #include <sys/ioctl.h> 97 #include <sys/malloc.h> 98 #include <sys/mbuf.h> 99 100 #include <net/if.h> 101 #include <net/if_types.h> 102 #include <net/netisr.h> 103 104 #if NBPFILTER > 0 105 #include <sys/time.h> 106 #include <net/bpf.h> 107 #endif 108 109 #ifdef INET 110 #include <netinet/in_var.h> 111 /* #include <netinet/in.h> */ 112 #else 113 #error Cannot config lp/plip without inet 114 #endif 115 116 #include <dev/ppbus/ppbus_base.h> 117 #include <dev/ppbus/ppbus_device.h> 118 #include <dev/ppbus/ppbus_io.h> 119 #include <dev/ppbus/ppbus_var.h> 120 121 #include <machine/types.h> 122 #include <sys/intr.h> 123 124 #ifndef LPMTU /* MTU for the lp# interfaces */ 125 #define LPMTU 1500 126 #endif 127 128 #ifndef LPMAXSPIN1 /* DELAY factor for the lp# interfaces */ 129 #define LPMAXSPIN1 8000 /* Spinning for remote intr to happen */ 130 #endif 131 132 #ifndef LPMAXSPIN2 /* DELAY factor for the lp# interfaces */ 133 #define LPMAXSPIN2 500 /* Spinning for remote handshake to happen */ 134 #endif 135 136 #ifndef LPMAXERRS /* Max errors before !RUNNING */ 137 #define LPMAXERRS 100 138 #endif 139 140 #ifndef LPMAXRTRY 141 #define LPMAXRTRY 100 /* If channel busy, retry LPMAXRTRY 142 consecutive times */ 143 #endif 144 145 #define CLPIPHDRLEN 14 /* We send dummy ethernet addresses (two) + packet type in front of packet */ 146 #define CLPIP_SHAKE 0x80 /* This bit toggles between nibble reception */ 147 #define MLPIPHDRLEN CLPIPHDRLEN 148 149 #define LPIPHDRLEN 2 /* We send 0x08, 0x00 in front of packet */ 150 #define LPIP_SHAKE 0x40 /* This bit toggles between nibble reception */ 151 #if !defined(MLPIPHDRLEN) || LPIPHDRLEN > MLPIPHDRLEN 152 #define MLPIPHDRLEN LPIPHDRLEN 153 #endif 154 155 #define LPIPTBLSIZE 256 /* Size of octet translation table */ 156 157 #define LP_PRINTF if (lpflag) printf 158 159 #ifdef PLIP_DEBUG 160 static int volatile lpflag = 1; 161 #else 162 static int volatile lpflag = 0; 163 #endif 164 165 /* Tx/Rsv tables for the lp interface */ 166 static u_char *txmith; 167 #define txmitl (txmith+(1*LPIPTBLSIZE)) 168 #define trecvh (txmith+(2*LPIPTBLSIZE)) 169 #define trecvl (txmith+(3*LPIPTBLSIZE)) 170 static u_char *ctxmith; 171 #define ctxmitl (ctxmith+(1*LPIPTBLSIZE)) 172 #define ctrecvh (ctxmith+(2*LPIPTBLSIZE)) 173 #define ctrecvl (ctxmith+(3*LPIPTBLSIZE)) 174 static uint16_t lp_count = 0; 175 176 /* Autoconf functions */ 177 static int lp_probe(device_t, cfdata_t, void *); 178 static void lp_attach(device_t, device_t, void *); 179 static int lp_detach(device_t, int); 180 181 /* Soft config data */ 182 struct lp_softc { 183 struct ppbus_device_softc ppbus_dev; 184 struct ifnet sc_if; 185 u_char *sc_ifbuf; 186 unsigned short sc_iferrs; 187 unsigned short sc_xmit_rtry; 188 u_int8_t sc_dev_ok; /* Zero means ok */ 189 }; 190 191 /* Autoconf structure */ 192 CFATTACH_DECL_NEW(plip, sizeof(struct lp_softc), lp_probe, lp_attach, lp_detach, 193 NULL); 194 195 /* Functions for the lp interface */ 196 static void lpinittables(void); 197 static void lpfreetables(void); 198 static int lpioctl(struct ifnet *, u_long, void *); 199 static int lpoutput(struct ifnet *, struct mbuf *, const struct sockaddr *, 200 struct rtentry *); 201 static void lpstart(struct ifnet *); 202 static void lp_intr(void *); 203 204 205 static int 206 lp_probe(device_t parent, cfdata_t match, void *aux) 207 { 208 struct ppbus_attach_args * args = aux; 209 210 /* Fail if ppbus is not interrupt capable */ 211 if(args->capabilities & PPBUS_HAS_INTR) 212 return 1; 213 214 printf("%s(%s): not an interrupt-driven port.\n", __func__, 215 device_xname(parent)); 216 return 0; 217 } 218 219 static void 220 lp_attach(device_t parent, device_t self, void *aux) 221 { 222 struct lp_softc * lp = device_private(self); 223 struct ifnet * ifp = &lp->sc_if; 224 225 lp->ppbus_dev.sc_dev = self; 226 lp->sc_dev_ok = 0; 227 lp->sc_ifbuf = NULL; 228 lp->sc_iferrs = 0; 229 lp->sc_xmit_rtry = 0; 230 231 ifp->if_softc = lp; 232 strlcpy(ifp->if_xname, device_xname(self), IFNAMSIZ); 233 ifp->if_mtu = LPMTU; 234 ifp->if_flags = IFF_SIMPLEX | IFF_POINTOPOINT | IFF_MULTICAST; 235 ifp->if_ioctl = lpioctl; 236 ifp->if_output = lpoutput; 237 ifp->if_start = lpstart; 238 ifp->if_type = IFT_PARA; 239 ifp->if_hdrlen = 0; 240 ifp->if_addrlen = 0; 241 ifp->if_dlt = DLT_NULL; 242 IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); 243 IFQ_SET_READY(&ifp->if_snd); 244 if_attach(ifp); 245 if_alloc_sadl(ifp); 246 247 #if NBPFILTER > 0 248 bpfattach(ifp, DLT_NULL, sizeof(u_int32_t)); 249 #endif 250 251 if(lp_count++ == 0) 252 lpinittables(); 253 printf("\n"); 254 } 255 256 static int 257 lp_detach(device_t self, int flags) 258 { 259 int error = 0; 260 struct lp_softc * lp = device_private(self); 261 device_t ppbus = device_parent(self); 262 263 if(lp->sc_dev_ok) { 264 if(!(flags & DETACH_QUIET)) 265 LP_PRINTF("%s(%s): device not properly attached! " 266 "Skipping detach....\n", __func__, 267 device_xname(self)); 268 return error; 269 } 270 271 /* If interface is up, bring it down and release ppbus */ 272 if(lp->sc_if.if_flags & IFF_RUNNING) { 273 ppbus_wctr(ppbus, 0x00); 274 if_detach(&lp->sc_if); 275 error = ppbus_remove_handler(ppbus, lp_intr); 276 if(error) { 277 if(!(flags & DETACH_QUIET)) 278 LP_PRINTF("%s(%s): unable to remove interrupt " 279 "callback.\n", __func__, 280 device_xname(self)); 281 if(!(flags & DETACH_FORCE)) 282 return error; 283 } 284 error = ppbus_release_bus(ppbus, self, 0, 0); 285 if(error) { 286 if(!(flags & DETACH_QUIET)) 287 LP_PRINTF("%s(%s): error releasing bus %s.\n", 288 __func__, device_xname(self), 289 device_xname(ppbus)); 290 if(!(flags & DETACH_FORCE)) 291 return error; 292 } 293 } 294 295 if(lp->sc_ifbuf) 296 free(lp->sc_ifbuf, M_DEVBUF); 297 298 if(--lp_count == 0) 299 lpfreetables(); 300 return error; 301 } 302 303 /* 304 * Build the translation tables for the LPIP (BSD unix) protocol. 305 * We don't want to calculate these nasties in our tight loop, so we 306 * precalculate them when we initialize. 307 */ 308 static void 309 lpinittables (void) 310 { 311 int i; 312 313 if (!txmith) 314 txmith = malloc(4*LPIPTBLSIZE, M_DEVBUF, M_WAITOK); 315 316 if (!ctxmith) 317 ctxmith = malloc(4*LPIPTBLSIZE, M_DEVBUF, M_WAITOK); 318 319 for(i = 0; i < LPIPTBLSIZE; i++) { 320 ctxmith[i] = (i & 0xF0) >> 4; 321 ctxmitl[i] = 0x10 | (i & 0x0F); 322 ctrecvh[i] = (i & 0x78) << 1; 323 ctrecvl[i] = (i & 0x78) >> 3; 324 } 325 326 for(i = 0; i < LPIPTBLSIZE; i++) { 327 txmith[i] = ((i & 0x80) >> 3) | ((i & 0x70) >> 4) | 0x08; 328 txmitl[i] = ((i & 0x08) << 1) | (i & 0x07); 329 trecvh[i] = ((~i) & 0x80) | ((i & 0x38) << 1); 330 trecvl[i] = (((~i) & 0x80) >> 4) | ((i & 0x38) >> 3); 331 } 332 } 333 334 /* Free translation tables */ 335 static void 336 lpfreetables (void) 337 { 338 if (txmith) 339 free(txmith, M_DEVBUF); 340 if (ctxmith) 341 free(ctxmith, M_DEVBUF); 342 txmith = ctxmith = NULL; 343 } 344 345 346 /* Process an ioctl request. */ 347 static int 348 lpioctl (struct ifnet *ifp, u_long cmd, void *data) 349 { 350 struct lp_softc * sc = ifp->if_softc; 351 device_t dev = sc->ppbus_dev.sc_dev; 352 device_t ppbus = device_parent(dev); 353 struct ifaddr * ifa = (struct ifaddr *)data; 354 struct ifreq * ifr = (struct ifreq *)data; 355 u_char * ptr; 356 int error, s; 357 358 error = 0; 359 s = splnet(); 360 361 if(sc->sc_dev_ok) { 362 LP_PRINTF("%s(%s): device not properly attached!", __func__, 363 device_xname(dev)); 364 error = ENODEV; 365 goto end; 366 } 367 368 switch (cmd) { 369 370 case SIOCSIFDSTADDR: 371 if (ifa->ifa_addr->sa_family != AF_INET) 372 error = EAFNOSUPPORT; 373 break; 374 375 case SIOCSIFADDR: 376 if (ifa->ifa_addr->sa_family != AF_INET) { 377 error = EAFNOSUPPORT; 378 break; 379 } 380 ifp->if_flags |= IFF_UP; 381 /* FALLTHROUGH */ 382 case SIOCSIFFLAGS: 383 if((ifp->if_flags & (IFF_UP|IFF_RUNNING)) == IFF_UP) { 384 if((error = ppbus_request_bus(ppbus, dev, 0, 0))) 385 break; 386 error = ppbus_set_mode(ppbus, PPBUS_COMPATIBLE, 0); 387 if(error) 388 break; 389 390 error = ppbus_add_handler(ppbus, lp_intr, dev); 391 if(error) { 392 LP_PRINTF("%s(%s): unable to register interrupt" 393 " callback.\n", __func__, 394 device_xname(dev)); 395 ppbus_release_bus(ppbus, dev, 0, 0); 396 break; 397 } 398 399 /* Allocate a buffer if necessary */ 400 if(sc->sc_ifbuf == NULL) { 401 sc->sc_ifbuf = malloc(sc->sc_if.if_mtu + 402 MLPIPHDRLEN, M_DEVBUF, M_NOWAIT); 403 if (!sc->sc_ifbuf) { 404 error = ENOBUFS; 405 ppbus_release_bus(ppbus, dev, 0, 0); 406 break; 407 } 408 } 409 410 ppbus_wctr(ppbus, IRQENABLE); 411 ifp->if_flags |= IFF_RUNNING; 412 } 413 if((ifp->if_flags & (IFF_UP|IFF_RUNNING)) == IFF_RUNNING) { 414 ppbus_remove_handler(ppbus, lp_intr); 415 error = ppbus_release_bus(ppbus, dev, 0, 0); 416 ifp->if_flags &= ~IFF_RUNNING; 417 } 418 /* Go quiescent */ 419 ppbus_wdtr(ppbus, 0); 420 break; 421 422 case SIOCSIFMTU: 423 if(sc->sc_if.if_mtu == ifr->ifr_mtu) 424 break; 425 ptr = sc->sc_ifbuf; 426 sc->sc_ifbuf = malloc(ifr->ifr_mtu+MLPIPHDRLEN, M_DEVBUF, 427 M_NOWAIT); 428 if (!sc->sc_ifbuf) { 429 sc->sc_ifbuf = ptr; 430 error = ENOBUFS; 431 break; 432 } 433 if(ptr) 434 free(ptr,M_DEVBUF); 435 /*FALLTHROUGH*/ 436 case SIOCGIFMTU: 437 if ((error = ifioctl_common(ifp, cmd, data)) == ENETRESET) 438 error = 0; 439 break; 440 441 case SIOCADDMULTI: 442 case SIOCDELMULTI: 443 if (ifr == NULL) { 444 error = EAFNOSUPPORT; /* XXX */ 445 break; 446 } 447 switch (ifreq_getaddr(cmd, ifr)->sa_family) { 448 case AF_INET: 449 break; 450 default: 451 return EAFNOSUPPORT; 452 } 453 break; 454 455 case SIOCGIFMEDIA: 456 /* 457 * No ifmedia support at this stage; maybe use it 458 * in future for eg. protocol selection. 459 */ 460 default: 461 LP_PRINTF("LP:ioctl(0x%lx)\n", cmd); 462 error = EINVAL; 463 } 464 465 end: 466 splx(s); 467 return error; 468 } 469 470 static inline int 471 clpoutbyte (u_char byte, int spin, device_t ppbus) 472 { 473 int s = spin; 474 ppbus_wdtr(ppbus, ctxmitl[byte]); 475 while (ppbus_rstr(ppbus) & CLPIP_SHAKE) { 476 if (--s == 0) { 477 return 1; 478 } 479 } 480 s = spin; 481 ppbus_wdtr(ppbus, ctxmith[byte]); 482 while (!(ppbus_rstr(ppbus) & CLPIP_SHAKE)) { 483 if (--s == 0) { 484 return 1; 485 } 486 } 487 return 0; 488 } 489 490 static inline int 491 clpinbyte (int spin, device_t ppbus) 492 { 493 u_char c, cl; 494 int s = spin; 495 496 while(ppbus_rstr(ppbus) & CLPIP_SHAKE) { 497 if(!--s) { 498 return -1; 499 } 500 } 501 cl = ppbus_rstr(ppbus); 502 ppbus_wdtr(ppbus, 0x10); 503 504 s = spin; 505 while(!(ppbus_rstr(ppbus) & CLPIP_SHAKE)) { 506 if(!--s) { 507 return -1; 508 } 509 } 510 c = ppbus_rstr(ppbus); 511 ppbus_wdtr(ppbus, 0x00); 512 513 return (ctrecvl[cl] | ctrecvh[c]); 514 } 515 516 #if NBPFILTER > 0 517 static void 518 lptap(struct ifnet *ifp, struct mbuf *m) 519 { 520 /* 521 * Send a packet through bpf. We need to prepend the address family 522 * as a four byte field. Cons up a dummy header to pacify bpf. This 523 * is safe because bpf will only read from the mbuf (i.e., it won't 524 * try to free it or keep a pointer to it). 525 */ 526 u_int32_t af = AF_INET; 527 struct mbuf m0; 528 529 m0.m_next = m; 530 m0.m_len = sizeof(u_int32_t); 531 m0.m_data = (char *)⁡ 532 bpf_mtap(ifp->if_bpf, &m0); 533 } 534 #endif 535 536 /* Soft interrupt handler called by hardware interrupt handler */ 537 static void 538 lp_intr (void *arg) 539 { 540 device_t dev = (device_t)arg; 541 device_t ppbus = device_parent(dev); 542 struct lp_softc * sc = device_private(dev); 543 struct ifnet * ifp = &sc->sc_if; 544 struct mbuf *top; 545 int len, s, j; 546 u_char *bp; 547 u_char c, cl; 548 549 s = splnet(); 550 551 /* Do nothing if device not properly attached */ 552 if(sc->sc_dev_ok) { 553 LP_PRINTF("%s(%s): device not properly attached!", __func__, 554 device_xname(dev)); 555 goto done; 556 } 557 558 /* Do nothing if interface is not up */ 559 if((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 560 goto done; 561 562 /* If other side is no longer transmitting, do nothing */ 563 if(!(ppbus_rstr(ppbus) & LPIP_SHAKE)) 564 goto done; 565 566 /* Disable interrupts until we finish */ 567 ppbus_wctr(ppbus, ~IRQENABLE); 568 569 top = NULL; 570 bp = sc->sc_ifbuf; 571 /* Linux/crynwyr protocol receiving */ 572 if(ifp->if_flags & IFF_LINK0) { 573 /* Ack. the request */ 574 ppbus_wdtr(ppbus, 0x01); 575 576 /* Get the packet length */ 577 j = clpinbyte(LPMAXSPIN2, ppbus); 578 if(j == -1) 579 goto err; 580 len = j; 581 j = clpinbyte(LPMAXSPIN2, ppbus); 582 if(j == -1) 583 goto err; 584 len = len + (j << 8); 585 if(len > ifp->if_mtu + MLPIPHDRLEN) 586 goto err; 587 588 while(len--) { 589 j = clpinbyte(LPMAXSPIN2, ppbus); 590 if (j == -1) { 591 goto err; 592 } 593 *bp++ = j; 594 } 595 /* Get and ignore checksum */ 596 j = clpinbyte(LPMAXSPIN2, ppbus); 597 if(j == -1) { 598 goto err; 599 } 600 601 /* Return to idle state */ 602 ppbus_wdtr(ppbus, 0); 603 len = bp - sc->sc_ifbuf; 604 if (len <= CLPIPHDRLEN) 605 goto err; 606 len -= CLPIPHDRLEN; 607 top = m_devget(sc->sc_ifbuf + CLPIPHDRLEN, len, 0, ifp, NULL); 608 } 609 /* FreeBSD protocol receiving */ 610 else { 611 len = ifp->if_mtu + LPIPHDRLEN; 612 while(len--) { 613 cl = ppbus_rstr(ppbus); 614 ppbus_wdtr(ppbus, 0x08); 615 616 j = LPMAXSPIN2; 617 while((ppbus_rstr(ppbus) & LPIP_SHAKE)) { 618 if(!--j) goto err; 619 } 620 621 c = ppbus_rstr(ppbus); 622 ppbus_wdtr(ppbus, 0); 623 624 *bp++= trecvh[cl] | trecvl[c]; 625 626 j = LPMAXSPIN2; 627 while(!((cl=ppbus_rstr(ppbus)) & LPIP_SHAKE)) { 628 if(cl != c && 629 (((cl = ppbus_rstr(ppbus)) ^ 0xb8) & 630 0xf8) == (c & 0xf8)) 631 goto end; 632 if(!--j) goto err; 633 } 634 } 635 636 end: 637 len = bp - sc->sc_ifbuf; 638 if(len <= LPIPHDRLEN) 639 goto err; 640 len -= LPIPHDRLEN; 641 top = m_devget(sc->sc_ifbuf + LPIPHDRLEN, len, 0, ifp, NULL); 642 } 643 644 /* Do nothing if mbuf was not created or the queue is full */ 645 if((top == NULL) || (IF_QFULL(&ipintrq))) { 646 IF_DROP(&ipintrq); 647 ifp->if_iqdrops++; 648 LP_PRINTF("DROP"); 649 goto err; 650 } 651 #if NBPFILTER > 0 652 if(ifp->if_bpf) 653 lptap(ifp, top); 654 #endif 655 IF_ENQUEUE(&ipintrq, top); 656 schednetisr(NETISR_IP); 657 ifp->if_ipackets++; 658 ifp->if_ibytes += len; 659 sc->sc_iferrs = 0; 660 661 goto done; 662 663 err: 664 /* Return to idle state */ 665 ppbus_wdtr(ppbus, 0); 666 ifp->if_ierrors++; 667 sc->sc_iferrs++; 668 LP_PRINTF("R"); 669 /* Disable interface if there are too many errors */ 670 if(sc->sc_iferrs > LPMAXERRS) { 671 aprint_error_dev(dev, "Too many consecutive errors, going off-line.\n"); 672 ppbus_wctr(ppbus, ~IRQENABLE); 673 if_down(ifp); 674 sc->sc_iferrs = 0; 675 } 676 677 done: 678 /* Re-enable interrupts */ 679 ppbus_wctr(ppbus, IRQENABLE); 680 /* If interface is not active, send some packets */ 681 if((ifp->if_flags & IFF_OACTIVE) == 0) 682 lpstart(ifp); 683 splx(s); 684 return; 685 } 686 687 static inline int 688 lpoutbyte(u_char byte, int spin, device_t ppbus) 689 { 690 int s = spin; 691 ppbus_wdtr(ppbus, txmith[byte]); 692 while(!(ppbus_rstr(ppbus) & LPIP_SHAKE)) { 693 if(--s == 0) 694 return 1; 695 } 696 s = spin; 697 ppbus_wdtr(ppbus, txmitl[byte]); 698 while(ppbus_rstr(ppbus) & LPIP_SHAKE) { 699 if(--s == 0) 700 return 1; 701 } 702 return 0; 703 } 704 705 /* Queue a packet for delivery */ 706 static int 707 lpoutput(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, 708 struct rtentry *rt) 709 { 710 struct lp_softc * sc = ifp->if_softc; 711 device_t dev = sc->ppbus_dev.sc_dev; 712 device_t ppbus = device_parent(dev); 713 ALTQ_DECL(struct altq_pktattr pktattr;) 714 int err; 715 int s; 716 717 s = splnet(); 718 719 if(sc->sc_dev_ok) { 720 LP_PRINTF("%s(%s): device not properly attached!", __func__, 721 device_xname(dev)); 722 err = ENODEV; 723 goto endoutput; 724 } 725 726 if((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { 727 err = ENETDOWN; 728 goto endoutput; 729 } 730 731 /* Only support INET */ 732 if(dst->sa_family != AF_INET) { 733 LP_PRINTF("%s: af%d not supported\n", ifp->if_xname, 734 dst->sa_family); 735 ifp->if_noproto++; 736 err = EAFNOSUPPORT; 737 goto endoutput; 738 } 739 740 IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr); 741 IFQ_ENQUEUE(&ifp->if_snd, m, NULL, err); 742 if(err == 0) { 743 if((ifp->if_flags & IFF_OACTIVE) == 0) 744 lpstart(ifp); 745 } 746 else { 747 ifp->if_oerrors++; 748 sc->sc_iferrs++; 749 LP_PRINTF("Q"); 750 751 /* Disable interface if there are too many errors */ 752 if(sc->sc_iferrs > LPMAXERRS) { 753 aprint_error_dev(dev, "Too many errors, going off-line.\n"); 754 ppbus_wctr(ppbus, ~IRQENABLE); 755 if_down(ifp); 756 sc->sc_iferrs = 0; 757 } 758 } 759 760 endoutput: 761 if((err != 0) && (err != ENOBUFS)) 762 m_freem(m); 763 splx(s); 764 return err; 765 } 766 767 /* Send routine: send packets over PLIP cable. Call at splnet(). */ 768 void 769 lpstart(struct ifnet * ifp) 770 { 771 struct lp_softc * lp = ifp->if_softc; 772 device_t dev = lp->ppbus_dev.sc_dev; 773 device_t ppbus = device_parent(dev); 774 struct mbuf * mm; 775 struct mbuf * m; 776 u_char * cp; 777 int err, i, len, spin, count; 778 u_char str, chksum; 779 780 if(lp->sc_dev_ok) { 781 LP_PRINTF("%s(%s): device not properly attached!", __func__, 782 device_xname(dev)); 783 return; 784 } 785 786 if((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { 787 return; 788 } 789 790 ifp->if_flags |= IFF_OACTIVE; 791 792 /* Go quiescent */ 793 ppbus_wdtr(ppbus, 0); 794 795 /* Output loop */ 796 for(;;) { 797 /* Check if there are packets to send */ 798 if(IFQ_IS_EMPTY(&ifp->if_snd)) { 799 goto final; 800 } 801 /* Try to send a packet, dequeue it later if successful */ 802 IFQ_POLL(&ifp->if_snd, m); 803 if(m == NULL) 804 goto final; 805 806 str = ppbus_rstr(ppbus); 807 /* Wait until other side is not transmitting */ 808 if((str & LPIP_SHAKE) || 809 ((ifp->if_flags & IFF_LINK0) && !(str & CLPIP_SHAKE))) { 810 LP_PRINTF("&"); 811 if(++lp->sc_xmit_rtry > LPMAXRTRY) { 812 aprint_error_dev(dev, "Too many retries while channel " 813 "busy, going off-line.\n"); 814 ppbus_wctr(ppbus, ~IRQENABLE); 815 if_down(ifp); 816 lp->sc_xmit_rtry = 0; 817 } 818 goto final; 819 } 820 lp->sc_xmit_rtry = 0; 821 822 /* Disable interrupt generation */ 823 ppbus_wctr(ppbus, ~IRQENABLE); 824 825 err = 1; 826 827 /* Output packet for Linux/crynwyr compatible protocol */ 828 if(ifp->if_flags & IFF_LINK0) { 829 /* Calculate packet length */ 830 count = 14; /* Ethernet header len */ 831 for(mm = m; mm; mm = mm->m_next) { 832 count += mm->m_len; 833 } 834 835 /* Alert other end to pending packet */ 836 spin = LPMAXSPIN1; 837 ppbus_wdtr(ppbus, 0x08); 838 while((ppbus_rstr(ppbus) & 0x08) == 0) { 839 if (--spin == 0) { 840 goto nend; 841 } 842 } 843 844 if(clpoutbyte(count & 0xFF, LPMAXSPIN1, ppbus)) 845 goto nend; 846 if(clpoutbyte((count >> 8) & 0xFF, LPMAXSPIN1, ppbus)) 847 goto nend; 848 849 /* Send dummy ethernet header */ 850 chksum = 0; 851 for(i = 0; i < 12; i++) { 852 if(clpoutbyte(i, LPMAXSPIN1, ppbus)) 853 goto nend; 854 chksum += i; 855 } 856 857 if(clpoutbyte(0x08, LPMAXSPIN1, ppbus)) 858 goto nend; 859 if(clpoutbyte(0x00, LPMAXSPIN1, ppbus)) 860 goto nend; 861 chksum += 0x08 + 0x00; /* Add into checksum */ 862 863 mm = m; 864 do { 865 cp = mtod(mm, u_char *); 866 len = mm->m_len; 867 while(len--) { 868 if(clpoutbyte(*cp, LPMAXSPIN2, ppbus)) 869 goto nend; 870 chksum += *cp++; 871 } 872 } while ((mm = mm->m_next)); 873 874 /* Send checksum */ 875 if(clpoutbyte(chksum, LPMAXSPIN2, ppbus)) 876 goto nend; 877 878 /* No errors */ 879 err = 0; 880 /* Go quiescent */ 881 ppbus_wdtr(ppbus, 0); 882 } 883 /* Output packet for FreeBSD compatible protocol */ 884 else { 885 /* We need a sensible value if we abort */ 886 cp = NULL; 887 888 if(lpoutbyte(0x08, LPMAXSPIN1, ppbus)) 889 goto end; 890 if(lpoutbyte(0x00, LPMAXSPIN2, ppbus)) 891 goto end; 892 893 mm = m; 894 do { 895 cp = mtod(mm,u_char *); 896 len = mm->m_len; 897 while(len--) 898 if(lpoutbyte(*cp++, LPMAXSPIN2, ppbus)) 899 goto end; 900 } while ((mm = mm->m_next)); 901 902 /* no errors were encountered */ 903 err = 0; 904 905 end: 906 if(cp) 907 ppbus_wdtr(ppbus, txmitl[*(--cp)] ^ 0x17); 908 else 909 ppbus_wdtr(ppbus, txmitl['\0'] ^ 0x17); 910 } 911 912 nend: 913 /* Re-enable interrupt generation */ 914 ppbus_wctr(ppbus, IRQENABLE); 915 916 if(err) { 917 /* Go quiescent */ 918 ppbus_wdtr(ppbus, 0); 919 920 ifp->if_oerrors++; 921 lp->sc_iferrs++; 922 LP_PRINTF("X"); 923 924 /* Disable interface if there are too many errors */ 925 if(lp->sc_iferrs > LPMAXERRS) { 926 aprint_error_dev(dev, "Too many errors, going off-line.\n"); 927 ppbus_wctr(ppbus, ~IRQENABLE); 928 if_down(ifp); 929 lp->sc_iferrs = 0; 930 goto final; 931 } 932 } 933 else { 934 /* Dequeue packet on success */ 935 IFQ_DEQUEUE(&ifp->if_snd, m); 936 #if NBPFILTER > 0 937 if(ifp->if_bpf) 938 lptap(ifp, m); 939 #endif 940 ifp->if_opackets++; 941 ifp->if_obytes += m->m_pkthdr.len; 942 m_freem(m); 943 } 944 } 945 946 final: 947 ifp->if_flags &= ~IFF_OACTIVE; 948 return; 949 } 950