Annotation of sys/arch/macppc/dev/adb.c, Revision 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