Annotation of sys/arch/macppc/dev/adb.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: adb.c,v 1.27 2007/04/23 16:27:20 deraadt Exp $ */
2: /* $NetBSD: adb.c,v 1.6 1999/08/16 06:28:09 tsubai Exp $ */
3: /* $NetBSD: adb_direct.c,v 1.14 2000/06/08 22:10:45 tsubai Exp $ */
4:
5: /*
6: * Copyright (C) 1996, 1997 John P. Wittkoski
7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. All advertising materials mentioning features or use of this software
18: * must display the following acknowledgement:
19: * This product includes software developed by John P. Wittkoski.
20: * 4. The name of the author may not be used to endorse or promote products
21: * derived from this software without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33: */
34:
35: /*-
36: * Copyright (C) 1994 Bradley A. Grantham
37: * All rights reserved.
38: *
39: * Redistribution and use in source and binary forms, with or without
40: * modification, are permitted provided that the following conditions
41: * are met:
42: * 1. Redistributions of source code must retain the above copyright
43: * notice, this list of conditions and the following disclaimer.
44: * 2. Redistributions in binary form must reproduce the above copyright
45: * notice, this list of conditions and the following disclaimer in the
46: * documentation and/or other materials provided with the distribution.
47: * 3. All advertising materials mentioning features or use of this software
48: * must display the following acknowledgement:
49: * This product includes software developed by Bradley A. Grantham.
50: * 4. The name of the author may not be used to endorse or promote products
51: * derived from this software without specific prior written permission.
52: *
53: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
54: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
55: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
56: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
57: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
58: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
59: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
60: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
61: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
62: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
63: */
64:
65: /*
66: * This code is rather messy, but I don't have time right now
67: * to clean it up as much as I would like.
68: * But it works, so I'm happy. :-) jpw
69: */
70:
71: /*
72: * TO DO:
73: * - We could reduce the time spent in the adb_intr_* routines
74: * by having them save the incoming and outgoing data directly
75: * in the adbInbound and adbOutbound queues, as it would reduce
76: * the number of times we need to copy the data around. It
77: * would also make the code more readable and easier to follow.
78: * - (Related to above) Use the header part of adbCommand to
79: * reduce the number of copies we have to do of the data.
80: * - (Related to above) Actually implement the adbOutbound queue.
81: * This is fairly easy once you switch all the intr routines
82: * over to using adbCommand structs directly.
83: * - There is a bug in the state machine of adb_intr_cuda
84: * code that causes hangs, especially on 030 machines, probably
85: * because of some timing issues. Because I have been unable to
86: * determine the exact cause of this bug, I used the timeout function
87: * to check for and recover from this condition. If anyone finds
88: * the actual cause of this bug, the calls to timeout and the
89: * adb_cuda_tickle routine can be removed.
90: */
91:
92: #include <sys/param.h>
93: #include <sys/device.h>
94: #include <sys/fcntl.h>
95: #include <sys/poll.h>
96: #include <sys/selinfo.h>
97: #include <sys/proc.h>
98: #include <sys/signalvar.h>
99: #include <sys/timeout.h>
100: #include <sys/systm.h>
101:
102: #include <machine/autoconf.h>
103: #include <machine/cpu.h>
104: #include <dev/ofw/openfirm.h>
105:
106: #include <dev/adb/adb.h>
107: #include <macppc/dev/adbvar.h>
108: #include <macppc/dev/pm_direct.h>
109: #include <macppc/dev/viareg.h>
110:
111: #include "apm.h"
112:
113: #define printf_intr printf
114:
115: #ifdef DEBUG
116: #ifndef ADB_DEBUG
117: #define ADB_DEBUG
118: #endif
119: #endif
120:
121: int adb_polling; /* Are we polling? (Debugger mode) */
122: #ifdef ADB_DEBUG
123: int adb_debug; /* Output debugging messages */
124: #endif /* ADB_DEBUG */
125:
126: /* some misc. leftovers */
127: #define vPB 0x0000
128: #define vPB3 0x08
129: #define vPB4 0x10
130: #define vPB5 0x20
131: #define vSR_INT 0x04
132: #define vSR_OUT 0x10
133:
134: /* the type of ADB action that we are currently performing */
135: #define ADB_ACTION_NOTREADY 0x1 /* has not been initialized yet */
136: #define ADB_ACTION_IDLE 0x2 /* the bus is currently idle */
137: #define ADB_ACTION_OUT 0x3 /* sending out a command */
138: #define ADB_ACTION_IN 0x4 /* receiving data */
139:
140: /*
141: * Shortcuts for setting or testing the VIA bit states.
142: * Not all shortcuts are used for every type of ADB hardware.
143: */
144: #define ADB_SET_STATE_IDLE_CUDA() via_reg_or(VIA1, vBufB, (vPB4 | vPB5))
145: #define ADB_SET_STATE_TIP() via_reg_and(VIA1, vBufB, ~vPB5)
146: #define ADB_CLR_STATE_TIP() via_reg_or(VIA1, vBufB, vPB5)
147: #define ADB_TOGGLE_STATE_ACK_CUDA() via_reg_xor(VIA1, vBufB, vPB4)
148: #define ADB_SET_STATE_ACKOFF_CUDA() via_reg_or(VIA1, vBufB, vPB4)
149: #define ADB_SET_SR_INPUT() via_reg_and(VIA1, vACR, ~vSR_OUT)
150: #define ADB_SET_SR_OUTPUT() via_reg_or(VIA1, vACR, vSR_OUT)
151: #define ADB_SR() read_via_reg(VIA1, vSR)
152: #define ADB_VIA_INTR_ENABLE() write_via_reg(VIA1, vIER, 0x84)
153: #define ADB_VIA_INTR_DISABLE() write_via_reg(VIA1, vIER, 0x04)
154: #define ADB_VIA_CLR_INTR() write_via_reg(VIA1, vIFR, 0x04)
155: #define ADB_INTR_IS_OFF (vPB3 == (read_via_reg(VIA1, vBufB) & vPB3))
156: #define ADB_INTR_IS_ON (0 == (read_via_reg(VIA1, vBufB) & vPB3))
157: #define ADB_SR_INTR_IS_ON (vSR_INT == (read_via_reg(VIA1, \
158: vIFR) & vSR_INT))
159:
160: /*
161: * This is the delay that is required (in uS) between certain
162: * ADB transactions. The actual timing delay for for each uS is
163: * calculated at boot time to account for differences in machine speed.
164: */
165: #define ADB_DELAY 150
166:
167: /*
168: * Maximum ADB message length; includes space for data, result, and
169: * device code - plus a little for safety.
170: */
171: #define ADB_MAX_MSG_LENGTH 16
172: #define ADB_MAX_HDR_LENGTH 8
173:
174: #define ADB_QUEUE 32
175: #define ADB_TICKLE_TICKS 4
176:
177: /*
178: * A structure for storing information about each ADB device.
179: */
180: struct ADBDevEntry {
181: void (*ServiceRtPtr)(void);
182: void *DataAreaAddr;
183: int devType;
184: int origAddr;
185: int currentAddr;
186: };
187:
188: /*
189: * Used to hold ADB commands that are waiting to be sent out.
190: */
191: struct adbCmdHoldEntry {
192: u_char outBuf[ADB_MAX_MSG_LENGTH]; /* our message */
193: u_char *saveBuf; /* buffer to know where to save result */
194: u_char *compRout; /* completion routine pointer */
195: u_char *data; /* completion routine data pointer */
196: };
197:
198: /*
199: * Eventually used for two separate queues, the queue between
200: * the upper and lower halves, and the outgoing packet queue.
201: * TO DO: adbCommand can replace all of adbCmdHoldEntry eventually
202: */
203: struct adbCommand {
204: u_char header[ADB_MAX_HDR_LENGTH]; /* not used yet */
205: u_char data[ADB_MAX_MSG_LENGTH]; /* packet data only */
206: u_char *saveBuf; /* where to save result */
207: u_char *compRout; /* completion routine pointer */
208: u_char *compData; /* completion routine data pointer */
209: u_int cmd; /* the original command for this data */
210: u_int unsol; /* 1 if packet was unsolicited */
211: u_int ack_only; /* 1 for no special processing */
212: };
213:
214: /*
215: * A few variables that we need and their initial values.
216: */
217: int adbHardware = ADB_HW_UNKNOWN;
218: int adbActionState = ADB_ACTION_NOTREADY;
219: int adbWaiting; /* waiting for return data from the device */
220: int adbWriteDelay; /* working on (or waiting to do) a write */
221: int adbSoftPower; /* machine supports soft power */
222:
223: int adbWaitingCmd; /* ADB command we are waiting for */
224: u_char *adbBuffer; /* pointer to user data area */
225: void *adbCompRout; /* pointer to the completion routine */
226: void *adbCompData; /* pointer to the completion routine data */
227: int adbStarting = 1; /* doing adb_reinit so do polling differently */
228:
229: u_char adbInputBuffer[ADB_MAX_MSG_LENGTH]; /* data input buffer */
230: u_char adbOutputBuffer[ADB_MAX_MSG_LENGTH]; /* data output buffer */
231: struct adbCmdHoldEntry adbOutQueue; /* our 1 entry output queue */
232:
233: int adbSentChars; /* how many characters we have sent */
234:
235: struct ADBDevEntry ADBDevTable[16]; /* our ADB device table */
236: int ADBNumDevices; /* num. of ADB devices found with adb_reinit */
237:
238: struct adbCommand adbInbound[ADB_QUEUE]; /* incoming queue */
239: int adbInCount; /* how many packets in in queue */
240: int adbInHead; /* head of in queue */
241: int adbInTail; /* tail of in queue */
242: struct adbCommand adbOutbound[ADB_QUEUE]; /* outgoing queue - not used yet */
243: int adbOutCount; /* how many packets in out queue */
244: int adbOutHead; /* head of out queue */
245: int adbOutTail; /* tail of out queue */
246:
247: int tickle_count; /* how many tickles seen for this packet? */
248: int tickle_serial; /* the last packet tickled */
249: int adb_cuda_serial; /* the current packet */
250: struct timeout adb_cuda_timeout;
251: struct timeout adb_softintr_timeout;
252: int adbempty; /* nonzero if no adb devices */
253:
254: volatile u_char *Via1Base;
255:
256: /*
257: * The following are private routines.
258: */
259: #ifdef ADB_DEBUG
260: void print_single(u_char *);
261: #endif
262: void adb_intr_cuda(void);
263: void adb_soft_intr(void);
264: int send_adb_cuda(u_char *, u_char *, void *, void *, int);
265: void adb_cuda_tickle(void);
266: void adb_pass_up(struct adbCommand *);
267: void adb_op_comprout(caddr_t, caddr_t, int);
268: void adb_reinit(void);
269: int count_adbs(void);
270: int get_ind_adb_info(ADBDataBlock *, int);
271: int get_adb_info(ADBDataBlock *, int);
272: void adb_setup_hw_type(void);
273: int adb_op(Ptr, Ptr, Ptr, short);
274: void adb_hw_setup(void);
275: int adb_cmd_result(u_char *);
276: void setsoftadb(void);
277:
278: int adb_intr(void *arg);
279: void adb_cuda_autopoll(void);
280: void adb_cuda_fileserver_mode(void);
281:
282: #ifdef ADB_DEBUG
283: /*
284: * print_single
285: * Diagnostic display routine. Displays the hex values of the
286: * specified elements of the u_char. The length of the "string"
287: * is in [0].
288: */
289: void
290: print_single(str)
291: u_char *str;
292: {
293: int x;
294:
295: if (str == NULL) {
296: printf_intr("no data - null pointer\n");
297: return;
298: }
299: if (*str == '\0') {
300: printf_intr("nothing returned\n");
301: return;
302: }
303: if (*str > 20) {
304: printf_intr("ADB: ACK > 20 no way!\n");
305: *str = 20;
306: }
307: printf_intr("(length=0x%x):", *str);
308: for (x = 1; x <= *str; x++)
309: printf_intr(" 0x%02x", str[x]);
310: printf_intr("\n");
311: }
312: #endif
313:
314: void
315: adb_cuda_tickle(void)
316: {
317: volatile int s;
318:
319: if (adbActionState == ADB_ACTION_IN) {
320: if (tickle_serial == adb_cuda_serial) {
321: if (++tickle_count > 0) {
322: s = splhigh();
323: adbActionState = ADB_ACTION_IDLE;
324: adbInputBuffer[0] = 0;
325: ADB_SET_STATE_IDLE_CUDA();
326: splx(s);
327: }
328: } else {
329: tickle_serial = adb_cuda_serial;
330: tickle_count = 0;
331: }
332: } else {
333: tickle_serial = adb_cuda_serial;
334: tickle_count = 0;
335: }
336:
337: timeout_add(&adb_cuda_timeout, ADB_TICKLE_TICKS);
338: }
339:
340: /*
341: * called when when an adb interrupt happens
342: *
343: * Cuda version of adb_intr
344: * TO DO: do we want to add some calls to intr_dispatch() here to
345: * grab serial interrupts?
346: */
347: void
348: adb_intr_cuda(void)
349: {
350: volatile int i, ending;
351: volatile unsigned int s;
352: struct adbCommand packet;
353:
354: s = splhigh(); /* can't be too careful - might be called */
355: /* from a routine, NOT an interrupt */
356:
357: ADB_VIA_CLR_INTR(); /* clear interrupt */
358: ADB_VIA_INTR_DISABLE(); /* disable ADB interrupt on IIs. */
359:
360: switch_start:
361: switch (adbActionState) {
362: case ADB_ACTION_IDLE:
363: /*
364: * This is an unexpected packet, so grab the first (dummy)
365: * byte, set up the proper vars, and tell the chip we are
366: * starting to receive the packet by setting the TIP bit.
367: */
368: adbInputBuffer[1] = ADB_SR();
369: adb_cuda_serial++;
370: if (ADB_INTR_IS_OFF) /* must have been a fake start */
371: break;
372:
373: ADB_SET_SR_INPUT();
374: ADB_SET_STATE_TIP();
375:
376: adbInputBuffer[0] = 1;
377: adbActionState = ADB_ACTION_IN;
378: #ifdef ADB_DEBUG
379: if (adb_debug)
380: printf_intr("idle 0x%02x ", adbInputBuffer[1]);
381: #endif
382: break;
383:
384: case ADB_ACTION_IN:
385: adbInputBuffer[++adbInputBuffer[0]] = ADB_SR();
386: /* intr off means this is the last byte (end of frame) */
387: if (ADB_INTR_IS_OFF)
388: ending = 1;
389: else
390: ending = 0;
391:
392: if (1 == ending) { /* end of message? */
393: #ifdef ADB_DEBUG
394: if (adb_debug) {
395: printf_intr("in end 0x%02x ",
396: adbInputBuffer[adbInputBuffer[0]]);
397: print_single(adbInputBuffer);
398: }
399: #endif
400:
401: /*
402: * Are we waiting AND does this packet match what we
403: * are waiting for AND is it coming from either the
404: * ADB or RTC/PRAM sub-device? This section _should_
405: * recognize all ADB and RTC/PRAM type commands, but
406: * there may be more... NOTE: commands are always at
407: * [4], even for RTC/PRAM commands.
408: */
409: /* set up data for adb_pass_up */
410: memcpy(packet.data, adbInputBuffer, adbInputBuffer[0] + 1);
411:
412: if ((adbWaiting == 1) &&
413: (adbInputBuffer[4] == adbWaitingCmd) &&
414: ((adbInputBuffer[2] == 0x00) ||
415: (adbInputBuffer[2] == 0x01))) {
416: packet.saveBuf = adbBuffer;
417: packet.compRout = adbCompRout;
418: packet.compData = adbCompData;
419: packet.unsol = 0;
420: packet.ack_only = 0;
421: adb_pass_up(&packet);
422:
423: adbWaitingCmd = 0; /* reset "waiting" vars */
424: adbWaiting = 0;
425: adbBuffer = NULL;
426: adbCompRout = NULL;
427: adbCompData = NULL;
428: } else {
429: packet.unsol = 1;
430: packet.ack_only = 0;
431: adb_pass_up(&packet);
432: }
433:
434:
435: /* reset vars and signal the end of this frame */
436: adbActionState = ADB_ACTION_IDLE;
437: adbInputBuffer[0] = 0;
438: ADB_SET_STATE_IDLE_CUDA();
439: /*ADB_SET_SR_INPUT();*/
440:
441: /*
442: * If there is something waiting to be sent out,
443: * the set everything up and send the first byte.
444: */
445: if (adbWriteDelay == 1) {
446: delay(ADB_DELAY); /* required */
447: adbSentChars = 0;
448: adbActionState = ADB_ACTION_OUT;
449: /*
450: * If the interrupt is on, we were too slow
451: * and the chip has already started to send
452: * something to us, so back out of the write
453: * and start a read cycle.
454: */
455: if (ADB_INTR_IS_ON) {
456: ADB_SET_SR_INPUT();
457: ADB_SET_STATE_IDLE_CUDA();
458: adbSentChars = 0;
459: adbActionState = ADB_ACTION_IDLE;
460: adbInputBuffer[0] = 0;
461: break;
462: }
463: /*
464: * If we got here, it's ok to start sending
465: * so load the first byte and tell the chip
466: * we want to send.
467: */
468: ADB_SET_STATE_TIP();
469: ADB_SET_SR_OUTPUT();
470: write_via_reg(VIA1, vSR, adbOutputBuffer[adbSentChars + 1]);
471: }
472: } else {
473: ADB_TOGGLE_STATE_ACK_CUDA();
474: #ifdef ADB_DEBUG
475: if (adb_debug)
476: printf_intr("in 0x%02x ",
477: adbInputBuffer[adbInputBuffer[0]]);
478: #endif
479: }
480: break;
481:
482: case ADB_ACTION_OUT:
483: i = ADB_SR(); /* reset SR-intr in IFR */
484: #ifdef ADB_DEBUG
485: if (adb_debug)
486: printf_intr("intr out 0x%02x ", i);
487: #endif
488:
489: adbSentChars++;
490: if (ADB_INTR_IS_ON) { /* ADB intr low during write */
491: #ifdef ADB_DEBUG
492: if (adb_debug)
493: printf_intr("intr was on ");
494: #endif
495: ADB_SET_SR_INPUT(); /* make sure SR is set to IN */
496: ADB_SET_STATE_IDLE_CUDA();
497: adbSentChars = 0; /* must start all over */
498: adbActionState = ADB_ACTION_IDLE; /* new state */
499: adbInputBuffer[0] = 0;
500: adbWriteDelay = 1; /* must retry when done with
501: * read */
502: delay(ADB_DELAY);
503: goto switch_start; /* process next state right
504: * now */
505: break;
506: }
507: if (adbOutputBuffer[0] == adbSentChars) { /* check for done */
508: if (0 == adb_cmd_result(adbOutputBuffer)) { /* do we expect data
509: * back? */
510: adbWaiting = 1; /* signal waiting for return */
511: adbWaitingCmd = adbOutputBuffer[2]; /* save waiting command */
512: } else { /* no talk, so done */
513: /* set up stuff for adb_pass_up */
514: memcpy(packet.data, adbInputBuffer, adbInputBuffer[0] + 1);
515: packet.saveBuf = adbBuffer;
516: packet.compRout = adbCompRout;
517: packet.compData = adbCompData;
518: packet.cmd = adbWaitingCmd;
519: packet.unsol = 0;
520: packet.ack_only = 1;
521: adb_pass_up(&packet);
522:
523: /* reset "waiting" vars, just in case */
524: adbWaitingCmd = 0;
525: adbBuffer = NULL;
526: adbCompRout = NULL;
527: adbCompData = NULL;
528: }
529:
530: adbWriteDelay = 0; /* done writing */
531: adbActionState = ADB_ACTION_IDLE; /* signal bus is idle */
532: ADB_SET_SR_INPUT();
533: ADB_SET_STATE_IDLE_CUDA();
534: #ifdef ADB_DEBUG
535: if (adb_debug)
536: printf_intr("write done ");
537: #endif
538: } else {
539: write_via_reg(VIA1, vSR, adbOutputBuffer[adbSentChars + 1]); /* send next byte */
540: ADB_TOGGLE_STATE_ACK_CUDA(); /* signal byte ready to
541: * shift */
542: #ifdef ADB_DEBUG
543: if (adb_debug)
544: printf_intr("toggle ");
545: #endif
546: }
547: break;
548:
549: case ADB_ACTION_NOTREADY:
550: #ifdef ADB_DEBUG
551: if (adb_debug)
552: printf_intr("adb: not yet initialized\n");
553: #endif
554: break;
555:
556: default:
557: ;
558: #ifdef ADB_DEBUG
559: if (adb_debug)
560: printf_intr("intr: unknown ADB state\n");
561: #endif
562: }
563:
564: ADB_VIA_INTR_ENABLE(); /* enable ADB interrupt on IIs. */
565:
566: splx(s); /* restore */
567: }
568:
569:
570: int
571: send_adb_cuda(u_char * in, u_char * buffer, void *compRout, void *data, int
572: command)
573: {
574: int s, len;
575:
576: #ifdef ADB_DEBUG
577: if (adb_debug)
578: printf_intr("SEND\n");
579: #endif
580:
581: if (adbActionState == ADB_ACTION_NOTREADY)
582: return 1;
583:
584: /* Don't interrupt while we are messing with the ADB */
585: s = splhigh();
586:
587: if ((adbActionState == ADB_ACTION_IDLE) && /* ADB available? */
588: (ADB_INTR_IS_OFF)) { /* and no incoming interrupt? */
589: } else
590: if (adbWriteDelay == 0) /* it's busy, but is anything waiting? */
591: adbWriteDelay = 1; /* if no, then we'll "queue"
592: * it up */
593: else {
594: splx(s);
595: return 1; /* really busy! */
596: }
597:
598: #ifdef ADB_DEBUG
599: if (adb_debug)
600: printf_intr("QUEUE\n");
601: #endif
602: if ((long)in == (long)0) { /* need to convert? */
603: if ((command & 0x0c) == 0x08) /* copy addl data ONLY if
604: * doing a listen! */
605: len = buffer[0]; /* length of additional data */
606: else
607: len = 0;/* no additional data */
608:
609: adbOutputBuffer[0] = 2 + len; /* dev. type + command + addl.
610: * data */
611: adbOutputBuffer[1] = 0x00; /* mark as an ADB command */
612: adbOutputBuffer[2] = (u_char)command; /* load command */
613:
614: /* copy additional output data, if any */
615: memcpy(adbOutputBuffer + 3, buffer + 1, len);
616: } else
617: /* if data ready, just copy over */
618: memcpy(adbOutputBuffer, in, in[0] + 2);
619:
620: adbSentChars = 0; /* nothing sent yet */
621: adbBuffer = buffer; /* save buffer to know where to save result */
622: adbCompRout = compRout; /* save completion routine pointer */
623: adbCompData = data; /* save completion routine data pointer */
624: adbWaitingCmd = adbOutputBuffer[2]; /* save wait command */
625:
626: if (adbWriteDelay != 1) { /* start command now? */
627: #ifdef ADB_DEBUG
628: if (adb_debug)
629: printf_intr("out start NOW");
630: #endif
631: delay(ADB_DELAY);
632: adbActionState = ADB_ACTION_OUT; /* set next state */
633: ADB_SET_SR_OUTPUT(); /* set shift register for OUT */
634: write_via_reg(VIA1, vSR, adbOutputBuffer[adbSentChars + 1]); /* load byte for output */
635: ADB_SET_STATE_ACKOFF_CUDA();
636: ADB_SET_STATE_TIP(); /* tell ADB that we want to send */
637: }
638: adbWriteDelay = 1; /* something in the write "queue" */
639:
640: splx(s);
641:
642: if ((s & (1 << 18)) || adb_polling) /* XXX were VIA1 interrupts blocked ? */
643: /* poll until byte done */
644: while ((adbActionState != ADB_ACTION_IDLE) || (ADB_INTR_IS_ON)
645: || (adbWaiting == 1))
646: if (ADB_SR_INTR_IS_ON) { /* wait for "interrupt" */
647: adb_intr_cuda(); /* process it */
648: if (cold)
649: delay(ADB_DELAY);
650: adb_soft_intr();
651: }
652:
653: return 0;
654: }
655:
656: /*
657: * Called when when an adb interrupt happens.
658: * This routine simply transfers control over to the appropriate
659: * code for the machine we are running on.
660: */
661: int
662: adb_intr(void *arg)
663: {
664: switch (adbHardware) {
665: case ADB_HW_PMU:
666: pm_intr();
667: break;
668:
669: case ADB_HW_CUDA:
670: adb_intr_cuda();
671: break;
672: }
673: return 1;
674: }
675:
676:
677: /*
678: * adb_pass_up is called by the interrupt-time routines.
679: * It takes the raw packet data that was received from the
680: * device and puts it into the queue that the upper half
681: * processes. It then signals for a soft ADB interrupt which
682: * will eventually call the upper half routine (adb_soft_intr).
683: *
684: * If in->unsol is 0, then this is either the notification
685: * that the packet was sent (on a LISTEN, for example), or the
686: * response from the device (on a TALK). The completion routine
687: * is called only if the user specified one.
688: *
689: * If in->unsol is 1, then this packet was unsolicited and
690: * so we look up the device in the ADB device table to determine
691: * what its default service routine is.
692: *
693: * If in->ack_only is 1, then we really only need to call
694: * the completion routine, so don't do any other stuff.
695: *
696: * Note that in->data contains the packet header AND data,
697: * while adbInbound[]->data contains ONLY data.
698: *
699: * Note: Called only at interrupt time. Assumes this.
700: */
701: void
702: adb_pass_up(struct adbCommand *in)
703: {
704: int start = 0, len = 0, cmd = 0;
705: ADBDataBlock block;
706:
707: if (adbInCount >= ADB_QUEUE) {
708: #ifdef ADB_DEBUG
709: if (adb_debug)
710: printf_intr("adb: ring buffer overflow\n");
711: #endif
712: return;
713: }
714:
715: if (in->ack_only) {
716: len = in->data[0];
717: cmd = in->cmd;
718: start = 0;
719: } else {
720: switch (adbHardware) {
721: case ADB_HW_CUDA:
722: /* If it's unsolicited, accept only ADB data for now */
723: if (in->unsol)
724: if (0 != in->data[2])
725: return;
726: cmd = in->data[4];
727: if (in->data[0] < 5)
728: len = 0;
729: else
730: len = in->data[0]-4;
731: start = 4;
732: break;
733:
734: case ADB_HW_PMU:
735: cmd = in->data[1];
736: if (in->data[0] < 2)
737: len = 0;
738: else
739: len = in->data[0]-1;
740: start = 1;
741: break;
742:
743: case ADB_HW_UNKNOWN:
744: return;
745: }
746:
747: /* Make sure there is a valid device entry for this device */
748: if (in->unsol) {
749: /* ignore unsolicited data during adbreinit */
750: if (adbStarting)
751: return;
752: /* get device's comp. routine and data area */
753: if (-1 == get_adb_info(&block, ADB_CMDADDR(cmd)))
754: return;
755: }
756: }
757:
758: /*
759: * If this is an unsolicited packet, we need to fill in
760: * some info so adb_soft_intr can process this packet
761: * properly. If it's not unsolicited, then use what
762: * the caller sent us.
763: */
764: if (in->unsol) {
765: adbInbound[adbInTail].compRout = (void *)block.dbServiceRtPtr;
766: adbInbound[adbInTail].compData = (void *)block.dbDataAreaAddr;
767: adbInbound[adbInTail].saveBuf = (void *)adbInbound[adbInTail].data;
768: } else {
769: adbInbound[adbInTail].compRout = (void *)in->compRout;
770: adbInbound[adbInTail].compData = (void *)in->compData;
771: adbInbound[adbInTail].saveBuf = (void *)in->saveBuf;
772: }
773:
774: #ifdef ADB_DEBUG
775: if (adb_debug && in->data[1] == 2)
776: printf_intr("adb: caught error\n");
777: #endif
778:
779: /* copy the packet data over */
780: /*
781: * TO DO: If the *_intr routines fed their incoming data
782: * directly into an adbCommand struct, which is passed to
783: * this routine, then we could eliminate this copy.
784: */
785: memcpy(adbInbound[adbInTail].data + 1, in->data + start + 1, len);
786: adbInbound[adbInTail].data[0] = len;
787: adbInbound[adbInTail].cmd = cmd;
788:
789: adbInCount++;
790: if (++adbInTail >= ADB_QUEUE)
791: adbInTail = 0;
792:
793: /*
794: * If the debugger is running, call upper half manually.
795: * Otherwise, trigger a soft interrupt to handle the rest later.
796: */
797: if (adb_polling)
798: adb_soft_intr();
799: else
800: setsoftadb();
801: }
802:
803:
804: /*
805: * Called to process the packets after they have been
806: * placed in the incoming queue.
807: *
808: */
809: void
810: adb_soft_intr(void)
811: {
812: int s;
813: int cmd = 0;
814: u_char *buffer;
815: u_char *comprout;
816: u_char *compdata;
817:
818: /*delay(2*ADB_DELAY);*/
819:
820: while (adbInCount) {
821: #ifdef ADB_DEBUG
822: if (adb_debug & 0x80)
823: printf_intr("%x %x %x ",
824: adbInCount, adbInHead, adbInTail);
825: #endif
826: /* get the data we need from the queue */
827: buffer = adbInbound[adbInHead].saveBuf;
828: comprout = adbInbound[adbInHead].compRout;
829: compdata = adbInbound[adbInHead].compData;
830: cmd = adbInbound[adbInHead].cmd;
831:
832: /* copy over data to data area if it's valid */
833: /*
834: * Note that for unsol packets we don't want to copy the
835: * data anywhere, so buffer was already set to 0.
836: * For ack_only buffer was set to 0, so don't copy.
837: */
838: if (buffer)
839: memcpy(buffer, adbInbound[adbInHead].data,
840: adbInbound[adbInHead].data[0] + 1);
841:
842: #ifdef ADB_DEBUG
843: if (adb_debug & 0x80) {
844: printf_intr("%p %p %p %x ",
845: buffer, comprout, compdata, (short)cmd);
846: printf_intr("buf: ");
847: print_single(adbInbound[adbInHead].data);
848: }
849: #endif
850: /*
851: * Remove the packet from the queue before calling
852: * the completion routine, so that the completion
853: * routine can reentrantly process the queue. For
854: * example, this happens when polling is turned on
855: * by entering the debuger by keystroke.
856: */
857: s = splhigh();
858: adbInCount--;
859: if (++adbInHead >= ADB_QUEUE)
860: adbInHead = 0;
861: splx(s);
862:
863: /* call default completion routine if it's valid */
864: if (comprout) {
865: ((int (*)(u_char *, u_char *, int)) comprout)
866: (buffer, compdata, cmd);
867: }
868:
869: }
870: }
871:
872:
873: /*
874: * This is my version of the ADBOp routine. It mainly just calls the
875: * hardware-specific routine.
876: *
877: * data : pointer to data area to be used by compRout
878: * compRout : completion routine
879: * buffer : for LISTEN: points to data to send - MAX 8 data bytes,
880: * byte 0 = # of bytes
881: * : for TALK: points to place to save return data
882: * command : the adb command to send
883: * result : 0 = success
884: * : -1 = could not complete
885: */
886: int
887: adb_op(Ptr buffer, Ptr compRout, Ptr data, short command)
888: {
889: int result;
890:
891: switch (adbHardware) {
892: case ADB_HW_PMU:
893: result = pm_adb_op((u_char *)buffer, (void *)compRout,
894: (void *)data, (int)command);
895:
896: if (result == 0)
897: return 0;
898: else
899: return -1;
900: break;
901:
902: case ADB_HW_CUDA:
903: result = send_adb_cuda((u_char *)0, (u_char *)buffer,
904: (void *)compRout, (void *)data, (int)command);
905: if (result == 0)
906: return 0;
907: else
908: return -1;
909: break;
910:
911: default:
912: return -1;
913: }
914: }
915:
916:
917: /*
918: * adb_hw_setup
919: * This routine sets up the possible machine specific hardware
920: * config (mainly VIA settings) for the various models.
921: */
922: void
923: adb_hw_setup(void)
924: {
925: volatile int i;
926:
927: switch (adbHardware) {
928:
929: case ADB_HW_PMU:
930: /*
931: * XXX - really PM_VIA_CLR_INTR - should we put it in
932: * pm_direct.h?
933: */
934: write_via_reg(VIA1, vIFR, 0x90); /* clear interrupt */
935: break;
936:
937: case ADB_HW_CUDA:
938: via_reg_or(VIA1, vDirB, 0x30); /* register B bits 4 and 5:
939: * outputs */
940: via_reg_and(VIA1, vDirB, 0xf7); /* register B bit 3: input */
941: via_reg_and(VIA1, vACR, ~vSR_OUT); /* make sure SR is set
942: * to IN */
943: write_via_reg(VIA1, vACR, (read_via_reg(VIA1, vACR) | 0x0c) & ~0x10);
944: adbActionState = ADB_ACTION_IDLE; /* used by all types of
945: * hardware */
946: write_via_reg(VIA1, vIER, 0x84);/* make sure VIA interrupts
947: * are on */
948: ADB_SET_STATE_IDLE_CUDA(); /* set ADB bus state to idle */
949:
950: /* sort of a device reset */
951: i = ADB_SR(); /* clear interrupt */
952: ADB_VIA_INTR_DISABLE(); /* no interrupts while clearing */
953: ADB_SET_STATE_IDLE_CUDA(); /* reset state to idle */
954: delay(ADB_DELAY);
955: ADB_SET_STATE_TIP(); /* signal start of frame */
956: delay(ADB_DELAY);
957: ADB_TOGGLE_STATE_ACK_CUDA();
958: delay(ADB_DELAY);
959: ADB_CLR_STATE_TIP();
960: delay(ADB_DELAY);
961: ADB_SET_STATE_IDLE_CUDA(); /* back to idle state */
962: i = ADB_SR(); /* clear interrupt */
963: ADB_VIA_INTR_ENABLE(); /* ints ok now */
964: break;
965:
966: case ADB_HW_UNKNOWN:
967: default:
968: write_via_reg(VIA1, vIER, 0x04);/* turn interrupts off - TO
969: * DO: turn PB ints off? */
970: break;
971: }
972: }
973:
974: /*
975: * adb_reinit sets up the adb stuff
976: *
977: */
978: void
979: adb_reinit(void)
980: {
981: u_char send_string[ADB_MAX_MSG_LENGTH];
982: ADBDataBlock data; /* temp. holder for getting device info */
983: volatile int i, x;
984: int s;
985: int command;
986: int result;
987: int saveptr; /* point to next free relocation address */
988: int device;
989: int nonewtimes; /* times thru loop w/o any new devices */
990:
991: /* Make sure we are not interrupted while building the table. */
992: if (adbHardware != ADB_HW_PMU) /* ints must be on for PB? */
993: s = splhigh();
994:
995: ADBNumDevices = 0; /* no devices yet */
996:
997: /* Let intr routines know we are running reinit */
998: adbStarting = 1;
999:
1000: /*
1001: * Initialize the ADB table. For now, we'll always use the same table
1002: * that is defined at the beginning of this file - no mallocs.
1003: */
1004: for (i = 0; i < 16; i++)
1005: ADBDevTable[i].devType = 0;
1006:
1007: adb_setup_hw_type(); /* setup hardware type */
1008:
1009: adb_hw_setup(); /* init the VIA bits and hard reset ADB */
1010:
1011: delay(1000);
1012:
1013: /* send an ADB reset first */
1014: adb_op_sync((Ptr)0, (short)0x00);
1015: delay(200000);
1016:
1017: /*
1018: * Probe for ADB devices. Probe devices 1-15 quickly to determine
1019: * which device addresses are in use and which are free. For each
1020: * address that is in use, move the device at that address to a higher
1021: * free address. Continue doing this at that address until no device
1022: * responds at that address. Then move the last device that was moved
1023: * back to the original address. Do this for the remaining addresses
1024: * that we determined were in use.
1025: *
1026: * When finished, do this entire process over again with the updated
1027: * list of in use addresses. Do this until no new devices have been
1028: * found in 20 passes though the in use address list. (This probably
1029: * seems long and complicated, but it's the best way to detect multiple
1030: * devices at the same address - sometimes it takes a couple of tries
1031: * before the collision is detected.)
1032: */
1033:
1034: /* initial scan through the devices */
1035: for (i = 1; i < 16; i++) {
1036: send_string[0] = 0;
1037: command = ADBTALK(i, 3);
1038: result = adb_op_sync((Ptr)send_string, (short)command);
1039:
1040: if (send_string[0] != 0) {
1041: /* check for valid device handler */
1042: switch (send_string[2]) {
1043: case 0:
1044: case 0xfd:
1045: case 0xfe:
1046: case 0xff:
1047: continue; /* invalid, skip */
1048: }
1049:
1050: /* found a device */
1051: ++ADBNumDevices;
1052: KASSERT(ADBNumDevices < 16);
1053: ADBDevTable[ADBNumDevices].devType =
1054: (int)send_string[2];
1055: ADBDevTable[ADBNumDevices].origAddr = i;
1056: ADBDevTable[ADBNumDevices].currentAddr = i;
1057: ADBDevTable[ADBNumDevices].DataAreaAddr = NULL;
1058: ADBDevTable[ADBNumDevices].ServiceRtPtr = NULL;
1059: }
1060: }
1061:
1062: /* find highest unused address */
1063: for (saveptr = 15; saveptr > 0; saveptr--)
1064: if (-1 == get_adb_info(&data, saveptr))
1065: break;
1066:
1067: #ifdef ADB_DEBUG
1068: if (adb_debug & 0x80) {
1069: printf_intr("first free is: 0x%02x\n", saveptr);
1070: printf_intr("devices: %i\n", ADBNumDevices);
1071: }
1072: #endif
1073:
1074: nonewtimes = 0; /* no loops w/o new devices */
1075: while (saveptr > 0 && nonewtimes++ < 11) {
1076: for (i = 1; i <= ADBNumDevices; i++) {
1077: device = ADBDevTable[i].currentAddr;
1078: #ifdef ADB_DEBUG
1079: if (adb_debug & 0x80)
1080: printf_intr("moving device 0x%02x to 0x%02x "
1081: "(index 0x%02x) ", device, saveptr, i);
1082: #endif
1083:
1084: /* send TALK R3 to address */
1085: command = ADBTALK(device, 3);
1086: adb_op_sync((Ptr)send_string, (short)command);
1087:
1088: /* move device to higher address */
1089: command = ADBLISTEN(device, 3);
1090: send_string[0] = 2;
1091: send_string[1] = (u_char)(saveptr | 0x60);
1092: send_string[2] = 0xfe;
1093: adb_op_sync((Ptr)send_string, (short)command);
1094: delay(500);
1095:
1096: /* send TALK R3 - anything at new address? */
1097: command = ADBTALK(saveptr, 3);
1098: adb_op_sync((Ptr)send_string, (short)command);
1099: delay(500);
1100:
1101: if (send_string[0] == 0) {
1102: #ifdef ADB_DEBUG
1103: if (adb_debug & 0x80)
1104: printf_intr("failed, continuing\n");
1105: #endif
1106: continue;
1107: }
1108:
1109: /* send TALK R3 - anything at old address? */
1110: command = ADBTALK(device, 3);
1111: result = adb_op_sync((Ptr)send_string, (short)command);
1112: if (send_string[0] != 0) {
1113: /* check for valid device handler */
1114: switch (send_string[2]) {
1115: case 0:
1116: case 0xfd:
1117: case 0xfe:
1118: case 0xff:
1119: continue; /* invalid, skip */
1120: }
1121:
1122: /* new device found */
1123: /* update data for previously moved device */
1124: ADBDevTable[i].currentAddr = saveptr;
1125: #ifdef ADB_DEBUG
1126: if (adb_debug & 0x80)
1127: printf_intr("old device at index %i\n",i);
1128: #endif
1129: /* add new device in table */
1130: #ifdef ADB_DEBUG
1131: if (adb_debug & 0x80)
1132: printf_intr("new device found\n");
1133: #endif
1134: if (saveptr > ADBNumDevices) {
1135: ++ADBNumDevices;
1136: KASSERT(ADBNumDevices < 16);
1137: }
1138: ADBDevTable[ADBNumDevices].devType =
1139: (int)send_string[2];
1140: ADBDevTable[ADBNumDevices].origAddr = device;
1141: ADBDevTable[ADBNumDevices].currentAddr = device;
1142: /* These will be set correctly in adbsys.c */
1143: /* Until then, unsol. data will be ignored. */
1144: ADBDevTable[ADBNumDevices].DataAreaAddr = NULL;
1145: ADBDevTable[ADBNumDevices].ServiceRtPtr = NULL;
1146: /* find next unused address */
1147: for (x = saveptr; x > 0; x--) {
1148: if (-1 == get_adb_info(&data, x)) {
1149: saveptr = x;
1150: break;
1151: }
1152: }
1153: if (x == 0)
1154: saveptr = 0;
1155: #ifdef ADB_DEBUG
1156: if (adb_debug & 0x80)
1157: printf_intr("new free is 0x%02x\n",
1158: saveptr);
1159: #endif
1160: nonewtimes = 0;
1161: } else {
1162: #ifdef ADB_DEBUG
1163: if (adb_debug & 0x80)
1164: printf_intr("moving back...\n");
1165: #endif
1166: /* move old device back */
1167: command = ADBLISTEN(saveptr, 3);
1168: send_string[0] = 2;
1169: send_string[1] = (u_char)(device | 0x60);
1170: send_string[2] = 0xfe;
1171: adb_op_sync((Ptr)send_string, (short)command);
1172: delay(1000);
1173: }
1174: }
1175: }
1176:
1177: #ifdef ADB_DEBUG
1178: if (adb_debug) {
1179: for (i = 1; i <= ADBNumDevices; i++) {
1180: x = get_ind_adb_info(&data, i);
1181: if (x != -1)
1182: printf_intr("index 0x%x, addr 0x%x, type 0x%x\n",
1183: i, x, data.devType);
1184: }
1185: }
1186: #endif
1187:
1188: #ifdef ADB_DEBUG
1189: if (adb_debug) {
1190: if (0 == ADBNumDevices) /* tell user if no devices found */
1191: printf_intr("adb: no devices found\n");
1192: }
1193: #endif
1194:
1195: adbStarting = 0; /* not starting anymore */
1196: #ifdef ADB_DEBUG
1197: if (adb_debug)
1198: printf_intr("adb: adb_reinit complete\n");
1199: #endif
1200:
1201: if (adbHardware == ADB_HW_CUDA) {
1202: timeout_set(&adb_cuda_timeout, (void *)adb_cuda_tickle, NULL);
1203: timeout_add(&adb_cuda_timeout, ADB_TICKLE_TICKS);
1204: }
1205:
1206: if (adbHardware != ADB_HW_PMU) /* ints must be on for PB? */
1207: splx(s);
1208: }
1209:
1210:
1211: /*
1212: * adb_cmd_result
1213: *
1214: * This routine lets the caller know whether the specified adb command string
1215: * should expect a returned result, such as a TALK command.
1216: *
1217: * returns: 0 if a result should be expected
1218: * 1 if a result should NOT be expected
1219: */
1220: int
1221: adb_cmd_result(u_char *in)
1222: {
1223: switch (adbHardware) {
1224: case ADB_HW_CUDA:
1225: /* was it an ADB talk command? */
1226: if ((in[1] == 0x00) && ((in[2] & 0x0c) == 0x0c))
1227: return 0;
1228: /* was it an RTC/PRAM read date/time? */
1229: if ((in[1] == 0x01) && (in[2] == 0x03))
1230: return 0;
1231: return 1;
1232:
1233: case ADB_HW_PMU:
1234: return 1;
1235:
1236: default:
1237: return 1;
1238: }
1239: }
1240:
1241:
1242: /*
1243: * adb_op_sync
1244: *
1245: * This routine does exactly what the adb_op routine does, except that after
1246: * the adb_op is called, it waits until the return value is present before
1247: * returning.
1248: */
1249: int
1250: adb_op_sync(Ptr buffer, short command)
1251: {
1252: int tmout;
1253: int result;
1254: volatile int flag = 0;
1255:
1256: result = adb_op(buffer, (void *)adb_op_comprout,
1257: (void *)&flag, command); /* send command */
1258: if (result == 0) { /* send ok? */
1259: /*
1260: * Total time to wait is calculated as follows:
1261: * - Tlt (stop to start time): 260 usec
1262: * - start bit: 100 usec
1263: * - up to 8 data bytes: 64 * 100 usec = 6400 usec
1264: * - stop bit (with SRQ): 140 usec
1265: * Total: 6900 usec
1266: *
1267: * This is the total time allowed by the specification. Any
1268: * device that doesn't conform to this will fail to operate
1269: * properly on some Apple systems. In spite of this we
1270: * double the time to wait; some Cuda-based apparently
1271: * queues some commands and allows the main CPU to continue
1272: * processing (radical concept, eh?). To be safe, allow
1273: * time for two complete ADB transactions to occur.
1274: */
1275: for (tmout = 13800; !flag && tmout >= 10; tmout -= 10)
1276: delay(10);
1277: if (!flag && tmout > 0)
1278: delay(tmout);
1279:
1280: if (!flag)
1281: result = -2;
1282: }
1283:
1284: return result;
1285: }
1286:
1287:
1288: /*
1289: * adb_op_comprout
1290: *
1291: * This function is used by the adb_op_sync routine so it knows when the
1292: * function is done.
1293: */
1294: void
1295: adb_op_comprout(caddr_t buffer, caddr_t compdata, int cmd)
1296: {
1297: *(int *)compdata = 0x01; /* update flag value */
1298: }
1299:
1300: void
1301: adb_setup_hw_type(void)
1302: {
1303: switch (adbHardware) {
1304: case ADB_HW_CUDA:
1305: adbSoftPower = 1;
1306: return;
1307:
1308: case ADB_HW_PMU:
1309: adbSoftPower = 1;
1310: pm_setup_adb();
1311: return;
1312:
1313: default:
1314: panic("unknown adb hardware");
1315: }
1316: }
1317:
1318: int
1319: count_adbs(void)
1320: {
1321: int i;
1322: int found;
1323:
1324: found = 0;
1325:
1326: for (i = 1; i < 16; i++)
1327: if (0 != ADBDevTable[i].devType)
1328: found++;
1329:
1330: return found;
1331: }
1332:
1333: int
1334: get_ind_adb_info(ADBDataBlock * info, int index)
1335: {
1336: if ((index < 1) || (index > 15)) /* check range 1-15 */
1337: return (-1);
1338:
1339: #ifdef ADB_DEBUG
1340: if (adb_debug & 0x80)
1341: printf_intr("index 0x%x devType is: 0x%x\n", index,
1342: ADBDevTable[index].devType);
1343: #endif
1344: if (0 == ADBDevTable[index].devType) /* make sure it's a valid entry */
1345: return (-1);
1346:
1347: info->devType = ADBDevTable[index].devType;
1348: info->origADBAddr = ADBDevTable[index].origAddr;
1349: info->dbServiceRtPtr = (Ptr)ADBDevTable[index].ServiceRtPtr;
1350: info->dbDataAreaAddr = (Ptr)ADBDevTable[index].DataAreaAddr;
1351:
1352: return (ADBDevTable[index].currentAddr);
1353: }
1354:
1355: int
1356: get_adb_info(ADBDataBlock * info, int adbAddr)
1357: {
1358: int i;
1359:
1360: if ((adbAddr < 1) || (adbAddr > 15)) /* check range 1-15 */
1361: return (-1);
1362:
1363: for (i = 1; i < 15; i++)
1364: if (ADBDevTable[i].currentAddr == adbAddr) {
1365: info->devType = ADBDevTable[i].devType;
1366: info->origADBAddr = ADBDevTable[i].origAddr;
1367: info->dbServiceRtPtr = (Ptr)ADBDevTable[i].ServiceRtPtr;
1368: info->dbDataAreaAddr = ADBDevTable[i].DataAreaAddr;
1369: return 0; /* found */
1370: }
1371:
1372: return (-1); /* not found */
1373: }
1374:
1375: int
1376: set_adb_info(ADBSetInfoBlock * info, int adbAddr)
1377: {
1378: int i;
1379:
1380: if ((adbAddr < 1) || (adbAddr > 15)) /* check range 1-15 */
1381: return (-1);
1382:
1383: for (i = 1; i < 15; i++)
1384: if (ADBDevTable[i].currentAddr == adbAddr) {
1385: ADBDevTable[i].ServiceRtPtr =
1386: (void *)(info->siServiceRtPtr);
1387: ADBDevTable[i].DataAreaAddr = info->siDataAreaAddr;
1388: return 0; /* found */
1389: }
1390:
1391: return (-1); /* not found */
1392:
1393: }
1394:
1395: /* caller should really use machine-independent version: getPramTime */
1396: /* this version does pseudo-adb access only */
1397: int
1398: adb_read_date_time(time_t *time)
1399: {
1400: u_char output[ADB_MAX_MSG_LENGTH];
1401: int result;
1402: int retcode;
1403: volatile int flag = 0;
1404:
1405: switch (adbHardware) {
1406: case ADB_HW_PMU:
1407: pm_read_date_time(time);
1408: retcode = 0;
1409: break;
1410:
1411: case ADB_HW_CUDA:
1412: output[0] = 0x02; /* 2 byte message */
1413: output[1] = 0x01; /* to pram/rtc device */
1414: output[2] = 0x03; /* read date/time */
1415: result = send_adb_cuda((u_char *)output, (u_char *)output,
1416: (void *)adb_op_comprout, (void *)&flag, (int)0);
1417: if (result != 0) { /* exit if not sent */
1418: retcode = -1;
1419: break;
1420: }
1421:
1422: while (0 == flag) /* wait for result */
1423: ;
1424:
1425: delay(20); /* completion occurs too soon? */
1426: memcpy(time, output + 1, 4);
1427: retcode = 0;
1428: break;
1429:
1430: case ADB_HW_UNKNOWN:
1431: default:
1432: retcode = -1;
1433: break;
1434: }
1435: if (retcode == 0) {
1436: #define DIFF19041970 2082844800
1437: *time -= DIFF19041970;
1438:
1439: } else {
1440: *time = 0;
1441: }
1442: return retcode;
1443: }
1444:
1445: /* caller should really use machine-independent version: setPramTime */
1446: /* this version does pseudo-adb access only */
1447: int
1448: adb_set_date_time(time_t time)
1449: {
1450: u_char output[ADB_MAX_MSG_LENGTH];
1451: int result;
1452: volatile int flag = 0;
1453:
1454: time += DIFF19041970;
1455: switch (adbHardware) {
1456:
1457: case ADB_HW_CUDA:
1458: output[0] = 0x06; /* 6 byte message */
1459: output[1] = 0x01; /* to pram/rtc device */
1460: output[2] = 0x09; /* set date/time */
1461: output[3] = (u_char)(time >> 24);
1462: output[4] = (u_char)(time >> 16);
1463: output[5] = (u_char)(time >> 8);
1464: output[6] = (u_char)(time);
1465: result = send_adb_cuda((u_char *)output, (u_char *)0,
1466: (void *)adb_op_comprout, (void *)&flag, (int)0);
1467: if (result != 0) /* exit if not sent */
1468: return -1;
1469:
1470: while (0 == flag) /* wait for send to finish */
1471: ;
1472:
1473: return 0;
1474:
1475: case ADB_HW_PMU:
1476: pm_set_date_time(time);
1477: return 0;
1478:
1479: default:
1480: return -1;
1481: }
1482: }
1483:
1484:
1485: int
1486: adb_poweroff(void)
1487: {
1488: u_char output[ADB_MAX_MSG_LENGTH];
1489: int result;
1490:
1491: if (!adbSoftPower)
1492: return -1;
1493:
1494: adb_polling = 1;
1495:
1496: switch (adbHardware) {
1497: case ADB_HW_PMU:
1498: /* Clear the wake on AC loss event */
1499: pmu_fileserver_mode(0);
1500: pm_adb_poweroff();
1501:
1502: for (;;); /* wait for power off */
1503:
1504: return 0;
1505:
1506: case ADB_HW_CUDA:
1507: output[0] = 0x02; /* 2 byte message */
1508: output[1] = 0x01; /* to pram/rtc/soft-power device */
1509: output[2] = 0x0a; /* set poweroff */
1510: result = send_adb_cuda((u_char *)output, (u_char *)0,
1511: (void *)0, (void *)0, (int)0);
1512: if (result != 0) /* exit if not sent */
1513: return -1;
1514:
1515: for (;;); /* wait for power off */
1516:
1517: return 0;
1518:
1519: default:
1520: return -1;
1521: }
1522: }
1523:
1524: void
1525: setsoftadb()
1526: {
1527: if (!timeout_initialized(&adb_softintr_timeout))
1528: timeout_set(&adb_softintr_timeout, (void *)adb_soft_intr, NULL);
1529: timeout_add(&adb_softintr_timeout, 1);
1530: }
1531:
1532: void
1533: adb_cuda_autopoll()
1534: {
1535: volatile int flag = 0;
1536: int result;
1537: u_char output[16];
1538:
1539: output[0] = 0x03; /* 3-byte message */
1540: output[1] = 0x01; /* to pram/rtc/soft-power device */
1541: output[2] = 0x01; /* cuda autopoll */
1542: output[3] = 0x01;
1543: result = send_adb_cuda(output, output, adb_op_comprout,
1544: (void *)&flag, 0);
1545: if (result != 0) /* exit if not sent */
1546: return;
1547:
1548: while (flag == 0); /* wait for result */
1549: }
1550:
1551: void
1552: adb_cuda_fileserver_mode()
1553: {
1554: volatile int flag = 0;
1555: int result;
1556: u_char output[16];
1557:
1558: output[0] = 0x03; /* 3-byte message */
1559: output[1] = 0x01; /* to pram/rtc device/soft-power device */
1560: output[2] = 0x13; /* cuda file server mode */
1561: output[3] = 0x01; /* True - Turn on after AC loss */
1562:
1563: result = send_adb_cuda(output, output, adb_op_comprout,
1564: (void *)&flag, 0);
1565: if (result != 0)
1566: return;
1567:
1568: while (flag == 0);
1569: }
1570:
1571: void
1572: adb_restart()
1573: {
1574: int result;
1575: u_char output[16];
1576:
1577: adb_polling = 1;
1578:
1579: switch (adbHardware) {
1580: case ADB_HW_CUDA:
1581: output[0] = 0x02; /* 2 byte message */
1582: output[1] = 0x01; /* to pram/rtc/soft-power device */
1583: output[2] = 0x11; /* restart */
1584: result = send_adb_cuda((u_char *)output, (u_char *)0,
1585: (void *)0, (void *)0, (int)0);
1586: if (result != 0) /* exit if not sent */
1587: return;
1588: while (1); /* not return */
1589:
1590: case ADB_HW_PMU:
1591: pm_adb_restart();
1592: while (1); /* not return */
1593: }
1594: }
1595:
1596: /*
1597: * Driver definition.
1598: */
1599:
1600: int adbmatch(struct device *, void *, void *);
1601: void adbattach(struct device *, struct device *, void *);
1602:
1603: struct cfattach adb_ca = {
1604: sizeof(struct adb_softc), adbmatch, adbattach
1605: };
1606:
1607: int
1608: adbmatch(struct device *parent, void *cf, void *aux)
1609: {
1610: struct confargs *ca = aux;
1611:
1612: if (ca->ca_nreg < 8)
1613: return 0;
1614:
1615: if (ca->ca_nintr < 4)
1616: return 0;
1617:
1618: if (strcmp(ca->ca_name, "via-cuda") == 0)
1619: return 1;
1620:
1621: if (strcmp(ca->ca_name, "via-pmu") == 0)
1622: return 1;
1623:
1624: return 0;
1625: }
1626:
1627: void
1628: adbattach(struct device *parent, struct device *self, void *aux)
1629: {
1630: struct adb_softc *sc = (struct adb_softc *)self;
1631: struct confargs *ca = aux;
1632: struct confargs nca;
1633: char name[32];
1634: int node;
1635:
1636: ADBDataBlock adbdata;
1637: struct adb_attach_args aa_args;
1638: int totaladbs;
1639: int adbindex, adbaddr;
1640:
1641: ca->ca_reg[0] += ca->ca_baseaddr;
1642:
1643: sc->sc_regbase = mapiodev(ca->ca_reg[0], ca->ca_reg[1]);
1644: Via1Base = sc->sc_regbase;
1645:
1646: if (strcmp(ca->ca_name, "via-cuda") == 0)
1647: adbHardware = ADB_HW_CUDA;
1648: else if (strcmp(ca->ca_name, "via-pmu") == 0) {
1649: adbHardware = ADB_HW_PMU;
1650:
1651: /*
1652: * Bus reset can take a long time if no adb devices are
1653: * connected, e.g. on a Mac Mini; so check for an adb
1654: * child in the OF tree to speed up pm_adb_op().
1655: */
1656: adbempty = 1;
1657: for (node = OF_child(ca->ca_node); node; node = OF_peer(node)) {
1658: if (OF_getprop(node, "name", name, sizeof name) <= 0)
1659: continue;
1660: if (strcmp(name, "adb") == 0) {
1661: adbempty = 0;
1662: break;
1663: }
1664: }
1665: }
1666:
1667: adb_polling = 1;
1668: adb_reinit();
1669:
1670: mac_intr_establish(parent, ca->ca_intr[0], IST_LEVEL, IPL_HIGH,
1671: adb_intr, sc, sc->sc_dev.dv_xname);
1672:
1673: /* init powerpc globals which control RTC functionality */
1674: time_read = adb_read_date_time;
1675: time_write = adb_set_date_time;
1676:
1677: #ifdef ADB_DEBUG
1678: if (adb_debug)
1679: printf("adb: done with adb_reinit\n");
1680: #endif
1681: totaladbs = count_adbs();
1682:
1683: printf(" irq %d: %s, %d target%s\n", ca->ca_intr[0], ca->ca_name,
1684: totaladbs, (totaladbs == 1) ? "" : "s");
1685:
1686: /* for each ADB device */
1687: for (adbindex = 1; adbindex <= totaladbs; adbindex++) {
1688: /* Get the ADB information */
1689: adbaddr = get_ind_adb_info(&adbdata, adbindex);
1690:
1691: aa_args.origaddr = adbdata.origADBAddr;
1692: aa_args.adbaddr = adbaddr;
1693: aa_args.handler_id = adbdata.devType;
1694:
1695: (void)config_found(self, &aa_args, adbprint);
1696: }
1697:
1698: #if NAPM > 0
1699: /* Magic for signalling the apm driver to match. */
1700: aa_args.origaddr = ADBADDR_APM;
1701: aa_args.adbaddr = ADBADDR_APM;
1702: aa_args.handler_id = ADBADDR_APM;
1703:
1704: (void)config_found(self, &aa_args, NULL);
1705: #endif
1706:
1707: /* Attach I2C controller. */
1708: for (node = OF_child(ca->ca_node); node; node = OF_peer(node)) {
1709: if (OF_getprop(node, "name", name, sizeof name) <= 0)
1710: continue;
1711: if (strcmp(name, "pmu-i2c") == 0) {
1712: nca.ca_name = "piic";
1713: nca.ca_node = node;
1714: config_found(self, &nca, NULL);
1715: }
1716: }
1717:
1718: if (adbHardware == ADB_HW_CUDA)
1719: adb_cuda_fileserver_mode();
1720: if (adbHardware == ADB_HW_PMU)
1721: pmu_fileserver_mode(1);
1722:
1723: if (adbHardware == ADB_HW_CUDA)
1724: adb_cuda_autopoll();
1725: adb_polling = 0;
1726: }
CVSweb