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