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$"); 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_var.h> 101 #include <net/if_types.h> 102 #include <net/netisr.h> 103 #include <net/route.h> 104 105 #include <netinet/in.h> 106 #include <netinet/in_var.h> 107 108 #include <net/bpf.h> 109 110 #include <dev/ppbus/ppbconf.h> 111 #include "ppbus_if.h" 112 #include <dev/ppbus/ppbio.h> 113 114 #ifndef LPMTU /* MTU for the lp# interfaces */ 115 #define LPMTU 1500 116 #endif 117 118 #ifndef LPMAXSPIN1 /* DELAY factor for the lp# interfaces */ 119 #define LPMAXSPIN1 8000 /* Spinning for remote intr to happen */ 120 #endif 121 122 #ifndef LPMAXSPIN2 /* DELAY factor for the lp# interfaces */ 123 #define LPMAXSPIN2 500 /* Spinning for remote handshake to happen */ 124 #endif 125 126 #ifndef LPMAXERRS /* Max errors before !RUNNING */ 127 #define LPMAXERRS 100 128 #endif 129 130 #define CLPIPHDRLEN 14 /* We send dummy ethernet addresses (two) + packet type in front of packet */ 131 #define CLPIP_SHAKE 0x80 /* This bit toggles between nibble reception */ 132 #define MLPIPHDRLEN CLPIPHDRLEN 133 134 #define LPIPHDRLEN 2 /* We send 0x08, 0x00 in front of packet */ 135 #define LPIP_SHAKE 0x40 /* This bit toggles between nibble reception */ 136 #if !defined(MLPIPHDRLEN) || LPIPHDRLEN > MLPIPHDRLEN 137 #define MLPIPHDRLEN LPIPHDRLEN 138 #endif 139 140 #define LPIPTBLSIZE 256 /* Size of octet translation table */ 141 142 #define lprintf if (lptflag) printf 143 144 #ifdef PLIP_DEBUG 145 static int volatile lptflag = 1; 146 #else 147 static int volatile lptflag = 0; 148 #endif 149 150 struct lp_data { 151 struct ifnet *sc_ifp; 152 device_t sc_dev; 153 u_char *sc_ifbuf; 154 int sc_iferrs; 155 156 struct resource *res_irq; 157 void *sc_intr_cookie; 158 }; 159 160 static struct mtx lp_tables_lock; 161 MTX_SYSINIT(lp_tables, &lp_tables_lock, "plip tables", MTX_DEF); 162 163 /* Tables for the lp# interface */ 164 static u_char *txmith; 165 #define txmitl (txmith + (1 * LPIPTBLSIZE)) 166 #define trecvh (txmith + (2 * LPIPTBLSIZE)) 167 #define trecvl (txmith + (3 * LPIPTBLSIZE)) 168 169 static u_char *ctxmith; 170 #define ctxmitl (ctxmith + (1 * LPIPTBLSIZE)) 171 #define ctrecvh (ctxmith + (2 * LPIPTBLSIZE)) 172 #define ctrecvl (ctxmith + (3 * LPIPTBLSIZE)) 173 174 /* Functions for the lp# interface */ 175 static int lpinittables(void); 176 static int lpioctl(struct ifnet *, u_long, caddr_t); 177 static int lpoutput(struct ifnet *, struct mbuf *, const struct sockaddr *, 178 struct route *); 179 static void lpstop(struct lp_data *); 180 static void lp_intr(void *); 181 static int lp_module_handler(module_t, int, void *); 182 183 #define DEVTOSOFTC(dev) \ 184 ((struct lp_data *)device_get_softc(dev)) 185 186 static devclass_t lp_devclass; 187 188 static int 189 lp_module_handler(module_t mod, int what, void *arg) 190 { 191 192 switch (what) { 193 case MOD_UNLOAD: 194 mtx_lock(&lp_tables_lock); 195 if (txmith != NULL) { 196 free(txmith, M_DEVBUF); 197 txmith = NULL; 198 } 199 if (ctxmith != NULL) { 200 free(ctxmith, M_DEVBUF); 201 ctxmith = NULL; 202 } 203 mtx_unlock(&lp_tables_lock); 204 break; 205 case MOD_LOAD: 206 case MOD_QUIESCE: 207 break; 208 default: 209 return (EOPNOTSUPP); 210 } 211 return (0); 212 } 213 214 static void 215 lp_identify(driver_t *driver, device_t parent) 216 { 217 device_t dev; 218 219 dev = device_find_child(parent, "plip", -1); 220 if (!dev) 221 BUS_ADD_CHILD(parent, 0, "plip", -1); 222 } 223 224 static int 225 lp_probe(device_t dev) 226 { 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; 238 int error, rid = 0; 239 240 lp->sc_dev = dev; 241 242 /* 243 * Reserve the interrupt resource. If we don't have one, the 244 * attach fails. 245 */ 246 lp->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 247 RF_SHAREABLE); 248 if (lp->res_irq == 0) { 249 device_printf(dev, "cannot reserve interrupt, failed.\n"); 250 return (ENXIO); 251 } 252 253 ifp = lp->sc_ifp = if_alloc(IFT_PARA); 254 if (ifp == NULL) { 255 return (ENOSPC); 256 } 257 258 ifp->if_softc = lp; 259 if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 260 ifp->if_mtu = LPMTU; 261 ifp->if_flags = IFF_SIMPLEX | IFF_POINTOPOINT | IFF_MULTICAST; 262 ifp->if_ioctl = lpioctl; 263 ifp->if_output = lpoutput; 264 ifp->if_hdrlen = 0; 265 ifp->if_addrlen = 0; 266 ifp->if_snd.ifq_maxlen = ifqmaxlen; 267 if_attach(ifp); 268 269 bpfattach(ifp, DLT_NULL, sizeof(u_int32_t)); 270 271 /* 272 * Attach our interrupt handler. It is only called while we 273 * own the ppbus. 274 */ 275 error = bus_setup_intr(dev, lp->res_irq, INTR_TYPE_NET | INTR_MPSAFE, 276 NULL, lp_intr, lp, &lp->sc_intr_cookie); 277 if (error) { 278 bpfdetach(ifp); 279 if_detach(ifp); 280 bus_release_resource(dev, SYS_RES_IRQ, 0, lp->res_irq); 281 device_printf(dev, "Unable to register interrupt handler\n"); 282 return (error); 283 } 284 285 return (0); 286 } 287 288 static int 289 lp_detach(device_t dev) 290 { 291 struct lp_data *sc = device_get_softc(dev); 292 device_t ppbus = device_get_parent(dev); 293 294 ppb_lock(ppbus); 295 lpstop(sc); 296 ppb_unlock(ppbus); 297 bpfdetach(sc->sc_ifp); 298 if_detach(sc->sc_ifp); 299 bus_teardown_intr(dev, sc->res_irq, sc->sc_intr_cookie); 300 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->res_irq); 301 return (0); 302 } 303 304 /* 305 * Build the translation tables for the LPIP (BSD unix) protocol. 306 * We don't want to calculate these nasties in our tight loop, so we 307 * precalculate them when we initialize. 308 */ 309 static int 310 lpinittables(void) 311 { 312 int i; 313 314 mtx_lock(&lp_tables_lock); 315 if (txmith == NULL) 316 txmith = malloc(4 * LPIPTBLSIZE, M_DEVBUF, M_NOWAIT); 317 318 if (txmith == NULL) { 319 mtx_unlock(&lp_tables_lock); 320 return (1); 321 } 322 323 if (ctxmith == NULL) 324 ctxmith = malloc(4 * LPIPTBLSIZE, M_DEVBUF, M_NOWAIT); 325 326 if (ctxmith == NULL) { 327 mtx_unlock(&lp_tables_lock); 328 return (1); 329 } 330 331 for (i = 0; i < LPIPTBLSIZE; i++) { 332 ctxmith[i] = (i & 0xF0) >> 4; 333 ctxmitl[i] = 0x10 | (i & 0x0F); 334 ctrecvh[i] = (i & 0x78) << 1; 335 ctrecvl[i] = (i & 0x78) >> 3; 336 } 337 338 for (i = 0; i < LPIPTBLSIZE; i++) { 339 txmith[i] = ((i & 0x80) >> 3) | ((i & 0x70) >> 4) | 0x08; 340 txmitl[i] = ((i & 0x08) << 1) | (i & 0x07); 341 trecvh[i] = ((~i) & 0x80) | ((i & 0x38) << 1); 342 trecvl[i] = (((~i) & 0x80) >> 4) | ((i & 0x38) >> 3); 343 } 344 mtx_unlock(&lp_tables_lock); 345 346 return (0); 347 } 348 349 static void 350 lpstop(struct lp_data *sc) 351 { 352 device_t ppbus = device_get_parent(sc->sc_dev); 353 354 ppb_assert_locked(ppbus); 355 ppb_wctr(ppbus, 0x00); 356 sc->sc_ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 357 free(sc->sc_ifbuf, M_DEVBUF); 358 sc->sc_ifbuf = NULL; 359 360 /* IFF_UP is not set, try to release the bus anyway */ 361 ppb_release_bus(ppbus, sc->sc_dev); 362 } 363 364 static int 365 lpinit_locked(struct ifnet *ifp) 366 { 367 struct lp_data *sc = ifp->if_softc; 368 device_t dev = sc->sc_dev; 369 device_t ppbus = device_get_parent(dev); 370 int error; 371 372 ppb_assert_locked(ppbus); 373 error = ppb_request_bus(ppbus, dev, PPB_DONTWAIT); 374 if (error) 375 return (error); 376 377 /* Now IFF_UP means that we own the bus */ 378 ppb_set_mode(ppbus, PPB_COMPATIBLE); 379 380 if (lpinittables()) { 381 ppb_release_bus(ppbus, dev); 382 return (ENOBUFS); 383 } 384 385 sc->sc_ifbuf = malloc(sc->sc_ifp->if_mtu + MLPIPHDRLEN, 386 M_DEVBUF, M_NOWAIT); 387 if (sc->sc_ifbuf == NULL) { 388 ppb_release_bus(ppbus, dev); 389 return (ENOBUFS); 390 } 391 392 ppb_wctr(ppbus, IRQENABLE); 393 394 ifp->if_drv_flags |= IFF_DRV_RUNNING; 395 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 396 return (0); 397 } 398 399 /* 400 * Process an ioctl request. 401 */ 402 static int 403 lpioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 404 { 405 struct lp_data *sc = ifp->if_softc; 406 device_t dev = sc->sc_dev; 407 device_t ppbus = device_get_parent(dev); 408 struct ifaddr *ifa = (struct ifaddr *)data; 409 struct ifreq *ifr = (struct ifreq *)data; 410 u_char *ptr; 411 int error; 412 413 switch (cmd) { 414 case SIOCAIFADDR: 415 case SIOCSIFADDR: 416 if (ifa->ifa_addr->sa_family != AF_INET) 417 return (EAFNOSUPPORT); 418 419 ifp->if_flags |= IFF_UP; 420 /* FALLTHROUGH */ 421 case SIOCSIFFLAGS: 422 error = 0; 423 ppb_lock(ppbus); 424 if ((!(ifp->if_flags & IFF_UP)) && 425 (ifp->if_drv_flags & IFF_DRV_RUNNING)) 426 lpstop(sc); 427 else if (((ifp->if_flags & IFF_UP)) && 428 (!(ifp->if_drv_flags & IFF_DRV_RUNNING))) 429 error = lpinit_locked(ifp); 430 ppb_unlock(ppbus); 431 return (error); 432 433 case SIOCSIFMTU: 434 ppb_lock(ppbus); 435 if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 436 ptr = malloc(ifr->ifr_mtu + MLPIPHDRLEN, M_DEVBUF, 437 M_NOWAIT); 438 if (ptr == NULL) { 439 ppb_unlock(ppbus); 440 return (ENOBUFS); 441 } 442 if (sc->sc_ifbuf) 443 free(sc->sc_ifbuf, M_DEVBUF); 444 sc->sc_ifbuf = ptr; 445 } 446 sc->sc_ifp->if_mtu = ifr->ifr_mtu; 447 ppb_unlock(ppbus); 448 break; 449 450 case SIOCGIFMTU: 451 ifr->ifr_mtu = sc->sc_ifp->if_mtu; 452 break; 453 454 case SIOCADDMULTI: 455 case SIOCDELMULTI: 456 if (ifr == 0) { 457 return (EAFNOSUPPORT); /* XXX */ 458 } 459 switch (ifr->ifr_addr.sa_family) { 460 case AF_INET: 461 break; 462 default: 463 return (EAFNOSUPPORT); 464 } 465 break; 466 467 case SIOCGIFMEDIA: 468 /* 469 * No ifmedia support at this stage; maybe use it 470 * in future for eg. protocol selection. 471 */ 472 return (EINVAL); 473 474 default: 475 lprintf("LP:ioctl(0x%lx)\n", cmd); 476 return (EINVAL); 477 } 478 return (0); 479 } 480 481 static __inline int 482 clpoutbyte(u_char byte, int spin, device_t ppbus) 483 { 484 485 ppb_wdtr(ppbus, ctxmitl[byte]); 486 while (ppb_rstr(ppbus) & CLPIP_SHAKE) 487 if (--spin == 0) { 488 return (1); 489 } 490 ppb_wdtr(ppbus, ctxmith[byte]); 491 while (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) 492 if (--spin == 0) { 493 return (1); 494 } 495 return (0); 496 } 497 498 static __inline int 499 clpinbyte(int spin, device_t ppbus) 500 { 501 u_char c, cl; 502 503 while ((ppb_rstr(ppbus) & CLPIP_SHAKE)) 504 if (!--spin) { 505 return (-1); 506 } 507 cl = ppb_rstr(ppbus); 508 ppb_wdtr(ppbus, 0x10); 509 510 while (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) 511 if (!--spin) { 512 return (-1); 513 } 514 c = ppb_rstr(ppbus); 515 ppb_wdtr(ppbus, 0x00); 516 517 return (ctrecvl[cl] | ctrecvh[c]); 518 } 519 520 static void 521 lptap(struct ifnet *ifp, struct mbuf *m) 522 { 523 u_int32_t af = AF_INET; 524 525 bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m); 526 } 527 528 static void 529 lp_intr(void *arg) 530 { 531 struct lp_data *sc = arg; 532 device_t ppbus = device_get_parent(sc->sc_dev); 533 int len, j; 534 u_char *bp; 535 u_char c, cl; 536 struct mbuf *top; 537 538 ppb_assert_locked(ppbus); 539 if (sc->sc_ifp->if_flags & IFF_LINK0) { 540 541 /* Ack. the request */ 542 ppb_wdtr(ppbus, 0x01); 543 544 /* Get the packet length */ 545 j = clpinbyte(LPMAXSPIN2, ppbus); 546 if (j == -1) 547 goto err; 548 len = j; 549 j = clpinbyte(LPMAXSPIN2, ppbus); 550 if (j == -1) 551 goto err; 552 len = len + (j << 8); 553 if (len > sc->sc_ifp->if_mtu + MLPIPHDRLEN) 554 goto err; 555 556 bp = sc->sc_ifbuf; 557 558 while (len--) { 559 j = clpinbyte(LPMAXSPIN2, ppbus); 560 if (j == -1) { 561 goto err; 562 } 563 *bp++ = j; 564 } 565 566 /* Get and ignore checksum */ 567 j = clpinbyte(LPMAXSPIN2, ppbus); 568 if (j == -1) { 569 goto err; 570 } 571 572 len = bp - sc->sc_ifbuf; 573 if (len <= CLPIPHDRLEN) 574 goto err; 575 576 sc->sc_iferrs = 0; 577 578 len -= CLPIPHDRLEN; 579 sc->sc_ifp->if_ipackets++; 580 sc->sc_ifp->if_ibytes += len; 581 top = m_devget(sc->sc_ifbuf + CLPIPHDRLEN, len, 0, sc->sc_ifp, 582 0); 583 if (top) { 584 ppb_unlock(ppbus); 585 if (bpf_peers_present(sc->sc_ifp->if_bpf)) 586 lptap(sc->sc_ifp, top); 587 588 M_SETFIB(top, sc->sc_ifp->if_fib); 589 590 /* mbuf is free'd on failure. */ 591 netisr_queue(NETISR_IP, top); 592 ppb_lock(ppbus); 593 } 594 return; 595 } 596 while ((ppb_rstr(ppbus) & LPIP_SHAKE)) { 597 len = sc->sc_ifp->if_mtu + LPIPHDRLEN; 598 bp = sc->sc_ifbuf; 599 while (len--) { 600 601 cl = ppb_rstr(ppbus); 602 ppb_wdtr(ppbus, 8); 603 604 j = LPMAXSPIN2; 605 while ((ppb_rstr(ppbus) & LPIP_SHAKE)) 606 if (!--j) 607 goto err; 608 609 c = ppb_rstr(ppbus); 610 ppb_wdtr(ppbus, 0); 611 612 *bp++= trecvh[cl] | trecvl[c]; 613 614 j = LPMAXSPIN2; 615 while (!((cl = ppb_rstr(ppbus)) & LPIP_SHAKE)) { 616 if (cl != c && 617 (((cl = ppb_rstr(ppbus)) ^ 0xb8) & 0xf8) == 618 (c & 0xf8)) 619 goto end; 620 if (!--j) 621 goto err; 622 } 623 } 624 625 end: 626 len = bp - sc->sc_ifbuf; 627 if (len <= LPIPHDRLEN) 628 goto err; 629 630 sc->sc_iferrs = 0; 631 632 len -= LPIPHDRLEN; 633 sc->sc_ifp->if_ipackets++; 634 sc->sc_ifp->if_ibytes += len; 635 top = m_devget(sc->sc_ifbuf + LPIPHDRLEN, len, 0, sc->sc_ifp, 636 0); 637 if (top) { 638 ppb_unlock(ppbus); 639 if (bpf_peers_present(sc->sc_ifp->if_bpf)) 640 lptap(sc->sc_ifp, top); 641 642 M_SETFIB(top, sc->sc_ifp->if_fib); 643 644 /* mbuf is free'd on failure. */ 645 netisr_queue(NETISR_IP, top); 646 ppb_lock(ppbus); 647 } 648 } 649 return; 650 651 err: 652 ppb_wdtr(ppbus, 0); 653 lprintf("R"); 654 sc->sc_ifp->if_ierrors++; 655 sc->sc_iferrs++; 656 657 /* 658 * We are not able to send receive anything for now, 659 * so stop wasting our time 660 */ 661 if (sc->sc_iferrs > LPMAXERRS) { 662 if_printf(sc->sc_ifp, "Too many errors, Going off-line.\n"); 663 ppb_wctr(ppbus, 0x00); 664 sc->sc_ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 665 sc->sc_iferrs = 0; 666 } 667 } 668 669 static __inline int 670 lpoutbyte(u_char byte, int spin, device_t ppbus) 671 { 672 673 ppb_wdtr(ppbus, txmith[byte]); 674 while (!(ppb_rstr(ppbus) & LPIP_SHAKE)) 675 if (--spin == 0) 676 return (1); 677 ppb_wdtr(ppbus, txmitl[byte]); 678 while (ppb_rstr(ppbus) & LPIP_SHAKE) 679 if (--spin == 0) 680 return (1); 681 return (0); 682 } 683 684 static int 685 lpoutput(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, 686 struct route *ro) 687 { 688 struct lp_data *sc = ifp->if_softc; 689 device_t dev = sc->sc_dev; 690 device_t ppbus = device_get_parent(dev); 691 int err; 692 struct mbuf *mm; 693 u_char *cp = "\0\0"; 694 u_char chksum = 0; 695 int count = 0; 696 int i, len, spin; 697 698 /* We need a sensible value if we abort */ 699 cp++; 700 ppb_lock(ppbus); 701 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 702 703 err = 1; /* assume we're aborting because of an error */ 704 705 /* Suspend (on laptops) or receive-errors might have taken us offline */ 706 ppb_wctr(ppbus, IRQENABLE); 707 708 if (ifp->if_flags & IFF_LINK0) { 709 if (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) { 710 lprintf("&"); 711 lp_intr(sc); 712 } 713 714 /* Alert other end to pending packet */ 715 spin = LPMAXSPIN1; 716 ppb_wdtr(ppbus, 0x08); 717 while ((ppb_rstr(ppbus) & 0x08) == 0) 718 if (--spin == 0) { 719 goto nend; 720 } 721 722 /* Calculate length of packet, then send that */ 723 724 count += 14; /* Ethernet header len */ 725 726 mm = m; 727 for (mm = m; mm; mm = mm->m_next) { 728 count += mm->m_len; 729 } 730 if (clpoutbyte(count & 0xFF, LPMAXSPIN1, ppbus)) 731 goto nend; 732 if (clpoutbyte((count >> 8) & 0xFF, LPMAXSPIN1, ppbus)) 733 goto nend; 734 735 /* Send dummy ethernet header */ 736 for (i = 0; i < 12; i++) { 737 if (clpoutbyte(i, LPMAXSPIN1, ppbus)) 738 goto nend; 739 chksum += i; 740 } 741 742 if (clpoutbyte(0x08, LPMAXSPIN1, ppbus)) 743 goto nend; 744 if (clpoutbyte(0x00, LPMAXSPIN1, ppbus)) 745 goto nend; 746 chksum += 0x08 + 0x00; /* Add into checksum */ 747 748 mm = m; 749 do { 750 cp = mtod(mm, u_char *); 751 len = mm->m_len; 752 while (len--) { 753 chksum += *cp; 754 if (clpoutbyte(*cp++, LPMAXSPIN2, ppbus)) 755 goto nend; 756 } 757 } while ((mm = mm->m_next)); 758 759 /* Send checksum */ 760 if (clpoutbyte(chksum, LPMAXSPIN2, ppbus)) 761 goto nend; 762 763 /* Go quiescent */ 764 ppb_wdtr(ppbus, 0); 765 766 err = 0; /* No errors */ 767 768 nend: 769 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 770 if (err) { /* if we didn't timeout... */ 771 ifp->if_oerrors++; 772 lprintf("X"); 773 } else { 774 ifp->if_opackets++; 775 ifp->if_obytes += m->m_pkthdr.len; 776 if (bpf_peers_present(ifp->if_bpf)) 777 lptap(ifp, m); 778 } 779 780 m_freem(m); 781 782 if (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) { 783 lprintf("^"); 784 lp_intr(sc); 785 } 786 ppb_unlock(ppbus); 787 return (0); 788 } 789 790 if (ppb_rstr(ppbus) & LPIP_SHAKE) { 791 lprintf("&"); 792 lp_intr(sc); 793 } 794 795 if (lpoutbyte(0x08, LPMAXSPIN1, ppbus)) 796 goto end; 797 if (lpoutbyte(0x00, LPMAXSPIN2, ppbus)) 798 goto end; 799 800 mm = m; 801 do { 802 cp = mtod(mm, u_char *); 803 len = mm->m_len; 804 while (len--) 805 if (lpoutbyte(*cp++, LPMAXSPIN2, ppbus)) 806 goto end; 807 } while ((mm = mm->m_next)); 808 809 err = 0; /* no errors were encountered */ 810 811 end: 812 --cp; 813 ppb_wdtr(ppbus, txmitl[*cp] ^ 0x17); 814 815 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 816 if (err) { /* if we didn't timeout... */ 817 ifp->if_oerrors++; 818 lprintf("X"); 819 } else { 820 ifp->if_opackets++; 821 ifp->if_obytes += m->m_pkthdr.len; 822 if (bpf_peers_present(ifp->if_bpf)) 823 lptap(ifp, m); 824 } 825 826 m_freem(m); 827 828 if (ppb_rstr(ppbus) & LPIP_SHAKE) { 829 lprintf("^"); 830 lp_intr(sc); 831 } 832 833 ppb_unlock(ppbus); 834 return (0); 835 } 836 837 static device_method_t lp_methods[] = { 838 /* device interface */ 839 DEVMETHOD(device_identify, lp_identify), 840 DEVMETHOD(device_probe, lp_probe), 841 DEVMETHOD(device_attach, lp_attach), 842 DEVMETHOD(device_detach, lp_detach), 843 844 { 0, 0 } 845 }; 846 847 static driver_t lp_driver = { 848 "plip", 849 lp_methods, 850 sizeof(struct lp_data), 851 }; 852 853 DRIVER_MODULE(plip, ppbus, lp_driver, lp_devclass, lp_module_handler, 0); 854 MODULE_DEPEND(plip, ppbus, 1, 1, 1); 855