1 /*
2 * Copyright (c) 1982, 1986 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
6 * @(#)ad.c 7.8 (Berkeley) 12/16/90
7 */
8
9 #include "ad.h"
10 #if NAD > 0
11 /*
12 * Data translation AD converter interface -- Bill Reeves
13 */
14 #include "../include/pte.h"
15
16 #include "sys/param.h"
17 #include "sys/ioctl.h"
18 #include "sys/user.h"
19 #include "sys/buf.h"
20 #include "sys/systm.h"
21 #include "sys/map.h"
22
23 #include "ubareg.h"
24 #include "ubavar.h"
25 #include "adreg.h"
26
27 #define ADBUSY 01
28 #define ADWAITPRI (PZERO+1)
29
30 int adprobe(), adattach();
31 struct uba_device *addinfo[NAD];
32 u_short adstd[] = { 0770400, 0000000, 0 };
33 struct uba_driver addriver =
34 { adprobe, 0, adattach, 0, adstd, "ad", addinfo, 0, 0 };
35
36 struct ad {
37 char ad_open;
38 short int ad_uid;
39 short int ad_state;
40 short int ad_softcsr;
41 short int ad_softdata;
42 short int ad_chan;
43 int ad_icnt;
44 int ad_loop;
45 } ad[NAD];
46
47 #define ADUNIT(dev) (minor(dev))
48
adprobe(reg)49 adprobe(reg)
50 caddr_t reg;
51 {
52 register int br, cvec; /* value-result */
53 register struct addevice *adaddr = (struct addevice *) reg;
54
55 adaddr->ad_csr = AD_IENABLE | AD_START;
56 DELAY(40000);
57 adaddr->ad_csr = 0;
58 return (sizeof (struct addevice));
59 }
60
61 /*ARGSUSED*/
62 adattach(ui)
63 struct uba_device *ui;
64 {
65
66 }
67
adopen(dev)68 adopen(dev)
69 dev_t dev;
70 {
71 register struct ad *adp;
72 register struct uba_device *ui;
73
74 if (ADUNIT(dev) >= NAD || (adp = &ad[ADUNIT(dev)])->ad_open ||
75 (ui = addinfo[ADUNIT(dev)]) == 0 || ui->ui_alive == 0)
76 return (ENXIO);
77 adp->ad_open = 1;
78 adp->ad_icnt = 0;
79 adp->ad_state = 0;
80 adp->ad_uid = u.u_uid;
81 return (0);
82 }
83
adclose(dev)84 adclose(dev)
85 dev_t dev;
86 {
87
88 ad[ADUNIT(dev)].ad_open = 0;
89 ad[ADUNIT(dev)].ad_state = 0;
90 return (0);
91 }
92
93 /*ARGSUSED*/
adioctl(dev,cmd,addr,flag)94 adioctl(dev, cmd, addr, flag)
95 dev_t dev;
96 register caddr_t addr;
97 {
98 register struct addevice *adaddr =
99 (struct addevice *) addinfo[ADUNIT(dev)]->ui_addr;
100 register struct uba_device *ui = addinfo[ADUNIT(dev)];
101 register struct ad *adp;
102 register int i;
103 short int chan;
104
105 switch (cmd) {
106
107 case ADIOSCHAN:
108 adp = &ad[ADUNIT(dev)];
109 adp->ad_chan = (*(int *)addr)<<8;
110 break;
111
112 case ADIOGETW:
113 adp = &ad[ADUNIT(dev)];
114 spl6();
115 adaddr->ad_csr = adp->ad_chan;
116 i = 1000;
117 while (i-- > 0 && (adaddr->ad_csr&037400) != adp->ad_chan) {
118 adp->ad_loop++;
119 adaddr->ad_csr = adp->ad_chan;
120 }
121 adp->ad_state |= ADBUSY;
122 adaddr->ad_csr |= AD_IENABLE|AD_START;
123 i = 0;
124 while (adp->ad_state&ADBUSY)
125 if (i = tsleep((caddr_t)adp, ADWAITPRI | PCATCH,
126 devio, 0)
127 break;
128 spl0();
129 if (i)
130 return (i);
131 *(int *)addr = adp->ad_softdata;
132 break;
133
134 default:
135 return (ENOTTY); /* Not a legal ioctl cmd. */
136 }
137 return (0);
138 }
139
140 /*ARGSUSED*/
141 adintr(dev)
142 dev_t dev;
143 {
144 register struct addevice *adaddr =
145 (struct addevice *) addinfo[ADUNIT(dev)]->ui_addr;
146 register struct ad *adp = &ad[ADUNIT(dev)];
147
148 adp->ad_icnt++;
149 adp->ad_softcsr = adaddr->ad_csr;
150 adp->ad_softdata = adaddr->ad_data;
151 if(adp->ad_state&ADBUSY) {
152 adp->ad_state &= ~ADBUSY;
153 wakeup((caddr_t)adp);
154 }
155 }
156
157 adreset(uban)
158 int uban;
159 {
160 register int i;
161 register struct uba_device *ui;
162 register struct ad *adp = ad;
163 register struct addevice *adaddr;
164
165 for(i = 0; i < NAD; i++, adp++) {
166 if((ui = addinfo[i]) == 0 || ui->ui_alive == 0 ||
167 ui->ui_ubanum != uban || adp->ad_open == 0)
168 continue;
169 printf(" ad%d", i);
170 if(adp->ad_state&ADBUSY == 0)
171 continue;
172 adaddr = (struct addevice *) ui->ui_addr;
173 adaddr->ad_csr = 0;
174 adaddr->ad_csr = adp->ad_chan|AD_IENABLE|AD_START;
175 }
176 }
177 #endif
178