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/isa/satlink.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: satlink.c,v 1.22 2003/05/09 23:51:29 fvdl Exp $        */
    2 
    3 /*-
    4  * Copyright (c) 1997 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Canada Connect Corp.
    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  * Device driver for SatLink interface.
   41  *
   42  * This thing is really simple.  We essentially DMA into a ring buffer
   43  * which the user then reads from, and provide an ioctl interface to
   44  * reset the card, etc.
   45  */
   46 
   47 #include <sys/cdefs.h>
   48 __KERNEL_RCSID(0, "$NetBSD: satlink.c,v 1.22 2003/05/09 23:51:29 fvdl Exp $");
   49 
   50 #include <sys/param.h>
   51 #include <sys/systm.h>
   52 #include <sys/callout.h>
   53 #include <sys/errno.h>
   54 #include <sys/ioctl.h>
   55 #include <sys/device.h>
   56 #include <sys/conf.h>
   57 #include <sys/proc.h>
   58 #include <sys/uio.h>
   59 #include <sys/select.h>
   60 #include <sys/poll.h>
   61 #include <sys/kernel.h>
   62 #include <sys/file.h>
   63 #include <sys/tty.h>
   64 
   65 #include <machine/cpu.h>
   66 #include <machine/bus.h>
   67 #include <machine/intr.h>
   68 
   69 #include <dev/isa/isareg.h>
   70 #include <dev/isa/isavar.h>
   71 #include <dev/isa/isadmavar.h>
   72 
   73 #include <dev/isa/satlinkreg.h>
   74 #include <dev/isa/satlinkio.h>
   75 
   76 struct satlink_softc {
   77         struct  device sc_dev;          /* device glue */
   78         bus_space_tag_t sc_iot;         /* space tag */
   79         bus_space_handle_t sc_ioh;      /* space handle */
   80         isa_chipset_tag_t sc_ic;        /* ISA chipset info */
   81         int     sc_drq;                 /* the DRQ we're using */
   82         bus_size_t sc_bufsize;          /* DMA buffer size */
   83         caddr_t sc_buf;                 /* ring buffer for incoming data */
   84         int     sc_uptr;                /* user index into ring buffer */
   85         int     sc_sptr;                /* satlink index into ring buffer */
   86         int     sc_flags;               /* misc. flags. */
   87         int     sc_lastresid;           /* residual */
   88         struct selinfo sc_selq;         /* our select/poll queue */
   89         struct  satlink_id sc_id;       /* ID cached at attach time */
   90         struct callout sc_ch;           /* callout pseudo-interrupt */
   91 };
   92 
   93 /* sc_flags */
   94 #define SATF_ISOPEN             0x01    /* device is open */
   95 #define SATF_DATA               0x02    /* waiting for data */
   96 
   97 /*
   98  * Our pesudo-interrupt.  Since up to 328 bytes can arrive in 1/100 of
   99  * a second, this gives us 3280 bytes per timeout.
  100  */
  101 #define SATLINK_TIMEOUT         (hz/10)
  102 
  103 int     satlinkprobe __P((struct device *, struct cfdata *, void *));
  104 void    satlinkattach __P((struct device *, struct device *, void *));
  105 void    satlinktimeout __P((void *));
  106 
  107 CFATTACH_DECL(satlink, sizeof(struct satlink_softc),
  108     satlinkprobe, satlinkattach, NULL, NULL);
  109 
  110 extern struct cfdriver satlink_cd;
  111 
  112 dev_type_open(satlinkopen);
  113 dev_type_close(satlinkclose);
  114 dev_type_read(satlinkread);
  115 dev_type_ioctl(satlinkioctl);
  116 dev_type_poll(satlinkpoll);
  117 dev_type_kqfilter(satlinkkqfilter);
  118 
  119 const struct cdevsw satlink_cdevsw = {
  120         satlinkopen, satlinkclose, satlinkread, nowrite, satlinkioctl,
  121         nostop, notty, satlinkpoll, nommap, satlinkkqfilter,
  122 };
  123 
  124 int
  125 satlinkprobe(parent, match, aux)
  126         struct device *parent;
  127         struct cfdata *match;
  128         void *aux;
  129 {
  130         struct isa_attach_args *ia = aux;
  131         bus_space_tag_t iot = ia->ia_iot;
  132         bus_space_handle_t ioh;
  133         int rv = 0;
  134 
  135         if (ia->ia_nio < 1)
  136                 return (0);
  137         if (ia->ia_ndrq < 1)
  138                 return (0);
  139 
  140         if (ISA_DIRECT_CONFIG(ia))
  141                 return (0);
  142 
  143         /* Don't allow wildcarding of iobase or drq. */
  144         if (ia->ia_io[0].ir_addr == ISACF_PORT_DEFAULT)
  145                 return (0);
  146         if (ia->ia_drq[0].ir_drq == ISACF_DRQ_DEFAULT)
  147                 return (0);
  148 
  149         if (bus_space_map(iot, ia->ia_io[0].ir_addr, SATLINK_IOSIZE, 0, &ioh))
  150                 return (0);
  151 
  152         /*
  153          * XXX Should check manufacturer ID here, or something.
  154          */
  155 
  156         rv = 1;
  157 
  158         ia->ia_nio = 1;
  159         ia->ia_io[0].ir_size = SATLINK_IOSIZE;
  160 
  161         ia->ia_ndrq = 1;
  162 
  163         ia->ia_nirq = 0;
  164         ia->ia_niomem = 0;
  165 
  166         bus_space_unmap(iot, ioh, SATLINK_IOSIZE);
  167         return (rv);
  168 }
  169 
  170 void
  171 satlinkattach(parent, self, aux)
  172         struct device *parent, *self;
  173         void *aux;
  174 {
  175         struct satlink_softc *sc = (struct satlink_softc *)self;
  176         struct isa_attach_args *ia = aux;
  177         bus_space_tag_t iot = ia->ia_iot;
  178         bus_space_handle_t ioh;
  179         bus_addr_t ringaddr;
  180 
  181         printf("\n");
  182 
  183         /* Map the card. */
  184         if (bus_space_map(iot, ia->ia_io[0].ir_addr, SATLINK_IOSIZE, 0, &ioh)) {
  185                 printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname);
  186                 return;
  187         }
  188 
  189         sc->sc_iot = iot;
  190         sc->sc_ioh = ioh;
  191         sc->sc_ic = ia->ia_ic;
  192         sc->sc_drq = ia->ia_drq[0].ir_drq;
  193 
  194         /* Reset the card. */
  195         bus_space_write_1(iot, ioh, SATLINK_COMMAND, SATLINK_CMD_RESET);
  196 
  197         /* Read ID from the card. */
  198         sc->sc_id.sid_mfrid =
  199             bus_space_read_1(iot, ioh, SATLINK_MFRID_L) |
  200             (bus_space_read_1(iot, ioh, SATLINK_MFRID_H) << 8);
  201         sc->sc_id.sid_grpid = bus_space_read_1(iot, ioh, SATLINK_GRPID);
  202         sc->sc_id.sid_userid =
  203             bus_space_read_1(iot, ioh, SATLINK_USERID_L) |
  204             (bus_space_read_1(iot, ioh, SATLINK_USERID_H) << 8);
  205         sc->sc_id.sid_serial =
  206             bus_space_read_1(iot, ioh, SATLINK_SER_L) |
  207             (bus_space_read_1(iot, ioh, SATLINK_SER_M0) << 8) |
  208             (bus_space_read_1(iot, ioh, SATLINK_SER_M1) << 16) |
  209             (bus_space_read_1(iot, ioh, SATLINK_SER_H) << 24);
  210 
  211         printf("%s: mfrid 0x%x, grpid 0x%x, userid 0x%x, serial %d\n",
  212             sc->sc_dev.dv_xname, sc->sc_id.sid_mfrid,
  213             sc->sc_id.sid_grpid, sc->sc_id.sid_userid,
  214             sc->sc_id.sid_serial);
  215 
  216         callout_init(&sc->sc_ch);
  217 
  218         sc->sc_bufsize = isa_dmamaxsize(sc->sc_ic, sc->sc_drq);
  219 
  220         /* Allocate and map the ring buffer. */
  221         if (isa_dmamem_alloc(sc->sc_ic, sc->sc_drq, sc->sc_bufsize,
  222             &ringaddr, BUS_DMA_NOWAIT)) {
  223                 printf("%s: can't allocate ring buffer\n",
  224                     sc->sc_dev.dv_xname);
  225                 return;
  226         }
  227         if (isa_dmamem_map(sc->sc_ic, sc->sc_drq, ringaddr, sc->sc_bufsize,
  228             &sc->sc_buf, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) {
  229                 printf("%s: can't map ring buffer\n", sc->sc_dev.dv_xname);
  230                 isa_dmamem_free(sc->sc_ic, sc->sc_drq, ringaddr,
  231                     sc->sc_bufsize);
  232                 return;
  233         }
  234 
  235         if (isa_drq_alloc(sc->sc_ic, sc->sc_drq) != 0) {
  236                 printf("%s: can't reserve drq %d\n",
  237                     sc->sc_dev.dv_xname, sc->sc_drq);
  238                 isa_dmamem_unmap(sc->sc_ic, sc->sc_drq, sc->sc_buf,
  239                     sc->sc_bufsize);
  240                 isa_dmamem_free(sc->sc_ic, sc->sc_drq, ringaddr,
  241                     sc->sc_bufsize);
  242                 return;
  243         }
  244 
  245         /* Create the DMA map. */
  246         if (isa_dmamap_create(sc->sc_ic, sc->sc_drq, sc->sc_bufsize,
  247             BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
  248                 printf("%s: can't create DMA map\n", sc->sc_dev.dv_xname);
  249                 isa_dmamem_unmap(sc->sc_ic, sc->sc_drq, sc->sc_buf,
  250                     sc->sc_bufsize);
  251                 isa_dmamem_free(sc->sc_ic, sc->sc_drq, ringaddr,
  252                     sc->sc_bufsize);
  253                 return;
  254         }
  255 }
  256 
  257 int
  258 satlinkopen(dev, flags, fmt, p)
  259         dev_t dev;
  260         int flags, fmt;
  261         struct proc *p;
  262 {
  263         struct satlink_softc *sc;
  264         int error;
  265 
  266         sc = device_lookup(&satlink_cd, minor(dev));
  267         if (sc == NULL)
  268                 return (ENXIO);
  269 
  270         if (sc->sc_flags & SATF_ISOPEN)
  271                 return (EBUSY);
  272 
  273         bus_space_write_1(sc->sc_iot, sc->sc_ioh, SATLINK_COMMAND,
  274                     SATLINK_CMD_RESET);
  275 
  276         /* Reset the ring buffer, and start the DMA loop. */
  277         sc->sc_uptr = 0; 
  278         sc->sc_sptr = 0; 
  279         sc->sc_lastresid = sc->sc_bufsize;
  280         memset(sc->sc_buf, 0, sc->sc_bufsize);
  281         error = isa_dmastart(sc->sc_ic, sc->sc_drq, sc->sc_buf,
  282             sc->sc_bufsize, NULL, DMAMODE_READ|DMAMODE_LOOP, BUS_DMA_WAITOK);
  283         if (error)
  284                 return (error);
  285 
  286         sc->sc_flags |= SATF_ISOPEN;
  287 
  288         callout_reset(&sc->sc_ch, SATLINK_TIMEOUT, satlinktimeout, sc);
  289 
  290         return (0);
  291 }
  292 
  293 int
  294 satlinkclose(dev, flags, fmt, p)
  295         dev_t dev;
  296         int flags, fmt;
  297         struct proc *p;
  298 {
  299         struct satlink_softc *sc = device_lookup(&satlink_cd, minor(dev));
  300         int s;
  301 
  302         s = splsoftclock();
  303         sc->sc_flags &= ~SATF_ISOPEN;
  304         splx(s);
  305 
  306         isa_dmaabort(sc->sc_ic, sc->sc_drq);
  307         callout_stop(&sc->sc_ch);
  308 
  309         return (0);
  310 }
  311 
  312 int
  313 satlinkread(dev, uio, flags)
  314         dev_t dev;
  315         struct uio *uio;
  316         int flags;
  317 {
  318         struct satlink_softc *sc = device_lookup(&satlink_cd, minor(dev));
  319         int error, s, count, sptr;
  320         int wrapcnt, oresid;
  321 
  322         s = splsoftclock();
  323 
  324         /* Wait for data to be available. */
  325         while (sc->sc_sptr == sc->sc_uptr) {
  326                 if (flags & O_NONBLOCK) {
  327                         splx(s);
  328                         return (EWOULDBLOCK);
  329                 }
  330                 sc->sc_flags |= SATF_DATA;
  331                 if ((error = tsleep(sc, TTIPRI | PCATCH, "satio", 0)) != 0) {
  332                         splx(s);
  333                         return (error);
  334                 }
  335         }
  336 
  337         sptr = sc->sc_sptr;
  338         splx(s);
  339 
  340         /* Compute number of readable bytes. */
  341         if (sptr > sc->sc_uptr)
  342                 count = sptr - sc->sc_uptr;
  343         else
  344                 count = sc->sc_bufsize - sc->sc_uptr + sptr;
  345 
  346         if (count > uio->uio_resid)
  347                 count = uio->uio_resid;
  348 
  349         /* Send data out to user. */
  350         if (sptr > sc->sc_uptr) {
  351                 /*
  352                  * Easy case - no wrap-around.
  353                  */
  354                 error = uiomove(&sc->sc_buf[sc->sc_uptr], count, uio);
  355                 if (error == 0) {
  356                         sc->sc_uptr += count;
  357                         if (sc->sc_uptr == sc->sc_bufsize)
  358                                 sc->sc_uptr = 0;
  359                 }
  360                 return (error);
  361         }
  362 
  363         /*
  364          * We wrap around.  Copy to the end of the ring...
  365          */
  366         wrapcnt = sc->sc_bufsize - sc->sc_uptr;
  367         oresid = uio->uio_resid;
  368         if (wrapcnt > uio->uio_resid)
  369                 wrapcnt = uio->uio_resid;
  370         error = uiomove(&sc->sc_buf[sc->sc_uptr], wrapcnt, uio);
  371         sc->sc_uptr = 0;
  372         if (error != 0 || wrapcnt == oresid)
  373                 return (error);
  374 
  375         /* ...and the rest. */
  376         count -= wrapcnt;
  377         error = uiomove(sc->sc_buf, count, uio);
  378         sc->sc_uptr += count;
  379         if (sc->sc_uptr == sc->sc_bufsize)
  380                 sc->sc_uptr = 0;
  381 
  382         return (error);
  383 }
  384 
  385 int
  386 satlinkioctl(dev, cmd, data, flags, p)
  387         dev_t dev;
  388         u_long cmd;
  389         caddr_t data;
  390         int flags;
  391         struct proc *p;
  392 {
  393         struct satlink_softc *sc = device_lookup(&satlink_cd, minor(dev));
  394 
  395         switch (cmd) {
  396         case SATIORESET:
  397                 bus_space_write_1(sc->sc_iot, sc->sc_ioh, SATLINK_COMMAND,
  398                     SATLINK_CMD_RESET);
  399                 sc->sc_uptr = isa_dmacount(sc->sc_ic, sc->sc_drq);
  400                 sc->sc_sptr = sc->sc_uptr;
  401                 break;
  402 
  403         case SATIOGID:
  404                 memcpy(data, &sc->sc_id, sizeof(sc->sc_id));
  405                 break;
  406 
  407         default:
  408                 return (ENOTTY);
  409         }
  410 
  411         return (0);
  412 }
  413 
  414 int
  415 satlinkpoll(dev, events, p)
  416         dev_t dev;
  417         int events;
  418         struct proc *p;
  419 {
  420         struct satlink_softc *sc = device_lookup(&satlink_cd, minor(dev));
  421         int s, revents;
  422 
  423         revents = events & (POLLOUT | POLLWRNORM);
  424 
  425         /* Attempt to save some work. */
  426         if ((events & (POLLIN | POLLRDNORM)) == 0)
  427                 return (revents);
  428 
  429         /* We're timeout-driven, so must block the clock. */
  430         s = splsoftclock();
  431         if (sc->sc_uptr != sc->sc_sptr)
  432                 revents |= events & (POLLIN | POLLRDNORM);
  433         else
  434                 selrecord(p, &sc->sc_selq);
  435         splx(s);
  436 
  437         return (revents);
  438 }
  439 
  440 static void
  441 filt_satlinkrdetach(struct knote *kn)
  442 {
  443         struct satlink_softc *sc = kn->kn_hook;
  444         int s;
  445 
  446         s = splsoftclock();
  447         SLIST_REMOVE(&sc->sc_selq.sel_klist, kn, knote, kn_selnext);
  448         splx(s);
  449 }
  450 
  451 static int
  452 filt_satlinkread(struct knote *kn, long hint)
  453 {
  454         struct satlink_softc *sc = kn->kn_hook;
  455 
  456         if (sc->sc_uptr == sc->sc_sptr)
  457                 return (0);
  458 
  459         if (sc->sc_sptr > sc->sc_uptr)
  460                 kn->kn_data = sc->sc_sptr - sc->sc_uptr;
  461         else
  462                 kn->kn_data = (sc->sc_bufsize - sc->sc_uptr) +
  463                     sc->sc_sptr;
  464         return (1);
  465 }
  466 
  467 static const struct filterops satlinkread_filtops =
  468         { 1, NULL, filt_satlinkrdetach, filt_satlinkread };
  469 
  470 static const struct filterops satlink_seltrue_filtops =
  471         { 1, NULL, filt_satlinkrdetach, filt_seltrue };
  472 
  473 int
  474 satlinkkqfilter(dev_t dev, struct knote *kn)
  475 {
  476         struct satlink_softc *sc = device_lookup(&satlink_cd, minor(dev));
  477         struct klist *klist;
  478         int s;
  479 
  480         switch (kn->kn_filter) {
  481         case EVFILT_READ:
  482                 klist = &sc->sc_selq.sel_klist;
  483                 kn->kn_fop = &satlinkread_filtops;
  484                 break;
  485 
  486         case EVFILT_WRITE:
  487                 klist = &sc->sc_selq.sel_klist;
  488                 kn->kn_fop = &satlink_seltrue_filtops;
  489                 break;
  490 
  491         default:
  492                 return (1);
  493         }
  494 
  495         kn->kn_hook = sc;
  496 
  497         s = splsoftclock();
  498         SLIST_INSERT_HEAD(klist, kn, kn_selnext);
  499         splx(s);
  500 
  501         return (0);
  502 }
  503 
  504 void
  505 satlinktimeout(arg)
  506         void *arg;
  507 {
  508         struct satlink_softc *sc = arg;
  509         bus_size_t resid;
  510         int newidx;
  511 
  512         if ((sc->sc_flags & SATF_ISOPEN) == 0)
  513                 return;
  514 
  515         /*
  516          * Get the current residual count from the DMA controller
  517          * and compute the satlink's index into the ring buffer.
  518          */
  519         resid = isa_dmacount(sc->sc_ic, sc->sc_drq);
  520         newidx = sc->sc_bufsize - resid;
  521         if (newidx == sc->sc_bufsize)
  522                 newidx = 0;
  523 
  524         if (newidx == sc->sc_sptr)
  525                 goto out;
  526 
  527         sc->sc_sptr = newidx;
  528 
  529         /* Wake up anyone blocked in read... */
  530         if (sc->sc_flags & SATF_DATA) {
  531                 sc->sc_flags &= ~SATF_DATA;
  532                 wakeup(sc);
  533         }
  534 
  535         /* Wake up anyone blocked in poll... */
  536         selnotify(&sc->sc_selq, 0);
  537 
  538  out:
  539         callout_reset(&sc->sc_ch, SATLINK_TIMEOUT, satlinktimeout, sc);
  540 }

Cache object: 4941861594aa044ade102e1772a314fe


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