2 * Copyright (c) 1995 HD Associates, Inc.
7 * Pepperell, MA 01463-0276
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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
41 * $FreeBSD: src/sys/i386/isa/labpc.c,v 1.35 1999/09/25 18:24:08 phk Exp $
42 * $DragonFly: src/sys/dev/misc/labpc/labpc.c,v 1.23 2008/08/02 01:14:42 dillon Exp $
46 #include "use_labpc.h"
47 #include "opt_debug_outb.h"
48 #include <sys/param.h>
50 #include <sys/systm.h>
52 #include <sys/kernel.h>
53 #include <sys/malloc.h>
55 #define bio_actf bio_act.tqe_next
56 #include <sys/dataacq.h>
58 #include <sys/thread2.h>
61 #include <machine/clock.h>
64 #include <bus/isa/isa_device.h>
71 #define LABPC_MIN_TMO (hz)
74 #ifndef LABPC_DEFAULT_HERTZ
75 #define LABPC_DEFAULT_HERTZ 500
81 * S: SCAN bit for scan enable.
82 * I: INTERVAL for interval support
83 * D: 1: Digital I/O, 0: Analog I/O
86 * input: channel must be 0 to 7.
87 * output: channel must be 0 to 2
90 * 2: Alternate channel 0 then 1
93 * input: Channel must be 0 to 2.
94 * output: Channel must be 0 to 2.
100 #define UNIT(dev) (((minor(dev) & 0xB0) >> 6) & 0x3)
102 #define SCAN(dev) ((minor(dev) & 0x20) >> 5)
103 #define INTERVAL(dev) ((minor(dev) & 0x10) >> 4)
104 #define DIGITAL(dev) ((minor(dev) & 0x08) >> 3)
109 #define CHAN(dev) (minor(dev) & 0x7)
111 /* History: Derived from "dt2811.c" March 1995
117 #define DROPPED_INPUT 0x100
121 #define BUSY 0x00000001
127 struct bio start_queue; /* Start queue */
128 struct bio *last; /* End of start queue */
132 long tmo; /* Timeout in Hertz */
133 long min_tmo; /* Timeout in Hertz */
138 cdev_t dev; /* Copy of device */
140 void (*starter)(struct ctlr *ctlr, long count);
141 void (*stop)(struct ctlr *ctlr);
142 void (*intr)(struct ctlr *ctlr);
144 /* Digital I/O support. Copy of Data Control Register for 8255:
146 u_char dcr_val, dcr_is;
149 * Handle for canceling our timeout.
153 /* Device configuration structure:
158 /* loutb is a slow outb for debugging. The overrun test may fail
159 * with this for some slower processors.
162 loutb(int port, u_char val)
168 #define loutb(port, val) outb(port, val)
171 static struct ctlr **labpcs; /* XXX: Should be dynamic */
173 /* CR_EXPR: A macro that sets the shadow register in addition to
174 * sending out the data.
176 #define CR_EXPR(LABPC, CR, EXPR) do { \
177 (LABPC)->cr_image[CR - 1] EXPR ; \
178 loutb(((LABPC)->base + ( (CR == 4) ? (0x0F) : (CR - 1))), ((LABPC)->cr_image[(CR - 1)])); \
181 #define CR_CLR(LABPC, CR) CR_EXPR(LABPC, CR, &=0)
182 #define CR_REFRESH(LABPC, CR) CR_EXPR(LABPC, CR, &=0xff)
183 #define CR_SET(LABPC, CR, EXPR) CR_EXPR(LABPC, CR, = EXPR)
185 /* Configuration and Status Register Group.
187 #define CR1(LABPC) ((LABPC)->base + 0x00) /* Page 4-5 */
189 #define GAINMASK 0x70
190 #define GAIN(LABPC, SEL) do { \
191 (LABPC)->cr_image[1 - 1] &= ~GAINMASK; \
192 (LABPC)->cr_image[1 - 1] |= (SEL << 4); \
193 loutb((LABPC)->base + (1 - 1), (LABPC)->cr_image[(1 - 1)]); \
198 #define MA(LABPC, SEL) do { \
199 (LABPC)->cr_image[1 - 1] &= ~MAMASK; \
200 (LABPC)->cr_image[1 - 1] |= SEL; \
201 loutb((LABPC)->base + (1 - 1), (LABPC)->cr_image[(1 - 1)]); \
204 #define STATUS(LABPC) ((LABPC)->base + 0x00) /* Page 4-7 */
205 #define LABPCPLUS 0x80
206 #define EXTGATA0 0x40
210 #define OVERFLOW 0x04
214 #define CR2(LABPC) ((LABPC)->base + 0x01) /* Page 4-9 */
223 #define SWTRIGGERRED(LABPC) ((LABPC->cr_image[1]) & SWTRIG)
225 #define CR3(LABPC) ((LABPC)->base + 0x02) /* Page 4-11 */
226 #define FIFOINTEN 0x20
227 #define ERRINTEN 0x10
228 #define CNTINTEN 0x08
230 #define DIOINTEN 0x02
233 #define ALLINTEN 0x3E
234 #define FIFOINTENABLED(LABPC) ((LABPC->cr_image[2]) & FIFOINTEN)
236 #define CR4(LABPC) ((LABPC)->base + 0x0F) /* Page 4-13 */
243 /* Analog Input Register Group
245 #define ADFIFO(LABPC) ((LABPC)->base + 0x0A) /* Page 4-16 */
246 #define ADCLEAR(LABPC) ((LABPC)->base + 0x08) /* Page 4-18 */
247 #define ADSTART(LABPC) ((LABPC)->base + 0x03) /* Page 4-19 */
248 #define DMATCICLR(LABPC) ((LABPC)->base + 0x0A) /* Page 4-20 */
250 /* Analog Output Register Group
252 #define DAC0L(LABPC) ((LABPC)->base + 0x04) /* Page 4-22 */
253 #define DAC0H(LABPC) ((LABPC)->base + 0x05) /* Page 4-22 */
254 #define DAC1L(LABPC) ((LABPC)->base + 0x06) /* Page 4-22 */
255 #define DAC1H(LABPC) ((LABPC)->base + 0x07) /* Page 4-22 */
259 #define A0DATA(LABPC) ((LABPC)->base + 0x14)
260 #define A1DATA(LABPC) ((LABPC)->base + 0x15)
261 #define A2DATA(LABPC) ((LABPC)->base + 0x16)
262 #define AMODE(LABPC) ((LABPC)->base + 0x17)
264 #define TICR(LABPC) ((LABPC)->base + 0x0c)
266 #define B0DATA(LABPC) ((LABPC)->base + 0x18)
267 #define B1DATA(LABPC) ((LABPC)->base + 0x19)
268 #define B2DATA(LABPC) ((LABPC)->base + 0x1A)
269 #define BMODE(LABPC) ((LABPC)->base + 0x1B)
274 #define PORTX(LABPC, X) ((LABPC)->base + 0x10 + X)
276 #define PORTA(LABPC) PORTX(LABPC, 0)
277 #define PORTB(LABPC) PORTX(LABPC, 1)
278 #define PORTC(LABPC) PORTX(LABPC, 2)
280 #define DCR(LABPC) ((LABPC)->base + 0x13)
282 static int labpcattach(struct isa_device *dev);
283 static int labpcprobe(struct isa_device *dev);
284 struct isa_driver labpcdriver =
285 { labpcprobe, labpcattach, "labpc", 0 };
287 static d_open_t labpcopen;
288 static d_close_t labpcclose;
289 static d_ioctl_t labpcioctl;
290 static d_strategy_t labpcstrategy;
292 #define CDEV_MAJOR 66
293 static struct dev_ops labpc_ops = {
294 { "labpc", CDEV_MAJOR, 0 },
296 .d_close = labpcclose,
298 .d_write = physwrite,
299 .d_ioctl = labpcioctl,
300 .d_strategy = labpcstrategy,
303 static void labpcintr(void *);
304 static void start(struct ctlr *ctlr);
307 bp_done(struct bio *bio, int err)
309 struct buf *bp = bio->bio_buf;
311 if (err || bp->b_resid)
312 bp->b_flags |= B_ERROR;
316 static void tmo_stop(void *p);
319 done_and_start_next(struct ctlr *ctlr, struct bio *bio, int err)
321 struct buf *bp = bio->bio_buf;
323 bp->b_resid = ctlr->data_end - ctlr->data;
327 ctlr->start_queue.bio_actf = bio->bio_actf;
330 callout_stop(&ctlr->ch);
336 ad_clear(struct ctlr *ctlr)
339 loutb(ADCLEAR(ctlr), 0);
340 for (i = 0; i < 10000 && (inb(STATUS(ctlr)) & GATA0); i++)
342 (void)inb(ADFIFO(ctlr));
343 (void)inb(ADFIFO(ctlr));
346 /* reset: Reset the board following the sequence on page 5-1
349 reset(struct ctlr *ctlr)
352 CR_CLR(ctlr, 3); /* Turn off interrupts first */
359 loutb(AMODE(ctlr), 0x34);
360 loutb(A0DATA(ctlr),0x0A);
361 loutb(A0DATA(ctlr),0x00);
363 loutb(DMATCICLR(ctlr), 0x00);
364 loutb(TICR(ctlr), 0x00);
368 loutb(DAC0L(ctlr), 0);
369 loutb(DAC0H(ctlr), 0);
370 loutb(DAC1L(ctlr), 0);
371 loutb(DAC1H(ctlr), 0);
376 /* overrun: slam the start convert register and OVERRUN should get set:
379 overrun(struct ctlr *ctlr)
383 u_char status = inb(STATUS(ctlr));
384 for (i = 0; ((status & OVERRUN) == 0) && i < 100; i++)
386 loutb(ADSTART(ctlr), 1);
387 status = inb(STATUS(ctlr));
396 if (NLABPC > MAX_UNITS)
399 labpcs = kmalloc(NLABPC * sizeof(struct ctlr *), M_DEVBUF,
405 labpcprobe(struct isa_device *dev)
408 struct ctlr scratch, *ctlr, *l;
413 if (labpcinit() == 0)
415 kprintf("labpcprobe: init failed\n");
422 kprintf("Too many LAB-PCs. Reconfigure O/S.\n");
425 ctlr = &scratch; /* Need somebody with the right base for the macros */
426 ctlr->base = dev->id_iobase;
428 /* XXX: There really isn't a perfect way to probe this board.
429 * Here is my best attempt:
433 /* After reset none of these bits should be set:
435 status = inb(STATUS(ctlr));
436 if (status & (GATA0 | OVERFLOW | DAVAIL | OVERRUN))
439 /* Now try to overrun the board FIFO and get the overrun bit set:
441 status = overrun(ctlr);
443 if ((status & OVERRUN) == 0) /* No overrun bit set? */
446 /* Assume we have a board.
450 l = kmalloc(sizeof(struct ctlr), M_DEVBUF, M_WAITOK | M_ZERO);
451 l->base = ctlr->base;
454 dev->id_unit = l->unit;
460 /* attach: Set things in a normal state.
463 labpcattach(struct isa_device *dev)
465 struct ctlr *ctlr = labpcs[dev->id_unit];
467 dev->id_intr = (inthand2_t *)labpcintr;
468 callout_init(&ctlr->ch);
469 ctlr->sample_us = (1000000.0 / (double)LABPC_DEFAULT_HERTZ) + .50;
472 ctlr->min_tmo = LABPC_MIN_TMO;
474 ctlr->dcr_val = 0x80;
476 loutb(DCR(ctlr), ctlr->dcr_val);
478 dev_ops_add(&labpc_ops, -1, dev->id_unit);
479 make_dev(&labpc_ops, dev->id_unit, 0, 0, 0600,
480 "labpc%d", dev->id_unit);
486 static void null_intr (struct ctlr *ctlr) { }
487 static void null_start(struct ctlr *ctlr, long count) { }
488 static void null_stop (struct ctlr *ctlr) { }
491 trigger(struct ctlr *ctlr)
493 CR_EXPR(ctlr, 2, |= SWTRIG);
497 ad_start(struct ctlr *ctlr, long count)
499 if (!SWTRIGGERRED(ctlr)) {
500 int chan = CHAN(ctlr->dev);
501 CR_EXPR(ctlr, 1, &= ~SCANEN);
502 CR_EXPR(ctlr, 2, &= ~TBSEL);
505 GAIN(ctlr, ctlr->gains[chan]);
508 CR_EXPR(ctlr, 1, |= SCANEN);
510 loutb(AMODE(ctlr), 0x34);
511 loutb(A0DATA(ctlr), (u_char)((ctlr->sample_us & 0xff)));
512 loutb(A0DATA(ctlr), (u_char)((ctlr->sample_us >> 8)&0xff));
513 loutb(AMODE(ctlr), 0x70);
519 ctlr->tmo = ((count + 16) * (long)ctlr->sample_us * hz) / 1000000 +
524 ad_interval_start(struct ctlr *ctlr, long count)
526 int chan = CHAN(ctlr->dev);
527 int n_frames = count / (chan + 1);
529 if (!SWTRIGGERRED(ctlr)) {
530 CR_EXPR(ctlr, 1, &= ~SCANEN);
531 CR_EXPR(ctlr, 2, &= ~TBSEL);
534 GAIN(ctlr, ctlr->gains[chan]);
536 /* XXX: Is it really possible that you clear INTSCAN as
537 * the documentation says? That seems pretty unlikely.
539 CR_EXPR(ctlr, 4, &= ~INTSCAN); /* XXX: Is this possible? */
541 /* Program the sample interval counter to run as fast as
544 loutb(AMODE(ctlr), 0x34);
545 loutb(A0DATA(ctlr), (u_char)(0x02));
546 loutb(A0DATA(ctlr), (u_char)(0x00));
547 loutb(AMODE(ctlr), 0x70);
549 /* Program the interval scanning counter to run at the sample
552 loutb(BMODE(ctlr), 0x74);
553 loutb(B1DATA(ctlr), (u_char)((ctlr->sample_us & 0xff)));
554 loutb(B1DATA(ctlr), (u_char)((ctlr->sample_us >> 8)&0xff));
555 CR_EXPR(ctlr, 1, |= SCANEN);
561 /* Each frame time takes two microseconds per channel times
562 * the number of channels being sampled plus the sample period.
564 ctlr->tmo = ((n_frames + 16) *
565 ((long)ctlr->sample_us + (chan + 1 ) * 2 ) * hz) / 1000000 +
570 all_stop(struct ctlr *ctlr)
578 struct ctlr *ctlr = (struct ctlr *)p;
585 kprintf("labpc?: Null ctlr struct?\n");
590 kprintf("labpc%d: timeout", ctlr->unit);
594 bio = ctlr->start_queue.bio_actf;
597 kprintf(", Null bp.\n");
604 done_and_start_next(ctlr, bio, ETIMEDOUT);
609 static void ad_intr(struct ctlr *ctlr)
613 if (ctlr->cr_image[2] == 0)
615 if (ctlr->cleared_intr)
617 ctlr->cleared_intr = 0;
621 kprintf("ad_intr (should not happen) interrupt with interrupts off\n");
622 kprintf("status %x, cr3 %x\n", inb(STATUS(ctlr)), ctlr->cr_image[2]);
626 while ( (status = (inb(STATUS(ctlr)) & (DAVAIL|OVERRUN|OVERFLOW)) ) )
628 if ((status & (OVERRUN|OVERFLOW)))
630 struct bio *bio = ctlr->start_queue.bio_actf;
632 kprintf("ad_intr: error: bp %p, data %p, status %x",
633 bio->bio_buf, ctlr->data, status);
635 if (status & OVERRUN)
636 kprintf(" Conversion overrun (multiple A-D trigger)");
638 if (status & OVERFLOW)
639 kprintf(" FIFO overflow");
644 done_and_start_next(ctlr, bio, EIO);
647 kprintf("ad_intr: (should not happen) error between records\n");
648 ctlr->err = status; /* Set overrun condition */
652 else /* FIFO interrupt */
654 struct bio *bio = ctlr->start_queue.bio_actf;
657 *ctlr->data++ = inb(ADFIFO(ctlr));
658 if (ctlr->data == ctlr->data_end) {
659 /* Normal completion */
660 done_and_start_next(ctlr, bio, 0);
664 /* Interrupt with no where to put the data. */
665 kprintf("ad_intr: (should not happen) dropped input.\n");
666 (void)inb(ADFIFO(ctlr));
668 kprintf("bp %p, status %x, cr3 %x\n",
669 bio->bio_buf, status, ctlr->cr_image[2]);
670 ctlr->err = DROPPED_INPUT;
681 struct ctlr *ctlr = labpcs[unit];
685 /* lockout_multiple_opens: Return whether or not we can open again, or
686 * if the new mode is inconsistent with an already opened mode.
687 * We only permit multiple opens for digital I/O now.
691 lockout_multiple_open(cdev_t current, cdev_t next)
693 return ! (DIGITAL(current) && DIGITAL(next));
697 labpcopen(struct dev_open_args *ap)
699 cdev_t dev = ap->a_head.a_dev;
700 u_short unit = UNIT(dev);
704 if (unit >= MAX_UNITS)
712 /* Don't allow another open if we have to change modes.
715 if ( (ctlr->flags & BUSY) == 0)
724 ctlr->intr = null_intr;
725 ctlr->starter = null_start;
726 ctlr->stop = null_stop;
728 else if (lockout_multiple_open(ctlr->dev, dev))
735 labpcclose(struct dev_close_args *ap)
737 cdev_t dev = ap->a_head.a_dev;
738 struct ctlr *ctlr = labpcs[UNIT(dev)];
742 ctlr->flags &= ~BUSY;
748 * Start: Start a frame going in or out.
751 start(struct ctlr *ctlr)
756 if ((bio = ctlr->start_queue.bio_actf) == NULL) {
757 /* We must turn off FIFO interrupts when there is no
758 * place to put the data. We have to get back to
759 * reading before the FIFO overflows.
761 CR_EXPR(ctlr, 3, &= ~(FIFOINTEN|ERRINTEN));
762 ctlr->cleared_intr = 1;
768 ctlr->data = (u_char *)bp->b_data;
769 ctlr->data_end = ctlr->data + bp->b_bcount;
773 kprintf("labpc start: (should not happen) error between records.\n");
774 done_and_start_next(ctlr, bio, EIO);
780 kprintf("labpc start: (should not happen) NULL data pointer.\n");
781 done_and_start_next(ctlr, bio, EIO);
785 (*ctlr->starter)(ctlr, bp->b_bcount);
787 if (!FIFOINTENABLED(ctlr)) /* We can store the data again */
789 CR_EXPR(ctlr, 3, |= (FIFOINTEN|ERRINTEN));
791 /* Don't wait for the interrupts to fill things up.
796 callout_reset(&ctlr->ch, ctlr->tmo, tmo_stop, ctlr);
800 ad_strategy(struct bio *bio, struct ctlr *ctlr)
803 bio->bio_actf = NULL;
806 ctlr->last->bio_actf = bio;
810 ctlr->start_queue.bio_actf = bio;
817 /* da_strategy: Send data to the D-A. The CHAN field should be
820 * 2: Alternate port 0 then port 1
824 * 1. There is no state for CHAN field 2:
825 * the first sample in each buffer goes to channel 0.
827 * 2. No interrupt support yet.
830 da_strategy(struct bio *bio, struct ctlr *ctlr)
832 struct buf *bp = bio->bio_buf;
833 cdev_t dev = bio->bio_driver_info;
849 case 2: /* Device 2 handles both ports interleaved. */
850 if (bp->b_bcount <= 2)
856 len = bp->b_bcount / 2;
857 data = (u_char *)bp->b_data;
859 for (i = 0; i < len; i++)
861 loutb(DAC0H(ctlr), *data++);
862 loutb(DAC0L(ctlr), *data++);
863 loutb(DAC1H(ctlr), *data++);
864 loutb(DAC1L(ctlr), *data++);
867 bp->b_resid = bp->b_bcount & 3;
876 /* Port 0 or 1 falls through to here.
878 if (bp->b_bcount & 1) /* Odd transfers are illegal */
882 data = (u_char *)bp->b_data;
884 for (i = 0; i < len; i++)
886 loutb(port + 1, *data++);
887 loutb(port, *data++);
895 /* Input masks for MODE 0 of the ports treating PC as a single
896 * 8 bit port. Set these bits to set the port to input.
898 /* A B lowc highc combined */
899 static u_char set_input[] = { 0x10, 0x02, 0x01, 0x08, 0x09 };
901 static void flush_dcr(struct ctlr *ctlr)
903 if (ctlr->dcr_is != ctlr->dcr_val)
905 loutb(DCR(ctlr), ctlr->dcr_val);
906 ctlr->dcr_is = ctlr->dcr_val;
910 /* do: Digital output
913 digital_out_strategy(struct bio *bio, struct ctlr *ctlr)
915 struct buf *bp = bio->bio_buf;
916 cdev_t dev = bio->bio_driver_info;
921 int chan = CHAN(dev);
923 ctlr->dcr_val &= ~set_input[chan]; /* Digital out: Clear bit */
926 port = PORTX(ctlr, chan);
929 data = (u_char *)bp->b_data;
931 for (i = 0; i < len; i++)
933 loutb(port, *data++);
941 /* digital_in_strategy: Digital input
944 digital_in_strategy(struct bio *bio, struct ctlr *ctlr)
946 struct buf *bp = bio->bio_buf;
947 cdev_t dev = bio->bio_driver_info;
952 int chan = CHAN(dev);
954 ctlr->dcr_val |= set_input[chan]; /* Digital in: Set bit */
956 port = PORTX(ctlr, chan);
959 data = (u_char *)bp->b_data;
961 for (i = 0; i < len; i++)
973 labpcstrategy(struct dev_strategy_args *ap)
975 cdev_t dev = ap->a_head.a_dev;
976 struct bio *bio = ap->a_bio;
977 struct buf *bp = bio->bio_buf;
978 struct ctlr *ctlr = labpcs[UNIT(dev)];
980 bio->bio_driver_info = dev;
983 if (bp->b_cmd == BUF_CMD_READ) {
984 ctlr->starter = null_start;
985 ctlr->stop = all_stop;
986 ctlr->intr = null_intr;
987 digital_in_strategy(bio, ctlr);
991 ctlr->starter = null_start;
992 ctlr->stop = all_stop;
993 ctlr->intr = null_intr;
994 digital_out_strategy(bio, ctlr);
998 if (bp->b_cmd == BUF_CMD_READ) {
1000 ctlr->starter = INTERVAL(ctlr->dev) ? ad_interval_start : ad_start;
1001 ctlr->stop = all_stop;
1002 ctlr->intr = ad_intr;
1003 ad_strategy(bio, ctlr);
1007 ctlr->starter = null_start;
1008 ctlr->stop = all_stop;
1009 ctlr->intr = null_intr;
1010 da_strategy(bio, ctlr);
1017 labpcioctl(struct dev_ioctl_args *ap)
1019 cdev_t dev = ap->a_head.a_dev;
1020 caddr_t arg = ap->a_data;
1021 struct ctlr *ctlr = labpcs[UNIT(dev)];
1025 case AD_MICRO_PERIOD_SET:
1027 /* XXX I'm only supporting what I have to, which is
1028 * no slow periods. You can't get any slower than 15 Hz
1029 * with the current setup. To go slower you'll need to
1030 * support TCINTEN in CR3.
1033 long sample_us = *(long *)arg;
1035 if (sample_us > 65535)
1038 ctlr->sample_us = sample_us;
1042 case AD_MICRO_PERIOD_GET:
1043 *(long *)arg = ctlr->sample_us;
1054 case AD_SUPPORTED_GAINS:
1056 static double gains[] = {1., 1.25, 2., 5., 10., 20., 50., 100.};
1057 copyout(gains, *(caddr_t *)arg, sizeof(gains));
1064 copyin(*(caddr_t *)arg, ctlr->gains, sizeof(ctlr->gains));
1070 copyout(ctlr->gains, *(caddr_t *)arg, sizeof(ctlr->gains));