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