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/gpib/ppi.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: ppi.c,v 1.2 2003/08/07 16:30:56 agc Exp $      */
    2 
    3 /*-
    4  * Copyright (c) 1996-2003 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Jason R. Thorpe.
    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) 1982, 1990, 1993
   41  *      The Regents of the University of California.  All rights reserved.
   42  *
   43  * Redistribution and use in source and binary forms, with or without
   44  * modification, are permitted provided that the following conditions
   45  * are met:
   46  * 1. Redistributions of source code must retain the above copyright
   47  *    notice, this list of conditions and the following disclaimer.
   48  * 2. Redistributions in binary form must reproduce the above copyright
   49  *    notice, this list of conditions and the following disclaimer in the
   50  *    documentation and/or other materials provided with the distribution.
   51  * 3. Neither the name of the University nor the names of its contributors
   52  *    may be used to endorse or promote products derived from this software
   53  *    without specific prior written permission.
   54  *
   55  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   56  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   57  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   58  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   59  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   60  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   61  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   62  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   63  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   64  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   65  * SUCH DAMAGE.
   66  *
   67  *      @(#)ppi.c       8.1 (Berkeley) 6/16/93
   68  */
   69 
   70 /*
   71  * Printer/Plotter GPIB interface
   72  */
   73 
   74 #include <sys/cdefs.h>
   75 __KERNEL_RCSID(0, "$NetBSD: ppi.c,v 1.2 2003/08/07 16:30:56 agc Exp $");
   76 
   77 #include <sys/param.h>
   78 #include <sys/systm.h>
   79 #include <sys/callout.h>
   80 #include <sys/conf.h>
   81 #include <sys/device.h>
   82 #include <sys/malloc.h>
   83 #include <sys/proc.h>
   84 #include <sys/uio.h>
   85 
   86 #include <dev/gpib/gpibvar.h>
   87 
   88 #include <dev/gpib/ppiio.h>
   89 
   90 struct  ppi_softc {
   91         struct device sc_dev;
   92         gpib_chipset_tag_t sc_ic;
   93         gpib_handle_t sc_hdl;
   94 
   95         int sc_address;                 /* GPIB address */
   96         int     sc_flags;
   97         int     sc_sec;
   98         struct  ppiparam sc_param;
   99 #define sc_burst sc_param.burst
  100 #define sc_timo  sc_param.timo
  101 #define sc_delay sc_param.delay
  102         struct  callout sc_timo_ch;
  103         struct  callout sc_start_ch;
  104 };
  105 
  106 /* sc_flags values */
  107 #define PPIF_ALIVE      0x01    
  108 #define PPIF_OPEN       0x02    
  109 #define PPIF_UIO        0x04
  110 #define PPIF_TIMO       0x08
  111 #define PPIF_DELAY      0x10
  112 
  113 int     ppimatch(struct device *, struct cfdata *, void *);
  114 void    ppiattach(struct device *, struct device *, void *);
  115 
  116 CFATTACH_DECL(ppi, sizeof(struct ppi_softc),
  117         ppimatch, ppiattach, NULL, NULL);
  118 
  119 extern struct cfdriver ppi_cd;
  120 
  121 void    ppicallback(void *, int);
  122 void    ppistart(void *);
  123 
  124 void    ppitimo(void *);
  125 int     ppirw(dev_t, struct uio *);
  126 int     ppihztoms(int);
  127 int     ppimstohz(int);
  128 
  129 dev_type_open(ppiopen);
  130 dev_type_close(ppiclose);
  131 dev_type_read(ppiread);
  132 dev_type_write(ppiwrite);
  133 dev_type_ioctl(ppiioctl);
  134 
  135 const struct cdevsw ppi_cdevsw = {
  136         ppiopen, ppiclose, ppiread, ppiwrite, ppiioctl,
  137         nostop, notty, nopoll, nommap, nokqfilter,
  138 };
  139 
  140 #define UNIT(x)         minor(x)
  141 
  142 #ifdef DEBUG
  143 int     ppidebug = 0x80;
  144 #define PDB_FOLLOW      0x01
  145 #define PDB_IO          0x02
  146 #define PDB_NOCHECK     0x80
  147 #define DPRINTF(mask, str)      if (ppidebug & (mask)) printf str
  148 #else
  149 #define DPRINTF(mask, str)      /* nothing */
  150 #endif
  151 
  152 int
  153 ppimatch(parent, match, aux)
  154         struct device *parent;
  155         struct cfdata *match;
  156         void *aux;
  157 {
  158 
  159         return (1);
  160 }
  161 
  162 void
  163 ppiattach(parent, self, aux)
  164         struct device *parent, *self;
  165         void *aux;
  166 {
  167         struct ppi_softc *sc = (struct ppi_softc *)self;
  168         struct gpib_attach_args *ga = aux;
  169 
  170         printf("\n");
  171 
  172         sc->sc_ic = ga->ga_ic;
  173         sc->sc_address = ga->ga_address;
  174 
  175         callout_init(&sc->sc_timo_ch);
  176         callout_init(&sc->sc_start_ch);
  177 
  178         if (gpibregister(sc->sc_ic, sc->sc_address, ppicallback, sc,
  179             &sc->sc_hdl)) {
  180                 printf("%s: can't register callback\n", sc->sc_dev.dv_xname);
  181                 return;
  182         }
  183 
  184         sc->sc_flags = PPIF_ALIVE;
  185 }
  186 
  187 int
  188 ppiopen(dev, flags, fmt, p)
  189         dev_t dev;
  190         int flags, fmt;
  191         struct proc *p;
  192 {
  193         int unit = UNIT(dev);
  194         struct ppi_softc *sc;
  195 
  196         if (unit >= ppi_cd.cd_ndevs ||
  197             (sc = ppi_cd.cd_devs[unit]) == NULL ||
  198             (sc->sc_flags & PPIF_ALIVE) == 0)
  199                 return (ENXIO);
  200 
  201         DPRINTF(PDB_FOLLOW, ("ppiopen(%x, %x): flags %x\n",
  202             dev, flags, sc->sc_flags));
  203 
  204         if (sc->sc_flags & PPIF_OPEN)
  205                 return (EBUSY);
  206         sc->sc_flags |= PPIF_OPEN;
  207         sc->sc_burst = PPI_BURST;
  208         sc->sc_timo = ppimstohz(PPI_TIMO);
  209         sc->sc_delay = ppimstohz(PPI_DELAY);
  210         sc->sc_sec = -1;
  211         return (0);
  212 }
  213 
  214 int
  215 ppiclose(dev, flags, fmt, p)
  216         dev_t dev;
  217         int flags, fmt;
  218         struct proc *p;
  219 {
  220         int unit = UNIT(dev);
  221         struct ppi_softc *sc = ppi_cd.cd_devs[unit];
  222 
  223         DPRINTF(PDB_FOLLOW, ("ppiclose(%x, %x): flags %x\n",
  224                        dev, flags, sc->sc_flags));
  225 
  226         sc->sc_flags &= ~PPIF_OPEN;
  227         return (0);
  228 }
  229 
  230 void
  231 ppicallback(v, action)
  232         void *v;
  233         int action;
  234 {
  235         struct ppi_softc *sc = v;
  236 
  237         DPRINTF(PDB_FOLLOW, ("ppicallback: v=%p, action=%d\n", v, action));
  238 
  239         switch (action) {       
  240         case GPIBCBF_START:
  241                 ppistart(sc);
  242         case GPIBCBF_INTR:
  243                 /* no-op */
  244                 break;
  245 #ifdef DEBUG
  246         default:
  247                 DPRINTF(PDB_FOLLOW, ("ppicallback: unknown action %d\n",
  248                     action));
  249                 break;
  250 #endif
  251         }
  252 }
  253 
  254 void
  255 ppistart(v)
  256         void *v;
  257 {
  258         struct ppi_softc *sc = v;
  259 
  260         DPRINTF(PDB_FOLLOW, ("ppistart(%x)\n", sc->sc_dev.dv_unit));
  261 
  262         sc->sc_flags &= ~PPIF_DELAY;
  263         wakeup(sc);
  264 }
  265 
  266 void
  267 ppitimo(arg)
  268         void *arg;
  269 {
  270         struct ppi_softc *sc = arg;
  271 
  272         DPRINTF(PDB_FOLLOW, ("ppitimo(%x)\n", sc->sc_dev.dv_unit));
  273 
  274         sc->sc_flags &= ~(PPIF_UIO|PPIF_TIMO);
  275         wakeup(sc);
  276 }
  277 
  278 int
  279 ppiread(dev, uio, flags)
  280         dev_t dev;
  281         struct uio *uio;
  282         int flags;
  283 {
  284 
  285         DPRINTF(PDB_FOLLOW, ("ppiread(%x, %p)\n", dev, uio));
  286 
  287         return (ppirw(dev, uio));
  288 }
  289 
  290 int
  291 ppiwrite(dev, uio, flags)
  292         dev_t dev;
  293         struct uio *uio;
  294         int flags;
  295 {
  296 
  297         DPRINTF(PDB_FOLLOW, ("ppiwrite(%x, %p)\n", dev, uio));
  298 
  299         return (ppirw(dev, uio));
  300 }
  301 
  302 int
  303 ppirw(dev, uio)
  304         dev_t dev;
  305         struct uio *uio;
  306 {
  307         int unit = UNIT(dev);
  308         struct ppi_softc *sc = ppi_cd.cd_devs[unit];
  309         int s, len, cnt;
  310         char *cp;
  311         int error = 0, gotdata = 0;
  312         int buflen, address;
  313         char *buf;
  314 
  315         if (uio->uio_resid == 0)
  316                 return (0);
  317 
  318         address = sc->sc_address;
  319 
  320         DPRINTF(PDB_FOLLOW|PDB_IO,
  321             ("ppirw(%x, %p, %c): burst %d, timo %d, resid %x\n",
  322             dev, uio, uio->uio_rw == UIO_READ ? 'R' : 'W',
  323             sc->sc_burst, sc->sc_timo, uio->uio_resid));
  324 
  325         buflen = min(sc->sc_burst, uio->uio_resid);
  326         buf = (char *)malloc(buflen, M_DEVBUF, M_WAITOK);
  327         sc->sc_flags |= PPIF_UIO;
  328         if (sc->sc_timo > 0) {
  329                 sc->sc_flags |= PPIF_TIMO;
  330                 callout_reset(&sc->sc_timo_ch, sc->sc_timo, ppitimo, sc);
  331         }
  332         len = cnt = 0;
  333         while (uio->uio_resid > 0) {
  334                 len = min(buflen, uio->uio_resid);
  335                 cp = buf;
  336                 if (uio->uio_rw == UIO_WRITE) {
  337                         error = uiomove(cp, len, uio);
  338                         if (error)
  339                                 break;
  340                 }
  341 again:
  342                 s = splbio();
  343                 if (sc->sc_flags & PPIF_UIO) {
  344                         if (gpibrequest(sc->sc_ic, sc->sc_hdl) == 0)
  345                                 (void) tsleep(sc, PRIBIO + 1, "ppirw", 0);
  346                 }
  347                 /*
  348                  * Check if we timed out during sleep or uiomove
  349                  */
  350                 (void) spllowersoftclock();
  351                 if ((sc->sc_flags & PPIF_UIO) == 0) {
  352                         DPRINTF(PDB_IO,
  353                             ("ppirw: uiomove/sleep timo, flags %x\n",
  354                             sc->sc_flags));
  355                         if (sc->sc_flags & PPIF_TIMO) {
  356                                 callout_stop(&sc->sc_timo_ch);
  357                                 sc->sc_flags &= ~PPIF_TIMO;
  358                         }
  359                         splx(s);
  360                         break;
  361                 }
  362                 splx(s);
  363                 /*
  364                  * Perform the operation
  365                  */
  366                 if (uio->uio_rw == UIO_WRITE)
  367                         cnt = gpibsend(sc->sc_ic, address, sc->sc_sec,
  368                             cp, len);
  369                 else
  370                         cnt = gpibrecv(sc->sc_ic, address, sc->sc_sec,
  371                             cp, len);
  372                 s = splbio();
  373                 gpibrelease(sc->sc_ic, sc->sc_hdl);
  374                 DPRINTF(PDB_IO, ("ppirw: %s(%d, %x, %p, %d) -> %d\n",
  375                     uio->uio_rw == UIO_READ ? "recv" : "send",
  376                     address, sc->sc_sec, cp, len, cnt));
  377                 splx(s);
  378                 if (uio->uio_rw == UIO_READ) {
  379                         if (cnt) {
  380                                 error = uiomove(cp, cnt, uio);
  381                                 if (error)
  382                                         break;
  383                                 gotdata++;
  384                         }
  385                         /*
  386                          * Didn't get anything this time, but did in the past.
  387                          * Consider us done.
  388                          */
  389                         else if (gotdata)
  390                                 break;
  391                 }
  392                 s = splsoftclock();
  393                 /*
  394                  * Operation timeout (or non-blocking), quit now.
  395                  */
  396                 if ((sc->sc_flags & PPIF_UIO) == 0) {
  397                         DPRINTF(PDB_IO, ("ppirw: timeout/done\n"));
  398                         splx(s);
  399                         break;
  400                 }
  401                 /*
  402                  * Implement inter-read delay
  403                  */
  404                 if (sc->sc_delay > 0) {
  405                         sc->sc_flags |= PPIF_DELAY;
  406                         callout_reset(&sc->sc_start_ch, sc->sc_delay,
  407                             ppistart, sc);
  408                         error = tsleep(sc, (PCATCH|PZERO) + 1, "gpib", 0);
  409                         if (error) {
  410                                 splx(s);
  411                                 break;
  412                         }
  413                 }
  414                 splx(s);
  415                 /*
  416                  * Must not call uiomove again til we've used all data
  417                  * that we already grabbed.
  418                  */
  419                 if (uio->uio_rw == UIO_WRITE && cnt != len) {
  420                         cp += cnt;
  421                         len -= cnt;
  422                         cnt = 0;
  423                         goto again;
  424                 }
  425         }
  426         s = splsoftclock();
  427         if (sc->sc_flags & PPIF_TIMO) {
  428                 callout_stop(&sc->sc_timo_ch);
  429                 sc->sc_flags &= ~PPIF_TIMO;
  430         }
  431         if (sc->sc_flags & PPIF_DELAY) {
  432                 callout_stop(&sc->sc_start_ch);
  433                 sc->sc_flags &= ~PPIF_DELAY;
  434         }
  435         splx(s);
  436         /*
  437          * Adjust for those chars that we uiomove'ed but never wrote
  438          */
  439         if (uio->uio_rw == UIO_WRITE && cnt != len) {
  440                 uio->uio_resid += (len - cnt);
  441                 DPRINTF(PDB_IO, ("ppirw: short write, adjust by %d\n",
  442                     len - cnt));
  443         }
  444         free(buf, M_DEVBUF);
  445         DPRINTF(PDB_FOLLOW|PDB_IO, ("ppirw: return %d, resid %d\n",
  446             error, uio->uio_resid));
  447         return (error);
  448 }
  449 
  450 int
  451 ppiioctl(dev, cmd, data, flag, p)
  452         dev_t dev;
  453         u_long cmd;
  454         caddr_t data;
  455         int flag;
  456         struct proc *p;
  457 {
  458         struct ppi_softc *sc = ppi_cd.cd_devs[UNIT(dev)];
  459         struct ppiparam *pp, *upp;
  460         int error = 0;
  461 
  462         switch (cmd) {
  463         case PPIIOCGPARAM:
  464                 pp = &sc->sc_param;
  465                 upp = (struct ppiparam *)data;
  466                 upp->burst = pp->burst;
  467                 upp->timo = ppihztoms(pp->timo);
  468                 upp->delay = ppihztoms(pp->delay);
  469                 break;
  470         case PPIIOCSPARAM:
  471                 pp = &sc->sc_param;
  472                 upp = (struct ppiparam *)data;
  473                 if (upp->burst < PPI_BURST_MIN || upp->burst > PPI_BURST_MAX ||
  474                     upp->delay < PPI_DELAY_MIN || upp->delay > PPI_DELAY_MAX)
  475                         return (EINVAL);
  476                 pp->burst = upp->burst;
  477                 pp->timo = ppimstohz(upp->timo);
  478                 pp->delay = ppimstohz(upp->delay);
  479                 break;
  480         case PPIIOCSSEC:
  481                 sc->sc_sec = *(int *)data;
  482                 break;
  483         default:
  484                 return (EINVAL);
  485         }
  486         return (error);
  487 }
  488 
  489 int
  490 ppihztoms(h)
  491         int h;
  492 {
  493         extern int hz;
  494         int m = h;
  495 
  496         if (m > 0)
  497                 m = m * 1000 / hz;
  498         return (m);
  499 }
  500 
  501 int
  502 ppimstohz(m)
  503         int m;
  504 {
  505         extern int hz;
  506         int h = m;
  507 
  508         if (h > 0) {
  509                 h = h * hz / 1000;
  510                 if (h == 0)
  511                         h = 1000 / hz;
  512         }
  513         return (h);
  514 }

Cache object: 22281907f38a3a4d21ff7bf7445aefe5


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