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 #include <net/route.h> 103 104 #include <netinet/in.h> 105 #include <netinet/in_var.h> 106 107 #include <net/bpf.h> 108 109 #include <dev/ppbus/ppbconf.h> 110 #include "ppbus_if.h" 111 #include <dev/ppbus/ppbio.h> 112 113 #ifndef LPMTU /* MTU for the lp# interfaces */ 114 #define LPMTU 1500 115 #endif 116 117 #ifndef LPMAXSPIN1 /* DELAY factor for the lp# interfaces */ 118 #define LPMAXSPIN1 8000 /* Spinning for remote intr to happen */ 119 #endif 120 121 #ifndef LPMAXSPIN2 /* DELAY factor for the lp# interfaces */ 122 #define LPMAXSPIN2 500 /* Spinning for remote handshake to happen */ 123 #endif 124 125 #ifndef LPMAXERRS /* Max errors before !RUNNING */ 126 #define LPMAXERRS 100 127 #endif 128 129 #define CLPIPHDRLEN 14 /* We send dummy ethernet addresses (two) + packet type in front of packet */ 130 #define CLPIP_SHAKE 0x80 /* This bit toggles between nibble reception */ 131 #define MLPIPHDRLEN CLPIPHDRLEN 132 133 #define LPIPHDRLEN 2 /* We send 0x08, 0x00 in front of packet */ 134 #define LPIP_SHAKE 0x40 /* This bit toggles between nibble reception */ 135 #if !defined(MLPIPHDRLEN) || LPIPHDRLEN > MLPIPHDRLEN 136 #define MLPIPHDRLEN LPIPHDRLEN 137 #endif 138 139 #define LPIPTBLSIZE 256 /* Size of octet translation table */ 140 141 #define lprintf if (lptflag) printf 142 143 #ifdef PLIP_DEBUG 144 static int volatile lptflag = 1; 145 #else 146 static int volatile lptflag = 0; 147 #endif 148 149 struct lp_data { 150 struct ifnet *sc_ifp; 151 device_t sc_dev; 152 u_char *sc_ifbuf; 153 int sc_iferrs; 154 155 struct resource *res_irq; 156 void *sc_intr_cookie; 157 }; 158 159 static struct mtx lp_tables_lock; 160 MTX_SYSINIT(lp_tables, &lp_tables_lock, "plip tables", MTX_DEF); 161 162 /* Tables for the lp# interface */ 163 static u_char *txmith; 164 #define txmitl (txmith + (1 * LPIPTBLSIZE)) 165 #define trecvh (txmith + (2 * LPIPTBLSIZE)) 166 #define trecvl (txmith + (3 * LPIPTBLSIZE)) 167 168 static u_char *ctxmith; 169 #define ctxmitl (ctxmith + (1 * LPIPTBLSIZE)) 170 #define ctrecvh (ctxmith + (2 * LPIPTBLSIZE)) 171 #define ctrecvl (ctxmith + (3 * LPIPTBLSIZE)) 172 173 /* Functions for the lp# interface */ 174 static int lpinittables(void); 175 static int lpioctl(struct ifnet *, u_long, caddr_t); 176 static int lpoutput(struct ifnet *, struct mbuf *, struct sockaddr *, 177 struct route *); 178 static void lpstop(struct lp_data *); 179 static void lp_intr(void *); 180 static int lp_module_handler(module_t, int, void *); 181 182 #define DEVTOSOFTC(dev) \ 183 ((struct lp_data *)device_get_softc(dev)) 184 185 static devclass_t lp_devclass; 186 187 static int 188 lp_module_handler(module_t mod, int what, void *arg) 189 { 190 191 switch (what) { 192 case MOD_UNLOAD: 193 mtx_lock(&lp_tables_lock); 194 if (txmith != NULL) { 195 free(txmith, M_DEVBUF); 196 txmith = NULL; 197 } 198 if (ctxmith != NULL) { 199 free(ctxmith, M_DEVBUF); 200 ctxmith = NULL; 201 } 202 mtx_unlock(&lp_tables_lock); 203 break; 204 case MOD_LOAD: 205 case MOD_QUIESCE: 206 break; 207 default: 208 return (EOPNOTSUPP); 209 } 210 return (0); 211 } 212 213 static void 214 lp_identify(driver_t *driver, device_t parent) 215 { 216 device_t dev; 217 218 dev = device_find_child(parent, "plip", -1); 219 if (!dev) 220 BUS_ADD_CHILD(parent, 0, "plip", -1); 221 } 222 223 static int 224 lp_probe(device_t dev) 225 { 226 227 device_set_desc(dev, "PLIP network interface"); 228 229 return (0); 230 } 231 232 static int 233 lp_attach(device_t dev) 234 { 235 struct lp_data *lp = DEVTOSOFTC(dev); 236 struct ifnet *ifp; 237 int error, rid = 0; 238 239 lp->sc_dev = dev; 240 241 /* 242 * Reserve the interrupt resource. If we don't have one, the 243 * attach fails. 244 */ 245 lp->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 246 RF_SHAREABLE); 247 if (lp->res_irq == 0) { 248 device_printf(dev, "cannot reserve interrupt, failed.\n"); 249 return (ENXIO); 250 } 251 252 ifp = lp->sc_ifp = if_alloc(IFT_PARA); 253 if (ifp == NULL) { 254 return (ENOSPC); 255 } 256 257 ifp->if_softc = lp; 258 if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 259 ifp->if_mtu = LPMTU; 260 ifp->if_flags = IFF_SIMPLEX | IFF_POINTOPOINT | IFF_MULTICAST; 261 ifp->if_ioctl = lpioctl; 262 ifp->if_output = lpoutput; 263 ifp->if_hdrlen = 0; 264 ifp->if_addrlen = 0; 265 ifp->if_snd.ifq_maxlen = ifqmaxlen; 266 if_attach(ifp); 267 268 bpfattach(ifp, DLT_NULL, sizeof(u_int32_t)); 269 270 /* 271 * Attach our interrupt handler. It is only called while we 272 * own the ppbus. 273 */ 274 error = bus_setup_intr(dev, lp->res_irq, INTR_TYPE_NET | INTR_MPSAFE, 275 NULL, lp_intr, lp, &lp->sc_intr_cookie); 276 if (error) { 277 bpfdetach(ifp); 278 if_detach(ifp); 279 bus_release_resource(dev, SYS_RES_IRQ, 0, lp->res_irq); 280 device_printf(dev, "Unable to register interrupt handler\n"); 281 return (error); 282 } 283 284 return (0); 285 } 286 287 static int 288 lp_detach(device_t dev) 289 { 290 struct lp_data *sc = device_get_softc(dev); 291 device_t ppbus = device_get_parent(dev); 292 293 ppb_lock(ppbus); 294 lpstop(sc); 295 ppb_unlock(ppbus); 296 bpfdetach(sc->sc_ifp); 297 if_detach(sc->sc_ifp); 298 bus_teardown_intr(dev, sc->res_irq, sc->sc_intr_cookie); 299 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->res_irq); 300 return (0); 301 } 302 303 /* 304 * Build the translation tables for the LPIP (BSD unix) protocol. 305 * We don't want to calculate these nasties in our tight loop, so we 306 * precalculate them when we initialize. 307 */ 308 static int 309 lpinittables(void) 310 { 311 int i; 312 313 mtx_lock(&lp_tables_lock); 314 if (txmith == NULL) 315 txmith = malloc(4 * LPIPTBLSIZE, M_DEVBUF, M_NOWAIT); 316 317 if (txmith == NULL) { 318 mtx_unlock(&lp_tables_lock); 319 return (1); 320 } 321 322 if (ctxmith == NULL) 323 ctxmith = malloc(4 * LPIPTBLSIZE, M_DEVBUF, M_NOWAIT); 324 325 if (ctxmith == NULL) { 326 mtx_unlock(&lp_tables_lock); 327 return (1); 328 } 329 330 for (i = 0; i < LPIPTBLSIZE; i++) { 331 ctxmith[i] = (i & 0xF0) >> 4; 332 ctxmitl[i] = 0x10 | (i & 0x0F); 333 ctrecvh[i] = (i & 0x78) << 1; 334 ctrecvl[i] = (i & 0x78) >> 3; 335 } 336 337 for (i = 0; i < LPIPTBLSIZE; i++) { 338 txmith[i] = ((i & 0x80) >> 3) | ((i & 0x70) >> 4) | 0x08; 339 txmitl[i] = ((i & 0x08) << 1) | (i & 0x07); 340 trecvh[i] = ((~i) & 0x80) | ((i & 0x38) << 1); 341 trecvl[i] = (((~i) & 0x80) >> 4) | ((i & 0x38) >> 3); 342 } 343 mtx_unlock(&lp_tables_lock); 344 345 return (0); 346 } 347 348 static void 349 lpstop(struct lp_data *sc) 350 { 351 device_t ppbus = device_get_parent(sc->sc_dev); 352 353 ppb_assert_locked(ppbus); 354 ppb_wctr(ppbus, 0x00); 355 sc->sc_ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 356 free(sc->sc_ifbuf, M_DEVBUF); 357 sc->sc_ifbuf = NULL; 358 359 /* IFF_UP is not set, try to release the bus anyway */ 360 ppb_release_bus(ppbus, sc->sc_dev); 361 } 362 363 static int 364 lpinit_locked(struct ifnet *ifp) 365 { 366 struct lp_data *sc = ifp->if_softc; 367 device_t dev = sc->sc_dev; 368 device_t ppbus = device_get_parent(dev); 369 int error; 370 371 ppb_assert_locked(ppbus); 372 error = ppb_request_bus(ppbus, dev, PPB_DONTWAIT); 373 if (error) 374 return (error); 375 376 /* Now IFF_UP means that we own the bus */ 377 ppb_set_mode(ppbus, PPB_COMPATIBLE); 378 379 if (lpinittables()) { 380 ppb_release_bus(ppbus, dev); 381 return (ENOBUFS); 382 } 383 384 sc->sc_ifbuf = malloc(sc->sc_ifp->if_mtu + MLPIPHDRLEN, 385 M_DEVBUF, M_NOWAIT); 386 if (sc->sc_ifbuf == NULL) { 387 ppb_release_bus(ppbus, dev); 388 return (ENOBUFS); 389 } 390 391 ppb_wctr(ppbus, IRQENABLE); 392 393 ifp->if_drv_flags |= IFF_DRV_RUNNING; 394 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 395 return (0); 396 } 397 398 /* 399 * Process an ioctl request. 400 */ 401 static int 402 lpioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 403 { 404 struct lp_data *sc = ifp->if_softc; 405 device_t dev = sc->sc_dev; 406 device_t ppbus = device_get_parent(dev); 407 struct ifaddr *ifa = (struct ifaddr *)data; 408 struct ifreq *ifr = (struct ifreq *)data; 409 u_char *ptr; 410 int error; 411 412 switch (cmd) { 413 case SIOCSIFDSTADDR: 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 == 0) { 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 541 /* Ack. the request */ 542 ppb_wdtr(ppbus, 0x01); 543 544 /* Get the packet length */ 545 j = clpinbyte(LPMAXSPIN2, ppbus); 546 if (j == -1) 547 goto err; 548 len = j; 549 j = clpinbyte(LPMAXSPIN2, ppbus); 550 if (j == -1) 551 goto err; 552 len = len + (j << 8); 553 if (len > sc->sc_ifp->if_mtu + MLPIPHDRLEN) 554 goto err; 555 556 bp = sc->sc_ifbuf; 557 558 while (len--) { 559 j = clpinbyte(LPMAXSPIN2, ppbus); 560 if (j == -1) { 561 goto err; 562 } 563 *bp++ = j; 564 } 565 566 /* Get and ignore checksum */ 567 j = clpinbyte(LPMAXSPIN2, ppbus); 568 if (j == -1) { 569 goto err; 570 } 571 572 len = bp - sc->sc_ifbuf; 573 if (len <= CLPIPHDRLEN) 574 goto err; 575 576 sc->sc_iferrs = 0; 577 578 len -= CLPIPHDRLEN; 579 sc->sc_ifp->if_ipackets++; 580 sc->sc_ifp->if_ibytes += len; 581 top = m_devget(sc->sc_ifbuf + CLPIPHDRLEN, len, 0, sc->sc_ifp, 582 0); 583 if (top) { 584 ppb_unlock(ppbus); 585 if (bpf_peers_present(sc->sc_ifp->if_bpf)) 586 lptap(sc->sc_ifp, top); 587 588 /* mbuf is free'd on failure. */ 589 netisr_queue(NETISR_IP, top); 590 ppb_lock(ppbus); 591 } 592 return; 593 } 594 while ((ppb_rstr(ppbus) & LPIP_SHAKE)) { 595 len = sc->sc_ifp->if_mtu + LPIPHDRLEN; 596 bp = sc->sc_ifbuf; 597 while (len--) { 598 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 sc->sc_ifp->if_ipackets++; 632 sc->sc_ifp->if_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 /* mbuf is free'd on failure. */ 641 netisr_queue(NETISR_IP, top); 642 ppb_lock(ppbus); 643 } 644 } 645 return; 646 647 err: 648 ppb_wdtr(ppbus, 0); 649 lprintf("R"); 650 sc->sc_ifp->if_ierrors++; 651 sc->sc_iferrs++; 652 653 /* 654 * We are not able to send receive anything for now, 655 * so stop wasting our time 656 */ 657 if (sc->sc_iferrs > LPMAXERRS) { 658 if_printf(sc->sc_ifp, "Too many errors, Going off-line.\n"); 659 ppb_wctr(ppbus, 0x00); 660 sc->sc_ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 661 sc->sc_iferrs = 0; 662 } 663 } 664 665 static __inline int 666 lpoutbyte(u_char byte, int spin, device_t ppbus) 667 { 668 669 ppb_wdtr(ppbus, txmith[byte]); 670 while (!(ppb_rstr(ppbus) & LPIP_SHAKE)) 671 if (--spin == 0) 672 return (1); 673 ppb_wdtr(ppbus, txmitl[byte]); 674 while (ppb_rstr(ppbus) & LPIP_SHAKE) 675 if (--spin == 0) 676 return (1); 677 return (0); 678 } 679 680 static int 681 lpoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 682 struct route *ro) 683 { 684 struct lp_data *sc = ifp->if_softc; 685 device_t dev = sc->sc_dev; 686 device_t ppbus = device_get_parent(dev); 687 int err; 688 struct mbuf *mm; 689 u_char *cp = "\0\0"; 690 u_char chksum = 0; 691 int count = 0; 692 int i, len, spin; 693 694 /* We need a sensible value if we abort */ 695 cp++; 696 ppb_lock(ppbus); 697 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 698 699 err = 1; /* assume we're aborting because of an error */ 700 701 /* Suspend (on laptops) or receive-errors might have taken us offline */ 702 ppb_wctr(ppbus, IRQENABLE); 703 704 if (ifp->if_flags & IFF_LINK0) { 705 if (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) { 706 lprintf("&"); 707 lp_intr(sc); 708 } 709 710 /* Alert other end to pending packet */ 711 spin = LPMAXSPIN1; 712 ppb_wdtr(ppbus, 0x08); 713 while ((ppb_rstr(ppbus) & 0x08) == 0) 714 if (--spin == 0) { 715 goto nend; 716 } 717 718 /* Calculate length of packet, then send that */ 719 720 count += 14; /* Ethernet header len */ 721 722 mm = m; 723 for (mm = m; mm; mm = mm->m_next) { 724 count += mm->m_len; 725 } 726 if (clpoutbyte(count & 0xFF, LPMAXSPIN1, ppbus)) 727 goto nend; 728 if (clpoutbyte((count >> 8) & 0xFF, LPMAXSPIN1, ppbus)) 729 goto nend; 730 731 /* Send dummy ethernet header */ 732 for (i = 0; i < 12; i++) { 733 if (clpoutbyte(i, LPMAXSPIN1, ppbus)) 734 goto nend; 735 chksum += i; 736 } 737 738 if (clpoutbyte(0x08, LPMAXSPIN1, ppbus)) 739 goto nend; 740 if (clpoutbyte(0x00, LPMAXSPIN1, ppbus)) 741 goto nend; 742 chksum += 0x08 + 0x00; /* Add into checksum */ 743 744 mm = m; 745 do { 746 cp = mtod(mm, u_char *); 747 len = mm->m_len; 748 while (len--) { 749 chksum += *cp; 750 if (clpoutbyte(*cp++, LPMAXSPIN2, ppbus)) 751 goto nend; 752 } 753 } while ((mm = mm->m_next)); 754 755 /* Send checksum */ 756 if (clpoutbyte(chksum, LPMAXSPIN2, ppbus)) 757 goto nend; 758 759 /* Go quiescent */ 760 ppb_wdtr(ppbus, 0); 761 762 err = 0; /* No errors */ 763 764 nend: 765 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 766 if (err) { /* if we didn't timeout... */ 767 ifp->if_oerrors++; 768 lprintf("X"); 769 } else { 770 ifp->if_opackets++; 771 ifp->if_obytes += m->m_pkthdr.len; 772 if (bpf_peers_present(ifp->if_bpf)) 773 lptap(ifp, m); 774 } 775 776 m_freem(m); 777 778 if (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) { 779 lprintf("^"); 780 lp_intr(sc); 781 } 782 ppb_unlock(ppbus); 783 return (0); 784 } 785 786 if (ppb_rstr(ppbus) & LPIP_SHAKE) { 787 lprintf("&"); 788 lp_intr(sc); 789 } 790 791 if (lpoutbyte(0x08, LPMAXSPIN1, ppbus)) 792 goto end; 793 if (lpoutbyte(0x00, LPMAXSPIN2, ppbus)) 794 goto end; 795 796 mm = m; 797 do { 798 cp = mtod(mm, u_char *); 799 len = mm->m_len; 800 while (len--) 801 if (lpoutbyte(*cp++, LPMAXSPIN2, ppbus)) 802 goto end; 803 } while ((mm = mm->m_next)); 804 805 err = 0; /* no errors were encountered */ 806 807 end: 808 --cp; 809 ppb_wdtr(ppbus, txmitl[*cp] ^ 0x17); 810 811 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 812 if (err) { /* if we didn't timeout... */ 813 ifp->if_oerrors++; 814 lprintf("X"); 815 } else { 816 ifp->if_opackets++; 817 ifp->if_obytes += m->m_pkthdr.len; 818 if (bpf_peers_present(ifp->if_bpf)) 819 lptap(ifp, m); 820 } 821 822 m_freem(m); 823 824 if (ppb_rstr(ppbus) & LPIP_SHAKE) { 825 lprintf("^"); 826 lp_intr(sc); 827 } 828 829 ppb_unlock(ppbus); 830 return (0); 831 } 832 833 static device_method_t lp_methods[] = { 834 /* device interface */ 835 DEVMETHOD(device_identify, lp_identify), 836 DEVMETHOD(device_probe, lp_probe), 837 DEVMETHOD(device_attach, lp_attach), 838 DEVMETHOD(device_detach, lp_detach), 839 840 { 0, 0 } 841 }; 842 843 static driver_t lp_driver = { 844 "plip", 845 lp_methods, 846 sizeof(struct lp_data), 847 }; 848 849 DRIVER_MODULE(plip, ppbus, lp_driver, lp_devclass, lp_module_handler, 0); 850 MODULE_DEPEND(plip, ppbus, 1, 1, 1); 851