adb.c revision 1.39 1 /* $NetBSD: adb.c,v 1.39 2000/09/27 03:22:05 scottr Exp $ */
2
3 /*
4 * Copyright (C) 1994 Bradley A. Grantham
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Bradley A. Grantham.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include "opt_adb.h"
34
35 #include <sys/param.h>
36 #include <sys/device.h>
37 #include <sys/fcntl.h>
38 #include <sys/poll.h>
39 #include <sys/select.h>
40 #include <sys/proc.h>
41 #include <sys/signalvar.h>
42 #include <sys/systm.h>
43
44 #include <machine/autoconf.h>
45 #include <machine/cpu.h>
46
47 #include <mac68k/mac68k/macrom.h>
48 #include <mac68k/dev/adbvar.h>
49 #include <mac68k/dev/akbdvar.h>
50
51 #include "aed.h" /* ADB Event Device for compatibility */
52
53 /*
54 * Function declarations.
55 */
56 static int adbmatch __P((struct device *, struct cfdata *, void *));
57 static void adbattach __P((struct device *, struct device *, void *));
58 static int adbprint __P((void *, const char *));
59 void adb_config_interrupts __P((struct device *));
60
61 extern void adb_jadbproc __P((void));
62
63 /*
64 * Global variables.
65 */
66 int adb_polling = 0; /* Are we polling? (Debugger mode) */
67 #ifdef ADB_DEBUG
68 int adb_debug = 0; /* Output debugging messages */
69 #endif /* ADB_DEBUG */
70
71 extern struct mac68k_machine_S mac68k_machine;
72 extern int adbHardware;
73 extern char *adbHardwareDescr[];
74
75 /*
76 * Driver definition.
77 */
78 struct cfattach adb_ca = {
79 sizeof(struct device), adbmatch, adbattach
80 };
81
82 static int
83 adbmatch(parent, cf, aux)
84 struct device *parent;
85 struct cfdata *cf;
86 void *aux;
87 {
88 static int adb_matched = 0;
89
90 /* Allow only one instance. */
91 if (adb_matched)
92 return (0);
93
94 adb_matched = 1;
95 return (1);
96 }
97
98 static void
99 adbattach(parent, self, aux)
100 struct device *parent, *self;
101 void *aux;
102 {
103 printf("\n");
104
105 /*
106 * Defer configuration until interrupts are enabled.
107 */
108 config_interrupts(self, adb_config_interrupts);
109 }
110
111 void
112 adb_config_interrupts(self)
113 struct device *self;
114 {
115 ADBDataBlock adbdata;
116 struct adb_attach_args aa_args;
117 int totaladbs;
118 int adbindex, adbaddr;
119
120 printf("%s", self->dv_xname);
121 adb_polling = 1;
122
123 #ifdef MRG_ADB
124 if (!mrg_romready()) {
125 printf(": no ROM ADB driver in this kernel for this machine\n");
126 return;
127 }
128
129 #ifdef ADB_DEBUG
130 if (adb_debug)
131 printf("adb: call mrg_initadbintr\n");
132 #endif
133
134 mrg_initadbintr(); /* Mac ROM Glue okay to do ROM intr */
135 #ifdef ADB_DEBUG
136 if (adb_debug)
137 printf("adb: returned from mrg_initadbintr\n");
138 #endif
139
140 /* ADBReInit pre/post-processing */
141 JADBProc = adb_jadbproc;
142
143 /* Initialize ADB */
144 #ifdef ADB_DEBUG
145 if (adb_debug)
146 printf("adb: calling ADBAlternateInit.\n");
147 #endif
148
149 printf(" (mrg)");
150 ADBAlternateInit();
151 #else
152 ADBReInit();
153 printf(" (direct, %s)", adbHardwareDescr[adbHardware]);
154 #endif /* MRG_ADB */
155
156 #ifdef ADB_DEBUG
157 if (adb_debug)
158 printf("adb: done with ADBReInit\n");
159 #endif
160
161 totaladbs = CountADBs();
162
163 printf(": %d target%s\n", totaladbs, (totaladbs == 1) ? "" : "s");
164
165 #if NAED > 0
166 /* ADB event device for compatibility */
167 aa_args.origaddr = 0;
168 aa_args.adbaddr = 0;
169 aa_args.handler_id = 0;
170 (void)config_found(self, &aa_args, adbprint);
171 #endif
172
173 /* for each ADB device */
174 for (adbindex = 1; adbindex <= totaladbs; adbindex++) {
175 /* Get the ADB information */
176 adbaddr = GetIndADB(&adbdata, adbindex);
177
178 aa_args.origaddr = (int)(adbdata.origADBAddr);
179 aa_args.adbaddr = adbaddr;
180 aa_args.handler_id = (int)(adbdata.devType);
181
182 (void)config_found(self, &aa_args, adbprint);
183 }
184 adb_polling = 0;
185 }
186
187
188 int
189 adbprint(args, name)
190 void *args;
191 const char *name;
192 {
193 struct adb_attach_args *aa_args = (struct adb_attach_args *)args;
194 int rv = UNCONF;
195
196 if (name) { /* no configured device matched */
197 rv = UNSUPP; /* most ADB device types are unsupported */
198
199 /* print out what kind of ADB device we have found */
200 printf("%s addr %d: ", name, aa_args->adbaddr);
201 switch(aa_args->origaddr) {
202 #ifdef DIAGNOSTIC
203 case 0:
204 printf("ADB event device");
205 rv = UNCONF;
206 break;
207 case ADBADDR_SECURE:
208 printf("security dongle (%d)", aa_args->handler_id);
209 break;
210 #endif
211 case ADBADDR_MAP:
212 printf("mapped device (%d)", aa_args->handler_id);
213 rv = UNCONF;
214 break;
215 case ADBADDR_REL:
216 printf("relative positioning device (%d)",
217 aa_args->handler_id);
218 rv = UNCONF;
219 break;
220 #ifdef DIAGNOSTIC
221 case ADBADDR_ABS:
222 switch (aa_args->handler_id) {
223 case ADB_ARTPAD:
224 printf("WACOM ArtPad II");
225 break;
226 default:
227 printf("absolute positioning device (%d)",
228 aa_args->handler_id);
229 break;
230 }
231 break;
232 case ADBADDR_DATATX:
233 printf("data transfer device (modem?) (%d)",
234 aa_args->handler_id);
235 break;
236 case ADBADDR_MISC:
237 switch (aa_args->handler_id) {
238 case ADB_POWERKEY:
239 printf("Sophisticated Circuits PowerKey");
240 break;
241 default:
242 printf("misc. device (remote control?) (%d)",
243 aa_args->handler_id);
244 break;
245 }
246 break;
247 default:
248 printf("unknown type device, (handler %d)",
249 aa_args->handler_id);
250 break;
251 #endif /* DIAGNOSTIC */
252 }
253 } else /* a device matched and was configured */
254 printf(" addr %d: ", aa_args->adbaddr);
255
256 return (rv);
257 }
258
259
260 /*
261 * adb_op_sync
262 *
263 * This routine does exactly what the adb_op routine does, except that after
264 * the adb_op is called, it waits until the return value is present before
265 * returning.
266 *
267 * NOTE: The user specified compRout is ignored, since this routine specifies
268 * it's own to adb_op, which is why you really called this in the first place
269 * anyway.
270 */
271 int
272 adb_op_sync(Ptr buffer, Ptr compRout, Ptr data, short command)
273 {
274 int tmout;
275 int result;
276 volatile int flag = 0;
277
278 result = ADBOp(buffer, (void *)adb_op_comprout,
279 (void *)&flag, command); /* send command */
280 if (result == 0) { /* send ok? */
281 /*
282 * Total time to wait is calculated as follows:
283 * - Tlt (stop to start time): 260 usec
284 * - start bit: 100 usec
285 * - up to 8 data bytes: 64 * 100 usec = 6400 usec
286 * - stop bit (with SRQ): 140 usec
287 * Total: 6900 usec
288 */
289 for (tmout = 8000; !flag && tmout >= 10; tmout -= 10)
290 delay(10);
291 if (!flag && tmout > 0)
292 delay(tmout);
293
294 if (!flag)
295 result = -2;
296 }
297
298 return result;
299 }
300
301
302 /*
303 * adb_op_comprout
304 *
305 * This function is used by the adb_op_sync routine so it knows when the
306 * function is done.
307 */
308 void
309 adb_op_comprout(void)
310 {
311 #ifdef __NetBSD__
312 asm("movw #1,a2@ | update flag value");
313 #else /* for macos based testing */
314 asm {
315 move.w #1,(a2) } /* update flag value */
316 #endif
317 }
318