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