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