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