[BACK]Return to lpt.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / pc532 / dev

Annotation of src/sys/arch/pc532/dev/lpt.c, Revision 1.41

1.41    ! chs         1: /*     $NetBSD: lpt.c,v 1.40 2004/01/23 04:12:39 simonb Exp $  */
1.1       phil        2:
                      3: /*
                      4:  * Copyright (c) 1994 Matthias Pfaller.
1.3       phil        5:  * Copyright (c) 1994 Poul-Henning Kamp
1.27      mycroft     6:  * Copyright (c) 1993, 1994 Charles M. Hannum.
1.1       phil        7:  * Copyright (c) 1990 William F. Jolitz, TeleMuse
                      8:  * All rights reserved.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  * 3. All advertising materials mentioning features or use of this software
                     19:  *    must display the following acknowledgement:
1.40      simonb     20:  *     This software is a component of "386BSD" developed by
1.1       phil       21:  *     William F. Jolitz, TeleMuse.
                     22:  * 4. Neither the name of the developer nor the name "386BSD"
                     23:  *    may be used to endorse or promote products derived from this software
                     24:  *    without specific prior written permission.
                     25:  *
1.29      pk         26:  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND
                     27:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     28:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     29:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE DEVELOPER BE LIABLE
                     30:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     31:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     32:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     33:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     34:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     35:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     36:  * SUCH DAMAGE.
                     37:  */
                     38:
                     39: /*
1.40      simonb     40:  * THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ
                     41:  * AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS
                     42:  * SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT.
                     43:  * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT
1.1       phil       44:  * NOT MAKE USE OF THIS WORK.
                     45:  *
                     46:  * FOR USERS WHO WISH TO UNDERSTAND THE 386BSD SYSTEM DEVELOPED
1.40      simonb     47:  * BY WILLIAM F. JOLITZ, WE RECOMMEND THE USER STUDY WRITTEN
                     48:  * REFERENCES SUCH AS THE  "PORTING UNIX TO THE 386" SERIES
                     49:  * (BEGINNING JANUARY 1991 "DR. DOBBS JOURNAL", USA AND BEGINNING
                     50:  * JUNE 1991 "UNIX MAGAZIN", GERMANY) BY WILLIAM F. JOLITZ AND
                     51:  * LYNNE GREER JOLITZ, AS WELL AS OTHER BOOKS ON UNIX AND THE
                     52:  * ON-LINE 386BSD USER MANUAL BEFORE USE. A BOOK DISCUSSING THE INTERNALS
1.1       phil       53:  * OF 386BSD ENTITLED "386BSD FROM THE INSIDE OUT" WILL BE AVAILABLE LATE 1992.
                     54:  */
                     55:
                     56: /*
                     57:  * Device Driver for Matthias's parallel printer port.
1.3       phil       58:  * This driver is based on the i386 lpt driver and
                     59:  * some IP code from Poul-Henning Kamp.
1.1       phil       60:  */
1.39      lukem      61:
                     62: #include <sys/cdefs.h>
1.41    ! chs        63: __KERNEL_RCSID(0, "$NetBSD: lpt.c,v 1.40 2004/01/23 04:12:39 simonb Exp $");
1.39      lukem      64:
1.26      jonathan   65: #include "opt_inet.h"
1.1       phil       66:
                     67: #include <sys/param.h>
                     68: #include <sys/systm.h>
1.31      thorpej    69: #include <sys/callout.h>
1.1       phil       70: #include <sys/proc.h>
                     71: #include <sys/user.h>
                     72: #include <sys/buf.h>
                     73: #include <sys/kernel.h>
                     74: #include <sys/ioctl.h>
                     75: #include <sys/uio.h>
                     76: #include <sys/device.h>
                     77: #include <sys/syslog.h>
                     78: #include <sys/malloc.h>
1.35      gehenna    79: #include <sys/conf.h>
1.18      matthias   80:
                     81: #include <machine/autoconf.h>
1.6       phil       82:
1.1       phil       83: #if defined(INET) && defined(PLIP)
1.13      matthias   84: #include "bpfilter.h"
1.1       phil       85: #include <sys/mbuf.h>
                     86: #include <sys/socket.h>
1.19      is         87:
1.1       phil       88: #include <net/if.h>
1.13      matthias   89: #include <net/if_dl.h>
1.1       phil       90: #include <net/if_types.h>
1.19      is         91: #include <net/if_ether.h>
                     92:
1.1       phil       93: #include <netinet/in.h>
                     94: #include <netinet/in_systm.h>
                     95: #include <netinet/in_var.h>
                     96: #include <netinet/ip.h>
1.19      is         97: #include <netinet/if_inarp.h>
1.13      matthias   98: #if NBPFILTER > 0
                     99: #include <sys/time.h>
                    100: #include <net/bpf.h>
1.1       phil      101: #endif
1.13      matthias  102: #endif
                    103:
                    104: #include "lpt.h"
                    105: #include "lptreg.h"
1.1       phil      106:
1.3       phil      107: #define        LPT_INVERT      (LPC_NBUSY|LPC_NERROR|LPC_NACK|LPC_ONLINE)
                    108: #define        LPT_MASK        (LPC_NBUSY|LPC_NERROR|LPC_NACK|LPC_NOPAPER|LPC_ONLINE)
                    109:
1.1       phil      110: #define        TIMEOUT         hz*16   /* wait up to 16 seconds for a ready */
                    111: #define        STEP            hz/4
                    112:
                    113: #define        LPTPRI          (PZERO+8)
                    114: #define        LPT_BSIZE       1024
                    115:
                    116: #if defined(INET) && defined(PLIP)
1.3       phil      117: #ifndef PLIPMTU                        /* MTU for the plip# interfaces */
                    118: #if defined(COMPAT_PLIP10)
1.7       jtc       119: #define        PLIPMTU         1600                            /* Linux 1.0.x */
                    120: #elif defined(COMPAT_PLIP11)
                    121: #define        PLIPMTU         (ETHERMTU - ifp->if_hdrlen)     /* Linux 1.1.x */
1.3       phil      122: #else
1.7       jtc       123: #define PLIPMTU                ETHERMTU                        /* Linux 1.3.x */
1.3       phil      124: #endif
1.1       phil      125: #endif
                    126:
1.3       phil      127: #ifndef PLIPMXSPIN1            /* DELAY factor for the plip# interfaces */
1.23      matthias  128: #define        PLIPMXSPIN1     50000   /* Spinning for remote intr to happen */
1.1       phil      129: #endif
                    130:
1.3       phil      131: #ifndef PLIPMXSPIN2            /* DELAY factor for the plip# interfaces */
1.23      matthias  132: #define        PLIPMXSPIN2     50000   /* Spinning for remote handshake to happen */
1.1       phil      133: #endif
                    134:
                    135: #ifndef PLIPMXERRS             /* Max errors before !RUNNING */
1.4       phil      136: #define        PLIPMXERRS      20
1.1       phil      137: #endif
                    138: #ifndef PLIPMXRETRY
                    139: #define PLIPMXRETRY    20      /* Max number of retransmits */
                    140: #endif
                    141: #ifndef PLIPRETRY
                    142: #define PLIPRETRY      hz/50   /* Time between retransmits */
                    143: #endif
                    144: #endif
                    145:
                    146: struct lpt_softc {
                    147:        struct device sc_dev;
                    148:        size_t sc_count;
                    149:        u_char *sc_inbuf;
                    150:        u_char *sc_cp;
                    151:        volatile struct i8255 *sc_i8255;
                    152:        int sc_irq;
                    153:        u_char sc_state;
                    154: #define        LPT_OPEN        0x01    /* device is open */
                    155: #define        LPT_INIT        0x02    /* waiting to initialize for open */
                    156:
1.6       phil      157:        u_char sc_status;
1.1       phil      158:        u_char sc_flags;
                    159: #define        LPT_AUTOLF      0x20    /* automatic LF on CR */
                    160: #define        LPT_NOPRIME     0x40    /* don't prime on open */
                    161:
1.31      thorpej   162:        struct callout sc_out_ch;
                    163:
1.1       phil      164: #if defined(INET) && defined(PLIP)
1.19      is        165:        struct  ethercom sc_ethercom;
1.31      thorpej   166:        struct  callout sc_plipout_ch;
                    167:        struct  callout sc_pliprx_ch;
1.1       phil      168:        u_char          *sc_ifbuf;
1.4       phil      169:        int             sc_ifierrs;     /* consecutive input errors */
                    170:        int             sc_ifoerrs;     /* consecutive output errors */
1.6       phil      171:        int             sc_ifsoftint;   /* i/o software interrupt */
                    172:        volatile int    sc_pending;     /* interrputs pending */
                    173: #define PLIP_IPENDING  1
                    174: #define PLIP_OPENDING  2
                    175:
1.3       phil      176: #if defined(COMPAT_PLIP10)
1.1       phil      177:        u_char          sc_adrcksum;
                    178: #endif
1.3       phil      179: #endif
1.1       phil      180: };
                    181:
1.3       phil      182: #define        LPTUNIT(s)      (minor(s) & 0x1f)
                    183: #define        LPTFLAGS(s)     (minor(s) & 0xe0)
1.20      matthias  184: #define LPTSOFTC(n)    ((struct lpt_softc *) lpt_cd.cd_devs[n])
1.13      matthias  185:
1.17      matthias  186: static int lptmatch __P((struct device *, struct cfdata *, void *aux));
1.13      matthias  187: static void lptattach __P((struct device *, struct device *, void *));
1.16      matthias  188: static void lptintr __P((void *));
1.13      matthias  189: static int notready __P((u_char, struct lpt_softc *));
1.16      matthias  190: static void lptout __P((void *));
1.13      matthias  191: static int pushbytes __P((struct lpt_softc *));
1.1       phil      192:
                    193: #if defined(INET) && defined(PLIP)
                    194: /* Functions for the plip# interface */
1.23      matthias  195: static void    plipattach __P((struct lpt_softc *,int));
                    196: static void    plipinput __P((struct lpt_softc *));
                    197: static int     plipioctl __P((struct ifnet *, u_long, caddr_t));
                    198: static void    plipoutput __P((void *));
                    199: #ifndef __OPTIMIZE__
                    200: static
                    201: #endif
                    202:        int     plipreceive __P((volatile struct i8255 *, u_char *, int));
                    203: static void    pliprxenable __P((void *));
                    204: static void    plipsoftint __P((void *));
                    205: static void    plipstart __P((struct ifnet *));
                    206: #ifndef __OPTIMIZE__
                    207: static
                    208: #endif
                    209:        int     pliptransmit __P((volatile struct i8255 *, u_char *, int));
1.1       phil      210: #endif
                    211:
1.37      thorpej   212: CFATTACH_DECL(lpt, sizeof(struct lpt_softc),
                    213:     lptmatch, lptattach, NULL, NULL);
1.8       thorpej   214:
1.25      thorpej   215: extern struct cfdriver lpt_cd;
1.35      gehenna   216:
                    217: dev_type_open(lptopen);
                    218: dev_type_close(lptclose);
                    219: dev_type_write(lptwrite);
                    220: dev_type_ioctl(lptioctl);
                    221:
                    222: const struct cdevsw lpt_cdevsw = {
                    223:        lptopen, lptclose, noread, lptwrite, lptioctl,
1.38      jdolecek  224:        nostop, notty, nopoll, nommap, nokqfilter,
1.35      gehenna   225: };
1.1       phil      226:
1.13      matthias  227: static int
                    228: lptmatch(parent, cf, aux)
                    229:        struct device *parent;
1.17      matthias  230:        struct cfdata *cf;
                    231:        void *aux;
1.1       phil      232: {
1.18      matthias  233:        struct confargs *ca = aux;
1.1       phil      234:        volatile struct i8255 *i8255 =
1.41    ! chs       235:                (volatile struct i8255 *)cf->cf_addr;
1.1       phil      236:
1.41    ! chs       237:        if (cf->cf_addr == MAINBUSCF_ADDR_DEFAULT)
        !           238:                return 0;
        !           239:        if (cf->cf_irq == MAINBUSCF_IRQ_DEFAULT)
        !           240:                return 0;
1.1       phil      241:
                    242:        i8255->port_control = LPT_PROBE_MODE;
                    243:
                    244:        i8255->port_control = LPT_PROBE_CLR;
1.3       phil      245:        if ((i8255->port_c & LPT_PROBE_MASK) != 0)
1.1       phil      246:                return 0;
1.40      simonb    247:
1.1       phil      248:        i8255->port_control = LPT_PROBE_SET;
1.3       phil      249:        if ((i8255->port_c & LPT_PROBE_MASK) == 0)
1.1       phil      250:                return 0;
                    251:
                    252:        i8255->port_control = LPT_PROBE_CLR;
1.3       phil      253:        if ((i8255->port_c & LPT_PROBE_MASK) != 0)
1.1       phil      254:                return 0;
                    255:
                    256:        i8255->port_control = LPT_MODE;
1.3       phil      257:        i8255->port_a = LPA_ACTIVE | LPA_NPRIME;
1.18      matthias  258:
                    259:        ca->ca_addr = (int)i8255;
                    260:
1.1       phil      261:        return 1;
                    262: }
                    263:
1.13      matthias  264: static void
                    265: lptattach(parent, self, aux)
                    266:        struct device *parent, *self;
                    267:        void *aux;
1.1       phil      268: {
1.18      matthias  269:        struct confargs *ca = aux;
1.1       phil      270:        struct lpt_softc *sc = (struct lpt_softc *) self;
1.18      matthias  271:        volatile struct i8255 *i8255;
1.1       phil      272:
1.18      matthias  273:        printf("\n");
1.1       phil      274:
1.18      matthias  275:        sc->sc_irq = ca->ca_irq;
                    276:        i8255 = (volatile struct i8255 *)ca->ca_addr;
1.1       phil      277:        i8255->port_control = LPT_MODE;
1.3       phil      278:        i8255->port_a = LPA_ACTIVE | LPA_NPRIME;
1.1       phil      279:        i8255->port_control = LPT_IRQDISABLE;
                    280:
                    281:        sc->sc_state = 0;
                    282:        sc->sc_i8255 = i8255;
                    283:
1.31      thorpej   284:        callout_init(&sc->sc_out_ch);
                    285:
1.6       phil      286: #if defined(INET) && defined(PLIP)
1.1       phil      287:        plipattach(sc, self->dv_unit);
1.6       phil      288: #endif
1.5       phil      289:        intr_establish(sc->sc_irq, lptintr, sc, sc->sc_dev.dv_xname,
1.23      matthias  290:                        IPL_ZERO, IPL_ZERO, LOW_LEVEL);
1.1       phil      291: }
                    292:
                    293: /*
                    294:  * Reset the printer, then wait until it's selected and not busy.
                    295:  */
                    296: int
1.13      matthias  297: lptopen(dev, flag, mode, p)
                    298:        dev_t dev;
                    299:        int flag;
                    300:        int mode;
                    301:        struct proc *p;
1.1       phil      302: {
1.20      matthias  303:        struct lpt_softc *sc;
                    304:        volatile struct i8255 *i8255;
1.1       phil      305:        u_char flags = LPTFLAGS(dev);
                    306:        int error;
                    307:        int spin;
                    308:
1.20      matthias  309:        if (LPTUNIT(dev) >= lpt_cd.cd_ndevs)
                    310:                return ENXIO;
                    311:
                    312:        sc = LPTSOFTC(LPTUNIT(dev));
                    313:        if (!sc)
1.1       phil      314:                return ENXIO;
                    315:
1.6       phil      316:        if (sc->sc_state)
1.1       phil      317:                return EBUSY;
                    318:
1.20      matthias  319:        i8255 = sc->sc_i8255;
1.6       phil      320: #if defined(INET) && defined(PLIP)
1.19      is        321:        if (sc->sc_ethercom.ec_if.if_flags & IFF_UP)
1.6       phil      322:                return EBUSY;
                    323: #endif
                    324:
1.1       phil      325:        sc->sc_state = LPT_INIT;
                    326:        sc->sc_flags = flags;
                    327:
                    328:        if ((flags & LPT_NOPRIME) == 0) {
                    329:                /* assert INIT for 100 usec to start up printer */
1.3       phil      330:                i8255->port_a &= ~LPA_NPRIME;
1.1       phil      331:                DELAY(100);
                    332:        }
                    333:
                    334:        if (flags & LPT_AUTOLF)
1.3       phil      335:                i8255->port_a |= LPA_ALF | LPA_SELECT | LPA_NPRIME;
1.1       phil      336:        else
1.3       phil      337:                i8255->port_a = (i8255->port_a & ~LPA_ALF)
                    338:                                | LPA_SELECT | LPA_NPRIME;
1.1       phil      339:
                    340:        /* wait till ready (printer running diagnostics) */
1.3       phil      341:        for (spin = 0; notready(i8255->port_c, sc); spin += STEP) {
1.1       phil      342:                if (spin >= TIMEOUT) {
                    343:                        sc->sc_state = 0;
                    344:                        return EBUSY;
                    345:                }
                    346:
                    347:                /* wait 1/4 second, give up if we get a signal */
1.20      matthias  348:                error = tsleep((caddr_t)sc, LPTPRI | PCATCH, "lptopen", STEP);
                    349:                if (error != EWOULDBLOCK) {
1.1       phil      350:                        sc->sc_state = 0;
                    351:                        return error;
                    352:                }
                    353:        }
                    354:
                    355:        sc->sc_inbuf  = malloc(LPT_BSIZE, M_DEVBUF, M_WAITOK);
                    356:        sc->sc_status =
                    357:        sc->sc_count  = 0;
                    358:        sc->sc_state  = LPT_OPEN;
                    359:
                    360:        return 0;
                    361: }
                    362:
1.13      matthias  363: static int
                    364: notready(status, sc)
                    365:        u_char status;
                    366:        struct lpt_softc *sc;
1.1       phil      367: {
                    368:        status ^= LPT_INVERT;
                    369:
                    370:        if (status != sc->sc_status) {
                    371:                if (status & LPC_NOPAPER)
                    372:                        log(LOG_NOTICE, "%s: out of paper\n", sc->sc_dev.dv_xname);
1.3       phil      373:                if (status & LPC_ONLINE)
1.1       phil      374:                        log(LOG_NOTICE, "%s: offline\n", sc->sc_dev.dv_xname);
1.3       phil      375:                if (status & LPC_NERROR)
1.1       phil      376:                        log(LOG_NOTICE, "%s: output error\n", sc->sc_dev.dv_xname);
1.3       phil      377:                if (status & LPC_NACK)
                    378:                        log(LOG_NOTICE, "%s: NACK low\n", sc->sc_dev.dv_xname);
                    379:                if (status & LPC_NBUSY)
                    380:                        log(LOG_NOTICE, "%s: NBUSY low\n", sc->sc_dev.dv_xname);
1.1       phil      381:                sc->sc_status = status;
                    382:        }
                    383:        return status & LPT_MASK;
                    384: }
                    385:
1.13      matthias  386: static void
                    387: lptout(arg)
                    388:        void *arg;
1.1       phil      389: {
1.16      matthias  390:        struct lpt_softc *sc = arg;
1.3       phil      391:        if (sc->sc_count > 0)
1.1       phil      392:                sc->sc_i8255->port_control = LPT_IRQENABLE;
                    393: }
                    394:
                    395: /*
                    396:  * Close the device, and free the local line buffer.
                    397:  */
1.13      matthias  398: int
                    399: lptclose(dev, flag, mode, p)
                    400:        dev_t dev;
                    401:        int flag;
                    402:        int mode;
                    403:        struct proc *p;
1.1       phil      404: {
1.20      matthias  405:        struct lpt_softc *sc = LPTSOFTC(LPTUNIT(dev));
1.1       phil      406:
                    407:        if (sc->sc_count)
                    408:                (void) pushbytes(sc);
                    409:
                    410:        sc->sc_i8255->port_control = LPT_IRQDISABLE;
                    411:        sc->sc_state = 0;
                    412:        free(sc->sc_inbuf, M_DEVBUF);
                    413:
                    414:        return 0;
                    415: }
                    416:
1.13      matthias  417: static int
                    418: pushbytes(sc)
                    419:        struct lpt_softc *sc;
1.1       phil      420: {
                    421:        volatile struct i8255 *i8255 = sc->sc_i8255;
                    422:        int error;
                    423:
                    424:        while (sc->sc_count > 0) {
                    425:                i8255->port_control = LPT_IRQENABLE;
1.20      matthias  426:                error = tsleep((caddr_t)sc, LPTPRI | PCATCH, "lptwrite", 0);
1.40      simonb    427:                if (error != 0)
1.1       phil      428:                        return error;
                    429:        }
                    430:        return 0;
                    431: }
                    432:
1.40      simonb    433: /*
1.3       phil      434:  * Copy a line from user space to a local buffer, then call pushbytes to
                    435:  * get the chars moved to the output queue.
1.1       phil      436:  */
1.13      matthias  437: int
                    438: lptwrite(dev, uio, flags)
                    439:        dev_t dev;
                    440:        struct uio *uio;
                    441:        int flags;
1.1       phil      442: {
1.20      matthias  443:        struct lpt_softc *sc = LPTSOFTC(LPTUNIT(dev));
1.1       phil      444:        size_t n;
                    445:        int error = 0;
                    446:
                    447:        if (sc->sc_count) return EBUSY;
1.20      matthias  448:        while ((n = min(LPT_BSIZE, uio->uio_resid)) != 0) {
1.1       phil      449:                uiomove(sc->sc_cp = sc->sc_inbuf, n, uio);
                    450:                sc->sc_count = n;
                    451:                error = pushbytes(sc);
                    452:                if (error) {
                    453:                        /*
                    454:                         * Return accurate residual if interrupted or timed
                    455:                         * out.
                    456:                         */
                    457:                        uio->uio_resid += sc->sc_count;
                    458:                        sc->sc_count = 0;
                    459:                        return error;
                    460:                }
                    461:        }
                    462:        return 0;
                    463: }
                    464:
                    465: /*
                    466:  * Handle printer interrupts which occur when the printer is ready to accept
                    467:  * another char.
                    468:  */
1.13      matthias  469: static void
1.16      matthias  470: lptintr(arg)
                    471:        void *arg;
1.1       phil      472: {
1.16      matthias  473:        struct lpt_softc *sc = arg;
1.1       phil      474:        volatile struct i8255 *i8255 = sc->sc_i8255;
                    475:
                    476: #if defined(INET) && defined(PLIP)
1.19      is        477:        if (sc->sc_ethercom.ec_if.if_flags & IFF_UP) {
1.6       phil      478:                i8255->port_a &= ~LPA_ACKENABLE;
                    479:                sc->sc_pending |= PLIP_IPENDING;
                    480:                softintr(sc->sc_ifsoftint);
1.3       phil      481:                return;
1.1       phil      482:        }
                    483: #endif
                    484:
                    485:        if ((sc->sc_state & LPT_OPEN) == 0) {
                    486:                i8255->port_control = LPT_IRQDISABLE;
1.3       phil      487:                return;
1.1       phil      488:        }
                    489:
                    490:        if (sc->sc_count) {
                    491:                /* is printer online and ready for output? */
1.3       phil      492:                if (notready(i8255->port_c, sc)) {
1.1       phil      493:                        i8255->port_control = LPT_IRQDISABLE;
1.31      thorpej   494:                        callout_reset(&sc->sc_out_ch, STEP, lptout, sc);
1.3       phil      495:                        return;
1.1       phil      496:                }
                    497:                /* send char */
1.3       phil      498:                i8255->port_a &= ~LPA_ACTIVE;
                    499:                i8255->port_b = *sc->sc_cp++;
1.1       phil      500:                i8255->port_a |= LPA_ACTIVE;
                    501:                sc->sc_count--;
                    502:        }
                    503:
                    504:        if (sc->sc_count == 0) {
                    505:                /* none, wake up the top half to get more */
                    506:                i8255->port_control = LPT_IRQDISABLE;
                    507:                wakeup((caddr_t)sc);
                    508:        }
                    509: }
                    510:
                    511: int
1.13      matthias  512: lptioctl(dev, cmd, data, flag, p)
                    513:        dev_t dev;
                    514:        u_long cmd;
                    515:        caddr_t data;
                    516:        int flag;
                    517:        struct proc *p;
1.1       phil      518: {
                    519:        int error = 0;
                    520:
                    521:        switch (cmd) {
                    522:        default:
                    523:                error = EINVAL;
                    524:        }
                    525:
                    526:        return error;
                    527: }
                    528:
                    529: #if defined(INET) && defined(PLIP)
                    530:
                    531: static void
1.13      matthias  532: plipattach(sc, unit)
                    533:        struct lpt_softc *sc;
                    534:        int unit;
1.1       phil      535: {
1.19      is        536:        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1.20      matthias  537:        u_int8_t myaddr[ETHER_ADDR_LEN];
1.1       phil      538:
1.31      thorpej   539:        callout_init(&sc->sc_plipout_ch);
                    540:        callout_init(&sc->sc_pliprx_ch);
                    541:
1.1       phil      542:        sc->sc_ifbuf = NULL;
1.15      christos  543:        sprintf(ifp->if_xname, "plip%d", unit);
1.28      matthias  544:        memset(myaddr, 0, sizeof(myaddr));
1.9       thorpej   545:        ifp->if_softc = sc;
1.3       phil      546:        ifp->if_start = plipstart;
                    547:        ifp->if_ioctl = plipioctl;
                    548:        ifp->if_watchdog = 0;
1.13      matthias  549:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
1.3       phil      550:
1.13      matthias  551:        if_attach(ifp);
1.20      matthias  552:        ether_ifattach(ifp, myaddr);
1.1       phil      553:        ifp->if_mtu = PLIPMTU;
1.13      matthias  554:
1.6       phil      555:        sc->sc_ifsoftint = intr_establish(SOFTINT, plipsoftint, sc,
1.17      matthias  556:                                sc->sc_dev.dv_xname, IPL_NET, IPL_ZERO, 0);
1.1       phil      557: }
                    558:
                    559: /*
                    560:  * Process an ioctl request.
                    561:  */
                    562: static int
1.13      matthias  563: plipioctl(ifp, cmd, data)
                    564:        struct ifnet *ifp;
                    565:        u_long cmd;
                    566:        caddr_t data;
1.1       phil      567: {
1.6       phil      568:        struct proc *p = curproc;
1.9       thorpej   569:        struct lpt_softc *sc = (struct lpt_softc *)(ifp->if_softc);
1.1       phil      570:        volatile struct i8255 *i8255 = sc->sc_i8255;
                    571:        struct ifaddr *ifa = (struct ifaddr *)data;
1.40      simonb    572:        struct ifreq *ifr = (struct ifreq *)data;
1.13      matthias  573:        struct sockaddr_dl *sdl;
1.1       phil      574:        int error = 0;
                    575:
                    576:        switch (cmd) {
                    577:        case SIOCSIFFLAGS:
                    578:                if (((ifp->if_flags & IFF_UP) == 0) &&
                    579:                    (ifp->if_flags & IFF_RUNNING)) {
                    580:                        ifp->if_flags &= ~IFF_RUNNING;
                    581:                        sc->sc_i8255->port_control = LPT_MODE;
1.3       phil      582:                        i8255->port_a = LPA_ACTIVE | LPA_NPRIME;
1.1       phil      583:                        if (sc->sc_ifbuf)
                    584:                                free(sc->sc_ifbuf, M_DEVBUF);
                    585:                        sc->sc_ifbuf = NULL;
                    586:                }
                    587:                if (((ifp->if_flags & IFF_UP)) &&
                    588:                    ((ifp->if_flags & IFF_RUNNING) == 0)) {
1.3       phil      589:                        if (sc->sc_state) {
                    590:                                error = EBUSY;
                    591:                                break;
                    592:                        }
1.1       phil      593:                        if (!sc->sc_ifbuf)
                    594:                                sc->sc_ifbuf =
1.3       phil      595:                                        malloc(ifp->if_mtu + ifp->if_hdrlen,
                    596:                                               M_DEVBUF, M_WAITOK);
1.1       phil      597:                        ifp->if_flags |= IFF_RUNNING;
                    598:                        sc->sc_i8255->port_control = LPT_IRQDISABLE;
                    599:                        sc->sc_i8255->port_b = 0;
                    600:                        sc->sc_i8255->port_a |= LPA_ACKENABLE;
                    601:                }
                    602:                break;
                    603:
                    604:        case SIOCSIFADDR:
1.19      is        605:                sdl = ifp->if_sadl;
1.1       phil      606:                if (ifa->ifa_addr->sa_family == AF_INET) {
                    607:                        if (!sc->sc_ifbuf)
                    608:                                sc->sc_ifbuf =
1.3       phil      609:                                        malloc(PLIPMTU + ifp->if_hdrlen,
                    610:                                               M_DEVBUF, M_WAITOK);
1.19      is        611:                        LLADDR(sdl)[0] = 0xfc;
                    612:                        LLADDR(sdl)[1] = 0xfc;
1.28      matthias  613:                        memcpy((caddr_t)&LLADDR(sdl)[2],
                    614:                                (caddr_t)&IA_SIN(ifa)->sin_addr, 4);
1.3       phil      615: #if defined(COMPAT_PLIP10)
1.1       phil      616:                        if (ifp->if_flags & IFF_LINK0) {
                    617:                                int i;
1.19      is        618:                                LLADDR(sdl)[0] = 0xfd;
                    619:                                LLADDR(sdl)[1] = 0xfd;
1.1       phil      620:                                for (i = sc->sc_adrcksum = 0; i < 5; i++)
1.19      is        621:                                        sc->sc_adrcksum += LLADDR(sdl)[i];
1.1       phil      622:                                sc->sc_adrcksum *= 2;
                    623:                        }
1.3       phil      624: #endif
1.13      matthias  625:                        ifp->if_flags |= IFF_RUNNING | IFF_UP;
1.1       phil      626:                        sc->sc_i8255->port_control = LPT_IRQDISABLE;
                    627:                        sc->sc_i8255->port_b = 0;
                    628:                        sc->sc_i8255->port_a |= LPA_ACKENABLE;
1.19      is        629:                        arp_ifinit(ifp, ifa);
1.1       phil      630:                } else
                    631:                        error = EAFNOSUPPORT;
                    632:                break;
                    633:
1.3       phil      634:        case SIOCAIFADDR:
                    635:        case SIOCDIFADDR:
1.1       phil      636:        case SIOCSIFDSTADDR:
                    637:                if (ifa->ifa_addr->sa_family != AF_INET)
                    638:                        error = EAFNOSUPPORT;
                    639:                break;
                    640:
                    641:        case SIOCSIFMTU:
                    642:                if ((error = suser(p->p_ucred, &p->p_acflag)))
1.3       phil      643:                        return(error);
1.11      cgd       644:                if (ifp->if_mtu != ifr->ifr_mtu) {
                    645:                        ifp->if_mtu = ifr->ifr_mtu;
1.1       phil      646:                        if (sc->sc_ifbuf) {
                    647:                                free(sc->sc_ifbuf, M_DEVBUF);
                    648:                                sc->sc_ifbuf =
1.3       phil      649:                                        malloc(ifp->if_mtu + ifp->if_hdrlen,
                    650:                                               M_DEVBUF, M_WAITOK);
1.1       phil      651:                        }
                    652:                }
                    653:                break;
                    654:
                    655:        default:
                    656:                error = EINVAL;
                    657:        }
                    658:        return (error);
                    659: }
                    660:
1.6       phil      661: static void
1.16      matthias  662: plipsoftint(arg)
                    663:        void *arg;
1.6       phil      664: {
1.16      matthias  665:        struct lpt_softc *sc = arg;
1.6       phil      666:        int pending = sc->sc_pending;
                    667:
                    668:        while (sc->sc_pending & PLIP_IPENDING) {
                    669:                pending |= sc->sc_pending;
                    670:                sc->sc_pending = 0;
                    671:                plipinput(sc);
                    672:        }
                    673:
                    674:        if (pending & PLIP_OPENDING)
                    675:                plipoutput(sc);
                    676: }
                    677:
1.13      matthias  678: #ifdef __OPTIMIZE__
1.23      matthias  679: int plipreceive __P((volatile struct i8255 *, u_char *, int))
                    680:        __asm("plipreceive");
1.41    ! chs       681: __asm(" \
        !           682: plipreceive: \
        !           683:        enter   [r3,r4,r5,r6,r7],0 ; \
        !           684:        movqd   0,r0 ; \
        !           685:        movd    8(fp),r1 ; \
        !           686:        movd    12(fp),r2 ; \
        !           687:        movd    16(fp),r3 ; \
        !           688:        cmpqd   0,r3 ; \
        !           689:        beq     5f ; \
        !           690: \
        !           691:        movqd   0,r7 ; \
        !           692:        movd    50000,r4 ; \
        !           693: \
        !           694:        .align  2,0xa2 ; \
        !           695: 0:     movb    8,r5 ; \
        !           696: 1:     movb    2(r1),r6 ; \
        !           697:        andb    r6,r5 ; \
        !           698:        cmpqb   0,r5 ; \
        !           699:        beq     2f ; \
        !           700:        acbd    -1,r4,1b ; \
        !           701:        br      6f ; \
        !           702: \
        !           703:        .align  2,0xa2 ; \
        !           704: 2:     movb    0x11,1(r1) ; \
        !           705:        lshb    -4,r6 ; \
        !           706:        addd    r7,r0 ; \
        !           707:        addqd   1,r2 ; \
        !           708: \
        !           709:        movb    8,r5 ; \
        !           710: 3:     movb    2(r1),r7 ; \
        !           711:        bicb    r7,r5 ; \
        !           712:        cmpqb   0,r5 ; \
        !           713:        beq     4f ; \
        !           714:        acbd    -1,r4,3b ; \
        !           715:        br      6f ; \
        !           716: \
        !           717:        .align  2,0xa2 ; \
        !           718: 4:     movqb   0x01,1(r1) ; \
        !           719:        andb    0xf0,r7 ; \
        !           720:        orb     r6,r7 ; \
        !           721:        movb    r7,-1(r2) ; \
        !           722:        acbd    -1,r3,0b ; \
        !           723: \
        !           724:        addd    r7,r0 ; \
        !           725:        andd    0xff,r0 ; \
        !           726: 5:     exit    [r3,r4,r5,r6,r7] ; \
        !           727:        ret     0 ; \
        !           728: \
        !           729: 6:     movqd   -1,r0 ; \
        !           730:        exit    [r3,r4,r5,r6,r7] ; \
        !           731:        ret     0 \
1.13      matthias  732: ");
                    733: #else
1.1       phil      734: static int
1.13      matthias  735: plipreceive(i8255, buf, len)
                    736:        volatile struct i8255 *i8255;
                    737:        u_char *buf;
                    738:        int len;
1.1       phil      739: {
                    740:        int i;
                    741:        u_char cksum = 0, c;
                    742:
                    743:        while (len--) {
1.3       phil      744:                i = PLIPMXSPIN2;
                    745:                while ((i8255->port_c & LPC_NBUSY) != 0)
                    746:                        if (i-- < 0) return -1;
                    747:                c = i8255->port_c >> 4;
1.1       phil      748:                i8255->port_b = 0x11;
1.3       phil      749:                while ((i8255->port_c & LPC_NBUSY) == 0)
                    750:                        if (i-- < 0) return -1;
                    751:                c |= i8255->port_c & 0xf0;
1.1       phil      752:                i8255->port_b = 0x01;
                    753:                cksum += (*buf++ = c);
                    754:        }
                    755:        return(cksum);
                    756: }
1.13      matthias  757: #endif
1.1       phil      758:
                    759: static void
1.23      matthias  760: pliprxenable(arg)
                    761:        void *arg;
                    762: {
                    763:        struct lpt_softc *sc = arg;
                    764:        volatile struct i8255 *i8255 = sc->sc_i8255;
                    765:        i8255->port_a |= LPA_ACKENABLE | LPA_ACTIVE;
                    766: }
                    767:
                    768: static void
1.13      matthias  769: plipinput(sc)
                    770:        struct lpt_softc *sc;
1.1       phil      771: {
1.19      is        772:        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1.1       phil      773:        volatile struct i8255 *i8255 = sc->sc_i8255;
                    774:        struct mbuf *m;
                    775:        struct ether_header *eh;
                    776:        u_char *p = sc->sc_ifbuf, minibuf[4];
1.20      matthias  777:        int s, len, cksum;
1.1       phil      778:
1.6       phil      779:        if (!(i8255->port_c & LPC_NACK)) {
                    780:                i8255->port_a |= LPA_ACKENABLE;
                    781:                ifp->if_collisions++;
                    782:                return;
                    783:        }
                    784:        i8255->port_b = 0x01;
1.3       phil      785:        i8255->port_a &= ~(LPA_ACKENABLE | LPA_ACTIVE);
1.1       phil      786:
1.23      matthias  787:        if (sc->sc_ifierrs)
1.31      thorpej   788:                callout_stop(&sc->sc_pliprx_ch);
1.23      matthias  789:
1.3       phil      790: #if defined(COMPAT_PLIP10)
1.1       phil      791:        if (ifp->if_flags & IFF_LINK0) {
1.20      matthias  792:                int c;
1.1       phil      793:                if (plipreceive(i8255, minibuf, 3) < 0) goto err;
                    794:                len = (minibuf[1] << 8) | minibuf[2];
1.3       phil      795:                if (len > (ifp->if_mtu + ifp->if_hdrlen)) goto err;
1.1       phil      796:
                    797:                switch (minibuf[0]) {
                    798:                case 0xfc:
1.19      is        799:                        p[0] = p[ 6] = LLADDR(ifp->if_sadl)[0];
                    800:                        p[1] = p[ 7] = LLADDR(ifp->if_sadl)[1];
                    801:                        p[2] = p[ 8] = LLADDR(ifp->if_sadl)[2];
                    802:                        p[3] = p[ 9] = LLADDR(ifp->if_sadl)[3];
                    803:                        p[4] = p[10] = LLADDR(ifp->if_sadl)[4];
1.1       phil      804:                        p += 5;
                    805:                        if ((cksum = plipreceive(i8255, p, 1)) < 0) goto err;
                    806:                        p += 6;
                    807:                        if ((c = plipreceive(i8255, p, len - 11)) < 0) goto err;
                    808:                        cksum += c + sc->sc_adrcksum;
                    809:                        c = p[1]; p[1] = p[2]; p[2] = c;
                    810:                        cksum &= 0xff;
                    811:                        break;
                    812:                case 0xfd:
                    813:                        if ((cksum = plipreceive(i8255, p, len)) < 0) goto err;
                    814:                        break;
                    815:                default:
                    816:                        goto err;
                    817:                }
1.3       phil      818:        } else
                    819: #endif
                    820:        {
1.1       phil      821:                if (plipreceive(i8255, minibuf, 2) < 0) goto err;
                    822:                len = (minibuf[1] << 8) | minibuf[0];
1.3       phil      823:                if (len > (ifp->if_mtu + ifp->if_hdrlen)) {
1.13      matthias  824:                        log(LOG_NOTICE, "%s: packet (%x) > MTU\n", ifp->if_xname, len);
1.3       phil      825:                        goto err;
                    826:                }
1.1       phil      827:                if ((cksum = plipreceive(i8255, p, len)) < 0) goto err;
                    828:        }
1.6       phil      829:
1.1       phil      830:        if (plipreceive(i8255, minibuf, 1) < 0) goto err;
                    831:        if (cksum != minibuf[0]) {
1.9       thorpej   832:                log(LOG_NOTICE, "%s: checksum error\n", ifp->if_xname);
1.1       phil      833:                goto err;
                    834:        }
                    835:        i8255->port_b = 0x00;
                    836:
1.34      thorpej   837:        s = splnet();
1.20      matthias  838:        if ((m = m_devget(sc->sc_ifbuf, len, 0, ifp, NULL)) != NULL) {
1.1       phil      839:                /* We assume that the header fit entirely in one mbuf. */
                    840:                eh = mtod(m, struct ether_header *);
1.13      matthias  841: #if NBPFILTER > 0
                    842:                /*
                    843:                 * Check if there's a BPF listener on this interface.
                    844:                 * If so, hand off the raw packet to bpf.
                    845:                 */
                    846:                if (ifp->if_bpf) {
                    847:                        bpf_mtap(ifp->if_bpf, m);
                    848:                }
                    849: #endif
1.30      thorpej   850:                (*ifp->if_input)(ifp, m);
1.1       phil      851:        }
1.3       phil      852:        splx(s);
1.4       phil      853:        sc->sc_ifierrs = 0;
1.1       phil      854:        ifp->if_ipackets++;
1.3       phil      855:        i8255->port_a |= LPA_ACKENABLE | LPA_ACTIVE;
1.1       phil      856:        return;
                    857:
                    858: err:
                    859:        i8255->port_b = 0x00;
                    860:
1.4       phil      861:        if (sc->sc_ifierrs < PLIPMXERRS) {
                    862:                i8255->port_a |= LPA_ACKENABLE | LPA_ACTIVE;
                    863:        } else {
1.23      matthias  864:                /*
                    865:                 * We are not able to send or receive anything for now,
1.1       phil      866:                 * so stop wasting our time and leave the interrupt
                    867:                 * disabled.
                    868:                 */
1.4       phil      869:                if (sc->sc_ifierrs == PLIPMXERRS)
1.9       thorpej   870:                        log(LOG_NOTICE, "%s: rx hard error\n", ifp->if_xname);
1.3       phil      871:                i8255->port_a |= LPA_ACTIVE;
1.23      matthias  872:                /* But we will retry from time to time. */
1.31      thorpej   873:                callout_reset(&sc->sc_pliprx_ch, PLIPRETRY * 10,
                    874:                    pliprxenable, sc);
1.4       phil      875:        }
                    876:        ifp->if_ierrors++;
                    877:        sc->sc_ifierrs++;
1.1       phil      878:        return;
                    879: }
                    880:
1.13      matthias  881: #ifdef __OPTIMIZE__
1.23      matthias  882: int pliptransmit __P((volatile struct i8255 *, u_char *, int))
                    883:        __asm("pliptransmit");
1.41    ! chs       884: __asm(" \
        !           885: pliptransmit: \
        !           886:        enter   [r3,r4,r5,r6,r7],0 ; \
        !           887:        movqd   0,r0 ; \
        !           888:        movd    8(fp),r1 ; \
        !           889:        movd    12(fp),r2 ; \
        !           890:        movd    16(fp),r3 ; \
        !           891:        cmpqd   0,r3 ; \
        !           892:        beq     5f ; \
        !           893: \
        !           894:        movqd   0,r7 ; \
        !           895:        movd    50000,r4 ; \
        !           896: \
        !           897:        .align  2,0xa2 ; \
        !           898: 0:     movb    8,r5 ; \
        !           899: 1:     movb    2(r1),r6 ; \
        !           900:        bicb    r6,r5 ; \
        !           901:        cmpqb   0,r5 ; \
        !           902:        beq     2f ; \
        !           903:        acbd    -1,r4,1b ; \
        !           904:        br      6f ; \
        !           905: \
        !           906:        .align  2,0xa2 ; \
        !           907: 2:     movb    0(r2),r7 ; \
        !           908:        movb    0x0f,r5 ; \
        !           909:        andb    r7,r5 ; \
        !           910:        addqd   1,r2 ; \
        !           911:        movb    r5,1(r1) ; \
        !           912:        orb     0x10,r5 ; \
        !           913:        movb    r5,1(r1) ; \
        !           914: \
        !           915:        movb    8,r5 ; \
        !           916: 3:     movb    2(r1),r6 ; \
        !           917:        andb    r6,r5 ; \
        !           918:        cmpqb   0,r5 ; \
        !           919:        beq     4f ; \
        !           920:        acbd    -1,r4,3b ; \
        !           921:        br      6f ; \
        !           922: \
        !           923:        .align  2,0xa2 ; \
        !           924: 4:     addd    r7,r0 ; \
        !           925:        lshb    -4,r7 ; \
        !           926:        movb    0x10,r5 ; \
        !           927:        orb     r7,r5 ; \
        !           928:        movb    r5,1(r1) ; \
        !           929:        movb    r7,1(r1) ; \
        !           930:        acbd    -1,r3,0b ; \
        !           931: \
        !           932:        andd    0xff,r0 ; \
        !           933: 5:     exit    [r3,r4,r5,r6,r7] ; \
        !           934:        ret     0 ; \
        !           935: \
        !           936: 6:     movqd   -1,r0 ; \
        !           937:        exit    [r3,r4,r5,r6,r7] ; \
        !           938:        ret     0 \
1.13      matthias  939: ");
                    940: #else
1.1       phil      941: static int
1.33      matthias  942: pliptransmit(i8255, buf, len)
1.13      matthias  943:        volatile struct i8255 *i8255;
                    944:        u_char *buf;
                    945:        int len;
1.1       phil      946: {
                    947:        int i;
                    948:        u_char cksum = 0, c;
                    949:
                    950:        while (len--) {
1.3       phil      951:                i = PLIPMXSPIN2;
1.1       phil      952:                cksum += (c = *buf++);
1.3       phil      953:                while ((i8255->port_c & LPC_NBUSY) == 0)
                    954:                        if (i-- < 0) return -1;
1.1       phil      955:                i8255->port_b = c & 0x0f;
                    956:                i8255->port_b = c & 0x0f | 0x10;
                    957:                c >>= 4;
1.3       phil      958:                while ((i8255->port_c & LPC_NBUSY) != 0)
                    959:                        if (i-- < 0) return -1;
                    960:                i8255->port_b = c | 0x10;
                    961:                i8255->port_b = c;
1.1       phil      962:        }
                    963:        return(cksum);
                    964: }
1.13      matthias  965: #endif
1.1       phil      966:
                    967: /*
                    968:  * Setup output on interface.
                    969:  */
1.3       phil      970: static void
1.13      matthias  971: plipstart(ifp)
                    972:        struct ifnet *ifp;
1.1       phil      973: {
1.9       thorpej   974:        struct lpt_softc *sc = (struct lpt_softc *)(ifp->if_softc);
1.6       phil      975:        sc->sc_pending |= PLIP_OPENDING;
                    976:        softintr(sc->sc_ifsoftint);
                    977: }
                    978:
                    979: static void
1.16      matthias  980: plipoutput(arg)
                    981:        void *arg;
1.6       phil      982: {
1.16      matthias  983:        struct lpt_softc *sc = arg;
1.19      is        984:        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1.1       phil      985:        volatile struct i8255 *i8255 = sc->sc_i8255;
                    986:        struct mbuf *m0, *m;
1.3       phil      987:        u_char minibuf[4], cksum;
1.1       phil      988:        int len, i, s;
                    989:
1.3       phil      990:        if (ifp->if_flags & IFF_OACTIVE)
1.1       phil      991:                return;
                    992:        ifp->if_flags |= IFF_OACTIVE;
                    993:
1.4       phil      994:        if (sc->sc_ifoerrs)
1.31      thorpej   995:                callout_stop(&sc->sc_plipout_ch);
1.1       phil      996:
                    997:        for (;;) {
1.34      thorpej   998:                s = splnet();
1.1       phil      999:                IF_DEQUEUE(&ifp->if_snd, m0);
1.3       phil     1000:                splx(s);
1.1       phil     1001:                if (!m0)
                   1002:                        break;
                   1003:
1.13      matthias 1004: #if NBPFILTER > 0
                   1005:                if (ifp->if_bpf)
                   1006:                        bpf_mtap(ifp->if_bpf, m0);
                   1007: #endif
                   1008:
                   1009:                len = m0->m_pkthdr.len;
                   1010:
1.3       phil     1011: #if defined(COMPAT_PLIP10)
1.1       phil     1012:                if (ifp->if_flags & IFF_LINK0) {
                   1013:                        minibuf[0] = 3;
                   1014:                        minibuf[1] = 0xfd;
                   1015:                        minibuf[2] = len >> 8;
                   1016:                        minibuf[3] = len;
1.3       phil     1017:                } else
                   1018: #endif
                   1019:                {
1.1       phil     1020:                        minibuf[0] = 2;
                   1021:                        minibuf[1] = len;
                   1022:                        minibuf[2] = len >> 8;
                   1023:                }
                   1024:
                   1025:                /* Trigger remote interrupt */
1.6       phil     1026:                i = PLIPMXSPIN1;
                   1027:                do {
                   1028:                        if (sc->sc_pending & PLIP_IPENDING) {
                   1029:                                i8255->port_b = 0x00;
                   1030:                                sc->sc_pending = 0;
                   1031:                                plipinput(sc);
                   1032:                                i = PLIPMXSPIN1;
                   1033:                        } else if (i-- < 0)
1.1       phil     1034:                                goto retry;
1.6       phil     1035:                        /* Retrigger remote interrupt */
                   1036:                        i8255->port_b = 0x08;
                   1037:                } while ((i8255->port_c & LPC_NERROR) == 0);
                   1038:                i8255->port_a &= ~(LPA_ACKENABLE | LPA_ACTIVE);
1.1       phil     1039:
                   1040:                if (pliptransmit(i8255, minibuf + 1, minibuf[0]) < 0) goto retry;
                   1041:                for (cksum = 0, m = m0; m; m = m->m_next) {
                   1042:                        i = pliptransmit(i8255, mtod(m, u_char *), m->m_len);
                   1043:                        if (i < 0) goto retry;
                   1044:                        cksum += i;
                   1045:                }
                   1046:                if (pliptransmit(i8255, &cksum, 1) < 0) goto retry;
1.3       phil     1047:                i = PLIPMXSPIN2;
                   1048:                while ((i8255->port_c & LPC_NBUSY) == 0)
                   1049:                        if (i-- < 0) goto retry;
1.1       phil     1050:                i8255->port_b = 0x00;
1.3       phil     1051:
                   1052:                ifp->if_opackets++;
                   1053:                ifp->if_obytes += len + 4;
1.4       phil     1054:                sc->sc_ifoerrs = 0;
1.1       phil     1055:                m_freem(m0);
                   1056:                i8255->port_a |= LPA_ACKENABLE;
                   1057:        }
1.3       phil     1058:        i8255->port_a |= LPA_ACTIVE;
1.1       phil     1059:        ifp->if_flags &= ~IFF_OACTIVE;
1.3       phil     1060:        return;
1.1       phil     1061:
                   1062: retry:
                   1063:        if (i8255->port_c & LPC_NACK)
                   1064:                ifp->if_collisions++;
                   1065:        else
                   1066:                ifp->if_oerrors++;
1.6       phil     1067:
                   1068:        ifp->if_flags &= ~IFF_OACTIVE;
                   1069:        i8255->port_b = 0x00;
                   1070:
1.1       phil     1071:        if ((ifp->if_flags & (IFF_RUNNING | IFF_UP)) == (IFF_RUNNING | IFF_UP)
1.4       phil     1072:            && sc->sc_ifoerrs < PLIPMXRETRY) {
1.34      thorpej  1073:                s = splnet();
1.1       phil     1074:                IF_PREPEND(&ifp->if_snd, m0);
1.3       phil     1075:                splx(s);
1.31      thorpej  1076:                callout_reset(&sc->sc_plipout_ch, PLIPRETRY, plipoutput, sc);
1.1       phil     1077:        } else {
1.4       phil     1078:                if (sc->sc_ifoerrs == PLIPMXRETRY) {
1.9       thorpej  1079:                        log(LOG_NOTICE, "%s: tx hard error\n", ifp->if_xname);
1.3       phil     1080:                }
1.1       phil     1081:                m_freem(m0);
                   1082:        }
1.23      matthias 1083:        i8255->port_a |= LPA_ACKENABLE | LPA_ACTIVE;
1.4       phil     1084:        sc->sc_ifoerrs++;
1.1       phil     1085: }
                   1086:
                   1087: #endif

CVSweb <webmaster@jp.NetBSD.org>