1 /*- 2 * Copyright (c) 1997 Poul-Henning Kamp 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * From Id: lpt.c,v 1.55.2.1 1996/11/12 09:08:38 phk Exp 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 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_types.h> 101 #include <net/netisr.h> 102 103 #include <netinet/in.h> 104 #include <netinet/in_var.h> 105 106 #include <net/bpf.h> 107 108 #include <dev/ppbus/ppbconf.h> 109 #include "ppbus_if.h" 110 #include <dev/ppbus/ppbio.h> 111 112 #ifndef LPMTU /* MTU for the lp# interfaces */ 113 #define LPMTU 1500 114 #endif 115 116 #ifndef LPMAXSPIN1 /* DELAY factor for the lp# interfaces */ 117 #define LPMAXSPIN1 8000 /* Spinning for remote intr to happen */ 118 #endif 119 120 #ifndef LPMAXSPIN2 /* DELAY factor for the lp# interfaces */ 121 #define LPMAXSPIN2 500 /* Spinning for remote handshake to happen */ 122 #endif 123 124 #ifndef LPMAXERRS /* Max errors before !RUNNING */ 125 #define LPMAXERRS 100 126 #endif 127 128 #define CLPIPHDRLEN 14 /* We send dummy ethernet addresses (two) + packet type in front of packet */ 129 #define CLPIP_SHAKE 0x80 /* This bit toggles between nibble reception */ 130 #define MLPIPHDRLEN CLPIPHDRLEN 131 132 #define LPIPHDRLEN 2 /* We send 0x08, 0x00 in front of packet */ 133 #define LPIP_SHAKE 0x40 /* This bit toggles between nibble reception */ 134 #if !defined(MLPIPHDRLEN) || LPIPHDRLEN > MLPIPHDRLEN 135 #define MLPIPHDRLEN LPIPHDRLEN 136 #endif 137 138 #define LPIPTBLSIZE 256 /* Size of octet translation table */ 139 140 #define lprintf if (lptflag) printf 141 142 #ifdef PLIP_DEBUG 143 static int volatile lptflag = 1; 144 #else 145 static int volatile lptflag = 0; 146 #endif 147 148 struct lp_data { 149 struct ifnet *sc_ifp; 150 device_t sc_dev; 151 u_char *sc_ifbuf; 152 int sc_iferrs; 153 154 struct resource *res_irq; 155 void *sc_intr_cookie; 156 }; 157 158 static struct mtx lp_tables_lock; 159 MTX_SYSINIT(lp_tables, &lp_tables_lock, "plip tables", MTX_DEF); 160 161 /* Tables for the lp# interface */ 162 static u_char *txmith; 163 #define txmitl (txmith + (1 * LPIPTBLSIZE)) 164 #define trecvh (txmith + (2 * LPIPTBLSIZE)) 165 #define trecvl (txmith + (3 * LPIPTBLSIZE)) 166 167 static u_char *ctxmith; 168 #define ctxmitl (ctxmith + (1 * LPIPTBLSIZE)) 169 #define ctrecvh (ctxmith + (2 * LPIPTBLSIZE)) 170 #define ctrecvl (ctxmith + (3 * LPIPTBLSIZE)) 171 172 /* Functions for the lp# interface */ 173 static int lpinittables(void); 174 static int lpioctl(struct ifnet *, u_long, caddr_t); 175 static int lpoutput(struct ifnet *, struct mbuf *, struct sockaddr *, 176 struct rtentry *); 177 static void lpstop(struct lp_data *); 178 static void lp_intr(void *); 179 static int lp_module_handler(module_t, int, void *); 180 181 #define DEVTOSOFTC(dev) \ 182 ((struct lp_data *)device_get_softc(dev)) 183 184 static devclass_t lp_devclass; 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", -1); 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 struct ifnet *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 == 0) { 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 (ifp == NULL) { 253 return (ENOSPC); 254 } 255 256 ifp->if_softc = lp; 257 if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 258 ifp->if_mtu = LPMTU; 259 ifp->if_flags = IFF_SIMPLEX | IFF_POINTOPOINT | IFF_MULTICAST; 260 ifp->if_ioctl = lpioctl; 261 ifp->if_output = lpoutput; 262 ifp->if_hdrlen = 0; 263 ifp->if_addrlen = 0; 264 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; 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 sc->sc_ifp->if_drv_flags &= ~(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(struct ifnet *ifp) 364 { 365 struct lp_data *sc = ifp->if_softc; 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(sc->sc_ifp->if_mtu + 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 ifp->if_drv_flags |= IFF_DRV_RUNNING; 393 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 394 return (0); 395 } 396 397 /* 398 * Process an ioctl request. 399 */ 400 static int 401 lpioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 402 { 403 struct lp_data *sc = ifp->if_softc; 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 SIOCSIFDSTADDR: 413 case SIOCAIFADDR: 414 case SIOCSIFADDR: 415 if (ifa->ifa_addr->sa_family != AF_INET) 416 return (EAFNOSUPPORT); 417 418 ifp->if_flags |= IFF_UP; 419 /* FALLTHROUGH */ 420 case SIOCSIFFLAGS: 421 error = 0; 422 ppb_lock(ppbus); 423 if ((!(ifp->if_flags & IFF_UP)) && 424 (ifp->if_drv_flags & IFF_DRV_RUNNING)) 425 lpstop(sc); 426 else if (((ifp->if_flags & IFF_UP)) && 427 (!(ifp->if_drv_flags & IFF_DRV_RUNNING))) 428 error = lpinit_locked(ifp); 429 ppb_unlock(ppbus); 430 return (error); 431 432 case SIOCSIFMTU: 433 ppb_lock(ppbus); 434 if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 435 ptr = malloc(ifr->ifr_mtu + MLPIPHDRLEN, M_DEVBUF, 436 M_NOWAIT); 437 if (ptr == NULL) { 438 ppb_unlock(ppbus); 439 return (ENOBUFS); 440 } 441 if (sc->sc_ifbuf) 442 free(sc->sc_ifbuf, M_DEVBUF); 443 sc->sc_ifbuf = ptr; 444 } 445 sc->sc_ifp->if_mtu = ifr->ifr_mtu; 446 ppb_unlock(ppbus); 447 break; 448 449 case SIOCGIFMTU: 450 ifr->ifr_mtu = sc->sc_ifp->if_mtu; 451 break; 452 453 case SIOCADDMULTI: 454 case SIOCDELMULTI: 455 if (ifr == 0) { 456 return (EAFNOSUPPORT); /* XXX */ 457 } 458 switch (ifr->ifr_addr.sa_family) { 459 case AF_INET: 460 break; 461 default: 462 return (EAFNOSUPPORT); 463 } 464 break; 465 466 case SIOCGIFMEDIA: 467 /* 468 * No ifmedia support at this stage; maybe use it 469 * in future for eg. protocol selection. 470 */ 471 return (EINVAL); 472 473 default: 474 lprintf("LP:ioctl(0x%lx)\n", cmd); 475 return (EINVAL); 476 } 477 return (0); 478 } 479 480 static __inline int 481 clpoutbyte(u_char byte, int spin, device_t ppbus) 482 { 483 484 ppb_wdtr(ppbus, ctxmitl[byte]); 485 while (ppb_rstr(ppbus) & CLPIP_SHAKE) 486 if (--spin == 0) { 487 return (1); 488 } 489 ppb_wdtr(ppbus, ctxmith[byte]); 490 while (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) 491 if (--spin == 0) { 492 return (1); 493 } 494 return (0); 495 } 496 497 static __inline int 498 clpinbyte(int spin, device_t ppbus) 499 { 500 u_char c, cl; 501 502 while ((ppb_rstr(ppbus) & CLPIP_SHAKE)) 503 if (!--spin) { 504 return (-1); 505 } 506 cl = ppb_rstr(ppbus); 507 ppb_wdtr(ppbus, 0x10); 508 509 while (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) 510 if (!--spin) { 511 return (-1); 512 } 513 c = ppb_rstr(ppbus); 514 ppb_wdtr(ppbus, 0x00); 515 516 return (ctrecvl[cl] | ctrecvh[c]); 517 } 518 519 static void 520 lptap(struct ifnet *ifp, struct mbuf *m) 521 { 522 u_int32_t af = AF_INET; 523 524 bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m); 525 } 526 527 static void 528 lp_intr(void *arg) 529 { 530 struct lp_data *sc = arg; 531 device_t ppbus = device_get_parent(sc->sc_dev); 532 int len, j; 533 u_char *bp; 534 u_char c, cl; 535 struct mbuf *top; 536 537 ppb_assert_locked(ppbus); 538 if (sc->sc_ifp->if_flags & IFF_LINK0) { 539 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 sc->sc_ifp->if_ipackets++; 579 sc->sc_ifp->if_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 /* mbuf is free'd on failure. */ 588 netisr_queue(NETISR_IP, top); 589 ppb_lock(ppbus); 590 } 591 return; 592 } 593 while ((ppb_rstr(ppbus) & LPIP_SHAKE)) { 594 len = sc->sc_ifp->if_mtu + LPIPHDRLEN; 595 bp = sc->sc_ifbuf; 596 while (len--) { 597 598 cl = ppb_rstr(ppbus); 599 ppb_wdtr(ppbus, 8); 600 601 j = LPMAXSPIN2; 602 while ((ppb_rstr(ppbus) & LPIP_SHAKE)) 603 if (!--j) 604 goto err; 605 606 c = ppb_rstr(ppbus); 607 ppb_wdtr(ppbus, 0); 608 609 *bp++= trecvh[cl] | trecvl[c]; 610 611 j = LPMAXSPIN2; 612 while (!((cl = ppb_rstr(ppbus)) & LPIP_SHAKE)) { 613 if (cl != c && 614 (((cl = ppb_rstr(ppbus)) ^ 0xb8) & 0xf8) == 615 (c & 0xf8)) 616 goto end; 617 if (!--j) 618 goto err; 619 } 620 } 621 622 end: 623 len = bp - sc->sc_ifbuf; 624 if (len <= LPIPHDRLEN) 625 goto err; 626 627 sc->sc_iferrs = 0; 628 629 len -= LPIPHDRLEN; 630 sc->sc_ifp->if_ipackets++; 631 sc->sc_ifp->if_ibytes += len; 632 top = m_devget(sc->sc_ifbuf + LPIPHDRLEN, len, 0, sc->sc_ifp, 633 0); 634 if (top) { 635 ppb_unlock(ppbus); 636 if (bpf_peers_present(sc->sc_ifp->if_bpf)) 637 lptap(sc->sc_ifp, top); 638 639 /* mbuf is free'd on failure. */ 640 netisr_queue(NETISR_IP, top); 641 ppb_lock(ppbus); 642 } 643 } 644 return; 645 646 err: 647 ppb_wdtr(ppbus, 0); 648 lprintf("R"); 649 sc->sc_ifp->if_ierrors++; 650 sc->sc_iferrs++; 651 652 /* 653 * We are not able to send receive anything for now, 654 * so stop wasting our time 655 */ 656 if (sc->sc_iferrs > LPMAXERRS) { 657 if_printf(sc->sc_ifp, "Too many errors, Going off-line.\n"); 658 ppb_wctr(ppbus, 0x00); 659 sc->sc_ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 660 sc->sc_iferrs = 0; 661 } 662 } 663 664 static __inline int 665 lpoutbyte(u_char byte, int spin, device_t ppbus) 666 { 667 668 ppb_wdtr(ppbus, txmith[byte]); 669 while (!(ppb_rstr(ppbus) & LPIP_SHAKE)) 670 if (--spin == 0) 671 return (1); 672 ppb_wdtr(ppbus, txmitl[byte]); 673 while (ppb_rstr(ppbus) & LPIP_SHAKE) 674 if (--spin == 0) 675 return (1); 676 return (0); 677 } 678 679 static int 680 lpoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 681 struct rtentry *rt) 682 { 683 struct lp_data *sc = ifp->if_softc; 684 device_t dev = sc->sc_dev; 685 device_t ppbus = device_get_parent(dev); 686 int err; 687 struct mbuf *mm; 688 u_char *cp = "\0\0"; 689 u_char chksum = 0; 690 int count = 0; 691 int i, len, spin; 692 693 /* We need a sensible value if we abort */ 694 cp++; 695 ppb_lock(ppbus); 696 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 697 698 err = 1; /* assume we're aborting because of an error */ 699 700 /* Suspend (on laptops) or receive-errors might have taken us offline */ 701 ppb_wctr(ppbus, IRQENABLE); 702 703 if (ifp->if_flags & IFF_LINK0) { 704 if (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) { 705 lprintf("&"); 706 lp_intr(sc); 707 } 708 709 /* Alert other end to pending packet */ 710 spin = LPMAXSPIN1; 711 ppb_wdtr(ppbus, 0x08); 712 while ((ppb_rstr(ppbus) & 0x08) == 0) 713 if (--spin == 0) { 714 goto nend; 715 } 716 717 /* Calculate length of packet, then send that */ 718 719 count += 14; /* Ethernet header len */ 720 721 mm = m; 722 for (mm = m; mm; mm = mm->m_next) { 723 count += mm->m_len; 724 } 725 if (clpoutbyte(count & 0xFF, LPMAXSPIN1, ppbus)) 726 goto nend; 727 if (clpoutbyte((count >> 8) & 0xFF, LPMAXSPIN1, ppbus)) 728 goto nend; 729 730 /* Send dummy ethernet header */ 731 for (i = 0; i < 12; i++) { 732 if (clpoutbyte(i, LPMAXSPIN1, ppbus)) 733 goto nend; 734 chksum += i; 735 } 736 737 if (clpoutbyte(0x08, LPMAXSPIN1, ppbus)) 738 goto nend; 739 if (clpoutbyte(0x00, LPMAXSPIN1, ppbus)) 740 goto nend; 741 chksum += 0x08 + 0x00; /* Add into checksum */ 742 743 mm = m; 744 do { 745 cp = mtod(mm, u_char *); 746 len = mm->m_len; 747 while (len--) { 748 chksum += *cp; 749 if (clpoutbyte(*cp++, LPMAXSPIN2, ppbus)) 750 goto nend; 751 } 752 } while ((mm = mm->m_next)); 753 754 /* Send checksum */ 755 if (clpoutbyte(chksum, LPMAXSPIN2, ppbus)) 756 goto nend; 757 758 /* Go quiescent */ 759 ppb_wdtr(ppbus, 0); 760 761 err = 0; /* No errors */ 762 763 nend: 764 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 765 if (err) { /* if we didn't timeout... */ 766 ifp->if_oerrors++; 767 lprintf("X"); 768 } else { 769 ifp->if_opackets++; 770 ifp->if_obytes += m->m_pkthdr.len; 771 if (bpf_peers_present(ifp->if_bpf)) 772 lptap(ifp, m); 773 } 774 775 m_freem(m); 776 777 if (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) { 778 lprintf("^"); 779 lp_intr(sc); 780 } 781 ppb_unlock(ppbus); 782 return (0); 783 } 784 785 if (ppb_rstr(ppbus) & LPIP_SHAKE) { 786 lprintf("&"); 787 lp_intr(sc); 788 } 789 790 if (lpoutbyte(0x08, LPMAXSPIN1, ppbus)) 791 goto end; 792 if (lpoutbyte(0x00, LPMAXSPIN2, ppbus)) 793 goto end; 794 795 mm = m; 796 do { 797 cp = mtod(mm, u_char *); 798 len = mm->m_len; 799 while (len--) 800 if (lpoutbyte(*cp++, LPMAXSPIN2, ppbus)) 801 goto end; 802 } while ((mm = mm->m_next)); 803 804 err = 0; /* no errors were encountered */ 805 806 end: 807 --cp; 808 ppb_wdtr(ppbus, txmitl[*cp] ^ 0x17); 809 810 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 811 if (err) { /* if we didn't timeout... */ 812 ifp->if_oerrors++; 813 lprintf("X"); 814 } else { 815 ifp->if_opackets++; 816 ifp->if_obytes += m->m_pkthdr.len; 817 if (bpf_peers_present(ifp->if_bpf)) 818 lptap(ifp, m); 819 } 820 821 m_freem(m); 822 823 if (ppb_rstr(ppbus) & LPIP_SHAKE) { 824 lprintf("^"); 825 lp_intr(sc); 826 } 827 828 ppb_unlock(ppbus); 829 return (0); 830 } 831 832 static device_method_t lp_methods[] = { 833 /* device interface */ 834 DEVMETHOD(device_identify, lp_identify), 835 DEVMETHOD(device_probe, lp_probe), 836 DEVMETHOD(device_attach, lp_attach), 837 DEVMETHOD(device_detach, lp_detach), 838 839 { 0, 0 } 840 }; 841 842 static driver_t lp_driver = { 843 "plip", 844 lp_methods, 845 sizeof(struct lp_data), 846 }; 847 848 DRIVER_MODULE(plip, ppbus, lp_driver, lp_devclass, lp_module_handler, 0); 849 MODULE_DEPEND(plip, ppbus, 1, 1, 1); 850