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

Cache object: 6ed93fc7caca0a32088eed20e9bea36c


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