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.14 2008/06/12 22:45:46 cegger 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.14 2008/06/12 22:45:46 cegger Exp $");
   88 
   89 #include <sys/param.h>
   90 #include <sys/systm.h>
   91 #include <sys/proc.h>
   92 #include <sys/user.h>
   93 #include <sys/buf.h>
   94 #include <sys/kernel.h>
   95 #include <sys/ioctl.h>
   96 #include <sys/uio.h>
   97 #include <sys/device.h>
   98 #include <sys/conf.h>
   99 #include <sys/syslog.h>
  100 
  101 #include <sys/cpu.h>
  102 #include <sys/bus.h>
  103 
  104 #include <dev/mvme/lptvar.h>
  105 
  106 
  107 #define TIMEOUT         hz*16   /* wait up to 16 seconds for a ready */
  108 #define STEP            hz/4
  109 
  110 #define LPTPRI          (PZERO+8)
  111 #define LPT_BSIZE       1024
  112 
  113 #if !defined(DEBUG) || !defined(notdef)
  114 #define LPRINTF(a)
  115 #else
  116 #define LPRINTF         if (lptdebug) aprint_verbose_dev a
  117 int lptdebug = 1;
  118 #endif
  119 
  120 #define LPTUNIT(s)      (minor(s) & 0x0f)
  121 #define LPTFLAGS(s)     (minor(s) & 0xf0)
  122 
  123 static void lpt_wakeup(void *arg);
  124 static int pushbytes(struct lpt_softc *);
  125 
  126 extern struct cfdriver lpt_cd;
  127 
  128 dev_type_open(lptopen);
  129 dev_type_close(lptclose);
  130 dev_type_write(lptwrite);
  131 dev_type_ioctl(lptioctl);
  132 
  133 const struct cdevsw lpt_cdevsw = {
  134         lptopen, lptclose, noread, lptwrite, lptioctl,
  135         nostop, notty, nopoll, nommap, nokqfilter,
  136 };
  137 
  138 void
  139 lpt_attach_subr(sc)
  140         struct lpt_softc *sc;
  141 {
  142 
  143         sc->sc_state = 0;
  144         callout_init(&sc->sc_wakeup_ch, 0);
  145 }
  146 
  147 /*
  148  * Reset the printer, then wait until it's selected and not busy.
  149  */
  150 int
  151 lptopen(dev_t dev, int flag, int mode, struct lwp *l)
  152 {
  153         u_char flags;
  154         struct lpt_softc *sc;
  155         int error;
  156         int spin;
  157 
  158         flags = LPTFLAGS(dev);
  159 
  160         sc = device_lookup_private(&lpt_cd, LPTUNIT(dev));
  161         if (!sc)
  162                 return (ENXIO);
  163 
  164 #ifdef DIAGNOSTIC
  165         if (sc->sc_state)
  166                 aprint_verbose_dev(sc->sc_dev, "stat=0x%x not zero\n",
  167                     sc->sc_state);
  168 #endif
  169 
  170         if (sc->sc_state)
  171                 return (EBUSY);
  172 
  173         sc->sc_state = LPT_INIT;
  174         sc->sc_flags = flags;
  175         LPRINTF((sc->sc_dev, "open: flags=0x%x\n", flags));
  176 
  177         if ((flags & LPT_NOPRIME) == 0) {
  178                 /* assert Input Prime for 100 usec to start up printer */
  179                 (sc->sc_funcs->lf_iprime) (sc);
  180         }
  181 
  182         /* select fast or slow strobe depending on minor device number */
  183         if (flags & LPT_FAST_STROBE)
  184                 (sc->sc_funcs->lf_speed) (sc, LPT_STROBE_FAST);
  185         else
  186                 (sc->sc_funcs->lf_speed) (sc, LPT_STROBE_SLOW);
  187 
  188         /* wait till ready (printer running diagnostics) */
  189         for (spin = 0; (sc->sc_funcs->lf_notrdy) (sc, 1); spin += STEP) {
  190                 if (spin >= TIMEOUT) {
  191                         sc->sc_state = 0;
  192                         return (EBUSY);
  193                 }
  194                 /* wait 1/4 second, give up if we get a signal */
  195                 error = tsleep((void *) sc, LPTPRI | PCATCH, "lptopen", STEP);
  196                 if (error != EWOULDBLOCK) {
  197                         sc->sc_state = 0;
  198                         return (error);
  199                 }
  200         }
  201 
  202         sc->sc_inbuf = geteblk(LPT_BSIZE);
  203         sc->sc_count = 0;
  204         sc->sc_state = LPT_OPEN;
  205 
  206         if ((sc->sc_flags & LPT_NOINTR) == 0)
  207                 lpt_wakeup(sc);
  208 
  209         (sc->sc_funcs->lf_open) (sc, sc->sc_flags & LPT_NOINTR);
  210 
  211         LPRINTF((sc->sc_dev, "opened\n"));
  212         return (0);
  213 }
  214 
  215 void
  216 lpt_wakeup(arg)
  217         void *arg;
  218 {
  219         struct lpt_softc *sc;
  220         int s;
  221 
  222         sc = arg;
  223 
  224         s = spltty();
  225         lpt_intr(sc);
  226         splx(s);
  227 
  228         callout_reset(&sc->sc_wakeup_ch, STEP, lpt_wakeup, sc);
  229 }
  230 
  231 /*
  232  * Close the device, and free the local line buffer.
  233  */
  234 int
  235 lptclose(dev_t dev, int flag, int mode, struct lwp *l)
  236 {
  237         struct lpt_softc *sc;
  238 
  239         sc = device_lookup_private(&lpt_cd, LPTUNIT(dev));
  240 
  241         if (sc->sc_count)
  242                 (void) pushbytes(sc);
  243 
  244         if ((sc->sc_flags & LPT_NOINTR) == 0)
  245                 callout_stop(&sc->sc_wakeup_ch);
  246 
  247         (sc->sc_funcs->lf_close) (sc);
  248 
  249         sc->sc_state = 0;
  250         brelse(sc->sc_inbuf, 0);
  251 
  252         LPRINTF((sc->sc_dev, "%s: closed\n"));
  253         return (0);
  254 }
  255 
  256 int
  257 pushbytes(sc)
  258         struct lpt_softc *sc;
  259 {
  260         int s, error, spin, tic;
  261 
  262         if (sc->sc_flags & LPT_NOINTR) {
  263                 while (sc->sc_count > 0) {
  264                         spin = 0;
  265                         while ((sc->sc_funcs->lf_notrdy) (sc, 0)) {
  266                                 if (++spin < sc->sc_spinmax)
  267                                         continue;
  268                                 tic = 0;
  269                                 /* adapt busy-wait algorithm */
  270                                 sc->sc_spinmax++;
  271                                 while ((sc->sc_funcs->lf_notrdy) (sc, 1)) {
  272                                         /* exponential backoff */
  273                                         tic = tic + tic + 1;
  274                                         if (tic > TIMEOUT)
  275                                                 tic = TIMEOUT;
  276                                         error = tsleep((void *) sc,
  277                                             LPTPRI | PCATCH, "lptpsh", tic);
  278                                         if (error != EWOULDBLOCK)
  279                                                 return (error);
  280                                 }
  281                                 break;
  282                         }
  283 
  284                         (sc->sc_funcs->lf_wrdata) (sc, *sc->sc_cp++);
  285                         sc->sc_count--;
  286 
  287                         /* adapt busy-wait algorithm */
  288                         if (spin * 2 + 16 < sc->sc_spinmax)
  289                                 sc->sc_spinmax--;
  290                 }
  291         } else {
  292                 while (sc->sc_count > 0) {
  293                         /* if the printer is ready for a char, give it one */
  294                         if ((sc->sc_state & LPT_OBUSY) == 0) {
  295                                 LPRINTF((sc->sc_dev, "write %d\n",
  296                                         sc->sc_count));
  297                                 s = spltty();
  298                                 (void) lpt_intr(sc);
  299                                 splx(s);
  300                         }
  301                         error = tsleep((void *) sc, LPTPRI | PCATCH,
  302                             "lptwrite2", 0);
  303                         if (error)
  304                                 return (error);
  305                 }
  306         }
  307         return (0);
  308 }
  309 
  310 /*
  311  * Copy a line from user space to a local buffer, then call putc to get the
  312  * chars moved to the output queue.
  313  */
  314 int
  315 lptwrite(dev_t dev, struct uio *uio, int flags)
  316 {
  317         struct lpt_softc *sc;
  318         size_t n;
  319         int error;
  320 
  321         sc = device_lookup_private(&lpt_cd, LPTUNIT(dev));
  322         error = 0;
  323 
  324         while ((n = min(LPT_BSIZE, uio->uio_resid)) != 0) {
  325                 uiomove(sc->sc_cp = sc->sc_inbuf->b_data, n, uio);
  326                 sc->sc_count = n;
  327                 error = pushbytes(sc);
  328                 if (error) {
  329                         /*
  330                          * Return accurate residual if interrupted or timed
  331                          * out.
  332                          */
  333                         uio->uio_resid += sc->sc_count;
  334                         sc->sc_count = 0;
  335                         return (error);
  336                 }
  337         }
  338         return (0);
  339 }
  340 
  341 /*
  342  * Handle printer interrupts which occur when the printer is ready to accept
  343  * another char.
  344  */
  345 int
  346 lpt_intr(sc)
  347         struct lpt_softc *sc;
  348 {
  349 
  350         if (sc->sc_count) {
  351                 /* send char */
  352                 (sc->sc_funcs->lf_wrdata) (sc, *sc->sc_cp++);
  353                 sc->sc_count--;
  354                 sc->sc_state |= LPT_OBUSY;
  355         } else
  356                 sc->sc_state &= ~LPT_OBUSY;
  357 
  358         if (sc->sc_count == 0) {
  359                 /* none, wake up the top half to get more */
  360                 wakeup((void *) sc);
  361         }
  362 
  363         return (1);
  364 }
  365 
  366 /* ARGSUSED */
  367 int
  368 lptioctl(dev, cmd, data, flag, l)
  369         dev_t dev;
  370         u_long cmd;
  371         void *data;
  372         int flag;
  373         struct lwp *l;
  374 {
  375 
  376         return (ENODEV);
  377 }

Cache object: 4468dc6972f914187f685bca1b43e577


[ 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.