1 /*- 2 * Copyright (c) 1997 Poul-Henning Kamp 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * From Id: lpt.c,v 1.55.2.1 1996/11/12 09:08:38 phk Exp 27 * $FreeBSD: src/sys/dev/ppbus/if_plip.c,v 1.19.2.1 2000/05/24 00:20:57 n_hibma Exp $ 28 * $DragonFly: src/sys/dev/netif/plip/if_plip.c,v 1.10 2005/02/19 17:59:38 joerg Exp $ 29 */ 30 31 /* 32 * Parallel port TCP/IP interfaces added. I looked at the driver from 33 * MACH but this is a complete rewrite, and btw. incompatible, and it 34 * should perform better too. I have never run the MACH driver though. 35 * 36 * This driver sends two bytes (0x08, 0x00) in front of each packet, 37 * to allow us to distinguish another format later. 38 * 39 * Now added an Linux/Crynwr compatibility mode which is enabled using 40 * IF_LINK0 - Tim Wilkinson. 41 * 42 * TODO: 43 * Make HDLC/PPP mode, use IF_LLC1 to enable. 44 * 45 * Connect the two computers using a Laplink parallel cable to use this 46 * feature: 47 * 48 * +----------------------------------------+ 49 * |A-name A-End B-End Descr. Port/Bit | 50 * +----------------------------------------+ 51 * |DATA0 2 15 Data 0/0x01 | 52 * |-ERROR 15 2 1/0x08 | 53 * +----------------------------------------+ 54 * |DATA1 3 13 Data 0/0x02 | 55 * |+SLCT 13 3 1/0x10 | 56 * +----------------------------------------+ 57 * |DATA2 4 12 Data 0/0x04 | 58 * |+PE 12 4 1/0x20 | 59 * +----------------------------------------+ 60 * |DATA3 5 10 Strobe 0/0x08 | 61 * |-ACK 10 5 1/0x40 | 62 * +----------------------------------------+ 63 * |DATA4 6 11 Data 0/0x10 | 64 * |BUSY 11 6 1/~0x80 | 65 * +----------------------------------------+ 66 * |GND 18-25 18-25 GND - | 67 * +----------------------------------------+ 68 * 69 * Expect transfer-rates up to 75 kbyte/sec. 70 * 71 * If GCC could correctly grok 72 * register int port asm("edx") 73 * the code would be cleaner 74 * 75 * Poul-Henning Kamp <phk@freebsd.org> 76 */ 77 78 /* 79 * Update for ppbus, PLIP support only - Nicolas Souchu 80 */ 81 82 #include "opt_plip.h" 83 84 #include <sys/param.h> 85 #include <sys/systm.h> 86 #include <sys/module.h> 87 #include <sys/bus.h> 88 #include <sys/mbuf.h> 89 #include <sys/socket.h> 90 #include <sys/sockio.h> 91 #include <sys/kernel.h> 92 #include <sys/malloc.h> 93 94 #include <machine/clock.h> 95 #include <machine/bus.h> 96 #include <machine/resource.h> 97 #include <sys/rman.h> 98 99 #include <net/if.h> 100 #include <net/ifq_var.h> 101 #include <net/if_types.h> 102 #include <net/netisr.h> 103 104 #include <netinet/in.h> 105 #include <netinet/in_var.h> 106 107 #include <net/bpf.h> 108 109 #include <bus/ppbus/ppbconf.h> 110 #include "ppbus_if.h" 111 #include <bus/ppbus/ppbio.h> 112 113 #ifndef LPMTU /* MTU for the lp# interfaces */ 114 #define LPMTU 1500 115 #endif 116 117 #ifndef LPMAXSPIN1 /* DELAY factor for the lp# interfaces */ 118 #define LPMAXSPIN1 8000 /* Spinning for remote intr to happen */ 119 #endif 120 121 #ifndef LPMAXSPIN2 /* DELAY factor for the lp# interfaces */ 122 #define LPMAXSPIN2 500 /* Spinning for remote handshake to happen */ 123 #endif 124 125 #ifndef LPMAXERRS /* Max errors before !RUNNING */ 126 #define LPMAXERRS 100 127 #endif 128 129 #define CLPIPHDRLEN 14 /* We send dummy ethernet addresses (two) + packet type in front of packet */ 130 #define CLPIP_SHAKE 0x80 /* This bit toggles between nibble reception */ 131 #define MLPIPHDRLEN CLPIPHDRLEN 132 133 #define LPIPHDRLEN 2 /* We send 0x08, 0x00 in front of packet */ 134 #define LPIP_SHAKE 0x40 /* This bit toggles between nibble reception */ 135 #if !defined(MLPIPHDRLEN) || LPIPHDRLEN > MLPIPHDRLEN 136 #define MLPIPHDRLEN LPIPHDRLEN 137 #endif 138 139 #define LPIPTBLSIZE 256 /* Size of octet translation table */ 140 141 #define lprintf if (lptflag) printf 142 143 #ifdef PLIP_DEBUG 144 static int volatile lptflag = 1; 145 #else 146 static int volatile lptflag = 0; 147 #endif 148 149 struct lp_data { 150 unsigned short lp_unit; 151 152 struct ifnet sc_if; 153 u_char *sc_ifbuf; 154 int sc_iferrs; 155 156 struct resource *res_irq; 157 }; 158 159 /* Tables for the lp# interface */ 160 static u_char *txmith; 161 #define txmitl (txmith+(1*LPIPTBLSIZE)) 162 #define trecvh (txmith+(2*LPIPTBLSIZE)) 163 #define trecvl (txmith+(3*LPIPTBLSIZE)) 164 165 static u_char *ctxmith; 166 #define ctxmitl (ctxmith+(1*LPIPTBLSIZE)) 167 #define ctrecvh (ctxmith+(2*LPIPTBLSIZE)) 168 #define ctrecvl (ctxmith+(3*LPIPTBLSIZE)) 169 170 /* Functions for the lp# interface */ 171 static int lpinittables(void); 172 static int lpioctl(struct ifnet *, u_long, caddr_t, struct ucred *); 173 static int lpoutput(struct ifnet *, struct mbuf *, struct sockaddr *, 174 struct rtentry *); 175 static void lp_intr(void *); 176 177 #define DEVTOSOFTC(dev) \ 178 ((struct lp_data *)device_get_softc(dev)) 179 #define UNITOSOFTC(unit) \ 180 ((struct lp_data *)devclass_get_softc(lp_devclass, (unit))) 181 #define UNITODEVICE(unit) \ 182 (devclass_get_device(lp_devclass, (unit))) 183 184 static devclass_t lp_devclass; 185 186 static void 187 lp_identify(driver_t *driver, device_t parent) 188 { 189 190 BUS_ADD_CHILD(parent, 0, "plip", 0); 191 } 192 /* 193 * lpprobe() 194 */ 195 static int 196 lp_probe(device_t dev) 197 { 198 device_t ppbus = device_get_parent(dev); 199 struct lp_data *lp; 200 int zero = 0; 201 uintptr_t irq; 202 203 lp = DEVTOSOFTC(dev); 204 bzero(lp, sizeof(struct lp_data)); 205 206 /* retrieve the ppbus irq */ 207 BUS_READ_IVAR(ppbus, dev, PPBUS_IVAR_IRQ, &irq); 208 209 /* if we haven't interrupts, the probe fails */ 210 if (irq == -1) { 211 device_printf(dev, "not an interrupt driven port, failed.\n"); 212 return (ENXIO); 213 } 214 215 /* reserve the interrupt resource, expecting irq is available to continue */ 216 lp->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &zero, irq, irq, 1, 217 RF_SHAREABLE); 218 if (lp->res_irq == 0) { 219 device_printf(dev, "cannot reserve interrupt, failed.\n"); 220 return (ENXIO); 221 } 222 223 /* 224 * lp dependent initialisation. 225 */ 226 lp->lp_unit = device_get_unit(dev); 227 228 device_set_desc(dev, "PLIP network interface"); 229 230 return (0); 231 } 232 233 static int 234 lp_attach (device_t dev) 235 { 236 struct lp_data *lp = DEVTOSOFTC(dev); 237 struct ifnet *ifp = &lp->sc_if; 238 239 ifp->if_softc = lp; 240 if_initname(ifp, "lp", device_get_unit(dev)); 241 ifp->if_mtu = LPMTU; 242 ifp->if_flags = IFF_SIMPLEX | IFF_POINTOPOINT | IFF_MULTICAST; 243 ifp->if_ioctl = lpioctl; 244 ifp->if_output = lpoutput; 245 ifp->if_type = IFT_PARA; 246 ifp->if_hdrlen = 0; 247 ifp->if_addrlen = 0; 248 ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN); 249 if_attach(ifp); 250 251 bpfattach(ifp, DLT_NULL, sizeof(u_int32_t)); 252 253 return (0); 254 } 255 /* 256 * Build the translation tables for the LPIP (BSD unix) protocol. 257 * We don't want to calculate these nasties in our tight loop, so we 258 * precalculate them when we initialize. 259 */ 260 static int 261 lpinittables (void) 262 { 263 int i; 264 265 if (!txmith) 266 txmith = malloc(4*LPIPTBLSIZE, M_DEVBUF, M_WAITOK); 267 268 if (!ctxmith) 269 ctxmith = malloc(4*LPIPTBLSIZE, M_DEVBUF, M_WAITOK); 270 271 for (i=0; i < LPIPTBLSIZE; i++) { 272 ctxmith[i] = (i & 0xF0) >> 4; 273 ctxmitl[i] = 0x10 | (i & 0x0F); 274 ctrecvh[i] = (i & 0x78) << 1; 275 ctrecvl[i] = (i & 0x78) >> 3; 276 } 277 278 for (i=0; i < LPIPTBLSIZE; i++) { 279 txmith[i] = ((i & 0x80) >> 3) | ((i & 0x70) >> 4) | 0x08; 280 txmitl[i] = ((i & 0x08) << 1) | (i & 0x07); 281 trecvh[i] = ((~i) & 0x80) | ((i & 0x38) << 1); 282 trecvl[i] = (((~i) & 0x80) >> 4) | ((i & 0x38) >> 3); 283 } 284 285 return 0; 286 } 287 288 /* 289 * Process an ioctl request. 290 */ 291 292 static int 293 lpioctl (struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr) 294 { 295 device_t dev = UNITODEVICE(ifp->if_dunit); 296 device_t ppbus = device_get_parent(dev); 297 struct lp_data *sc = DEVTOSOFTC(dev); 298 struct ifaddr *ifa = (struct ifaddr *)data; 299 struct ifreq *ifr = (struct ifreq *)data; 300 u_char *ptr; 301 void *ih; 302 int error; 303 304 switch (cmd) { 305 306 case SIOCSIFDSTADDR: 307 case SIOCAIFADDR: 308 case SIOCSIFADDR: 309 if (ifa->ifa_addr->sa_family != AF_INET) 310 return EAFNOSUPPORT; 311 312 ifp->if_flags |= IFF_UP; 313 /* FALLTHROUGH */ 314 case SIOCSIFFLAGS: 315 if ((!(ifp->if_flags & IFF_UP)) && (ifp->if_flags & IFF_RUNNING)) { 316 317 ppb_wctr(ppbus, 0x00); 318 ifp->if_flags &= ~IFF_RUNNING; 319 320 /* IFF_UP is not set, try to release the bus anyway */ 321 ppb_release_bus(ppbus, dev); 322 break; 323 } 324 if (((ifp->if_flags & IFF_UP)) && (!(ifp->if_flags & IFF_RUNNING))) { 325 326 /* XXX 327 * Should the request be interruptible? 328 */ 329 if ((error = ppb_request_bus(ppbus, dev, PPB_WAIT|PPB_INTR))) 330 return (error); 331 332 /* Now IFF_UP means that we own the bus */ 333 334 ppb_set_mode(ppbus, PPB_COMPATIBLE); 335 336 if (lpinittables()) { 337 ppb_release_bus(ppbus, dev); 338 return ENOBUFS; 339 } 340 341 sc->sc_ifbuf = malloc(sc->sc_if.if_mtu + MLPIPHDRLEN, 342 M_DEVBUF, M_WAITOK); 343 if (!sc->sc_ifbuf) { 344 ppb_release_bus(ppbus, dev); 345 return ENOBUFS; 346 } 347 348 /* attach our interrupt handler, later detached when the bus is released */ 349 if ((error = BUS_SETUP_INTR(ppbus, dev, sc->res_irq, 350 INTR_TYPE_NET, lp_intr, dev, &ih))) { 351 ppb_release_bus(ppbus, dev); 352 return (error); 353 } 354 355 ppb_wctr(ppbus, IRQENABLE); 356 ifp->if_flags |= IFF_RUNNING; 357 } 358 break; 359 360 case SIOCSIFMTU: 361 ptr = sc->sc_ifbuf; 362 sc->sc_ifbuf = malloc(ifr->ifr_mtu+MLPIPHDRLEN, M_DEVBUF, M_WAITOK); 363 if (ptr) 364 free(ptr,M_DEVBUF); 365 sc->sc_if.if_mtu = ifr->ifr_mtu; 366 break; 367 368 case SIOCGIFMTU: 369 ifr->ifr_mtu = sc->sc_if.if_mtu; 370 break; 371 372 case SIOCADDMULTI: 373 case SIOCDELMULTI: 374 if (ifr == 0) { 375 return EAFNOSUPPORT; /* XXX */ 376 } 377 switch (ifr->ifr_addr.sa_family) { 378 379 case AF_INET: 380 break; 381 382 default: 383 return EAFNOSUPPORT; 384 } 385 break; 386 387 case SIOCGIFMEDIA: 388 /* 389 * No ifmedia support at this stage; maybe use it 390 * in future for eg. protocol selection. 391 */ 392 return EINVAL; 393 394 default: 395 lprintf("LP:ioctl(0x%lx)\n", cmd); 396 return EINVAL; 397 } 398 return 0; 399 } 400 401 static __inline int 402 clpoutbyte (u_char byte, int spin, device_t ppbus) 403 { 404 ppb_wdtr(ppbus, ctxmitl[byte]); 405 while (ppb_rstr(ppbus) & CLPIP_SHAKE) 406 if (--spin == 0) { 407 return 1; 408 } 409 ppb_wdtr(ppbus, ctxmith[byte]); 410 while (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) 411 if (--spin == 0) { 412 return 1; 413 } 414 return 0; 415 } 416 417 static __inline int 418 clpinbyte (int spin, device_t ppbus) 419 { 420 u_char c, cl; 421 422 while((ppb_rstr(ppbus) & CLPIP_SHAKE)) 423 if(!--spin) { 424 return -1; 425 } 426 cl = ppb_rstr(ppbus); 427 ppb_wdtr(ppbus, 0x10); 428 429 while(!(ppb_rstr(ppbus) & CLPIP_SHAKE)) 430 if(!--spin) { 431 return -1; 432 } 433 c = ppb_rstr(ppbus); 434 ppb_wdtr(ppbus, 0x00); 435 436 return (ctrecvl[cl] | ctrecvh[c]); 437 } 438 439 static void 440 lptap(struct ifnet *ifp, struct mbuf *m) 441 { 442 /* 443 * We need to prepend the address family as a four byte field. 444 */ 445 static const uint32_t af = AF_INET; 446 447 if (ifp->if_bpf) 448 bpf_ptap(ifp->if_bpf, m, &af, sizeof(af)); 449 } 450 451 static void 452 lp_intr (void *arg) 453 { 454 device_t dev = (device_t)arg; 455 device_t ppbus = device_get_parent(dev); 456 struct lp_data *sc = DEVTOSOFTC(dev); 457 int len, s, j; 458 u_char *bp; 459 u_char c, cl; 460 struct mbuf *top; 461 462 s = splhigh(); 463 464 if (sc->sc_if.if_flags & IFF_LINK0) { 465 466 /* Ack. the request */ 467 ppb_wdtr(ppbus, 0x01); 468 469 /* Get the packet length */ 470 j = clpinbyte(LPMAXSPIN2, ppbus); 471 if (j == -1) 472 goto err; 473 len = j; 474 j = clpinbyte(LPMAXSPIN2, ppbus); 475 if (j == -1) 476 goto err; 477 len = len + (j << 8); 478 if (len > sc->sc_if.if_mtu + MLPIPHDRLEN) 479 goto err; 480 481 bp = sc->sc_ifbuf; 482 483 while (len--) { 484 j = clpinbyte(LPMAXSPIN2, ppbus); 485 if (j == -1) { 486 goto err; 487 } 488 *bp++ = j; 489 } 490 /* Get and ignore checksum */ 491 j = clpinbyte(LPMAXSPIN2, ppbus); 492 if (j == -1) { 493 goto err; 494 } 495 496 len = bp - sc->sc_ifbuf; 497 if (len <= CLPIPHDRLEN) 498 goto err; 499 500 sc->sc_iferrs = 0; 501 502 len -= CLPIPHDRLEN; 503 sc->sc_if.if_ipackets++; 504 sc->sc_if.if_ibytes += len; 505 top = m_devget(sc->sc_ifbuf + CLPIPHDRLEN, len, 0, &sc->sc_if, 0); 506 if (top) { 507 if (sc->sc_if.if_bpf) 508 lptap(&sc->sc_if, top); 509 netisr_queue(NETISR_IP, top); 510 } 511 goto done; 512 } 513 while ((ppb_rstr(ppbus) & LPIP_SHAKE)) { 514 len = sc->sc_if.if_mtu + LPIPHDRLEN; 515 bp = sc->sc_ifbuf; 516 while (len--) { 517 518 cl = ppb_rstr(ppbus); 519 ppb_wdtr(ppbus, 8); 520 521 j = LPMAXSPIN2; 522 while((ppb_rstr(ppbus) & LPIP_SHAKE)) 523 if(!--j) goto err; 524 525 c = ppb_rstr(ppbus); 526 ppb_wdtr(ppbus, 0); 527 528 *bp++= trecvh[cl] | trecvl[c]; 529 530 j = LPMAXSPIN2; 531 while (!((cl=ppb_rstr(ppbus)) & LPIP_SHAKE)) { 532 if (cl != c && 533 (((cl = ppb_rstr(ppbus)) ^ 0xb8) & 0xf8) == 534 (c & 0xf8)) 535 goto end; 536 if (!--j) goto err; 537 } 538 } 539 540 end: 541 len = bp - sc->sc_ifbuf; 542 if (len <= LPIPHDRLEN) 543 goto err; 544 545 sc->sc_iferrs = 0; 546 547 len -= LPIPHDRLEN; 548 sc->sc_if.if_ipackets++; 549 sc->sc_if.if_ibytes += len; 550 top = m_devget(sc->sc_ifbuf + LPIPHDRLEN, len, 0, &sc->sc_if, 0); 551 if (top) { 552 if (sc->sc_if.if_bpf) 553 lptap(&sc->sc_if, top); 554 netisr_queue(NETISR_IP, top); 555 } 556 } 557 goto done; 558 559 err: 560 ppb_wdtr(ppbus, 0); 561 lprintf("R"); 562 sc->sc_if.if_ierrors++; 563 sc->sc_iferrs++; 564 565 /* 566 * We are not able to send receive anything for now, 567 * so stop wasting our time 568 */ 569 if (sc->sc_iferrs > LPMAXERRS) { 570 printf("lp%d: Too many errors, Going off-line.\n", device_get_unit(dev)); 571 ppb_wctr(ppbus, 0x00); 572 sc->sc_if.if_flags &= ~IFF_RUNNING; 573 sc->sc_iferrs=0; 574 } 575 576 done: 577 splx(s); 578 return; 579 } 580 581 static __inline int 582 lpoutbyte (u_char byte, int spin, device_t ppbus) 583 { 584 ppb_wdtr(ppbus, txmith[byte]); 585 while (!(ppb_rstr(ppbus) & LPIP_SHAKE)) 586 if (--spin == 0) 587 return 1; 588 ppb_wdtr(ppbus, txmitl[byte]); 589 while (ppb_rstr(ppbus) & LPIP_SHAKE) 590 if (--spin == 0) 591 return 1; 592 return 0; 593 } 594 595 static int 596 lpoutput (struct ifnet *ifp, struct mbuf *m, 597 struct sockaddr *dst, struct rtentry *rt) 598 { 599 device_t dev = UNITODEVICE(ifp->if_dunit); 600 device_t ppbus = device_get_parent(dev); 601 int s, err; 602 struct mbuf *mm; 603 u_char *cp = "\0\0"; 604 u_char chksum = 0; 605 int count = 0; 606 int i, len, spin; 607 608 /* We need a sensible value if we abort */ 609 cp++; 610 ifp->if_flags |= IFF_RUNNING; 611 612 err = 1; /* assume we're aborting because of an error */ 613 614 s = splhigh(); 615 616 /* Suspend (on laptops) or receive-errors might have taken us offline */ 617 ppb_wctr(ppbus, IRQENABLE); 618 619 if (ifp->if_flags & IFF_LINK0) { 620 621 if (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) { 622 lprintf("&"); 623 lp_intr(dev); 624 } 625 626 /* Alert other end to pending packet */ 627 spin = LPMAXSPIN1; 628 ppb_wdtr(ppbus, 0x08); 629 while ((ppb_rstr(ppbus) & 0x08) == 0) 630 if (--spin == 0) { 631 goto nend; 632 } 633 634 /* Calculate length of packet, then send that */ 635 636 count += 14; /* Ethernet header len */ 637 638 mm = m; 639 for (mm = m; mm; mm = mm->m_next) { 640 count += mm->m_len; 641 } 642 if (clpoutbyte(count & 0xFF, LPMAXSPIN1, ppbus)) 643 goto nend; 644 if (clpoutbyte((count >> 8) & 0xFF, LPMAXSPIN1, ppbus)) 645 goto nend; 646 647 /* Send dummy ethernet header */ 648 for (i = 0; i < 12; i++) { 649 if (clpoutbyte(i, LPMAXSPIN1, ppbus)) 650 goto nend; 651 chksum += i; 652 } 653 654 if (clpoutbyte(0x08, LPMAXSPIN1, ppbus)) 655 goto nend; 656 if (clpoutbyte(0x00, LPMAXSPIN1, ppbus)) 657 goto nend; 658 chksum += 0x08 + 0x00; /* Add into checksum */ 659 660 mm = m; 661 do { 662 cp = mtod(mm, u_char *); 663 len = mm->m_len; 664 while (len--) { 665 chksum += *cp; 666 if (clpoutbyte(*cp++, LPMAXSPIN2, ppbus)) 667 goto nend; 668 } 669 } while ((mm = mm->m_next)); 670 671 /* Send checksum */ 672 if (clpoutbyte(chksum, LPMAXSPIN2, ppbus)) 673 goto nend; 674 675 /* Go quiescent */ 676 ppb_wdtr(ppbus, 0); 677 678 err = 0; /* No errors */ 679 680 nend: 681 if (err) { /* if we didn't timeout... */ 682 ifp->if_oerrors++; 683 lprintf("X"); 684 } else { 685 ifp->if_opackets++; 686 ifp->if_obytes += m->m_pkthdr.len; 687 if (ifp->if_bpf) 688 lptap(ifp, m); 689 } 690 691 m_freem(m); 692 693 if (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) { 694 lprintf("^"); 695 lp_intr(dev); 696 } 697 (void) splx(s); 698 return 0; 699 } 700 701 if (ppb_rstr(ppbus) & LPIP_SHAKE) { 702 lprintf("&"); 703 lp_intr(dev); 704 } 705 706 if (lpoutbyte(0x08, LPMAXSPIN1, ppbus)) 707 goto end; 708 if (lpoutbyte(0x00, LPMAXSPIN2, ppbus)) 709 goto end; 710 711 mm = m; 712 do { 713 cp = mtod(mm,u_char *); 714 len = mm->m_len; 715 while (len--) 716 if (lpoutbyte(*cp++, LPMAXSPIN2, ppbus)) 717 goto end; 718 } while ((mm = mm->m_next)); 719 720 err = 0; /* no errors were encountered */ 721 722 end: 723 --cp; 724 ppb_wdtr(ppbus, txmitl[*cp] ^ 0x17); 725 726 if (err) { /* if we didn't timeout... */ 727 ifp->if_oerrors++; 728 lprintf("X"); 729 } else { 730 ifp->if_opackets++; 731 ifp->if_obytes += m->m_pkthdr.len; 732 if (ifp->if_bpf) 733 lptap(ifp, m); 734 } 735 736 m_freem(m); 737 738 if (ppb_rstr(ppbus) & LPIP_SHAKE) { 739 lprintf("^"); 740 lp_intr(dev); 741 } 742 743 (void) splx(s); 744 return 0; 745 } 746 747 static device_method_t lp_methods[] = { 748 /* device interface */ 749 DEVMETHOD(device_identify, lp_identify), 750 DEVMETHOD(device_probe, lp_probe), 751 DEVMETHOD(device_attach, lp_attach), 752 753 { 0, 0 } 754 }; 755 756 static driver_t lp_driver = { 757 "plip", 758 lp_methods, 759 sizeof(struct lp_data), 760 }; 761 762 DECLARE_DUMMY_MODULE(if_plip); 763 DRIVER_MODULE(if_plip, ppbus, lp_driver, lp_devclass, 0, 0); 764 765