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(struct ifnet *, u_long, caddr_t); 179 static int lpoutput(struct ifnet *, 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 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 == 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 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 == NULL) { 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 /* Ack. the request */ 541 ppb_wdtr(ppbus, 0x01); 542 543 /* Get the packet length */ 544 j = clpinbyte(LPMAXSPIN2, ppbus); 545 if (j == -1) 546 goto err; 547 len = j; 548 j = clpinbyte(LPMAXSPIN2, ppbus); 549 if (j == -1) 550 goto err; 551 len = len + (j << 8); 552 if (len > sc->sc_ifp->if_mtu + MLPIPHDRLEN) 553 goto err; 554 555 bp = sc->sc_ifbuf; 556 557 while (len--) { 558 j = clpinbyte(LPMAXSPIN2, ppbus); 559 if (j == -1) { 560 goto err; 561 } 562 *bp++ = j; 563 } 564 565 /* Get and ignore checksum */ 566 j = clpinbyte(LPMAXSPIN2, ppbus); 567 if (j == -1) { 568 goto err; 569 } 570 571 len = bp - sc->sc_ifbuf; 572 if (len <= CLPIPHDRLEN) 573 goto err; 574 575 sc->sc_iferrs = 0; 576 577 len -= CLPIPHDRLEN; 578 if_inc_counter(sc->sc_ifp, IFCOUNTER_IPACKETS, 1); 579 if_inc_counter(sc->sc_ifp, IFCOUNTER_IBYTES, len); 580 top = m_devget(sc->sc_ifbuf + CLPIPHDRLEN, len, 0, sc->sc_ifp, 581 0); 582 if (top) { 583 ppb_unlock(ppbus); 584 if (bpf_peers_present(sc->sc_ifp->if_bpf)) 585 lptap(sc->sc_ifp, top); 586 587 M_SETFIB(top, sc->sc_ifp->if_fib); 588 589 /* mbuf is free'd on failure. */ 590 netisr_queue(NETISR_IP, top); 591 ppb_lock(ppbus); 592 } 593 return; 594 } 595 while ((ppb_rstr(ppbus) & LPIP_SHAKE)) { 596 len = sc->sc_ifp->if_mtu + LPIPHDRLEN; 597 bp = sc->sc_ifbuf; 598 while (len--) { 599 cl = ppb_rstr(ppbus); 600 ppb_wdtr(ppbus, 8); 601 602 j = LPMAXSPIN2; 603 while ((ppb_rstr(ppbus) & LPIP_SHAKE)) 604 if (!--j) 605 goto err; 606 607 c = ppb_rstr(ppbus); 608 ppb_wdtr(ppbus, 0); 609 610 *bp++= trecvh[cl] | trecvl[c]; 611 612 j = LPMAXSPIN2; 613 while (!((cl = ppb_rstr(ppbus)) & LPIP_SHAKE)) { 614 if (cl != c && 615 (((cl = ppb_rstr(ppbus)) ^ 0xb8) & 0xf8) == 616 (c & 0xf8)) 617 goto end; 618 if (!--j) 619 goto err; 620 } 621 } 622 623 end: 624 len = bp - sc->sc_ifbuf; 625 if (len <= LPIPHDRLEN) 626 goto err; 627 628 sc->sc_iferrs = 0; 629 630 len -= LPIPHDRLEN; 631 if_inc_counter(sc->sc_ifp, IFCOUNTER_IPACKETS, 1); 632 if_inc_counter(sc->sc_ifp, IFCOUNTER_IBYTES, len); 633 top = m_devget(sc->sc_ifbuf + LPIPHDRLEN, len, 0, sc->sc_ifp, 634 0); 635 if (top) { 636 ppb_unlock(ppbus); 637 if (bpf_peers_present(sc->sc_ifp->if_bpf)) 638 lptap(sc->sc_ifp, top); 639 640 M_SETFIB(top, sc->sc_ifp->if_fib); 641 642 /* mbuf is free'd on failure. */ 643 netisr_queue(NETISR_IP, top); 644 ppb_lock(ppbus); 645 } 646 } 647 return; 648 649 err: 650 ppb_wdtr(ppbus, 0); 651 lprintf("R"); 652 if_inc_counter(sc->sc_ifp, IFCOUNTER_IERRORS, 1); 653 sc->sc_iferrs++; 654 655 /* 656 * We are not able to send receive anything for now, 657 * so stop wasting our time 658 */ 659 if (sc->sc_iferrs > LPMAXERRS) { 660 if_printf(sc->sc_ifp, "Too many errors, Going off-line.\n"); 661 ppb_wctr(ppbus, 0x00); 662 sc->sc_ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 663 sc->sc_iferrs = 0; 664 } 665 } 666 667 static __inline int 668 lpoutbyte(u_char byte, int spin, device_t ppbus) 669 { 670 671 ppb_wdtr(ppbus, txmith[byte]); 672 while (!(ppb_rstr(ppbus) & LPIP_SHAKE)) 673 if (--spin == 0) 674 return (1); 675 ppb_wdtr(ppbus, txmitl[byte]); 676 while (ppb_rstr(ppbus) & LPIP_SHAKE) 677 if (--spin == 0) 678 return (1); 679 return (0); 680 } 681 682 static int 683 lpoutput(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, 684 struct route *ro) 685 { 686 struct lp_data *sc = ifp->if_softc; 687 device_t dev = sc->sc_dev; 688 device_t ppbus = device_get_parent(dev); 689 int err; 690 struct mbuf *mm; 691 u_char *cp = "\0\0"; 692 u_char chksum = 0; 693 int count = 0; 694 int i, len, spin; 695 696 /* We need a sensible value if we abort */ 697 cp++; 698 ppb_lock(ppbus); 699 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 700 701 err = 1; /* assume we're aborting because of an error */ 702 703 /* Suspend (on laptops) or receive-errors might have taken us offline */ 704 ppb_wctr(ppbus, IRQENABLE); 705 706 if (ifp->if_flags & IFF_LINK0) { 707 if (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) { 708 lprintf("&"); 709 lp_intr(sc); 710 } 711 712 /* Alert other end to pending packet */ 713 spin = LPMAXSPIN1; 714 ppb_wdtr(ppbus, 0x08); 715 while ((ppb_rstr(ppbus) & 0x08) == 0) 716 if (--spin == 0) { 717 goto nend; 718 } 719 720 /* Calculate length of packet, then send that */ 721 722 count += 14; /* Ethernet header len */ 723 724 mm = m; 725 for (mm = m; mm; mm = mm->m_next) { 726 count += mm->m_len; 727 } 728 if (clpoutbyte(count & 0xFF, LPMAXSPIN1, ppbus)) 729 goto nend; 730 if (clpoutbyte((count >> 8) & 0xFF, LPMAXSPIN1, ppbus)) 731 goto nend; 732 733 /* Send dummy ethernet header */ 734 for (i = 0; i < 12; i++) { 735 if (clpoutbyte(i, LPMAXSPIN1, ppbus)) 736 goto nend; 737 chksum += i; 738 } 739 740 if (clpoutbyte(0x08, LPMAXSPIN1, ppbus)) 741 goto nend; 742 if (clpoutbyte(0x00, LPMAXSPIN1, ppbus)) 743 goto nend; 744 chksum += 0x08 + 0x00; /* Add into checksum */ 745 746 mm = m; 747 do { 748 cp = mtod(mm, u_char *); 749 len = mm->m_len; 750 while (len--) { 751 chksum += *cp; 752 if (clpoutbyte(*cp++, LPMAXSPIN2, ppbus)) 753 goto nend; 754 } 755 } while ((mm = mm->m_next)); 756 757 /* Send checksum */ 758 if (clpoutbyte(chksum, LPMAXSPIN2, ppbus)) 759 goto nend; 760 761 /* Go quiescent */ 762 ppb_wdtr(ppbus, 0); 763 764 err = 0; /* No errors */ 765 766 nend: 767 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 768 if (err) { /* if we didn't timeout... */ 769 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 770 lprintf("X"); 771 } else { 772 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 773 if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len); 774 if (bpf_peers_present(ifp->if_bpf)) 775 lptap(ifp, m); 776 } 777 778 m_freem(m); 779 780 if (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) { 781 lprintf("^"); 782 lp_intr(sc); 783 } 784 ppb_unlock(ppbus); 785 return (0); 786 } 787 788 if (ppb_rstr(ppbus) & LPIP_SHAKE) { 789 lprintf("&"); 790 lp_intr(sc); 791 } 792 793 if (lpoutbyte(0x08, LPMAXSPIN1, ppbus)) 794 goto end; 795 if (lpoutbyte(0x00, LPMAXSPIN2, ppbus)) 796 goto end; 797 798 mm = m; 799 do { 800 cp = mtod(mm, u_char *); 801 len = mm->m_len; 802 while (len--) 803 if (lpoutbyte(*cp++, LPMAXSPIN2, ppbus)) 804 goto end; 805 } while ((mm = mm->m_next)); 806 807 err = 0; /* no errors were encountered */ 808 809 end: 810 --cp; 811 ppb_wdtr(ppbus, txmitl[*cp] ^ 0x17); 812 813 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 814 if (err) { /* if we didn't timeout... */ 815 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 816 lprintf("X"); 817 } else { 818 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 819 if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len); 820 if (bpf_peers_present(ifp->if_bpf)) 821 lptap(ifp, m); 822 } 823 824 m_freem(m); 825 826 if (ppb_rstr(ppbus) & LPIP_SHAKE) { 827 lprintf("^"); 828 lp_intr(sc); 829 } 830 831 ppb_unlock(ppbus); 832 return (0); 833 } 834 835 static device_method_t lp_methods[] = { 836 /* device interface */ 837 DEVMETHOD(device_identify, lp_identify), 838 DEVMETHOD(device_probe, lp_probe), 839 DEVMETHOD(device_attach, lp_attach), 840 DEVMETHOD(device_detach, lp_detach), 841 { 0, 0 } 842 }; 843 844 static driver_t lp_driver = { 845 "plip", 846 lp_methods, 847 sizeof(struct lp_data), 848 }; 849 850 DRIVER_MODULE(plip, ppbus, lp_driver, lp_module_handler, NULL); 851 MODULE_DEPEND(plip, ppbus, 1, 1, 1); 852