1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 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 __FBSDID("$FreeBSD$"); 33 34 /* 35 * Parallel port TCP/IP interfaces added. I looked at the driver from 36 * MACH but this is a complete rewrite, and btw. incompatible, and it 37 * should perform better too. I have never run the MACH driver though. 38 * 39 * This driver sends two bytes (0x08, 0x00) in front of each packet, 40 * to allow us to distinguish another format later. 41 * 42 * Now added a Linux/Crynwr compatibility mode which is enabled using 43 * IF_LINK0 - Tim Wilkinson. 44 * 45 * TODO: 46 * Make HDLC/PPP mode, use IF_LLC1 to enable. 47 * 48 * Connect the two computers using a Laplink parallel cable to use this 49 * feature: 50 * 51 * +----------------------------------------+ 52 * |A-name A-End B-End Descr. Port/Bit | 53 * +----------------------------------------+ 54 * |DATA0 2 15 Data 0/0x01 | 55 * |-ERROR 15 2 1/0x08 | 56 * +----------------------------------------+ 57 * |DATA1 3 13 Data 0/0x02 | 58 * |+SLCT 13 3 1/0x10 | 59 * +----------------------------------------+ 60 * |DATA2 4 12 Data 0/0x04 | 61 * |+PE 12 4 1/0x20 | 62 * +----------------------------------------+ 63 * |DATA3 5 10 Strobe 0/0x08 | 64 * |-ACK 10 5 1/0x40 | 65 * +----------------------------------------+ 66 * |DATA4 6 11 Data 0/0x10 | 67 * |BUSY 11 6 1/~0x80 | 68 * +----------------------------------------+ 69 * |GND 18-25 18-25 GND - | 70 * +----------------------------------------+ 71 * 72 * Expect transfer-rates up to 75 kbyte/sec. 73 * 74 * If GCC could correctly grok 75 * register int port asm("edx") 76 * the code would be cleaner 77 * 78 * Poul-Henning Kamp <phk@freebsd.org> 79 */ 80 81 /* 82 * Update for ppbus, PLIP support only - Nicolas Souchu 83 */ 84 85 #include "opt_plip.h" 86 87 #include <sys/param.h> 88 #include <sys/systm.h> 89 #include <sys/module.h> 90 #include <sys/bus.h> 91 #include <sys/mbuf.h> 92 #include <sys/socket.h> 93 #include <sys/sockio.h> 94 #include <sys/kernel.h> 95 #include <sys/malloc.h> 96 97 #include <machine/bus.h> 98 #include <machine/resource.h> 99 #include <sys/rman.h> 100 101 #include <net/if.h> 102 #include <net/if_var.h> 103 #include <net/if_types.h> 104 #include <net/netisr.h> 105 #include <net/route.h> 106 107 #include <netinet/in.h> 108 #include <netinet/in_var.h> 109 110 #include <net/bpf.h> 111 112 #include <dev/ppbus/ppbconf.h> 113 #include "ppbus_if.h" 114 #include <dev/ppbus/ppbio.h> 115 116 #ifndef LPMTU /* MTU for the lp# interfaces */ 117 #define LPMTU 1500 118 #endif 119 120 #ifndef LPMAXSPIN1 /* DELAY factor for the lp# interfaces */ 121 #define LPMAXSPIN1 8000 /* Spinning for remote intr to happen */ 122 #endif 123 124 #ifndef LPMAXSPIN2 /* DELAY factor for the lp# interfaces */ 125 #define LPMAXSPIN2 500 /* Spinning for remote handshake to happen */ 126 #endif 127 128 #ifndef LPMAXERRS /* Max errors before !RUNNING */ 129 #define LPMAXERRS 100 130 #endif 131 132 #define CLPIPHDRLEN 14 /* We send dummy ethernet addresses (two) + packet type in front of packet */ 133 #define CLPIP_SHAKE 0x80 /* This bit toggles between nibble reception */ 134 #define MLPIPHDRLEN CLPIPHDRLEN 135 136 #define LPIPHDRLEN 2 /* We send 0x08, 0x00 in front of packet */ 137 #define LPIP_SHAKE 0x40 /* This bit toggles between nibble reception */ 138 #if !defined(MLPIPHDRLEN) || LPIPHDRLEN > MLPIPHDRLEN 139 #define MLPIPHDRLEN LPIPHDRLEN 140 #endif 141 142 #define LPIPTBLSIZE 256 /* Size of octet translation table */ 143 144 #define lprintf if (lptflag) printf 145 146 #ifdef PLIP_DEBUG 147 static int volatile lptflag = 1; 148 #else 149 static int volatile lptflag = 0; 150 #endif 151 152 struct lp_data { 153 struct ifnet *sc_ifp; 154 device_t sc_dev; 155 u_char *sc_ifbuf; 156 int sc_iferrs; 157 158 struct resource *res_irq; 159 void *sc_intr_cookie; 160 }; 161 162 static struct mtx lp_tables_lock; 163 MTX_SYSINIT(lp_tables, &lp_tables_lock, "plip tables", MTX_DEF); 164 165 /* Tables for the lp# interface */ 166 static u_char *txmith; 167 #define txmitl (txmith + (1 * LPIPTBLSIZE)) 168 #define trecvh (txmith + (2 * LPIPTBLSIZE)) 169 #define trecvl (txmith + (3 * LPIPTBLSIZE)) 170 171 static u_char *ctxmith; 172 #define ctxmitl (ctxmith + (1 * LPIPTBLSIZE)) 173 #define ctrecvh (ctxmith + (2 * LPIPTBLSIZE)) 174 #define ctrecvl (ctxmith + (3 * LPIPTBLSIZE)) 175 176 /* Functions for the lp# interface */ 177 static int lpinittables(void); 178 static int lpioctl(if_t, u_long, caddr_t); 179 static int lpoutput(if_t, struct mbuf *, const struct sockaddr *, 180 struct route *); 181 static void lpstop(struct lp_data *); 182 static void lp_intr(void *); 183 static int lp_module_handler(module_t, int, void *); 184 185 #define DEVTOSOFTC(dev) \ 186 ((struct lp_data *)device_get_softc(dev)) 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 if_t 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 == NULL) { 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 if_setsoftc(ifp, lp); 259 if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 260 if_setmtu(ifp, LPMTU); 261 if_setflags(ifp, IFF_SIMPLEX | IFF_POINTOPOINT | IFF_MULTICAST); 262 if_setioctlfn(ifp, lpioctl); 263 if_setoutputfn(ifp, lpoutput); 264 if_setsendqlen(ifp, ifqmaxlen); 265 if_attach(ifp); 266 267 bpfattach(ifp, DLT_NULL, sizeof(u_int32_t)); 268 269 /* 270 * Attach our interrupt handler. It is only called while we 271 * own the ppbus. 272 */ 273 error = bus_setup_intr(dev, lp->res_irq, INTR_TYPE_NET | INTR_MPSAFE, 274 NULL, lp_intr, lp, &lp->sc_intr_cookie); 275 if (error) { 276 bpfdetach(ifp); 277 if_detach(ifp); 278 bus_release_resource(dev, SYS_RES_IRQ, 0, lp->res_irq); 279 device_printf(dev, "Unable to register interrupt handler\n"); 280 return (error); 281 } 282 283 return (0); 284 } 285 286 static int 287 lp_detach(device_t dev) 288 { 289 struct lp_data *sc = device_get_softc(dev); 290 device_t ppbus = device_get_parent(dev); 291 292 ppb_lock(ppbus); 293 lpstop(sc); 294 ppb_unlock(ppbus); 295 bpfdetach(sc->sc_ifp); 296 if_detach(sc->sc_ifp); 297 bus_teardown_intr(dev, sc->res_irq, sc->sc_intr_cookie); 298 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->res_irq); 299 return (0); 300 } 301 302 /* 303 * Build the translation tables for the LPIP (BSD unix) protocol. 304 * We don't want to calculate these nasties in our tight loop, so we 305 * precalculate them when we initialize. 306 */ 307 static int 308 lpinittables(void) 309 { 310 int i; 311 312 mtx_lock(&lp_tables_lock); 313 if (txmith == NULL) 314 txmith = malloc(4 * LPIPTBLSIZE, M_DEVBUF, M_NOWAIT); 315 316 if (txmith == NULL) { 317 mtx_unlock(&lp_tables_lock); 318 return (1); 319 } 320 321 if (ctxmith == NULL) 322 ctxmith = malloc(4 * LPIPTBLSIZE, M_DEVBUF, M_NOWAIT); 323 324 if (ctxmith == NULL) { 325 mtx_unlock(&lp_tables_lock); 326 return (1); 327 } 328 329 for (i = 0; i < LPIPTBLSIZE; i++) { 330 ctxmith[i] = (i & 0xF0) >> 4; 331 ctxmitl[i] = 0x10 | (i & 0x0F); 332 ctrecvh[i] = (i & 0x78) << 1; 333 ctrecvl[i] = (i & 0x78) >> 3; 334 } 335 336 for (i = 0; i < LPIPTBLSIZE; i++) { 337 txmith[i] = ((i & 0x80) >> 3) | ((i & 0x70) >> 4) | 0x08; 338 txmitl[i] = ((i & 0x08) << 1) | (i & 0x07); 339 trecvh[i] = ((~i) & 0x80) | ((i & 0x38) << 1); 340 trecvl[i] = (((~i) & 0x80) >> 4) | ((i & 0x38) >> 3); 341 } 342 mtx_unlock(&lp_tables_lock); 343 344 return (0); 345 } 346 347 static void 348 lpstop(struct lp_data *sc) 349 { 350 device_t ppbus = device_get_parent(sc->sc_dev); 351 352 ppb_assert_locked(ppbus); 353 ppb_wctr(ppbus, 0x00); 354 if_setdrvflagbits(sc->sc_ifp, 0, (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)); 355 free(sc->sc_ifbuf, M_DEVBUF); 356 sc->sc_ifbuf = NULL; 357 358 /* IFF_UP is not set, try to release the bus anyway */ 359 ppb_release_bus(ppbus, sc->sc_dev); 360 } 361 362 static int 363 lpinit_locked(if_t ifp) 364 { 365 struct lp_data *sc = if_getsoftc(ifp); 366 device_t dev = sc->sc_dev; 367 device_t ppbus = device_get_parent(dev); 368 int error; 369 370 ppb_assert_locked(ppbus); 371 error = ppb_request_bus(ppbus, dev, PPB_DONTWAIT); 372 if (error) 373 return (error); 374 375 /* Now IFF_UP means that we own the bus */ 376 ppb_set_mode(ppbus, PPB_COMPATIBLE); 377 378 if (lpinittables()) { 379 ppb_release_bus(ppbus, dev); 380 return (ENOBUFS); 381 } 382 383 sc->sc_ifbuf = malloc(if_getmtu(sc->sc_ifp) + MLPIPHDRLEN, 384 M_DEVBUF, M_NOWAIT); 385 if (sc->sc_ifbuf == NULL) { 386 ppb_release_bus(ppbus, dev); 387 return (ENOBUFS); 388 } 389 390 ppb_wctr(ppbus, IRQENABLE); 391 392 if_setdrvflagbits(ifp, IFF_DRV_RUNNING, 0); 393 if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE); 394 return (0); 395 } 396 397 /* 398 * Process an ioctl request. 399 */ 400 static int 401 lpioctl(if_t ifp, u_long cmd, caddr_t data) 402 { 403 struct lp_data *sc = if_getsoftc(ifp); 404 device_t dev = sc->sc_dev; 405 device_t ppbus = device_get_parent(dev); 406 struct ifaddr *ifa = (struct ifaddr *)data; 407 struct ifreq *ifr = (struct ifreq *)data; 408 u_char *ptr; 409 int error; 410 411 switch (cmd) { 412 case SIOCAIFADDR: 413 case SIOCSIFADDR: 414 if (ifa->ifa_addr->sa_family != AF_INET) 415 return (EAFNOSUPPORT); 416 417 if_setflagbits(ifp, IFF_UP, 0); 418 /* FALLTHROUGH */ 419 case SIOCSIFFLAGS: 420 error = 0; 421 ppb_lock(ppbus); 422 if ((!(if_getflags(ifp) & IFF_UP)) && 423 (if_getdrvflags(ifp) & IFF_DRV_RUNNING)) 424 lpstop(sc); 425 else if (((if_getflags(ifp) & IFF_UP)) && 426 (!(if_getdrvflags(ifp) & IFF_DRV_RUNNING))) 427 error = lpinit_locked(ifp); 428 ppb_unlock(ppbus); 429 return (error); 430 431 case SIOCSIFMTU: 432 ppb_lock(ppbus); 433 if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) { 434 ptr = malloc(ifr->ifr_mtu + MLPIPHDRLEN, M_DEVBUF, 435 M_NOWAIT); 436 if (ptr == NULL) { 437 ppb_unlock(ppbus); 438 return (ENOBUFS); 439 } 440 if (sc->sc_ifbuf) 441 free(sc->sc_ifbuf, M_DEVBUF); 442 sc->sc_ifbuf = ptr; 443 } 444 if_setmtu(ifp, ifr->ifr_mtu); 445 ppb_unlock(ppbus); 446 break; 447 448 case SIOCGIFMTU: 449 ifr->ifr_mtu = if_getmtu(sc->sc_ifp); 450 break; 451 452 case SIOCADDMULTI: 453 case SIOCDELMULTI: 454 if (ifr == NULL) { 455 return (EAFNOSUPPORT); /* XXX */ 456 } 457 switch (ifr->ifr_addr.sa_family) { 458 case AF_INET: 459 break; 460 default: 461 return (EAFNOSUPPORT); 462 } 463 break; 464 465 case SIOCGIFMEDIA: 466 /* 467 * No ifmedia support at this stage; maybe use it 468 * in future for eg. protocol selection. 469 */ 470 return (EINVAL); 471 472 default: 473 lprintf("LP:ioctl(0x%lx)\n", cmd); 474 return (EINVAL); 475 } 476 return (0); 477 } 478 479 static __inline int 480 clpoutbyte(u_char byte, int spin, device_t ppbus) 481 { 482 483 ppb_wdtr(ppbus, ctxmitl[byte]); 484 while (ppb_rstr(ppbus) & CLPIP_SHAKE) 485 if (--spin == 0) { 486 return (1); 487 } 488 ppb_wdtr(ppbus, ctxmith[byte]); 489 while (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) 490 if (--spin == 0) { 491 return (1); 492 } 493 return (0); 494 } 495 496 static __inline int 497 clpinbyte(int spin, device_t ppbus) 498 { 499 u_char c, cl; 500 501 while ((ppb_rstr(ppbus) & CLPIP_SHAKE)) 502 if (!--spin) { 503 return (-1); 504 } 505 cl = ppb_rstr(ppbus); 506 ppb_wdtr(ppbus, 0x10); 507 508 while (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) 509 if (!--spin) { 510 return (-1); 511 } 512 c = ppb_rstr(ppbus); 513 ppb_wdtr(ppbus, 0x00); 514 515 return (ctrecvl[cl] | ctrecvh[c]); 516 } 517 518 static void 519 lptap(if_t ifp, struct mbuf *m) 520 { 521 u_int32_t af = AF_INET; 522 523 bpf_mtap2_if(ifp, &af, sizeof(af), m); 524 } 525 526 static void 527 lp_intr(void *arg) 528 { 529 struct lp_data *sc = arg; 530 device_t ppbus = device_get_parent(sc->sc_dev); 531 int len, j; 532 u_char *bp; 533 u_char c, cl; 534 struct mbuf *top; 535 536 ppb_assert_locked(ppbus); 537 if (if_getflags(sc->sc_ifp) & IFF_LINK0) { 538 /* Ack. the request */ 539 ppb_wdtr(ppbus, 0x01); 540 541 /* Get the packet length */ 542 j = clpinbyte(LPMAXSPIN2, ppbus); 543 if (j == -1) 544 goto err; 545 len = j; 546 j = clpinbyte(LPMAXSPIN2, ppbus); 547 if (j == -1) 548 goto err; 549 len = len + (j << 8); 550 if (len > if_getmtu(sc->sc_ifp) + MLPIPHDRLEN) 551 goto err; 552 553 bp = sc->sc_ifbuf; 554 555 while (len--) { 556 j = clpinbyte(LPMAXSPIN2, ppbus); 557 if (j == -1) { 558 goto err; 559 } 560 *bp++ = j; 561 } 562 563 /* Get and ignore checksum */ 564 j = clpinbyte(LPMAXSPIN2, ppbus); 565 if (j == -1) { 566 goto err; 567 } 568 569 len = bp - sc->sc_ifbuf; 570 if (len <= CLPIPHDRLEN) 571 goto err; 572 573 sc->sc_iferrs = 0; 574 575 len -= CLPIPHDRLEN; 576 if_inc_counter(sc->sc_ifp, IFCOUNTER_IPACKETS, 1); 577 if_inc_counter(sc->sc_ifp, IFCOUNTER_IBYTES, len); 578 top = m_devget(sc->sc_ifbuf + CLPIPHDRLEN, len, 0, sc->sc_ifp, 579 0); 580 if (top) { 581 ppb_unlock(ppbus); 582 lptap(sc->sc_ifp, top); 583 584 M_SETFIB(top, if_getfib(sc->sc_ifp)); 585 586 /* mbuf is free'd on failure. */ 587 netisr_queue(NETISR_IP, top); 588 ppb_lock(ppbus); 589 } 590 return; 591 } 592 while ((ppb_rstr(ppbus) & LPIP_SHAKE)) { 593 len = if_getmtu(sc->sc_ifp) + LPIPHDRLEN; 594 bp = sc->sc_ifbuf; 595 while (len--) { 596 cl = ppb_rstr(ppbus); 597 ppb_wdtr(ppbus, 8); 598 599 j = LPMAXSPIN2; 600 while ((ppb_rstr(ppbus) & LPIP_SHAKE)) 601 if (!--j) 602 goto err; 603 604 c = ppb_rstr(ppbus); 605 ppb_wdtr(ppbus, 0); 606 607 *bp++= trecvh[cl] | trecvl[c]; 608 609 j = LPMAXSPIN2; 610 while (!((cl = ppb_rstr(ppbus)) & LPIP_SHAKE)) { 611 if (cl != c && 612 (((cl = ppb_rstr(ppbus)) ^ 0xb8) & 0xf8) == 613 (c & 0xf8)) 614 goto end; 615 if (!--j) 616 goto err; 617 } 618 } 619 620 end: 621 len = bp - sc->sc_ifbuf; 622 if (len <= LPIPHDRLEN) 623 goto err; 624 625 sc->sc_iferrs = 0; 626 627 len -= LPIPHDRLEN; 628 if_inc_counter(sc->sc_ifp, IFCOUNTER_IPACKETS, 1); 629 if_inc_counter(sc->sc_ifp, IFCOUNTER_IBYTES, len); 630 top = m_devget(sc->sc_ifbuf + LPIPHDRLEN, len, 0, sc->sc_ifp, 631 0); 632 if (top) { 633 ppb_unlock(ppbus); 634 lptap(sc->sc_ifp, top); 635 636 M_SETFIB(top, if_getfib(sc->sc_ifp)); 637 638 /* mbuf is free'd on failure. */ 639 netisr_queue(NETISR_IP, top); 640 ppb_lock(ppbus); 641 } 642 } 643 return; 644 645 err: 646 ppb_wdtr(ppbus, 0); 647 lprintf("R"); 648 if_inc_counter(sc->sc_ifp, IFCOUNTER_IERRORS, 1); 649 sc->sc_iferrs++; 650 651 /* 652 * We are not able to send receive anything for now, 653 * so stop wasting our time 654 */ 655 if (sc->sc_iferrs > LPMAXERRS) { 656 if_printf(sc->sc_ifp, "Too many errors, Going off-line.\n"); 657 ppb_wctr(ppbus, 0x00); 658 if_setdrvflagbits(sc->sc_ifp, 0, IFF_DRV_RUNNING); 659 sc->sc_iferrs = 0; 660 } 661 } 662 663 static __inline int 664 lpoutbyte(u_char byte, int spin, device_t ppbus) 665 { 666 667 ppb_wdtr(ppbus, txmith[byte]); 668 while (!(ppb_rstr(ppbus) & LPIP_SHAKE)) 669 if (--spin == 0) 670 return (1); 671 ppb_wdtr(ppbus, txmitl[byte]); 672 while (ppb_rstr(ppbus) & LPIP_SHAKE) 673 if (--spin == 0) 674 return (1); 675 return (0); 676 } 677 678 static int 679 lpoutput(if_t ifp, struct mbuf *m, const struct sockaddr *dst, 680 struct route *ro) 681 { 682 struct lp_data *sc = if_getsoftc(ifp); 683 device_t dev = sc->sc_dev; 684 device_t ppbus = device_get_parent(dev); 685 int err; 686 struct mbuf *mm; 687 u_char *cp = "\0\0"; 688 u_char chksum = 0; 689 int count = 0; 690 int i, len, spin; 691 692 /* We need a sensible value if we abort */ 693 cp++; 694 ppb_lock(ppbus); 695 if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0); 696 697 err = 1; /* assume we're aborting because of an error */ 698 699 /* Suspend (on laptops) or receive-errors might have taken us offline */ 700 ppb_wctr(ppbus, IRQENABLE); 701 702 if (if_getflags(ifp) & IFF_LINK0) { 703 if (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) { 704 lprintf("&"); 705 lp_intr(sc); 706 } 707 708 /* Alert other end to pending packet */ 709 spin = LPMAXSPIN1; 710 ppb_wdtr(ppbus, 0x08); 711 while ((ppb_rstr(ppbus) & 0x08) == 0) 712 if (--spin == 0) { 713 goto nend; 714 } 715 716 /* Calculate length of packet, then send that */ 717 718 count += 14; /* Ethernet header len */ 719 720 mm = m; 721 for (mm = m; mm; mm = mm->m_next) { 722 count += mm->m_len; 723 } 724 if (clpoutbyte(count & 0xFF, LPMAXSPIN1, ppbus)) 725 goto nend; 726 if (clpoutbyte((count >> 8) & 0xFF, LPMAXSPIN1, ppbus)) 727 goto nend; 728 729 /* Send dummy ethernet header */ 730 for (i = 0; i < 12; i++) { 731 if (clpoutbyte(i, LPMAXSPIN1, ppbus)) 732 goto nend; 733 chksum += i; 734 } 735 736 if (clpoutbyte(0x08, LPMAXSPIN1, ppbus)) 737 goto nend; 738 if (clpoutbyte(0x00, LPMAXSPIN1, ppbus)) 739 goto nend; 740 chksum += 0x08 + 0x00; /* Add into checksum */ 741 742 mm = m; 743 do { 744 cp = mtod(mm, u_char *); 745 len = mm->m_len; 746 while (len--) { 747 chksum += *cp; 748 if (clpoutbyte(*cp++, LPMAXSPIN2, ppbus)) 749 goto nend; 750 } 751 } while ((mm = mm->m_next)); 752 753 /* Send checksum */ 754 if (clpoutbyte(chksum, LPMAXSPIN2, ppbus)) 755 goto nend; 756 757 /* Go quiescent */ 758 ppb_wdtr(ppbus, 0); 759 760 err = 0; /* No errors */ 761 762 nend: 763 if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE); 764 if (err) { /* if we didn't timeout... */ 765 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 766 lprintf("X"); 767 } else { 768 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 769 if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len); 770 lptap(ifp, m); 771 } 772 773 m_freem(m); 774 775 if (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) { 776 lprintf("^"); 777 lp_intr(sc); 778 } 779 ppb_unlock(ppbus); 780 return (0); 781 } 782 783 if (ppb_rstr(ppbus) & LPIP_SHAKE) { 784 lprintf("&"); 785 lp_intr(sc); 786 } 787 788 if (lpoutbyte(0x08, LPMAXSPIN1, ppbus)) 789 goto end; 790 if (lpoutbyte(0x00, LPMAXSPIN2, ppbus)) 791 goto end; 792 793 mm = m; 794 do { 795 cp = mtod(mm, u_char *); 796 len = mm->m_len; 797 while (len--) 798 if (lpoutbyte(*cp++, LPMAXSPIN2, ppbus)) 799 goto end; 800 } while ((mm = mm->m_next)); 801 802 err = 0; /* no errors were encountered */ 803 804 end: 805 --cp; 806 ppb_wdtr(ppbus, txmitl[*cp] ^ 0x17); 807 808 if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE); 809 if (err) { /* if we didn't timeout... */ 810 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 811 lprintf("X"); 812 } else { 813 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 814 if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len); 815 lptap(ifp, m); 816 } 817 818 m_freem(m); 819 820 if (ppb_rstr(ppbus) & LPIP_SHAKE) { 821 lprintf("^"); 822 lp_intr(sc); 823 } 824 825 ppb_unlock(ppbus); 826 return (0); 827 } 828 829 static device_method_t lp_methods[] = { 830 /* device interface */ 831 DEVMETHOD(device_identify, lp_identify), 832 DEVMETHOD(device_probe, lp_probe), 833 DEVMETHOD(device_attach, lp_attach), 834 DEVMETHOD(device_detach, lp_detach), 835 { 0, 0 } 836 }; 837 838 static driver_t lp_driver = { 839 "plip", 840 lp_methods, 841 sizeof(struct lp_data), 842 }; 843 844 DRIVER_MODULE(plip, ppbus, lp_driver, lp_module_handler, NULL); 845 MODULE_DEPEND(plip, ppbus, 1, 1, 1); 846