Initial import from FreeBSD RELENG_4:
[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 "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 b_actf  b_act.tqe_next
55 #include <sys/dataacq.h>
56 #include <sys/conf.h>
57
58 #ifdef LOUTB
59 #include <machine/clock.h>
60 #endif
61
62 #include <i386/isa/isa_device.h>
63
64
65
66 /* Miniumum timeout:
67  */
68 #ifndef LABPC_MIN_TMO
69 #define LABPC_MIN_TMO (hz)
70 #endif
71
72 #ifndef LABPC_DEFAULT_HERZ
73 #define LABPC_DEFAULT_HERZ 500
74 #endif
75
76 /* Minor number:
77  * UUSIDCCC
78  * UU: Board unit.
79  * S: SCAN bit for scan enable.
80  * I: INTERVAL for interval support
81  * D: 1: Digital I/O, 0: Analog I/O
82  * CCC: Channel.
83  *  Analog (D==0):
84  *  input: channel must be 0 to 7.
85  *  output: channel must be 0 to 2
86  *          0: D-A 0
87  *          1: D-A 1
88  *          2: Alternate channel 0 then 1
89  *
90  *  Digital (D==1):
91  *  input: Channel must be 0 to 2.
92  *  output: Channel must be 0 to 2.
93  */
94
95 /* Up to four boards:
96  */
97 #define MAX_UNITS 4
98 #define UNIT(dev) (((minor(dev) & 0xB0) >> 6) & 0x3)
99
100 #define SCAN(dev)     ((minor(dev) & 0x20) >> 5)
101 #define INTERVAL(dev) ((minor(dev) & 0x10) >> 4)
102 #define DIGITAL(dev)  ((minor(dev) & 0x08) >> 3)
103
104 /* Eight channels:
105  */
106
107 #define CHAN(dev) (minor(dev) & 0x7)
108
109 /* History: Derived from "dt2811.c" March 1995
110  */
111
112 struct ctlr
113 {
114         int err;
115 #define DROPPED_INPUT 0x100
116         int base;
117         int unit;
118         unsigned long flags;
119 #define BUSY 0x00000001
120
121         u_char cr_image[4];
122
123         u_short sample_us;
124
125         struct buf start_queue; /* Start queue */
126         struct buf *last;       /* End of start queue */
127         u_char *data;
128         u_char *data_end;
129         long tmo;                       /* Timeout in Herz */
130         long min_tmo;           /* Timeout in Herz */
131         int cleared_intr;
132
133         int gains[8];
134
135         dev_t dev;                      /* Copy of device */
136
137         void (*starter)(struct ctlr *ctlr, long count);
138         void (*stop)(struct ctlr *ctlr);
139         void (*intr)(struct ctlr *ctlr);
140
141         /* Digital I/O support.  Copy of Data Control Register for 8255:
142          */
143         u_char dcr_val, dcr_is;
144
145         /*
146          * Handle for canceling our timeout.
147          */
148         struct callout_handle ch;
149
150         /* Device configuration structure:
151          */
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         /* open */      labpcopen,
291         /* close */     labpcclose,
292         /* read */      physread,
293         /* write */     physwrite,
294         /* ioctl */     labpcioctl,
295         /* poll */      nopoll,
296         /* mmap */      nommap,
297         /* strategy */  labpcstrategy,
298         /* name */      "labpc",
299         /* maj */       CDEV_MAJOR,
300         /* dump */      nodump,
301         /* psize */     nopsize,
302         /* flags */     0,
303         /* bmaj */      -1
304 };
305
306 static ointhand2_t labpcintr;
307 static void start(struct ctlr *ctlr);
308
309 static void
310 bp_done(struct buf *bp, int err)
311 {
312         bp->b_error = err;
313
314         if (err || bp->b_resid)
315         {
316                 bp->b_flags |= B_ERROR;
317         }
318
319         biodone(bp);
320 }
321
322 static void tmo_stop(void *p);
323
324 static void
325 done_and_start_next(struct ctlr *ctlr, struct buf *bp, int err)
326 {
327         bp->b_resid = ctlr->data_end - ctlr->data;
328
329         ctlr->data = 0;
330
331         ctlr->start_queue.b_actf = bp->b_actf;
332         bp_done(bp, err);
333
334         untimeout(tmo_stop, ctlr, ctlr->ch);
335
336         start(ctlr);
337 }
338
339 static __inline void
340 ad_clear(struct ctlr *ctlr)
341 {
342         int i;
343         loutb(ADCLEAR(ctlr), 0);
344         for (i = 0; i < 10000 && (inb(STATUS(ctlr)) & GATA0); i++)
345                 ;
346         (void)inb(ADFIFO(ctlr));
347         (void)inb(ADFIFO(ctlr));
348 }
349
350 /* reset: Reset the board following the sequence on page 5-1
351  */
352 static __inline void
353 reset(struct ctlr *ctlr)
354 {
355         int s = splhigh();
356
357         CR_CLR(ctlr, 3);        /* Turn off interrupts first */
358         splx(s);
359
360         CR_CLR(ctlr, 1);
361         CR_CLR(ctlr, 2);
362         CR_CLR(ctlr, 4);
363
364         loutb(AMODE(ctlr), 0x34);
365         loutb(A0DATA(ctlr),0x0A);
366         loutb(A0DATA(ctlr),0x00);
367
368         loutb(DMATCICLR(ctlr), 0x00);
369         loutb(TICR(ctlr), 0x00);
370
371         ad_clear(ctlr);
372
373         loutb(DAC0L(ctlr), 0);
374         loutb(DAC0H(ctlr), 0);
375         loutb(DAC1L(ctlr), 0);
376         loutb(DAC1H(ctlr), 0);
377
378         ad_clear(ctlr);
379 }
380
381 /* overrun: slam the start convert register and OVERRUN should get set:
382  */
383 static u_char
384 overrun(struct ctlr *ctlr)
385 {
386         int i;
387
388         u_char status = inb(STATUS(ctlr));
389         for (i = 0; ((status & OVERRUN) == 0) && i < 100; i++)
390         {
391                 loutb(ADSTART(ctlr), 1);
392                 status = inb(STATUS(ctlr));
393         }
394
395         return status;
396 }
397
398 static int
399 labpcinit(void)
400 {
401         if (NLABPC > MAX_UNITS)
402                 return 0;
403
404         labpcs = malloc(NLABPC * sizeof(struct ctlr *), M_DEVBUF, M_NOWAIT);
405         if (labpcs)
406         {
407                 bzero(labpcs, NLABPC * sizeof(struct ctlr *));
408                 return 1;
409         }
410         cdevsw_add(&labpc_cdevsw);
411         return 0;
412 }
413
414 static int
415 labpcprobe(struct isa_device *dev)
416 {
417         static int unit;
418         struct ctlr scratch, *ctlr;
419         u_char status;
420
421         if (!labpcs)
422         {
423                 if (labpcinit() == 0)
424                 {
425                         printf("labpcprobe: init failed\n");
426                         return 0;
427                 }
428         }
429
430         if (unit > NLABPC)
431         {
432                 printf("Too many LAB-PCs.  Reconfigure O/S.\n");
433                 return 0;
434         }
435         ctlr = &scratch;        /* Need somebody with the right base for the macros */
436         ctlr->base = dev->id_iobase;
437
438         /* XXX: There really isn't a perfect way to probe this board.
439          *      Here is my best attempt:
440          */
441         reset(ctlr);
442
443         /* After reset none of these bits should be set:
444          */
445         status = inb(STATUS(ctlr));
446         if (status & (GATA0 | OVERFLOW | DAVAIL | OVERRUN))
447                 return 0;
448
449         /* Now try to overrun the board FIFO and get the overrun bit set:
450          */
451         status = overrun(ctlr);
452
453         if ((status & OVERRUN) == 0)    /* No overrun bit set? */
454                 return 0;
455
456         /* Assume we have a board.
457          */
458         reset(ctlr);
459
460         if ( (labpcs[unit] = malloc(sizeof(struct ctlr), M_DEVBUF, M_NOWAIT)) )
461         {
462                 struct ctlr *l = labpcs[unit];
463
464                 bzero(l, sizeof(struct ctlr));
465                 l->base = ctlr->base;
466                 dev->id_unit = l->unit = unit;
467
468                 unit++;
469                 return 0x20;
470         }
471         else
472         {
473                 printf("labpc%d: Can't malloc.\n", unit);
474                 return 0;
475         }
476 }
477
478 /* attach: Set things in a normal state.
479  */
480 static int
481 labpcattach(struct isa_device *dev)
482 {
483         struct ctlr *ctlr = labpcs[dev->id_unit];
484
485         dev->id_ointr = labpcintr;
486         callout_handle_init(&ctlr->ch);
487         ctlr->sample_us = (1000000.0 / (double)LABPC_DEFAULT_HERZ) + .50;
488         reset(ctlr);
489
490         ctlr->min_tmo = LABPC_MIN_TMO;
491
492         ctlr->dcr_val = 0x80;
493         ctlr->dcr_is = 0x80;
494         loutb(DCR(ctlr), ctlr->dcr_val);
495
496         make_dev(&labpc_cdevsw, 0, 0, 0, 0600, "labpc%d", dev->id_unit);
497         return 1;
498 }
499
500 /* Null handlers:
501  */
502 static void null_intr (struct ctlr *ctlr)             { }
503 static void null_start(struct ctlr *ctlr, long count) { }
504 static void null_stop (struct ctlr *ctlr)             { }
505
506 static __inline void
507 trigger(struct ctlr *ctlr)
508 {
509         CR_EXPR(ctlr, 2, |= SWTRIG);
510 }
511
512 static void
513 ad_start(struct ctlr *ctlr, long count)
514 {
515         if (!SWTRIGGERRED(ctlr)) {
516                 int chan = CHAN(ctlr->dev);
517                 CR_EXPR(ctlr, 1, &= ~SCANEN);
518                 CR_EXPR(ctlr, 2, &= ~TBSEL);
519
520                 MA(ctlr, chan);
521                 GAIN(ctlr, ctlr->gains[chan]);
522
523                 if (SCAN(ctlr->dev))
524                         CR_EXPR(ctlr, 1, |= SCANEN);
525
526                 loutb(AMODE(ctlr), 0x34);
527                 loutb(A0DATA(ctlr), (u_char)((ctlr->sample_us & 0xff)));
528                 loutb(A0DATA(ctlr), (u_char)((ctlr->sample_us >> 8)&0xff));
529                 loutb(AMODE(ctlr), 0x70);
530
531                 ad_clear(ctlr);
532                 trigger(ctlr);
533         }
534
535         ctlr->tmo = ((count + 16) * (long)ctlr->sample_us * hz) / 1000000 +
536                 ctlr->min_tmo;
537 }
538
539 static void
540 ad_interval_start(struct ctlr *ctlr, long count)
541 {
542         int chan = CHAN(ctlr->dev);
543         int n_frames = count / (chan + 1);
544
545         if (!SWTRIGGERRED(ctlr)) {
546                 CR_EXPR(ctlr, 1, &= ~SCANEN);
547                 CR_EXPR(ctlr, 2, &= ~TBSEL);
548
549                 MA(ctlr, chan);
550                 GAIN(ctlr, ctlr->gains[chan]);
551
552                 /* XXX: Is it really possible that you clear INTSCAN as
553                  * the documentation says?  That seems pretty unlikely.
554                  */
555                 CR_EXPR(ctlr, 4, &= ~INTSCAN);  /* XXX: Is this possible? */
556
557                 /* Program the sample interval counter to run as fast as
558                  * possible.
559                  */
560                 loutb(AMODE(ctlr), 0x34);
561                 loutb(A0DATA(ctlr), (u_char)(0x02));
562                 loutb(A0DATA(ctlr), (u_char)(0x00));
563                 loutb(AMODE(ctlr), 0x70);
564
565                 /* Program the interval scanning counter to run at the sample
566                  * frequency.
567                  */
568                 loutb(BMODE(ctlr), 0x74);
569                 loutb(B1DATA(ctlr), (u_char)((ctlr->sample_us & 0xff)));
570                 loutb(B1DATA(ctlr), (u_char)((ctlr->sample_us >> 8)&0xff));
571                 CR_EXPR(ctlr, 1, |= SCANEN);
572
573                 ad_clear(ctlr);
574                 trigger(ctlr);
575         }
576
577         /* Each frame time takes two microseconds per channel times
578          * the number of channels being sampled plus the sample period.
579          */
580         ctlr->tmo = ((n_frames + 16) *
581         ((long)ctlr->sample_us + (chan + 1 ) * 2 ) * hz) / 1000000 +
582                 ctlr->min_tmo;
583 }
584
585 static void
586 all_stop(struct ctlr *ctlr)
587 {
588         reset(ctlr);
589 }
590
591 static void
592 tmo_stop(void *p)
593 {
594         struct ctlr *ctlr = (struct ctlr *)p;
595         struct buf *bp;
596
597         int s = spltty();
598
599         if (ctlr == 0)
600         {
601                 printf("labpc?: Null ctlr struct?\n");
602                 splx(s);
603                 return;
604         }
605
606         printf("labpc%d: timeout", ctlr->unit);
607
608         (*ctlr->stop)(ctlr);
609
610         bp = ctlr->start_queue.b_actf;
611
612         if (bp == 0) {
613                 printf(", Null bp.\n");
614                 splx(s);
615                 return;
616         }
617
618         printf("\n");
619
620         done_and_start_next(ctlr, bp, ETIMEDOUT);
621
622         splx(s);
623 }
624
625 static void ad_intr(struct ctlr *ctlr)
626 {
627         u_char status;
628
629         if (ctlr->cr_image[2] == 0)
630         {
631                 if (ctlr->cleared_intr)
632                 {
633                         ctlr->cleared_intr = 0;
634                         return;
635                 }
636
637                 printf("ad_intr (should not happen) interrupt with interrupts off\n");
638                 printf("status %x, cr3 %x\n", inb(STATUS(ctlr)), ctlr->cr_image[2]);
639                 return;
640         }
641
642         while ( (status = (inb(STATUS(ctlr)) & (DAVAIL|OVERRUN|OVERFLOW)) ) )
643         {
644                 if ((status & (OVERRUN|OVERFLOW)))
645                 {
646                         struct buf *bp = ctlr->start_queue.b_actf;
647
648                         printf("ad_intr: error: bp %p, data %p, status %x",
649                             (void *)bp, (void *)ctlr->data, status);
650
651                         if (status & OVERRUN)
652                                 printf(" Conversion overrun (multiple A-D trigger)");
653
654                         if (status & OVERFLOW)
655                                 printf(" FIFO overflow");
656
657                         printf("\n");
658
659                         if (bp)
660                         {
661                                 done_and_start_next(ctlr, bp, EIO);
662                                 return;
663                         }
664                         else
665                         {
666                                 printf("ad_intr: (should not happen) error between records\n");
667                                 ctlr->err = status;     /* Set overrun condition */
668                                 return;
669                         }
670                 }
671                 else    /* FIFO interrupt */
672                 {
673                         struct buf *bp = ctlr->start_queue.b_actf;
674
675                         if (ctlr->data)
676                         {
677                                 *ctlr->data++ = inb(ADFIFO(ctlr));
678                                 if (ctlr->data == ctlr->data_end)       /* Normal completion */
679                                 {
680                                         done_and_start_next(ctlr, bp, 0);
681                                         return;
682                                 }
683                         }
684                         else    /* Interrupt with no where to put the data.  */
685                         {
686                                 printf("ad_intr: (should not happen) dropped input.\n");
687                                 (void)inb(ADFIFO(ctlr));
688
689                                 printf("bp %p, status %x, cr3 %x\n",
690                                     (void *)bp, status, ctlr->cr_image[2]);
691
692                                 ctlr->err = DROPPED_INPUT;
693                                 return;
694                         }
695                 }
696         }
697 }
698
699 static void labpcintr(int unit)
700 {
701         struct ctlr *ctlr = labpcs[unit];
702         (*ctlr->intr)(ctlr);
703 }
704
705 /* lockout_multiple_opens: Return whether or not we can open again, or
706  * if the new mode is inconsistent with an already opened mode.
707  * We only permit multiple opens for digital I/O now.
708  */
709
710 static int
711 lockout_multiple_open(dev_t current, dev_t next)
712 {
713         return ! (DIGITAL(current) && DIGITAL(next));
714 }
715
716 static  int
717 labpcopen(dev_t dev, int flags, int fmt, struct proc *p)
718 {
719         u_short unit = UNIT(dev);
720
721         struct ctlr *ctlr;
722
723         if (unit >= MAX_UNITS)
724                 return ENXIO;
725
726         ctlr = labpcs[unit];
727
728         if (ctlr == 0)
729                 return ENXIO;
730
731         /* Don't allow another open if we have to change modes.
732          */
733
734         if ( (ctlr->flags & BUSY) == 0)
735         {
736                 ctlr->flags |= BUSY;
737
738                 reset(ctlr);
739
740                 ctlr->err = 0;
741                 ctlr->dev = dev;
742
743                 ctlr->intr = null_intr;
744                 ctlr->starter = null_start;
745                 ctlr->stop = null_stop;
746         }
747         else if (lockout_multiple_open(ctlr->dev, dev))
748                 return EBUSY;
749
750         return 0;
751 }
752
753 static  int
754 labpcclose(dev_t dev, int flags, int fmt, struct proc *p)
755 {
756         struct ctlr *ctlr = labpcs[UNIT(dev)];
757
758         (*ctlr->stop)(ctlr);
759
760         ctlr->flags &= ~BUSY;
761
762         return 0;
763 }
764
765 /*
766  * Start: Start a frame going in or out.
767  */
768 static void
769 start(struct ctlr *ctlr)
770 {
771         struct buf *bp;
772
773         if ((bp = ctlr->start_queue.b_actf) == 0)
774         {
775                 /* We must turn off FIFO interrupts when there is no
776                  * place to put the data.  We have to get back to
777                  * reading before the FIFO overflows.
778                  */
779                 CR_EXPR(ctlr, 3, &= ~(FIFOINTEN|ERRINTEN));
780                 ctlr->cleared_intr = 1;
781                 ctlr->start_queue.b_bcount = 0;
782                 return;
783         }
784
785         ctlr->data = (u_char *)bp->b_data;
786         ctlr->data_end = ctlr->data + bp->b_bcount;
787
788         if (ctlr->err)
789         {
790                 printf("labpc start: (should not happen) error between records.\n");
791                 done_and_start_next(ctlr, bp, EIO);
792                 return;
793         }
794
795         if (ctlr->data == 0)
796         {
797                 printf("labpc start: (should not happen) NULL data pointer.\n");
798                 done_and_start_next(ctlr, bp, EIO);
799                 return;
800         }
801
802
803         (*ctlr->starter)(ctlr, bp->b_bcount);
804
805         if (!FIFOINTENABLED(ctlr))      /* We can store the data again */
806         {
807                 CR_EXPR(ctlr, 3, |= (FIFOINTEN|ERRINTEN));
808
809                 /* Don't wait for the interrupts to fill things up.
810                  */
811                 (*ctlr->intr)(ctlr);
812         }
813
814         ctlr->ch = timeout(tmo_stop, ctlr, ctlr->tmo);
815 }
816
817 static void
818 ad_strategy(struct buf *bp, struct ctlr *ctlr)
819 {
820         int s;
821
822         s = spltty();
823         bp->b_actf = NULL;
824
825         if (ctlr->start_queue.b_bcount)
826         {
827                 ctlr->last->b_actf = bp;
828                 ctlr->last = bp;
829         }
830         else
831         {
832                 ctlr->start_queue.b_bcount = 1;
833                 ctlr->start_queue.b_actf = bp;
834                 ctlr->last = bp;
835                 start(ctlr);
836         }
837         splx(s);
838 }
839
840 /* da_strategy: Send data to the D-A.  The CHAN field should be
841  * 0: D-A port 0
842  * 1: D-A port 1
843  * 2: Alternate port 0 then port 1
844  *
845  * XXX:
846  *
847  * 1. There is no state for CHAN field 2:
848  * the first sample in each buffer goes to channel 0.
849  *
850  * 2. No interrupt support yet.
851  */
852 static void
853 da_strategy(struct buf *bp, struct ctlr *ctlr)
854 {
855         int len;
856         u_char *data;
857         int port;
858         int i;
859
860         switch(CHAN(bp->b_dev))
861         {
862                 case 0:
863                         port = DAC0L(ctlr);
864                         break;
865
866                 case 1:
867                         port = DAC1L(ctlr);
868                         break;
869
870                 case 2: /* Device 2 handles both ports interleaved. */
871                         if (bp->b_bcount <= 2)
872                         {
873                                 port = DAC0L(ctlr);
874                                 break;
875                         }
876
877                         len = bp->b_bcount / 2;
878                         data = (u_char *)bp->b_data;
879
880                         for (i = 0; i < len; i++)
881                         {
882                                 loutb(DAC0H(ctlr), *data++);
883                                 loutb(DAC0L(ctlr), *data++);
884                                 loutb(DAC1H(ctlr), *data++);
885                                 loutb(DAC1L(ctlr), *data++);
886                         }
887
888                         bp->b_resid = bp->b_bcount & 3;
889                         bp_done(bp, 0);
890                         return;
891
892                 default:
893                         bp_done(bp, ENXIO);
894                         return;
895         }
896
897         /* Port 0 or 1 falls through to here.
898          */
899         if (bp->b_bcount & 1)   /* Odd transfers are illegal */
900                 bp_done(bp, EIO);
901
902         len = bp->b_bcount;
903         data = (u_char *)bp->b_data;
904
905         for (i = 0; i < len; i++)
906         {
907                 loutb(port + 1, *data++);
908                 loutb(port, *data++);
909         }
910
911         bp->b_resid = 0;
912
913         bp_done(bp, 0);
914 }
915
916 /* Input masks for MODE 0 of the ports treating PC as a single
917  * 8 bit port.  Set these bits to set the port to input.
918  */
919                             /* A     B    lowc  highc combined */
920 static u_char set_input[] = { 0x10, 0x02, 0x01,  0x08,  0x09 };
921
922 static void flush_dcr(struct ctlr *ctlr)
923 {
924         if (ctlr->dcr_is != ctlr->dcr_val)
925         {
926                 loutb(DCR(ctlr), ctlr->dcr_val);
927                 ctlr->dcr_is = ctlr->dcr_val;
928         }
929 }
930
931 /* do: Digital output
932  */
933 static void
934 digital_out_strategy(struct buf *bp, struct ctlr *ctlr)
935 {
936         int len;
937         u_char *data;
938         int port;
939         int i;
940         int chan = CHAN(bp->b_dev);
941
942         ctlr->dcr_val &= ~set_input[chan];      /* Digital out: Clear bit */
943         flush_dcr(ctlr);
944
945         port = PORTX(ctlr, chan);
946
947         len = bp->b_bcount;
948         data = (u_char *)bp->b_data;
949
950         for (i = 0; i < len; i++)
951         {
952                 loutb(port, *data++);
953         }
954
955         bp->b_resid = 0;
956
957         bp_done(bp, 0);
958 }
959
960 /* digital_in_strategy: Digital input
961  */
962 static void
963 digital_in_strategy(struct buf *bp, struct ctlr *ctlr)
964 {
965         int len;
966         u_char *data;
967         int port;
968         int i;
969         int chan = CHAN(bp->b_dev);
970
971         ctlr->dcr_val |= set_input[chan];       /* Digital in: Set bit */
972         flush_dcr(ctlr);
973         port = PORTX(ctlr, chan);
974
975         len = bp->b_bcount;
976         data = (u_char *)bp->b_data;
977
978         for (i = 0; i < len; i++)
979         {
980                 *data++ = inb(port);
981         }
982
983         bp->b_resid = 0;
984
985         bp_done(bp, 0);
986 }
987
988
989 static  void
990 labpcstrategy(struct buf *bp)
991 {
992         struct ctlr *ctlr = labpcs[UNIT(bp->b_dev)];
993
994         if (DIGITAL(bp->b_dev)) {
995                 if (bp->b_flags & B_READ) {
996                         ctlr->starter = null_start;
997                         ctlr->stop = all_stop;
998                         ctlr->intr = null_intr;
999                         digital_in_strategy(bp, ctlr);
1000                 }
1001                 else
1002                 {
1003                         ctlr->starter = null_start;
1004                         ctlr->stop = all_stop;
1005                         ctlr->intr = null_intr;
1006                         digital_out_strategy(bp, ctlr);
1007                 }
1008         }
1009         else {
1010                 if (bp->b_flags & B_READ) {
1011
1012                         ctlr->starter = INTERVAL(ctlr->dev) ? ad_interval_start : ad_start;
1013                         ctlr->stop = all_stop;
1014                         ctlr->intr = ad_intr;
1015                         ad_strategy(bp, ctlr);
1016                 }
1017                 else
1018                 {
1019                         ctlr->starter = null_start;
1020                         ctlr->stop = all_stop;
1021                         ctlr->intr = null_intr;
1022                         da_strategy(bp, ctlr);
1023                 }
1024         }
1025 }
1026
1027 static  int
1028 labpcioctl(dev_t dev, u_long cmd, caddr_t arg, int mode, struct proc *p)
1029 {
1030         struct ctlr *ctlr = labpcs[UNIT(dev)];
1031
1032         switch(cmd)
1033         {
1034                 case AD_MICRO_PERIOD_SET:
1035                 {
1036                         /* XXX I'm only supporting what I have to, which is
1037                          * no slow periods.  You can't get any slower than 15 Hz
1038                          * with the current setup.  To go slower you'll need to
1039                          * support TCINTEN in CR3.
1040                          */
1041
1042                         long sample_us = *(long *)arg;
1043
1044                         if (sample_us > 65535)
1045                                 return EIO;
1046
1047                         ctlr->sample_us = sample_us;
1048                         return 0;
1049                 }
1050
1051                 case AD_MICRO_PERIOD_GET:
1052                         *(long *)arg = ctlr->sample_us;
1053                         return 0;
1054
1055                 case AD_NGAINS_GET:
1056                         *(int *)arg = 8;
1057                         return 0;
1058
1059                 case AD_NCHANS_GET:
1060                         *(int *)arg = 8;
1061                         return 0;
1062
1063                 case AD_SUPPORTED_GAINS:
1064                 {
1065                         static double gains[] = {1., 1.25, 2., 5., 10., 20., 50., 100.};
1066                         copyout(gains, *(caddr_t *)arg, sizeof(gains));
1067
1068                         return 0;
1069                 }
1070
1071                 case AD_GAINS_SET:
1072                 {
1073                         copyin(*(caddr_t *)arg, ctlr->gains, sizeof(ctlr->gains));
1074                         return 0;
1075                 }
1076
1077                 case AD_GAINS_GET:
1078                 {
1079                         copyout(ctlr->gains, *(caddr_t *)arg, sizeof(ctlr->gains));
1080                         return 0;
1081                 }
1082
1083                 default:
1084                         return ENOTTY;
1085         }
1086 }