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