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