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/i386/isa/labpc.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 /*
    2  * Copyright (c) 1995 HD Associates, Inc.
    3  * All rights reserved.
    4  *
    5  * HD Associates, Inc.
    6  * PO Box 276
    7  * Pepperell, MA 01463-0276
    8  * dufault@hda.com
    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 HD Associates, Inc.
   21  * 4. The name of HD Associates, Inc.
   22  *    may not be used to endorse or promote products derived from this software
   23  *    without specific prior written permission.
   24  *
   25  * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES ``AS IS'' AND
   26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   35  * SUCH DAMAGE.
   36  *
   37  * Written by:
   38  * Peter Dufault
   39  * dufault@hda.com
   40  */
   41 
   42 #include "labpc.h"
   43 
   44 #include <sys/types.h>
   45 #include <sys/param.h>
   46 #include <sys/time.h>
   47 
   48 #include <sys/systm.h>
   49 
   50 #include <sys/kernel.h>
   51 #include <sys/malloc.h>
   52 #include <sys/errno.h>
   53 #include <sys/buf.h>
   54 #define b_actf  b_act.tqe_next
   55 #include <sys/dataacq.h>
   56 #include <sys/conf.h>
   57 #include <sys/kernel.h>
   58 #ifdef DEVFS
   59 #include <sys/devfsext.h>
   60 #endif /*DEVFS*/
   61 
   62 #include <machine/clock.h>
   63 
   64 #include <i386/isa/isa_device.h>
   65 
   66 
   67 
   68 /* Miniumum timeout:
   69  */
   70 #ifndef LABPC_MIN_TMO
   71 #define LABPC_MIN_TMO (hz)
   72 #endif
   73 
   74 #ifndef LABPC_DEFAULT_HERZ
   75 #define LABPC_DEFAULT_HERZ 500
   76 #endif
   77 
   78 /* Minor number:
   79  * UUSIDCCC
   80  * UU: Board unit.
   81  * S: SCAN bit for scan enable.
   82  * I: INTERVAL for interval support
   83  * D: 1: Digital I/O, 0: Analog I/O
   84  * CCC: Channel.
   85  *  Analog (D==0):
   86  *  input: channel must be 0 to 7.
   87  *  output: channel must be 0 to 2
   88  *          0: D-A 0
   89  *          1: D-A 1
   90  *          2: Alternate channel 0 then 1
   91  *
   92  *  Digital (D==1):
   93  *  input: Channel must be 0 to 2.
   94  *  output: Channel must be 0 to 2.
   95  */
   96 
   97 /* Up to four boards:
   98  */
   99 #define MAX_UNITS 4
  100 #define UNIT(dev) (((minor(dev) & 0xB0) >> 6) & 0x3)
  101 
  102 #define SCAN(dev)     ((minor(dev) & 0x20) >> 5)
  103 #define INTERVAL(dev) ((minor(dev) & 0x10) >> 4)
  104 #define DIGITAL(dev)  ((minor(dev) & 0x08) >> 3)
  105 
  106 /* Eight channels:
  107  */
  108 
  109 #define CHAN(dev) (minor(dev) & 0x7)
  110 
  111 /* History: Derived from "dt2811.c" March 1995
  112  */
  113 
  114 struct ctlr
  115 {
  116         int err;
  117 #define DROPPED_INPUT 0x100
  118         int base;
  119         int unit;
  120         unsigned long flags;
  121 #define BUSY 0x00000001
  122 
  123         u_char cr_image[4];
  124 
  125         u_short sample_us;
  126 
  127         struct buf start_queue; /* Start queue */
  128         struct buf *last;       /* End of start queue */
  129         u_char *data;
  130         u_char *data_end;
  131         long tmo;                       /* Timeout in Herz */
  132         long min_tmo;           /* Timeout in Herz */
  133         int cleared_intr;
  134 
  135         int gains[8];
  136 
  137         dev_t dev;                      /* Copy of device */
  138 
  139         void (*starter)(struct ctlr *ctlr, long count);
  140         void (*stop)(struct ctlr *ctlr);
  141         void (*intr)(struct ctlr *ctlr);
  142 
  143         /* Digital I/O support.  Copy of Data Control Register for 8255:
  144          */
  145         u_char dcr_val, dcr_is;
  146 
  147         /* Device configuration structure:
  148          */
  149 #ifdef DEVFS
  150         void *devfs_token;
  151 #endif
  152 };
  153 
  154 #ifdef LOUTB
  155 /* loutb is a slow outb for debugging.  The overrun test may fail
  156  * with this for some slower processors.
  157  */
  158 static inline void loutb(int port, u_char val)
  159 {
  160         outb(port, val);
  161         DELAY(1);
  162 }
  163 #else
  164 #define loutb(port, val) outb(port, val)
  165 #endif
  166 
  167 static struct ctlr **labpcs;    /* XXX: Should be dynamic */
  168 
  169 /* CR_EXPR: A macro that sets the shadow register in addition to
  170  * sending out the data.
  171  */
  172 #define CR_EXPR(LABPC, CR, EXPR) do { \
  173         (LABPC)->cr_image[CR - 1] EXPR ; \
  174         loutb(((LABPC)->base + ( (CR == 4) ? (0x0F) : (CR - 1))), ((LABPC)->cr_image[(CR - 1)])); \
  175 } while (0)
  176 
  177 #define CR_CLR(LABPC, CR) CR_EXPR(LABPC, CR, &=0)
  178 #define CR_REFRESH(LABPC, CR) CR_EXPR(LABPC, CR, &=0xff)
  179 #define CR_SET(LABPC, CR, EXPR) CR_EXPR(LABPC, CR, = EXPR)
  180 
  181 /* Configuration and Status Register Group.
  182  */
  183 #define     CR1(LABPC) ((LABPC)->base + 0x00)   /* Page 4-5 */
  184         #define SCANEN    0x80
  185         #define GAINMASK  0x70
  186         #define GAIN(LABPC, SEL) do { \
  187                 (LABPC)->cr_image[1 - 1] &= ~GAINMASK; \
  188                 (LABPC)->cr_image[1 - 1] |= (SEL << 4); \
  189                 loutb((LABPC)->base + (1 - 1), (LABPC)->cr_image[(1 - 1)]); \
  190                 } while (0)
  191 
  192         #define TWOSCMP   0x08
  193         #define MAMASK    0x07
  194         #define MA(LABPC, SEL) do { \
  195                 (LABPC)->cr_image[1 - 1] &= ~MAMASK; \
  196                 (LABPC)->cr_image[1 - 1] |= SEL; \
  197                 loutb((LABPC)->base + (1 - 1), (LABPC)->cr_image[(1 - 1)]); \
  198                 } while (0)
  199 
  200 #define  STATUS(LABPC) ((LABPC)->base + 0x00)   /* Page 4-7 */
  201         #define LABPCPLUS 0x80
  202         #define EXTGATA0  0x40
  203         #define GATA0     0x20
  204         #define DMATC     0x10
  205         #define CNTINT    0x08
  206         #define OVERFLOW  0x04
  207         #define OVERRUN   0x02
  208         #define DAVAIL    0x01
  209 
  210 #define     CR2(LABPC) ((LABPC)->base + 0x01)   /* Page 4-9 */
  211         #define LDAC1     0x80
  212         #define LDAC0     0x40
  213         #define _2SDAC1   0x20
  214         #define _2SDAC0   0x10
  215         #define TBSEL     0x08
  216         #define SWTRIG    0x04
  217         #define HWTRIG    0x02
  218         #define PRETRIG   0x01
  219         #define SWTRIGGERRED(LABPC) ((LABPC->cr_image[1]) & SWTRIG)
  220 
  221 #define     CR3(LABPC) ((LABPC)->base + 0x02)   /* Page 4-11 */
  222         #define FIFOINTEN 0x20
  223         #define ERRINTEN  0x10
  224         #define CNTINTEN  0x08
  225         #define TCINTEN   0x04
  226         #define DIOINTEN  0x02
  227         #define DMAEN     0x01
  228 
  229         #define ALLINTEN  0x3E
  230         #define FIFOINTENABLED(LABPC) ((LABPC->cr_image[2]) & FIFOINTEN)
  231 
  232 #define     CR4(LABPC) ((LABPC)->base + 0x0F)   /* Page 4-13 */
  233         #define ECLKRCV   0x10
  234         #define SE_D      0x08
  235         #define ECKDRV    0x04
  236         #define EOIRCV    0x02
  237         #define INTSCAN   0x01
  238 
  239 /* Analog Input Register Group
  240  */
  241 #define   ADFIFO(LABPC) ((LABPC)->base + 0x0A)  /* Page 4-16 */
  242 #define  ADCLEAR(LABPC) ((LABPC)->base + 0x08)  /* Page 4-18 */
  243 #define  ADSTART(LABPC) ((LABPC)->base + 0x03)  /* Page 4-19 */
  244 #define DMATCICLR(LABPC) ((LABPC)->base + 0x0A) /* Page 4-20 */
  245 
  246 /* Analog Output Register Group
  247  */
  248 #define    DAC0L(LABPC) ((LABPC)->base + 0x04)  /* Page 4-22 */
  249 #define    DAC0H(LABPC) ((LABPC)->base + 0x05)  /* Page 4-22 */
  250 #define    DAC1L(LABPC) ((LABPC)->base + 0x06)  /* Page 4-22 */
  251 #define    DAC1H(LABPC) ((LABPC)->base + 0x07)  /* Page 4-22 */
  252 
  253 /* 8253 registers:
  254  */
  255 #define A0DATA(LABPC) ((LABPC)->base + 0x14)
  256 #define A1DATA(LABPC) ((LABPC)->base + 0x15)
  257 #define A2DATA(LABPC) ((LABPC)->base + 0x16)
  258 #define AMODE(LABPC) ((LABPC)->base + 0x17)
  259 
  260 #define TICR(LABPC) ((LABPC)->base + 0x0c)
  261 
  262 #define B0DATA(LABPC) ((LABPC)->base + 0x18)
  263 #define B1DATA(LABPC) ((LABPC)->base + 0x19)
  264 #define B2DATA(LABPC) ((LABPC)->base + 0x1A)
  265 #define BMODE(LABPC) ((LABPC)->base + 0x1B)
  266 
  267 /* 8255 registers:
  268  */
  269 
  270 #define PORTX(LABPC, X) ((LABPC)->base + 0x10 + X)
  271 
  272 #define PORTA(LABPC) PORTX(LABPC, 0)
  273 #define PORTB(LABPC) PORTX(LABPC, 1)
  274 #define PORTC(LABPC) PORTX(LABPC, 2)
  275 
  276 #define DCR(LABPC) ((LABPC)->base + 0x13)
  277 
  278 static int labpcattach(struct isa_device *dev);
  279 static int labpcprobe(struct isa_device *dev);
  280 struct isa_driver labpcdriver =
  281         { labpcprobe, labpcattach, "labpc", 0  };
  282 
  283 static  d_open_t        labpcopen;
  284 static  d_close_t       labpcclose;
  285 static  d_ioctl_t       labpcioctl;
  286 static  d_strategy_t    labpcstrategy;
  287 
  288 #define CDEV_MAJOR 66
  289 static struct cdevsw labpc_cdevsw = 
  290         { labpcopen,    labpcclose,     rawread,        rawwrite,       /*66*/
  291           labpcioctl,   nostop,         nullreset,      nodevtotty,/* labpc */
  292           seltrue,      nommap,         labpcstrategy, "labpc", NULL,   -1 };
  293 
  294 static void start(struct ctlr *ctlr);
  295 
  296 static void
  297 bp_done(struct buf *bp, int err)
  298 {
  299         bp->b_error = err;
  300 
  301         if (err || bp->b_resid)
  302         {
  303                 bp->b_flags |= B_ERROR;
  304         }
  305 
  306         biodone(bp);
  307 }
  308 
  309 static void tmo_stop(void *p);
  310 
  311 static void
  312 done_and_start_next(struct ctlr *ctlr, struct buf *bp, int err)
  313 {
  314         bp->b_resid = ctlr->data_end - ctlr->data;
  315 
  316         ctlr->data = 0;
  317 
  318         ctlr->start_queue.b_actf = bp->b_actf;
  319         bp_done(bp, err);
  320 
  321         untimeout(tmo_stop, ctlr);
  322 
  323         start(ctlr);
  324 }
  325 
  326 static inline void
  327 ad_clear(struct ctlr *ctlr)
  328 {
  329         int i;
  330         loutb(ADCLEAR(ctlr), 0);
  331         for (i = 0; i < 10000 && (inb(STATUS(ctlr)) & GATA0); i++)
  332                 ;
  333         (void)inb(ADFIFO(ctlr));
  334         (void)inb(ADFIFO(ctlr));
  335 }
  336 
  337 /* reset: Reset the board following the sequence on page 5-1
  338  */
  339 static inline void
  340 reset(struct ctlr *ctlr)
  341 {
  342         int s = splhigh();
  343 
  344         CR_CLR(ctlr, 3);        /* Turn off interrupts first */
  345         splx(s);
  346 
  347         CR_CLR(ctlr, 1);
  348         CR_CLR(ctlr, 2);
  349         CR_CLR(ctlr, 4);
  350 
  351         loutb(AMODE(ctlr), 0x34);
  352         loutb(A0DATA(ctlr),0x0A);
  353         loutb(A0DATA(ctlr),0x00);
  354 
  355         loutb(DMATCICLR(ctlr), 0x00);
  356         loutb(TICR(ctlr), 0x00);
  357 
  358         ad_clear(ctlr);
  359 
  360         loutb(DAC0L(ctlr), 0);
  361         loutb(DAC0H(ctlr), 0);
  362         loutb(DAC1L(ctlr), 0);
  363         loutb(DAC1H(ctlr), 0);
  364 
  365         ad_clear(ctlr);
  366 }
  367 
  368 /* overrun: slam the start convert register and OVERRUN should get set:
  369  */
  370 static u_char
  371 overrun(struct ctlr *ctlr)
  372 {
  373         int i;
  374 
  375         u_char status = inb(STATUS(ctlr));
  376         for (i = 0; ((status & OVERRUN) == 0) && i < 100; i++)
  377         {
  378                 loutb(ADSTART(ctlr), 1);
  379                 status = inb(STATUS(ctlr));
  380         }
  381 
  382         return status;
  383 }
  384 
  385 static int
  386 labpcinit(void)
  387 {
  388         if (NLABPC > MAX_UNITS)
  389                 return 0;
  390 
  391         labpcs = malloc(NLABPC * sizeof(struct ctlr *), M_DEVBUF, M_NOWAIT);
  392         if (labpcs)
  393         {
  394                 bzero(labpcs, NLABPC * sizeof(struct cltr *));
  395                 return 1;
  396         }
  397         return 0;
  398 }
  399 
  400 static int
  401 labpcprobe(struct isa_device *dev)
  402 {
  403         static unit;
  404         struct ctlr scratch, *ctlr;
  405         u_char status;
  406 
  407         if (!labpcs)
  408         {
  409                 if (labpcinit() == 0)
  410                 {
  411                         printf("labpcprobe: init failed\n");
  412                         return 0;
  413                 }
  414         }
  415 
  416         if (unit > NLABPC)
  417         {
  418                 printf("Too many LAB-PCs.  Reconfigure O/S.\n");
  419                 return 0;
  420         }
  421         ctlr = &scratch;        /* Need somebody with the right base for the macros */
  422         ctlr->base = dev->id_iobase;
  423 
  424         /* XXX: There really isn't a perfect way to probe this board.
  425          *      Here is my best attempt:
  426          */
  427         reset(ctlr);
  428 
  429         /* After reset none of these bits should be set:
  430          */
  431         status = inb(STATUS(ctlr));
  432         if (status & (GATA0 | OVERFLOW | DAVAIL | OVERRUN))
  433                 return 0;
  434 
  435         /* Now try to overrun the board FIFO and get the overrun bit set:
  436          */
  437         status = overrun(ctlr);
  438 
  439         if ((status & OVERRUN) == 0)    /* No overrun bit set? */
  440                 return 0;
  441 
  442         /* Assume we have a board.
  443          */
  444         reset(ctlr);
  445 
  446         if ( (labpcs[unit] = malloc(sizeof(struct ctlr), M_DEVBUF, M_NOWAIT)) )
  447         {
  448                 struct ctlr *l = labpcs[unit];
  449 
  450                 bzero(l, sizeof(struct ctlr));
  451                 l->base = ctlr->base;
  452                 dev->id_unit = l->unit = unit;
  453 
  454                 unit++;
  455                 return 0x20;
  456         }
  457         else
  458         {
  459                 printf("labpc%d: Can't malloc.\n", unit);
  460                 return 0;
  461         }
  462 }
  463 
  464 /* attach: Set things in a normal state.
  465  */
  466 static int
  467 labpcattach(struct isa_device *dev)
  468 {
  469         struct ctlr *ctlr = labpcs[dev->id_unit];
  470 
  471         ctlr->sample_us = (1000000.0 / (double)LABPC_DEFAULT_HERZ) + .50;
  472         reset(ctlr);
  473 
  474         ctlr->min_tmo = LABPC_MIN_TMO;
  475 
  476         ctlr->dcr_val = 0x80;
  477         ctlr->dcr_is = 0x80;
  478         loutb(DCR(ctlr), ctlr->dcr_val);
  479 
  480 #ifdef DEVFS
  481         ctlr->devfs_token = 
  482                 devfs_add_devswf(&labpc_cdevsw, 0, DV_CHR, 
  483                                  /* what  UID GID PERM */
  484                                  0, 0, 0600, 
  485                                  "labpc%d", dev->id_unit);
  486 #endif
  487         return 1;
  488 }
  489 
  490 /* Null handlers:
  491  */
  492 static void null_intr (struct ctlr *ctlr)             { }
  493 static void null_start(struct ctlr *ctlr, long count) { }
  494 static void null_stop (struct ctlr *ctlr)             { }
  495 
  496 static inline void
  497 trigger(struct ctlr *ctlr)
  498 {
  499         CR_EXPR(ctlr, 2, |= SWTRIG);
  500 }
  501 
  502 static void
  503 ad_start(struct ctlr *ctlr, long count)
  504 {
  505         if (!SWTRIGGERRED(ctlr)) {
  506                 int chan = CHAN(ctlr->dev);
  507                 CR_EXPR(ctlr, 1, &= ~SCANEN);
  508                 CR_EXPR(ctlr, 2, &= ~TBSEL);
  509 
  510                 MA(ctlr, chan);
  511                 GAIN(ctlr, ctlr->gains[chan]);
  512 
  513                 if (SCAN(ctlr->dev))
  514                         CR_EXPR(ctlr, 1, |= SCANEN);
  515 
  516                 loutb(AMODE(ctlr), 0x34);
  517                 loutb(A0DATA(ctlr), (u_char)((ctlr->sample_us & 0xff)));
  518                 loutb(A0DATA(ctlr), (u_char)((ctlr->sample_us >> 8)&0xff));
  519                 loutb(AMODE(ctlr), 0x70);
  520 
  521                 ad_clear(ctlr);
  522                 trigger(ctlr);
  523         }
  524 
  525         ctlr->tmo = ((count + 16) * (long)ctlr->sample_us * hz) / 1000000 +
  526                 ctlr->min_tmo;
  527 }
  528 
  529 static void
  530 ad_interval_start(struct ctlr *ctlr, long count)
  531 {
  532         int chan = CHAN(ctlr->dev);
  533         int n_frames = count / (chan + 1);
  534 
  535         if (!SWTRIGGERRED(ctlr)) {
  536                 CR_EXPR(ctlr, 1, &= ~SCANEN);
  537                 CR_EXPR(ctlr, 2, &= ~TBSEL);
  538 
  539                 MA(ctlr, chan);
  540                 GAIN(ctlr, ctlr->gains[chan]);
  541 
  542                 /* XXX: Is it really possible that you clear INTSCAN as
  543                  * the documentation says?  That seems pretty unlikely.
  544                  */
  545                 CR_EXPR(ctlr, 4, &= ~INTSCAN);  /* XXX: Is this possible? */
  546 
  547                 /* Program the sample interval counter to run as fast as
  548                  * possible.
  549                  */
  550                 loutb(AMODE(ctlr), 0x34);
  551                 loutb(A0DATA(ctlr), (u_char)(0x02));
  552                 loutb(A0DATA(ctlr), (u_char)(0x00));
  553                 loutb(AMODE(ctlr), 0x70);
  554 
  555                 /* Program the interval scanning counter to run at the sample
  556                  * frequency.
  557                  */
  558                 loutb(BMODE(ctlr), 0x74);
  559                 loutb(B1DATA(ctlr), (u_char)((ctlr->sample_us & 0xff)));
  560                 loutb(B1DATA(ctlr), (u_char)((ctlr->sample_us >> 8)&0xff));
  561                 CR_EXPR(ctlr, 1, |= SCANEN);
  562 
  563                 ad_clear(ctlr);
  564                 trigger(ctlr);
  565         }
  566 
  567         /* Each frame time takes two microseconds per channel times
  568          * the number of channels being sampled plus the sample period.
  569          */
  570         ctlr->tmo = ((n_frames + 16) *
  571         ((long)ctlr->sample_us + (chan + 1 ) * 2 ) * hz) / 1000000 +
  572                 ctlr->min_tmo;
  573 }
  574 
  575 static void
  576 all_stop(struct ctlr *ctlr)
  577 {
  578         reset(ctlr);
  579 }
  580 
  581 static void
  582 tmo_stop(void *p)
  583 {
  584         struct ctlr *ctlr = (struct ctlr *)p;
  585         struct buf *bp;
  586 
  587         int s = spltty();
  588 
  589         if (ctlr == 0)
  590         {
  591                 printf("labpc?: Null ctlr struct?\n");
  592                 splx(s);
  593                 return;
  594         }
  595 
  596         printf("labpc%d: timeout", ctlr->unit);
  597 
  598         (*ctlr->stop)(ctlr);
  599 
  600         bp = ctlr->start_queue.b_actf;
  601 
  602         if (bp == 0) {
  603                 printf(", Null bp.\n");
  604                 splx(s);
  605                 return;
  606         }
  607 
  608         printf("\n");
  609 
  610         done_and_start_next(ctlr, bp, ETIMEDOUT);
  611 
  612         splx(s);
  613 }
  614 
  615 static void ad_intr(struct ctlr *ctlr)
  616 {
  617         u_char status;
  618 
  619         if (ctlr->cr_image[2] == 0)
  620         {
  621                 if (ctlr->cleared_intr)
  622                 {
  623                         ctlr->cleared_intr = 0;
  624                         return;
  625                 }
  626 
  627                 printf("ad_intr (should not happen) interrupt with interrupts off\n");
  628                 printf("status %x, cr3 %x\n", inb(STATUS(ctlr)), ctlr->cr_image[2]);
  629                 return;
  630         }
  631 
  632         while ( (status = (inb(STATUS(ctlr)) & (DAVAIL|OVERRUN|OVERFLOW)) ) )
  633         {
  634                 if ((status & (OVERRUN|OVERFLOW)))
  635                 {
  636                         struct buf *bp = ctlr->start_queue.b_actf;
  637 
  638                         printf("ad_intr: error: bp %0p, data %0p, status %x",
  639                         bp, ctlr->data, status);
  640 
  641                         if (status & OVERRUN)
  642                                 printf(" Conversion overrun (multiple A-D trigger)");
  643 
  644                         if (status & OVERFLOW)
  645                                 printf(" FIFO overflow");
  646 
  647                         printf("\n");
  648 
  649                         if (bp)
  650                         {
  651                                 done_and_start_next(ctlr, bp, EIO);
  652                                 return;
  653                         }
  654                         else
  655                         {
  656                                 printf("ad_intr: (should not happen) error between records\n");
  657                                 ctlr->err = status;     /* Set overrun condition */
  658                                 return;
  659                         }
  660                 }
  661                 else    /* FIFO interrupt */
  662                 {
  663                         struct buf *bp = ctlr->start_queue.b_actf;
  664 
  665                         if (ctlr->data)
  666                         {
  667                                 *ctlr->data++ = inb(ADFIFO(ctlr));
  668                                 if (ctlr->data == ctlr->data_end)       /* Normal completion */
  669                                 {
  670                                         done_and_start_next(ctlr, bp, 0);
  671                                         return;
  672                                 }
  673                         }
  674                         else    /* Interrupt with no where to put the data.  */
  675                         {
  676                                 printf("ad_intr: (should not happen) dropped input.\n");
  677                                 (void)inb(ADFIFO(ctlr));
  678 
  679                                 printf("bp %0p, status %x, cr3 %x\n", bp, status,
  680                                 ctlr->cr_image[2]);
  681 
  682                                 ctlr->err = DROPPED_INPUT;
  683                                 return;
  684                         }
  685                 }
  686         }
  687 }
  688 
  689 void labpcintr(int unit)
  690 {
  691         struct ctlr *ctlr = labpcs[unit];
  692         (*ctlr->intr)(ctlr);
  693 }
  694 
  695 /* lockout_multiple_opens: Return whether or not we can open again, or
  696  * if the new mode is inconsistent with an already opened mode.
  697  * We only permit multiple opens for digital I/O now.
  698  */
  699 
  700 static int
  701 lockout_multiple_open(dev_t current, dev_t next)
  702 {
  703         return ! (DIGITAL(current) && DIGITAL(next));
  704 }
  705 
  706 static  int
  707 labpcopen(dev_t dev, int flags, int fmt, struct proc *p)
  708 {
  709         u_short unit = UNIT(dev);
  710 
  711         struct ctlr *ctlr;
  712 
  713         if (unit >= MAX_UNITS)
  714                 return ENXIO;
  715 
  716         ctlr = labpcs[unit];
  717 
  718         if (ctlr == 0)
  719                 return ENXIO;
  720 
  721         /* Don't allow another open if we have to change modes.
  722          */
  723 
  724         if ( (ctlr->flags & BUSY) == 0)
  725         {
  726                 ctlr->flags |= BUSY;
  727 
  728                 reset(ctlr);
  729 
  730                 ctlr->err = 0;
  731                 ctlr->dev = dev;
  732 
  733                 ctlr->intr = null_intr;
  734                 ctlr->starter = null_start;
  735                 ctlr->stop = null_stop;
  736         }
  737         else if (lockout_multiple_open(ctlr->dev, dev))
  738                 return EBUSY;
  739 
  740         return 0;
  741 }
  742 
  743 static  int
  744 labpcclose(dev_t dev, int flags, int fmt, struct proc *p)
  745 {
  746         struct ctlr *ctlr = labpcs[UNIT(dev)];
  747 
  748         (*ctlr->stop)(ctlr);
  749 
  750         ctlr->flags &= ~BUSY;
  751 
  752         return 0;
  753 }
  754 
  755 /* Start: Start a frame going in or out.
  756  */
  757 static void
  758 start(struct ctlr *ctlr)
  759 {
  760         struct buf *bp;
  761 
  762         if ((bp = ctlr->start_queue.b_actf) == 0)
  763         {
  764                 /* We must turn off FIFO interrupts when there is no
  765                  * place to put the data.  We have to get back to
  766                  * reading before the FIFO overflows.
  767                  */
  768                 CR_EXPR(ctlr, 3, &= ~(FIFOINTEN|ERRINTEN));
  769                 ctlr->cleared_intr = 1;
  770                 ctlr->start_queue.b_bcount = 0;
  771                 return;
  772         }
  773 
  774         ctlr->data = (u_char *)bp->b_un.b_addr;
  775         ctlr->data_end = ctlr->data + bp->b_bcount;
  776 
  777         if (ctlr->err)
  778         {
  779                 printf("labpc start: (should not happen) error between records.\n");
  780                 done_and_start_next(ctlr, bp, EIO);
  781                 return;
  782         }
  783 
  784         if (ctlr->data == 0)
  785         {
  786                 printf("labpc start: (should not happen) NULL data pointer.\n");
  787                 done_and_start_next(ctlr, bp, EIO);
  788                 return;
  789         }
  790 
  791 
  792         (*ctlr->starter)(ctlr, bp->b_bcount);
  793 
  794         if (!FIFOINTENABLED(ctlr))      /* We can store the data again */
  795         {
  796                 CR_EXPR(ctlr, 3, |= (FIFOINTEN|ERRINTEN));
  797 
  798                 /* Don't wait for the interrupts to fill things up.
  799                  */
  800                 (*ctlr->intr)(ctlr);
  801         }
  802 
  803         timeout(tmo_stop, ctlr, ctlr->tmo);
  804 }
  805 
  806 static void
  807 ad_strategy(struct buf *bp, struct ctlr *ctlr)
  808 {
  809         int s;
  810 
  811         s = spltty();
  812         bp->b_actf = NULL;
  813 
  814         if (ctlr->start_queue.b_bcount)
  815         {
  816                 ctlr->last->b_actf = bp;
  817                 ctlr->last = bp;
  818         }
  819         else
  820         {
  821                 ctlr->start_queue.b_bcount = 1;
  822                 ctlr->start_queue.b_actf = bp;
  823                 ctlr->last = bp;
  824                 start(ctlr);
  825         }
  826         splx(s);
  827 }
  828 
  829 /* da_strategy: Send data to the D-A.  The CHAN field should be
  830  * 0: D-A port 0
  831  * 1: D-A port 1
  832  * 2: Alternate port 0 then port 1
  833  *
  834  * XXX:
  835  *
  836  * 1. There is no state for CHAN field 2:
  837  * the first sample in each buffer goes to channel 0.
  838  *
  839  * 2. No interrupt support yet.
  840  */
  841 static void
  842 da_strategy(struct buf *bp, struct ctlr *ctlr)
  843 {
  844         int len;
  845         u_char *data;
  846         int port;
  847         int i;
  848 
  849         switch(CHAN(bp->b_dev))
  850         {
  851                 case 0:
  852                         port = DAC0L(ctlr);
  853                         break;
  854 
  855                 case 1:
  856                         port = DAC1L(ctlr);
  857                         break;
  858 
  859                 case 2: /* Device 2 handles both ports interleaved. */
  860                         if (bp->b_bcount <= 2)
  861                         {
  862                                 port = DAC0L(ctlr);
  863                                 break;
  864                         }
  865 
  866                         len = bp->b_bcount / 2;
  867                         data = (u_char *)bp->b_un.b_addr;
  868 
  869                         for (i = 0; i < len; i++)
  870                         {
  871                                 loutb(DAC0H(ctlr), *data++);
  872                                 loutb(DAC0L(ctlr), *data++);
  873                                 loutb(DAC1H(ctlr), *data++);
  874                                 loutb(DAC1L(ctlr), *data++);
  875                         }
  876 
  877                         bp->b_resid = bp->b_bcount & 3;
  878                         bp_done(bp, 0);
  879                         return;
  880 
  881                 default:
  882                         bp_done(bp, ENXIO);
  883                         return;
  884         }
  885 
  886         /* Port 0 or 1 falls through to here.
  887          */
  888         if (bp->b_bcount & 1)   /* Odd transfers are illegal */
  889                 bp_done(bp, EIO);
  890 
  891         len = bp->b_bcount;
  892         data = (u_char *)bp->b_un.b_addr;
  893 
  894         for (i = 0; i < len; i++)
  895         {
  896                 loutb(port + 1, *data++);
  897                 loutb(port, *data++);
  898         }
  899 
  900         bp->b_resid = 0;
  901 
  902         bp_done(bp, 0);
  903 }
  904 
  905 /* Input masks for MODE 0 of the ports treating PC as a single
  906  * 8 bit port.  Set these bits to set the port to input.
  907  */
  908                             /* A     B    lowc  highc combined */
  909 static u_char set_input[] = { 0x10, 0x02, 0x01,  0x08,  0x09 };
  910 
  911 static void flush_dcr(struct ctlr *ctlr)
  912 {
  913         if (ctlr->dcr_is != ctlr->dcr_val)
  914         {
  915                 loutb(DCR(ctlr), ctlr->dcr_val);
  916                 ctlr->dcr_is = ctlr->dcr_val;
  917         }
  918 }
  919 
  920 /* do: Digital output
  921  */
  922 static void
  923 digital_out_strategy(struct buf *bp, struct ctlr *ctlr)
  924 {
  925         int len;
  926         u_char *data;
  927         int port;
  928         int i;
  929         int chan = CHAN(bp->b_dev);
  930 
  931         ctlr->dcr_val &= ~set_input[chan];      /* Digital out: Clear bit */
  932         flush_dcr(ctlr);
  933 
  934         port = PORTX(ctlr, chan);
  935 
  936         len = bp->b_bcount;
  937         data = (u_char *)bp->b_un.b_addr;
  938 
  939         for (i = 0; i < len; i++)
  940         {
  941                 loutb(port, *data++);
  942         }
  943 
  944         bp->b_resid = 0;
  945 
  946         bp_done(bp, 0);
  947 }
  948 
  949 /* digital_in_strategy: Digital input
  950  */
  951 static void
  952 digital_in_strategy(struct buf *bp, struct ctlr *ctlr)
  953 {
  954         int len;
  955         u_char *data;
  956         int port;
  957         int i;
  958         int chan = CHAN(bp->b_dev);
  959 
  960         ctlr->dcr_val |= set_input[chan];       /* Digital in: Set bit */
  961         flush_dcr(ctlr);
  962         port = PORTX(ctlr, chan);
  963 
  964         len = bp->b_bcount;
  965         data = (u_char *)bp->b_un.b_addr;
  966 
  967         for (i = 0; i < len; i++)
  968         {
  969                 *data++ = inb(port);
  970         }
  971 
  972         bp->b_resid = 0;
  973 
  974         bp_done(bp, 0);
  975 }
  976 
  977 
  978 static  void
  979 labpcstrategy(struct buf *bp)
  980 {
  981         struct ctlr *ctlr = labpcs[UNIT(bp->b_dev)];
  982 
  983         if (DIGITAL(bp->b_dev)) {
  984                 if (bp->b_flags & B_READ) {
  985                         ctlr->starter = null_start;
  986                         ctlr->stop = all_stop;
  987                         ctlr->intr = null_intr;
  988                         digital_in_strategy(bp, ctlr);
  989                 }
  990                 else
  991                 {
  992                         ctlr->starter = null_start;
  993                         ctlr->stop = all_stop;
  994                         ctlr->intr = null_intr;
  995                         digital_out_strategy(bp, ctlr);
  996                 }
  997         }
  998         else {
  999                 if (bp->b_flags & B_READ) {
 1000 
 1001                         ctlr->starter = INTERVAL(ctlr->dev) ? ad_interval_start : ad_start;
 1002                         ctlr->stop = all_stop;
 1003                         ctlr->intr = ad_intr;
 1004                         ad_strategy(bp, ctlr);
 1005                 }
 1006                 else
 1007                 {
 1008                         ctlr->starter = null_start;
 1009                         ctlr->stop = all_stop;
 1010                         ctlr->intr = null_intr;
 1011                         da_strategy(bp, ctlr);
 1012                 }
 1013         }
 1014 }
 1015 
 1016 static  int
 1017 labpcioctl(dev_t dev, int cmd, caddr_t arg, int mode, struct proc *p)
 1018 {
 1019         struct ctlr *ctlr = labpcs[UNIT(dev)];
 1020 
 1021         switch(cmd)
 1022         {
 1023                 case AD_MICRO_PERIOD_SET:
 1024                 {
 1025                         /* XXX I'm only supporting what I have to, which is
 1026                          * no slow periods.  You can't get any slower than 15 Hz
 1027                          * with the current setup.  To go slower you'll need to
 1028                          * support TCINTEN in CR3.
 1029                          */
 1030 
 1031                         long sample_us = *(long *)arg;
 1032 
 1033                         if (sample_us > 65535)
 1034                                 return EIO;
 1035 
 1036                         ctlr->sample_us = sample_us;
 1037                         return 0;
 1038                 }
 1039 
 1040                 case AD_MICRO_PERIOD_GET:
 1041                         *(long *)arg = ctlr->sample_us;
 1042                         return 0;
 1043 
 1044                 case AD_NGAINS_GET:
 1045                         *(int *)arg = 8;
 1046                         return 0;
 1047 
 1048                 case AD_NCHANS_GET:
 1049                         *(int *)arg = 8;
 1050                         return 0;
 1051 
 1052                 case AD_SUPPORTED_GAINS:
 1053                 {
 1054                         static double gains[] = {1., 1.25, 2., 5., 10., 20., 50., 100.};
 1055                         copyout(gains, *(caddr_t *)arg, sizeof(gains));
 1056 
 1057                         return 0;
 1058                 }
 1059 
 1060                 case AD_GAINS_SET:
 1061                 {
 1062                         copyin(*(caddr_t *)arg, ctlr->gains, sizeof(ctlr->gains));
 1063                         return 0;
 1064                 }
 1065 
 1066                 case AD_GAINS_GET:
 1067                 {
 1068                         copyout(ctlr->gains, *(caddr_t *)arg, sizeof(ctlr->gains));
 1069                         return 0;
 1070                 }
 1071 
 1072                 default:
 1073                         return ENOTTY;
 1074         }
 1075 }
 1076 
 1077 
 1078 static labpc_devsw_installed = 0;
 1079 
 1080 static void     labpc_drvinit(void *unused)
 1081 {
 1082         dev_t dev;
 1083 
 1084         if( ! labpc_devsw_installed ) {
 1085                 dev = makedev(CDEV_MAJOR,0);
 1086                 cdevsw_add(&dev,&labpc_cdevsw,NULL);
 1087                 labpc_devsw_installed = 1;
 1088         }
 1089 }
 1090 
 1091 SYSINIT(labpcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,labpc_drvinit,NULL)
 1092 
 1093 

Cache object: c42d8b2c1d10feed1d4bdb367640ff9f


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