The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/mvme/lpt_mvme.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: lpt_mvme.c,v 1.19 2018/09/03 16:29:32 riastradh Exp $  */
    2 
    3 /*-
    4  * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Steve C. Woodford.
    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  *
   19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 /*
   33  * Copyright (c) 1993, 1994 Charles M. Hannum.
   34  * Copyright (c) 1990 William F. Jolitz, TeleMuse
   35  * All rights reserved.
   36  *
   37  * Redistribution and use in source and binary forms, with or without
   38  * modification, are permitted provided that the following conditions
   39  * are met:
   40  * 1. Redistributions of source code must retain the above copyright
   41  *    notice, this list of conditions and the following disclaimer.
   42  * 2. Redistributions in binary form must reproduce the above copyright
   43  *    notice, this list of conditions and the following disclaimer in the
   44  *    documentation and/or other materials provided with the distribution.
   45  * 3. All advertising materials mentioning features or use of this software
   46  *    must display the following acknowledgement:
   47  *      This software is a component of "386BSD" developed by
   48  *      William F. Jolitz, TeleMuse.
   49  * 4. Neither the name of the developer nor the name "386BSD"
   50  *    may be used to endorse or promote products derived from this software
   51  *    without specific prior written permission.
   52  *
   53  * THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ
   54  * AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS
   55  * SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT.
   56  * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT
   57  * NOT MAKE USE OF THIS WORK.
   58  *
   59  * FOR USERS WHO WISH TO UNDERSTAND THE 386BSD SYSTEM DEVELOPED
   60  * BY WILLIAM F. JOLITZ, WE RECOMMEND THE USER STUDY WRITTEN
   61  * REFERENCES SUCH AS THE  "PORTING UNIX TO THE 386" SERIES
   62  * (BEGINNING JANUARY 1991 "DR. DOBBS JOURNAL", USA AND BEGINNING
   63  * JUNE 1991 "UNIX MAGAZIN", GERMANY) BY WILLIAM F. JOLITZ AND
   64  * LYNNE GREER JOLITZ, AS WELL AS OTHER BOOKS ON UNIX AND THE
   65  * ON-LINE 386BSD USER MANUAL BEFORE USE. A BOOK DISCUSSING THE INTERNALS
   66  * OF 386BSD ENTITLED "386BSD FROM THE INSIDE OUT" WILL BE AVAILABLE LATE 1992.
   67  *
   68  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND
   69  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   70  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   71  * ARE DISCLAIMED.  IN NO EVENT SHALL THE DEVELOPER BE LIABLE
   72  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   73  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   74  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   75  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   76  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   77  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   78  * SUCH DAMAGE.
   79  */
   80 
   81 /*
   82  * Device Driver for an MVME68K/MVME88K board's parallel printer port
   83  * This driver attaches above the board-specific back-end.
   84  */
   85 
   86 #include <sys/cdefs.h>
   87 __KERNEL_RCSID(0, "$NetBSD: lpt_mvme.c,v 1.19 2018/09/03 16:29:32 riastradh Exp $");
   88 
   89 #include <sys/param.h>
   90 #include <sys/systm.h>
   91 #include <sys/proc.h>
   92 #include <sys/buf.h>
   93 #include <sys/kernel.h>
   94 #include <sys/ioctl.h>
   95 #include <sys/uio.h>
   96 #include <sys/device.h>
   97 #include <sys/conf.h>
   98 #include <sys/syslog.h>
   99 
  100 #include <sys/cpu.h>
  101 #include <sys/bus.h>
  102 
  103 #include <dev/mvme/lptvar.h>
  104 
  105 
  106 #define TIMEOUT         hz*16   /* wait up to 16 seconds for a ready */
  107 #define STEP            hz/4
  108 
  109 #define LPTPRI          (PZERO+8)
  110 #define LPT_BSIZE       1024
  111 
  112 #if !defined(DEBUG) || !defined(notdef)
  113 #define LPRINTF(a)
  114 #else
  115 #define LPRINTF         if (lptdebug) aprint_verbose_dev a
  116 int lptdebug = 1;
  117 #endif
  118 
  119 #define LPTUNIT(s)      (minor(s) & 0x0f)
  120 #define LPTFLAGS(s)     (minor(s) & 0xf0)
  121 
  122 static void lpt_wakeup(void *arg);
  123 static int pushbytes(struct lpt_softc *);
  124 
  125 extern struct cfdriver lpt_cd;
  126 
  127 dev_type_open(lptopen);
  128 dev_type_close(lptclose);
  129 dev_type_write(lptwrite);
  130 dev_type_ioctl(lptioctl);
  131 
  132 const struct cdevsw lpt_cdevsw = {
  133         .d_open = lptopen,
  134         .d_close = lptclose,
  135         .d_read = noread,
  136         .d_write = lptwrite,
  137         .d_ioctl = lptioctl,
  138         .d_stop = nostop,
  139         .d_tty = notty,
  140         .d_poll = nopoll,
  141         .d_mmap = nommap,
  142         .d_kqfilter = nokqfilter,
  143         .d_discard = nodiscard,
  144         .d_flag = 0
  145 };
  146 
  147 void
  148 lpt_attach_subr(struct lpt_softc *sc)
  149 {
  150 
  151         sc->sc_state = 0;
  152         callout_init(&sc->sc_wakeup_ch, 0);
  153 }
  154 
  155 /*
  156  * Reset the printer, then wait until it's selected and not busy.
  157  */
  158 int
  159 lptopen(dev_t dev, int flag, int mode, struct lwp *l)
  160 {
  161         u_char flags;
  162         struct lpt_softc *sc;
  163         int error;
  164         int spin;
  165 
  166         flags = LPTFLAGS(dev);
  167 
  168         sc = device_lookup_private(&lpt_cd, LPTUNIT(dev));
  169         if (!sc)
  170                 return (ENXIO);
  171 
  172 #ifdef DIAGNOSTIC
  173         if (sc->sc_state)
  174                 aprint_verbose_dev(sc->sc_dev, "stat=0x%x not zero\n",
  175                     sc->sc_state);
  176 #endif
  177 
  178         if (sc->sc_state)
  179                 return (EBUSY);
  180 
  181         sc->sc_state = LPT_INIT;
  182         sc->sc_flags = flags;
  183         LPRINTF((sc->sc_dev, "open: flags=0x%x\n", flags));
  184 
  185         if ((flags & LPT_NOPRIME) == 0) {
  186                 /* assert Input Prime for 100 usec to start up printer */
  187                 (sc->sc_funcs->lf_iprime) (sc);
  188         }
  189 
  190         /* select fast or slow strobe depending on minor device number */
  191         if (flags & LPT_FAST_STROBE)
  192                 (sc->sc_funcs->lf_speed) (sc, LPT_STROBE_FAST);
  193         else
  194                 (sc->sc_funcs->lf_speed) (sc, LPT_STROBE_SLOW);
  195 
  196         /* wait till ready (printer running diagnostics) */
  197         for (spin = 0; (sc->sc_funcs->lf_notrdy) (sc, 1); spin += STEP) {
  198                 if (spin >= TIMEOUT) {
  199                         sc->sc_state = 0;
  200                         return (EBUSY);
  201                 }
  202                 /* wait 1/4 second, give up if we get a signal */
  203                 error = tsleep((void *) sc, LPTPRI | PCATCH, "lptopen", STEP);
  204                 if (error != EWOULDBLOCK) {
  205                         sc->sc_state = 0;
  206                         return (error);
  207                 }
  208         }
  209 
  210         sc->sc_inbuf = geteblk(LPT_BSIZE);
  211         sc->sc_count = 0;
  212         sc->sc_state = LPT_OPEN;
  213 
  214         if ((sc->sc_flags & LPT_NOINTR) == 0)
  215                 lpt_wakeup(sc);
  216 
  217         (sc->sc_funcs->lf_open) (sc, sc->sc_flags & LPT_NOINTR);
  218 
  219         LPRINTF((sc->sc_dev, "opened\n"));
  220         return (0);
  221 }
  222 
  223 void
  224 lpt_wakeup(void *arg)
  225 {
  226         struct lpt_softc *sc;
  227         int s;
  228 
  229         sc = arg;
  230 
  231         s = spltty();
  232         lpt_intr(sc);
  233         splx(s);
  234 
  235         callout_reset(&sc->sc_wakeup_ch, STEP, lpt_wakeup, sc);
  236 }
  237 
  238 /*
  239  * Close the device, and free the local line buffer.
  240  */
  241 int
  242 lptclose(dev_t dev, int flag, int mode, struct lwp *l)
  243 {
  244         struct lpt_softc *sc;
  245 
  246         sc = device_lookup_private(&lpt_cd, LPTUNIT(dev));
  247 
  248         if (sc->sc_count)
  249                 (void) pushbytes(sc);
  250 
  251         if ((sc->sc_flags & LPT_NOINTR) == 0)
  252                 callout_stop(&sc->sc_wakeup_ch);
  253 
  254         (sc->sc_funcs->lf_close) (sc);
  255 
  256         sc->sc_state = 0;
  257         brelse(sc->sc_inbuf, 0);
  258 
  259         LPRINTF((sc->sc_dev, "%s: closed\n"));
  260         return (0);
  261 }
  262 
  263 int
  264 pushbytes(struct lpt_softc *sc)
  265 {
  266         int s, error, spin, tic;
  267 
  268         if (sc->sc_flags & LPT_NOINTR) {
  269                 while (sc->sc_count > 0) {
  270                         spin = 0;
  271                         while ((sc->sc_funcs->lf_notrdy) (sc, 0)) {
  272                                 if (++spin < sc->sc_spinmax)
  273                                         continue;
  274                                 tic = 0;
  275                                 /* adapt busy-wait algorithm */
  276                                 sc->sc_spinmax++;
  277                                 while ((sc->sc_funcs->lf_notrdy) (sc, 1)) {
  278                                         /* exponential backoff */
  279                                         tic = tic + tic + 1;
  280                                         if (tic > TIMEOUT)
  281                                                 tic = TIMEOUT;
  282                                         error = tsleep((void *) sc,
  283                                             LPTPRI | PCATCH, "lptpsh", tic);
  284                                         if (error != EWOULDBLOCK)
  285                                                 return (error);
  286                                 }
  287                                 break;
  288                         }
  289 
  290                         (sc->sc_funcs->lf_wrdata) (sc, *sc->sc_cp++);
  291                         sc->sc_count--;
  292 
  293                         /* adapt busy-wait algorithm */
  294                         if (spin * 2 + 16 < sc->sc_spinmax)
  295                                 sc->sc_spinmax--;
  296                 }
  297         } else {
  298                 while (sc->sc_count > 0) {
  299                         /* if the printer is ready for a char, give it one */
  300                         if ((sc->sc_state & LPT_OBUSY) == 0) {
  301                                 LPRINTF((sc->sc_dev, "write %d\n",
  302                                         sc->sc_count));
  303                                 s = spltty();
  304                                 (void) lpt_intr(sc);
  305                                 splx(s);
  306                         }
  307                         error = tsleep((void *) sc, LPTPRI | PCATCH,
  308                             "lptwrite2", 0);
  309                         if (error)
  310                                 return (error);
  311                 }
  312         }
  313         return (0);
  314 }
  315 
  316 /*
  317  * Copy a line from user space to a local buffer, then call putc to get the
  318  * chars moved to the output queue.
  319  */
  320 int
  321 lptwrite(dev_t dev, struct uio *uio, int flags)
  322 {
  323         struct lpt_softc *sc;
  324         size_t n;
  325         int error;
  326 
  327         sc = device_lookup_private(&lpt_cd, LPTUNIT(dev));
  328         error = 0;
  329 
  330         while ((n = uimin(LPT_BSIZE, uio->uio_resid)) != 0) {
  331                 uiomove(sc->sc_cp = sc->sc_inbuf->b_data, n, uio);
  332                 sc->sc_count = n;
  333                 error = pushbytes(sc);
  334                 if (error) {
  335                         /*
  336                          * Return accurate residual if interrupted or timed
  337                          * out.
  338                          */
  339                         uio->uio_resid += sc->sc_count;
  340                         sc->sc_count = 0;
  341                         return (error);
  342                 }
  343         }
  344         return (0);
  345 }
  346 
  347 /*
  348  * Handle printer interrupts which occur when the printer is ready to accept
  349  * another char.
  350  */
  351 int
  352 lpt_intr(struct lpt_softc *sc)
  353 {
  354 
  355         if (sc->sc_count) {
  356                 /* send char */
  357                 (sc->sc_funcs->lf_wrdata) (sc, *sc->sc_cp++);
  358                 sc->sc_count--;
  359                 sc->sc_state |= LPT_OBUSY;
  360         } else
  361                 sc->sc_state &= ~LPT_OBUSY;
  362 
  363         if (sc->sc_count == 0) {
  364                 /* none, wake up the top half to get more */
  365                 wakeup((void *) sc);
  366         }
  367 
  368         return (1);
  369 }
  370 
  371 /* ARGSUSED */
  372 int
  373 lptioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
  374 {
  375 
  376         return (ENODEV);
  377 }

Cache object: b076b84fe6bb9a5fd7de8651ac6daa1f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.