1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 1997 Poul-Henning Kamp 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * From Id: lpt.c,v 1.55.2.1 1996/11/12 09:08:38 phk Exp 29 */ 30 31 #include <sys/cdefs.h> 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(if_t, u_long, caddr_t); 177 static int lpoutput(if_t, 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 int 187 lp_module_handler(module_t mod, int what, void *arg) 188 { 189 190 switch (what) { 191 case MOD_UNLOAD: 192 mtx_lock(&lp_tables_lock); 193 if (txmith != NULL) { 194 free(txmith, M_DEVBUF); 195 txmith = NULL; 196 } 197 if (ctxmith != NULL) { 198 free(ctxmith, M_DEVBUF); 199 ctxmith = NULL; 200 } 201 mtx_unlock(&lp_tables_lock); 202 break; 203 case MOD_LOAD: 204 case MOD_QUIESCE: 205 break; 206 default: 207 return (EOPNOTSUPP); 208 } 209 return (0); 210 } 211 212 static void 213 lp_identify(driver_t *driver, device_t parent) 214 { 215 device_t dev; 216 217 dev = device_find_child(parent, "plip", -1); 218 if (!dev) 219 BUS_ADD_CHILD(parent, 0, "plip", -1); 220 } 221 222 static int 223 lp_probe(device_t dev) 224 { 225 226 device_set_desc(dev, "PLIP network interface"); 227 228 return (0); 229 } 230 231 static int 232 lp_attach(device_t dev) 233 { 234 struct lp_data *lp = DEVTOSOFTC(dev); 235 if_t ifp; 236 int error, rid = 0; 237 238 lp->sc_dev = dev; 239 240 /* 241 * Reserve the interrupt resource. If we don't have one, the 242 * attach fails. 243 */ 244 lp->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 245 RF_SHAREABLE); 246 if (lp->res_irq == NULL) { 247 device_printf(dev, "cannot reserve interrupt, failed.\n"); 248 return (ENXIO); 249 } 250 251 ifp = lp->sc_ifp = if_alloc(IFT_PARA); 252 if (ifp == NULL) { 253 return (ENOSPC); 254 } 255 256 if_setsoftc(ifp, lp); 257 if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 258 if_setmtu(ifp, LPMTU); 259 if_setflags(ifp, IFF_SIMPLEX | IFF_POINTOPOINT | IFF_MULTICAST); 260 if_setioctlfn(ifp, lpioctl); 261 if_setoutputfn(ifp, lpoutput); 262 if_setsendqlen(ifp, ifqmaxlen); 263 if_attach(ifp); 264 265 bpfattach(ifp, DLT_NULL, sizeof(u_int32_t)); 266 267 /* 268 * Attach our interrupt handler. It is only called while we 269 * own the ppbus. 270 */ 271 error = bus_setup_intr(dev, lp->res_irq, INTR_TYPE_NET | INTR_MPSAFE, 272 NULL, lp_intr, lp, &lp->sc_intr_cookie); 273 if (error) { 274 bpfdetach(ifp); 275 if_detach(ifp); 276 bus_release_resource(dev, SYS_RES_IRQ, 0, lp->res_irq); 277 device_printf(dev, "Unable to register interrupt handler\n"); 278 return (error); 279 } 280 281 return (0); 282 } 283 284 static int 285 lp_detach(device_t dev) 286 { 287 struct lp_data *sc = device_get_softc(dev); 288 device_t ppbus = device_get_parent(dev); 289 290 ppb_lock(ppbus); 291 lpstop(sc); 292 ppb_unlock(ppbus); 293 bpfdetach(sc->sc_ifp); 294 if_detach(sc->sc_ifp); 295 bus_teardown_intr(dev, sc->res_irq, sc->sc_intr_cookie); 296 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->res_irq); 297 return (0); 298 } 299 300 /* 301 * Build the translation tables for the LPIP (BSD unix) protocol. 302 * We don't want to calculate these nasties in our tight loop, so we 303 * precalculate them when we initialize. 304 */ 305 static int 306 lpinittables(void) 307 { 308 int i; 309 310 mtx_lock(&lp_tables_lock); 311 if (txmith == NULL) 312 txmith = malloc(4 * LPIPTBLSIZE, M_DEVBUF, M_NOWAIT); 313 314 if (txmith == NULL) { 315 mtx_unlock(&lp_tables_lock); 316 return (1); 317 } 318 319 if (ctxmith == NULL) 320 ctxmith = malloc(4 * LPIPTBLSIZE, M_DEVBUF, M_NOWAIT); 321 322 if (ctxmith == NULL) { 323 mtx_unlock(&lp_tables_lock); 324 return (1); 325 } 326 327 for (i = 0; i < LPIPTBLSIZE; i++) { 328 ctxmith[i] = (i & 0xF0) >> 4; 329 ctxmitl[i] = 0x10 | (i & 0x0F); 330 ctrecvh[i] = (i & 0x78) << 1; 331 ctrecvl[i] = (i & 0x78) >> 3; 332 } 333 334 for (i = 0; i < LPIPTBLSIZE; i++) { 335 txmith[i] = ((i & 0x80) >> 3) | ((i & 0x70) >> 4) | 0x08; 336 txmitl[i] = ((i & 0x08) << 1) | (i & 0x07); 337 trecvh[i] = ((~i) & 0x80) | ((i & 0x38) << 1); 338 trecvl[i] = (((~i) & 0x80) >> 4) | ((i & 0x38) >> 3); 339 } 340 mtx_unlock(&lp_tables_lock); 341 342 return (0); 343 } 344 345 static void 346 lpstop(struct lp_data *sc) 347 { 348 device_t ppbus = device_get_parent(sc->sc_dev); 349 350 ppb_assert_locked(ppbus); 351 ppb_wctr(ppbus, 0x00); 352 if_setdrvflagbits(sc->sc_ifp, 0, (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)); 353 free(sc->sc_ifbuf, M_DEVBUF); 354 sc->sc_ifbuf = NULL; 355 356 /* IFF_UP is not set, try to release the bus anyway */ 357 ppb_release_bus(ppbus, sc->sc_dev); 358 } 359 360 static int 361 lpinit_locked(if_t ifp) 362 { 363 struct lp_data *sc = if_getsoftc(ifp); 364 device_t dev = sc->sc_dev; 365 device_t ppbus = device_get_parent(dev); 366 int error; 367 368 ppb_assert_locked(ppbus); 369 error = ppb_request_bus(ppbus, dev, PPB_DONTWAIT); 370 if (error) 371 return (error); 372 373 /* Now IFF_UP means that we own the bus */ 374 ppb_set_mode(ppbus, PPB_COMPATIBLE); 375 376 if (lpinittables()) { 377 ppb_release_bus(ppbus, dev); 378 return (ENOBUFS); 379 } 380 381 sc->sc_ifbuf = malloc(if_getmtu(sc->sc_ifp) + MLPIPHDRLEN, 382 M_DEVBUF, M_NOWAIT); 383 if (sc->sc_ifbuf == NULL) { 384 ppb_release_bus(ppbus, dev); 385 return (ENOBUFS); 386 } 387 388 ppb_wctr(ppbus, IRQENABLE); 389 390 if_setdrvflagbits(ifp, IFF_DRV_RUNNING, 0); 391 if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE); 392 return (0); 393 } 394 395 /* 396 * Process an ioctl request. 397 */ 398 static int 399 lpioctl(if_t ifp, u_long cmd, caddr_t data) 400 { 401 struct lp_data *sc = if_getsoftc(ifp); 402 device_t dev = sc->sc_dev; 403 device_t ppbus = device_get_parent(dev); 404 struct ifaddr *ifa = (struct ifaddr *)data; 405 struct ifreq *ifr = (struct ifreq *)data; 406 u_char *ptr; 407 int error; 408 409 switch (cmd) { 410 case SIOCAIFADDR: 411 case SIOCSIFADDR: 412 if (ifa->ifa_addr->sa_family != AF_INET) 413 return (EAFNOSUPPORT); 414 415 if_setflagbits(ifp, IFF_UP, 0); 416 /* FALLTHROUGH */ 417 case SIOCSIFFLAGS: 418 error = 0; 419 ppb_lock(ppbus); 420 if ((!(if_getflags(ifp) & IFF_UP)) && 421 (if_getdrvflags(ifp) & IFF_DRV_RUNNING)) 422 lpstop(sc); 423 else if (((if_getflags(ifp) & IFF_UP)) && 424 (!(if_getdrvflags(ifp) & IFF_DRV_RUNNING))) 425 error = lpinit_locked(ifp); 426 ppb_unlock(ppbus); 427 return (error); 428 429 case SIOCSIFMTU: 430 ppb_lock(ppbus); 431 if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) { 432 ptr = malloc(ifr->ifr_mtu + MLPIPHDRLEN, M_DEVBUF, 433 M_NOWAIT); 434 if (ptr == NULL) { 435 ppb_unlock(ppbus); 436 return (ENOBUFS); 437 } 438 if (sc->sc_ifbuf) 439 free(sc->sc_ifbuf, M_DEVBUF); 440 sc->sc_ifbuf = ptr; 441 } 442 if_setmtu(ifp, ifr->ifr_mtu); 443 ppb_unlock(ppbus); 444 break; 445 446 case SIOCGIFMTU: 447 ifr->ifr_mtu = if_getmtu(sc->sc_ifp); 448 break; 449 450 case SIOCADDMULTI: 451 case SIOCDELMULTI: 452 if (ifr == NULL) { 453 return (EAFNOSUPPORT); /* XXX */ 454 } 455 switch (ifr->ifr_addr.sa_family) { 456 case AF_INET: 457 break; 458 default: 459 return (EAFNOSUPPORT); 460 } 461 break; 462 463 case SIOCGIFMEDIA: 464 /* 465 * No ifmedia support at this stage; maybe use it 466 * in future for eg. protocol selection. 467 */ 468 return (EINVAL); 469 470 default: 471 lprintf("LP:ioctl(0x%lx)\n", cmd); 472 return (EINVAL); 473 } 474 return (0); 475 } 476 477 static __inline int 478 clpoutbyte(u_char byte, int spin, device_t ppbus) 479 { 480 481 ppb_wdtr(ppbus, ctxmitl[byte]); 482 while (ppb_rstr(ppbus) & CLPIP_SHAKE) 483 if (--spin == 0) { 484 return (1); 485 } 486 ppb_wdtr(ppbus, ctxmith[byte]); 487 while (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) 488 if (--spin == 0) { 489 return (1); 490 } 491 return (0); 492 } 493 494 static __inline int 495 clpinbyte(int spin, device_t ppbus) 496 { 497 u_char c, cl; 498 499 while ((ppb_rstr(ppbus) & CLPIP_SHAKE)) 500 if (!--spin) { 501 return (-1); 502 } 503 cl = ppb_rstr(ppbus); 504 ppb_wdtr(ppbus, 0x10); 505 506 while (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) 507 if (!--spin) { 508 return (-1); 509 } 510 c = ppb_rstr(ppbus); 511 ppb_wdtr(ppbus, 0x00); 512 513 return (ctrecvl[cl] | ctrecvh[c]); 514 } 515 516 static void 517 lptap(if_t ifp, struct mbuf *m) 518 { 519 u_int32_t af = AF_INET; 520 521 bpf_mtap2_if(ifp, &af, sizeof(af), m); 522 } 523 524 static void 525 lp_intr(void *arg) 526 { 527 struct lp_data *sc = arg; 528 device_t ppbus = device_get_parent(sc->sc_dev); 529 int len, j; 530 u_char *bp; 531 u_char c, cl; 532 struct mbuf *top; 533 534 ppb_assert_locked(ppbus); 535 if (if_getflags(sc->sc_ifp) & IFF_LINK0) { 536 /* Ack. the request */ 537 ppb_wdtr(ppbus, 0x01); 538 539 /* Get the packet length */ 540 j = clpinbyte(LPMAXSPIN2, ppbus); 541 if (j == -1) 542 goto err; 543 len = j; 544 j = clpinbyte(LPMAXSPIN2, ppbus); 545 if (j == -1) 546 goto err; 547 len = len + (j << 8); 548 if (len > if_getmtu(sc->sc_ifp) + MLPIPHDRLEN) 549 goto err; 550 551 bp = sc->sc_ifbuf; 552 553 while (len--) { 554 j = clpinbyte(LPMAXSPIN2, ppbus); 555 if (j == -1) { 556 goto err; 557 } 558 *bp++ = j; 559 } 560 561 /* Get and ignore checksum */ 562 j = clpinbyte(LPMAXSPIN2, ppbus); 563 if (j == -1) { 564 goto err; 565 } 566 567 len = bp - sc->sc_ifbuf; 568 if (len <= CLPIPHDRLEN) 569 goto err; 570 571 sc->sc_iferrs = 0; 572 573 len -= CLPIPHDRLEN; 574 if_inc_counter(sc->sc_ifp, IFCOUNTER_IPACKETS, 1); 575 if_inc_counter(sc->sc_ifp, IFCOUNTER_IBYTES, len); 576 top = m_devget(sc->sc_ifbuf + CLPIPHDRLEN, len, 0, sc->sc_ifp, 577 0); 578 if (top) { 579 ppb_unlock(ppbus); 580 lptap(sc->sc_ifp, top); 581 582 M_SETFIB(top, if_getfib(sc->sc_ifp)); 583 584 /* mbuf is free'd on failure. */ 585 netisr_queue(NETISR_IP, top); 586 ppb_lock(ppbus); 587 } 588 return; 589 } 590 while ((ppb_rstr(ppbus) & LPIP_SHAKE)) { 591 len = if_getmtu(sc->sc_ifp) + LPIPHDRLEN; 592 bp = sc->sc_ifbuf; 593 while (len--) { 594 cl = ppb_rstr(ppbus); 595 ppb_wdtr(ppbus, 8); 596 597 j = LPMAXSPIN2; 598 while ((ppb_rstr(ppbus) & LPIP_SHAKE)) 599 if (!--j) 600 goto err; 601 602 c = ppb_rstr(ppbus); 603 ppb_wdtr(ppbus, 0); 604 605 *bp++= trecvh[cl] | trecvl[c]; 606 607 j = LPMAXSPIN2; 608 while (!((cl = ppb_rstr(ppbus)) & LPIP_SHAKE)) { 609 if (cl != c && 610 (((cl = ppb_rstr(ppbus)) ^ 0xb8) & 0xf8) == 611 (c & 0xf8)) 612 goto end; 613 if (!--j) 614 goto err; 615 } 616 } 617 618 end: 619 len = bp - sc->sc_ifbuf; 620 if (len <= LPIPHDRLEN) 621 goto err; 622 623 sc->sc_iferrs = 0; 624 625 len -= LPIPHDRLEN; 626 if_inc_counter(sc->sc_ifp, IFCOUNTER_IPACKETS, 1); 627 if_inc_counter(sc->sc_ifp, IFCOUNTER_IBYTES, len); 628 top = m_devget(sc->sc_ifbuf + LPIPHDRLEN, len, 0, sc->sc_ifp, 629 0); 630 if (top) { 631 ppb_unlock(ppbus); 632 lptap(sc->sc_ifp, top); 633 634 M_SETFIB(top, if_getfib(sc->sc_ifp)); 635 636 /* mbuf is free'd on failure. */ 637 netisr_queue(NETISR_IP, top); 638 ppb_lock(ppbus); 639 } 640 } 641 return; 642 643 err: 644 ppb_wdtr(ppbus, 0); 645 lprintf("R"); 646 if_inc_counter(sc->sc_ifp, IFCOUNTER_IERRORS, 1); 647 sc->sc_iferrs++; 648 649 /* 650 * We are not able to send receive anything for now, 651 * so stop wasting our time 652 */ 653 if (sc->sc_iferrs > LPMAXERRS) { 654 if_printf(sc->sc_ifp, "Too many errors, Going off-line.\n"); 655 ppb_wctr(ppbus, 0x00); 656 if_setdrvflagbits(sc->sc_ifp, 0, IFF_DRV_RUNNING); 657 sc->sc_iferrs = 0; 658 } 659 } 660 661 static __inline int 662 lpoutbyte(u_char byte, int spin, device_t ppbus) 663 { 664 665 ppb_wdtr(ppbus, txmith[byte]); 666 while (!(ppb_rstr(ppbus) & LPIP_SHAKE)) 667 if (--spin == 0) 668 return (1); 669 ppb_wdtr(ppbus, txmitl[byte]); 670 while (ppb_rstr(ppbus) & LPIP_SHAKE) 671 if (--spin == 0) 672 return (1); 673 return (0); 674 } 675 676 static int 677 lpoutput(if_t ifp, struct mbuf *m, const struct sockaddr *dst, 678 struct route *ro) 679 { 680 struct lp_data *sc = if_getsoftc(ifp); 681 device_t dev = sc->sc_dev; 682 device_t ppbus = device_get_parent(dev); 683 int err; 684 struct mbuf *mm; 685 u_char *cp = "\0\0"; 686 u_char chksum = 0; 687 int count = 0; 688 int i, len, spin; 689 690 /* We need a sensible value if we abort */ 691 cp++; 692 ppb_lock(ppbus); 693 if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0); 694 695 err = 1; /* assume we're aborting because of an error */ 696 697 /* Suspend (on laptops) or receive-errors might have taken us offline */ 698 ppb_wctr(ppbus, IRQENABLE); 699 700 if (if_getflags(ifp) & IFF_LINK0) { 701 if (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) { 702 lprintf("&"); 703 lp_intr(sc); 704 } 705 706 /* Alert other end to pending packet */ 707 spin = LPMAXSPIN1; 708 ppb_wdtr(ppbus, 0x08); 709 while ((ppb_rstr(ppbus) & 0x08) == 0) 710 if (--spin == 0) { 711 goto nend; 712 } 713 714 /* Calculate length of packet, then send that */ 715 716 count += 14; /* Ethernet header len */ 717 718 mm = m; 719 for (mm = m; mm; mm = mm->m_next) { 720 count += mm->m_len; 721 } 722 if (clpoutbyte(count & 0xFF, LPMAXSPIN1, ppbus)) 723 goto nend; 724 if (clpoutbyte((count >> 8) & 0xFF, LPMAXSPIN1, ppbus)) 725 goto nend; 726 727 /* Send dummy ethernet header */ 728 for (i = 0; i < 12; i++) { 729 if (clpoutbyte(i, LPMAXSPIN1, ppbus)) 730 goto nend; 731 chksum += i; 732 } 733 734 if (clpoutbyte(0x08, LPMAXSPIN1, ppbus)) 735 goto nend; 736 if (clpoutbyte(0x00, LPMAXSPIN1, ppbus)) 737 goto nend; 738 chksum += 0x08 + 0x00; /* Add into checksum */ 739 740 mm = m; 741 do { 742 cp = mtod(mm, u_char *); 743 len = mm->m_len; 744 while (len--) { 745 chksum += *cp; 746 if (clpoutbyte(*cp++, LPMAXSPIN2, ppbus)) 747 goto nend; 748 } 749 } while ((mm = mm->m_next)); 750 751 /* Send checksum */ 752 if (clpoutbyte(chksum, LPMAXSPIN2, ppbus)) 753 goto nend; 754 755 /* Go quiescent */ 756 ppb_wdtr(ppbus, 0); 757 758 err = 0; /* No errors */ 759 760 nend: 761 if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE); 762 if (err) { /* if we didn't timeout... */ 763 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 764 lprintf("X"); 765 } else { 766 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 767 if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len); 768 lptap(ifp, m); 769 } 770 771 m_freem(m); 772 773 if (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) { 774 lprintf("^"); 775 lp_intr(sc); 776 } 777 ppb_unlock(ppbus); 778 return (0); 779 } 780 781 if (ppb_rstr(ppbus) & LPIP_SHAKE) { 782 lprintf("&"); 783 lp_intr(sc); 784 } 785 786 if (lpoutbyte(0x08, LPMAXSPIN1, ppbus)) 787 goto end; 788 if (lpoutbyte(0x00, LPMAXSPIN2, ppbus)) 789 goto end; 790 791 mm = m; 792 do { 793 cp = mtod(mm, u_char *); 794 len = mm->m_len; 795 while (len--) 796 if (lpoutbyte(*cp++, LPMAXSPIN2, ppbus)) 797 goto end; 798 } while ((mm = mm->m_next)); 799 800 err = 0; /* no errors were encountered */ 801 802 end: 803 --cp; 804 ppb_wdtr(ppbus, txmitl[*cp] ^ 0x17); 805 806 if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE); 807 if (err) { /* if we didn't timeout... */ 808 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 809 lprintf("X"); 810 } else { 811 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 812 if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len); 813 lptap(ifp, m); 814 } 815 816 m_freem(m); 817 818 if (ppb_rstr(ppbus) & LPIP_SHAKE) { 819 lprintf("^"); 820 lp_intr(sc); 821 } 822 823 ppb_unlock(ppbus); 824 return (0); 825 } 826 827 static device_method_t lp_methods[] = { 828 /* device interface */ 829 DEVMETHOD(device_identify, lp_identify), 830 DEVMETHOD(device_probe, lp_probe), 831 DEVMETHOD(device_attach, lp_attach), 832 DEVMETHOD(device_detach, lp_detach), 833 { 0, 0 } 834 }; 835 836 static driver_t lp_driver = { 837 "plip", 838 lp_methods, 839 sizeof(struct lp_data), 840 }; 841 842 DRIVER_MODULE(plip, ppbus, lp_driver, lp_module_handler, NULL); 843 MODULE_DEPEND(plip, ppbus, 1, 1, 1); 844