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