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