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", DEVICE_UNIT_ANY); 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_setsoftc(ifp, lp); 253 if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 254 if_setmtu(ifp, LPMTU); 255 if_setflags(ifp, IFF_SIMPLEX | IFF_POINTOPOINT | IFF_MULTICAST); 256 if_setioctlfn(ifp, lpioctl); 257 if_setoutputfn(ifp, lpoutput); 258 if_setsendqlen(ifp, ifqmaxlen); 259 if_attach(ifp); 260 261 bpfattach(ifp, DLT_NULL, sizeof(u_int32_t)); 262 263 /* 264 * Attach our interrupt handler. It is only called while we 265 * own the ppbus. 266 */ 267 error = bus_setup_intr(dev, lp->res_irq, INTR_TYPE_NET | INTR_MPSAFE, 268 NULL, lp_intr, lp, &lp->sc_intr_cookie); 269 if (error) { 270 bpfdetach(ifp); 271 if_detach(ifp); 272 bus_release_resource(dev, SYS_RES_IRQ, 0, lp->res_irq); 273 device_printf(dev, "Unable to register interrupt handler\n"); 274 return (error); 275 } 276 277 return (0); 278 } 279 280 static int 281 lp_detach(device_t dev) 282 { 283 struct lp_data *sc = device_get_softc(dev); 284 device_t ppbus = device_get_parent(dev); 285 286 ppb_lock(ppbus); 287 lpstop(sc); 288 ppb_unlock(ppbus); 289 bpfdetach(sc->sc_ifp); 290 if_detach(sc->sc_ifp); 291 bus_teardown_intr(dev, sc->res_irq, sc->sc_intr_cookie); 292 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->res_irq); 293 return (0); 294 } 295 296 /* 297 * Build the translation tables for the LPIP (BSD unix) protocol. 298 * We don't want to calculate these nasties in our tight loop, so we 299 * precalculate them when we initialize. 300 */ 301 static int 302 lpinittables(void) 303 { 304 int i; 305 306 mtx_lock(&lp_tables_lock); 307 if (txmith == NULL) 308 txmith = malloc(4 * LPIPTBLSIZE, M_DEVBUF, M_NOWAIT); 309 310 if (txmith == NULL) { 311 mtx_unlock(&lp_tables_lock); 312 return (1); 313 } 314 315 if (ctxmith == NULL) 316 ctxmith = malloc(4 * LPIPTBLSIZE, M_DEVBUF, M_NOWAIT); 317 318 if (ctxmith == NULL) { 319 mtx_unlock(&lp_tables_lock); 320 return (1); 321 } 322 323 for (i = 0; i < LPIPTBLSIZE; i++) { 324 ctxmith[i] = (i & 0xF0) >> 4; 325 ctxmitl[i] = 0x10 | (i & 0x0F); 326 ctrecvh[i] = (i & 0x78) << 1; 327 ctrecvl[i] = (i & 0x78) >> 3; 328 } 329 330 for (i = 0; i < LPIPTBLSIZE; i++) { 331 txmith[i] = ((i & 0x80) >> 3) | ((i & 0x70) >> 4) | 0x08; 332 txmitl[i] = ((i & 0x08) << 1) | (i & 0x07); 333 trecvh[i] = ((~i) & 0x80) | ((i & 0x38) << 1); 334 trecvl[i] = (((~i) & 0x80) >> 4) | ((i & 0x38) >> 3); 335 } 336 mtx_unlock(&lp_tables_lock); 337 338 return (0); 339 } 340 341 static void 342 lpstop(struct lp_data *sc) 343 { 344 device_t ppbus = device_get_parent(sc->sc_dev); 345 346 ppb_assert_locked(ppbus); 347 ppb_wctr(ppbus, 0x00); 348 if_setdrvflagbits(sc->sc_ifp, 0, (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)); 349 free(sc->sc_ifbuf, M_DEVBUF); 350 sc->sc_ifbuf = NULL; 351 352 /* IFF_UP is not set, try to release the bus anyway */ 353 ppb_release_bus(ppbus, sc->sc_dev); 354 } 355 356 static int 357 lpinit_locked(if_t ifp) 358 { 359 struct lp_data *sc = if_getsoftc(ifp); 360 device_t dev = sc->sc_dev; 361 device_t ppbus = device_get_parent(dev); 362 int error; 363 364 ppb_assert_locked(ppbus); 365 error = ppb_request_bus(ppbus, dev, PPB_DONTWAIT); 366 if (error) 367 return (error); 368 369 /* Now IFF_UP means that we own the bus */ 370 ppb_set_mode(ppbus, PPB_COMPATIBLE); 371 372 if (lpinittables()) { 373 ppb_release_bus(ppbus, dev); 374 return (ENOBUFS); 375 } 376 377 sc->sc_ifbuf = malloc(if_getmtu(sc->sc_ifp) + MLPIPHDRLEN, 378 M_DEVBUF, M_NOWAIT); 379 if (sc->sc_ifbuf == NULL) { 380 ppb_release_bus(ppbus, dev); 381 return (ENOBUFS); 382 } 383 384 ppb_wctr(ppbus, IRQENABLE); 385 386 if_setdrvflagbits(ifp, IFF_DRV_RUNNING, 0); 387 if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE); 388 return (0); 389 } 390 391 /* 392 * Process an ioctl request. 393 */ 394 static int 395 lpioctl(if_t ifp, u_long cmd, caddr_t data) 396 { 397 struct lp_data *sc = if_getsoftc(ifp); 398 device_t dev = sc->sc_dev; 399 device_t ppbus = device_get_parent(dev); 400 struct ifaddr *ifa = (struct ifaddr *)data; 401 struct ifreq *ifr = (struct ifreq *)data; 402 u_char *ptr; 403 int error; 404 405 switch (cmd) { 406 case SIOCAIFADDR: 407 case SIOCSIFADDR: 408 if (ifa->ifa_addr->sa_family != AF_INET) 409 return (EAFNOSUPPORT); 410 411 if_setflagbits(ifp, IFF_UP, 0); 412 /* FALLTHROUGH */ 413 case SIOCSIFFLAGS: 414 error = 0; 415 ppb_lock(ppbus); 416 if ((!(if_getflags(ifp) & IFF_UP)) && 417 (if_getdrvflags(ifp) & IFF_DRV_RUNNING)) 418 lpstop(sc); 419 else if (((if_getflags(ifp) & IFF_UP)) && 420 (!(if_getdrvflags(ifp) & IFF_DRV_RUNNING))) 421 error = lpinit_locked(ifp); 422 ppb_unlock(ppbus); 423 return (error); 424 425 case SIOCSIFMTU: 426 ppb_lock(ppbus); 427 if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) { 428 ptr = malloc(ifr->ifr_mtu + MLPIPHDRLEN, M_DEVBUF, 429 M_NOWAIT); 430 if (ptr == NULL) { 431 ppb_unlock(ppbus); 432 return (ENOBUFS); 433 } 434 if (sc->sc_ifbuf) 435 free(sc->sc_ifbuf, M_DEVBUF); 436 sc->sc_ifbuf = ptr; 437 } 438 if_setmtu(ifp, ifr->ifr_mtu); 439 ppb_unlock(ppbus); 440 break; 441 442 case SIOCGIFMTU: 443 ifr->ifr_mtu = if_getmtu(sc->sc_ifp); 444 break; 445 446 case SIOCADDMULTI: 447 case SIOCDELMULTI: 448 if (ifr == NULL) { 449 return (EAFNOSUPPORT); /* XXX */ 450 } 451 switch (ifr->ifr_addr.sa_family) { 452 case AF_INET: 453 break; 454 default: 455 return (EAFNOSUPPORT); 456 } 457 break; 458 459 case SIOCGIFMEDIA: 460 /* 461 * No ifmedia support at this stage; maybe use it 462 * in future for eg. protocol selection. 463 */ 464 return (EINVAL); 465 466 default: 467 lprintf("LP:ioctl(0x%lx)\n", cmd); 468 return (EINVAL); 469 } 470 return (0); 471 } 472 473 static __inline int 474 clpoutbyte(u_char byte, int spin, device_t ppbus) 475 { 476 477 ppb_wdtr(ppbus, ctxmitl[byte]); 478 while (ppb_rstr(ppbus) & CLPIP_SHAKE) 479 if (--spin == 0) { 480 return (1); 481 } 482 ppb_wdtr(ppbus, ctxmith[byte]); 483 while (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) 484 if (--spin == 0) { 485 return (1); 486 } 487 return (0); 488 } 489 490 static __inline int 491 clpinbyte(int spin, device_t ppbus) 492 { 493 u_char c, cl; 494 495 while ((ppb_rstr(ppbus) & CLPIP_SHAKE)) 496 if (!--spin) { 497 return (-1); 498 } 499 cl = ppb_rstr(ppbus); 500 ppb_wdtr(ppbus, 0x10); 501 502 while (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) 503 if (!--spin) { 504 return (-1); 505 } 506 c = ppb_rstr(ppbus); 507 ppb_wdtr(ppbus, 0x00); 508 509 return (ctrecvl[cl] | ctrecvh[c]); 510 } 511 512 static void 513 lptap(if_t ifp, struct mbuf *m) 514 { 515 u_int32_t af = AF_INET; 516 517 bpf_mtap2_if(ifp, &af, sizeof(af), m); 518 } 519 520 static void 521 lp_intr(void *arg) 522 { 523 struct lp_data *sc = arg; 524 device_t ppbus = device_get_parent(sc->sc_dev); 525 int len, j; 526 u_char *bp; 527 u_char c, cl; 528 struct mbuf *top; 529 530 ppb_assert_locked(ppbus); 531 if (if_getflags(sc->sc_ifp) & IFF_LINK0) { 532 /* Ack. the request */ 533 ppb_wdtr(ppbus, 0x01); 534 535 /* Get the packet length */ 536 j = clpinbyte(LPMAXSPIN2, ppbus); 537 if (j == -1) 538 goto err; 539 len = j; 540 j = clpinbyte(LPMAXSPIN2, ppbus); 541 if (j == -1) 542 goto err; 543 len = len + (j << 8); 544 if (len > if_getmtu(sc->sc_ifp) + MLPIPHDRLEN) 545 goto err; 546 547 bp = sc->sc_ifbuf; 548 549 while (len--) { 550 j = clpinbyte(LPMAXSPIN2, ppbus); 551 if (j == -1) { 552 goto err; 553 } 554 *bp++ = j; 555 } 556 557 /* Get and ignore checksum */ 558 j = clpinbyte(LPMAXSPIN2, ppbus); 559 if (j == -1) { 560 goto err; 561 } 562 563 len = bp - sc->sc_ifbuf; 564 if (len <= CLPIPHDRLEN) 565 goto err; 566 567 sc->sc_iferrs = 0; 568 569 len -= CLPIPHDRLEN; 570 if_inc_counter(sc->sc_ifp, IFCOUNTER_IPACKETS, 1); 571 if_inc_counter(sc->sc_ifp, IFCOUNTER_IBYTES, len); 572 top = m_devget(sc->sc_ifbuf + CLPIPHDRLEN, len, 0, sc->sc_ifp, 573 0); 574 if (top) { 575 ppb_unlock(ppbus); 576 lptap(sc->sc_ifp, top); 577 578 M_SETFIB(top, if_getfib(sc->sc_ifp)); 579 580 /* mbuf is free'd on failure. */ 581 netisr_queue(NETISR_IP, top); 582 ppb_lock(ppbus); 583 } 584 return; 585 } 586 while ((ppb_rstr(ppbus) & LPIP_SHAKE)) { 587 len = if_getmtu(sc->sc_ifp) + LPIPHDRLEN; 588 bp = sc->sc_ifbuf; 589 while (len--) { 590 cl = ppb_rstr(ppbus); 591 ppb_wdtr(ppbus, 8); 592 593 j = LPMAXSPIN2; 594 while ((ppb_rstr(ppbus) & LPIP_SHAKE)) 595 if (!--j) 596 goto err; 597 598 c = ppb_rstr(ppbus); 599 ppb_wdtr(ppbus, 0); 600 601 *bp++= trecvh[cl] | trecvl[c]; 602 603 j = LPMAXSPIN2; 604 while (!((cl = ppb_rstr(ppbus)) & LPIP_SHAKE)) { 605 if (cl != c && 606 (((cl = ppb_rstr(ppbus)) ^ 0xb8) & 0xf8) == 607 (c & 0xf8)) 608 goto end; 609 if (!--j) 610 goto err; 611 } 612 } 613 614 end: 615 len = bp - sc->sc_ifbuf; 616 if (len <= LPIPHDRLEN) 617 goto err; 618 619 sc->sc_iferrs = 0; 620 621 len -= LPIPHDRLEN; 622 if_inc_counter(sc->sc_ifp, IFCOUNTER_IPACKETS, 1); 623 if_inc_counter(sc->sc_ifp, IFCOUNTER_IBYTES, len); 624 top = m_devget(sc->sc_ifbuf + LPIPHDRLEN, len, 0, sc->sc_ifp, 625 0); 626 if (top) { 627 ppb_unlock(ppbus); 628 lptap(sc->sc_ifp, top); 629 630 M_SETFIB(top, if_getfib(sc->sc_ifp)); 631 632 /* mbuf is free'd on failure. */ 633 netisr_queue(NETISR_IP, top); 634 ppb_lock(ppbus); 635 } 636 } 637 return; 638 639 err: 640 ppb_wdtr(ppbus, 0); 641 lprintf("R"); 642 if_inc_counter(sc->sc_ifp, IFCOUNTER_IERRORS, 1); 643 sc->sc_iferrs++; 644 645 /* 646 * We are not able to send receive anything for now, 647 * so stop wasting our time 648 */ 649 if (sc->sc_iferrs > LPMAXERRS) { 650 if_printf(sc->sc_ifp, "Too many errors, Going off-line.\n"); 651 ppb_wctr(ppbus, 0x00); 652 if_setdrvflagbits(sc->sc_ifp, 0, IFF_DRV_RUNNING); 653 sc->sc_iferrs = 0; 654 } 655 } 656 657 static __inline int 658 lpoutbyte(u_char byte, int spin, device_t ppbus) 659 { 660 661 ppb_wdtr(ppbus, txmith[byte]); 662 while (!(ppb_rstr(ppbus) & LPIP_SHAKE)) 663 if (--spin == 0) 664 return (1); 665 ppb_wdtr(ppbus, txmitl[byte]); 666 while (ppb_rstr(ppbus) & LPIP_SHAKE) 667 if (--spin == 0) 668 return (1); 669 return (0); 670 } 671 672 static int 673 lpoutput(if_t ifp, struct mbuf *m, const struct sockaddr *dst, 674 struct route *ro) 675 { 676 struct lp_data *sc = if_getsoftc(ifp); 677 device_t dev = sc->sc_dev; 678 device_t ppbus = device_get_parent(dev); 679 int err; 680 struct mbuf *mm; 681 u_char *cp = "\0\0"; 682 u_char chksum = 0; 683 int count = 0; 684 int i, len, spin; 685 686 /* We need a sensible value if we abort */ 687 cp++; 688 ppb_lock(ppbus); 689 if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0); 690 691 err = 1; /* assume we're aborting because of an error */ 692 693 /* Suspend (on laptops) or receive-errors might have taken us offline */ 694 ppb_wctr(ppbus, IRQENABLE); 695 696 if (if_getflags(ifp) & IFF_LINK0) { 697 if (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) { 698 lprintf("&"); 699 lp_intr(sc); 700 } 701 702 /* Alert other end to pending packet */ 703 spin = LPMAXSPIN1; 704 ppb_wdtr(ppbus, 0x08); 705 while ((ppb_rstr(ppbus) & 0x08) == 0) 706 if (--spin == 0) { 707 goto nend; 708 } 709 710 /* Calculate length of packet, then send that */ 711 712 count += 14; /* Ethernet header len */ 713 714 mm = m; 715 for (mm = m; mm; mm = mm->m_next) { 716 count += mm->m_len; 717 } 718 if (clpoutbyte(count & 0xFF, LPMAXSPIN1, ppbus)) 719 goto nend; 720 if (clpoutbyte((count >> 8) & 0xFF, LPMAXSPIN1, ppbus)) 721 goto nend; 722 723 /* Send dummy ethernet header */ 724 for (i = 0; i < 12; i++) { 725 if (clpoutbyte(i, LPMAXSPIN1, ppbus)) 726 goto nend; 727 chksum += i; 728 } 729 730 if (clpoutbyte(0x08, LPMAXSPIN1, ppbus)) 731 goto nend; 732 if (clpoutbyte(0x00, LPMAXSPIN1, ppbus)) 733 goto nend; 734 chksum += 0x08 + 0x00; /* Add into checksum */ 735 736 mm = m; 737 do { 738 cp = mtod(mm, u_char *); 739 len = mm->m_len; 740 while (len--) { 741 chksum += *cp; 742 if (clpoutbyte(*cp++, LPMAXSPIN2, ppbus)) 743 goto nend; 744 } 745 } while ((mm = mm->m_next)); 746 747 /* Send checksum */ 748 if (clpoutbyte(chksum, LPMAXSPIN2, ppbus)) 749 goto nend; 750 751 /* Go quiescent */ 752 ppb_wdtr(ppbus, 0); 753 754 err = 0; /* No errors */ 755 756 nend: 757 if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE); 758 if (err) { /* if we didn't timeout... */ 759 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 760 lprintf("X"); 761 } else { 762 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 763 if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len); 764 lptap(ifp, m); 765 } 766 767 m_freem(m); 768 769 if (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) { 770 lprintf("^"); 771 lp_intr(sc); 772 } 773 ppb_unlock(ppbus); 774 return (0); 775 } 776 777 if (ppb_rstr(ppbus) & LPIP_SHAKE) { 778 lprintf("&"); 779 lp_intr(sc); 780 } 781 782 if (lpoutbyte(0x08, LPMAXSPIN1, ppbus)) 783 goto end; 784 if (lpoutbyte(0x00, LPMAXSPIN2, ppbus)) 785 goto end; 786 787 mm = m; 788 do { 789 cp = mtod(mm, u_char *); 790 len = mm->m_len; 791 while (len--) 792 if (lpoutbyte(*cp++, LPMAXSPIN2, ppbus)) 793 goto end; 794 } while ((mm = mm->m_next)); 795 796 err = 0; /* no errors were encountered */ 797 798 end: 799 --cp; 800 ppb_wdtr(ppbus, txmitl[*cp] ^ 0x17); 801 802 if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE); 803 if (err) { /* if we didn't timeout... */ 804 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 805 lprintf("X"); 806 } else { 807 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 808 if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len); 809 lptap(ifp, m); 810 } 811 812 m_freem(m); 813 814 if (ppb_rstr(ppbus) & LPIP_SHAKE) { 815 lprintf("^"); 816 lp_intr(sc); 817 } 818 819 ppb_unlock(ppbus); 820 return (0); 821 } 822 823 static device_method_t lp_methods[] = { 824 /* device interface */ 825 DEVMETHOD(device_identify, lp_identify), 826 DEVMETHOD(device_probe, lp_probe), 827 DEVMETHOD(device_attach, lp_attach), 828 DEVMETHOD(device_detach, lp_detach), 829 { 0, 0 } 830 }; 831 832 static driver_t lp_driver = { 833 "plip", 834 lp_methods, 835 sizeof(struct lp_data), 836 }; 837 838 DRIVER_MODULE(plip, ppbus, lp_driver, lp_module_handler, NULL); 839 MODULE_DEPEND(plip, ppbus, 1, 1, 1); 840