diff options
Diffstat (limited to 'sys/arch/mac68k/dev')
-rw-r--r-- | sys/arch/mac68k/dev/adb.c | 2832 | ||||
-rw-r--r-- | sys/arch/mac68k/dev/adb_direct.c | 2759 | ||||
-rw-r--r-- | sys/arch/mac68k/dev/adbvar.h | 56 | ||||
-rw-r--r-- | sys/arch/mac68k/dev/akbd.c | 550 | ||||
-rw-r--r-- | sys/arch/mac68k/dev/akbd_machdep.c | 136 | ||||
-rw-r--r-- | sys/arch/mac68k/dev/akbdmap.h | 431 | ||||
-rw-r--r-- | sys/arch/mac68k/dev/akbdvar.h | 71 | ||||
-rw-r--r-- | sys/arch/mac68k/dev/ams.c | 534 | ||||
-rw-r--r-- | sys/arch/mac68k/dev/amsvar.h | 67 | ||||
-rw-r--r-- | sys/arch/mac68k/dev/pm_direct.c | 3 |
10 files changed, 2870 insertions, 4569 deletions
diff --git a/sys/arch/mac68k/dev/adb.c b/sys/arch/mac68k/dev/adb.c index aa8918ba0e7..37d361da486 100644 --- a/sys/arch/mac68k/dev/adb.c +++ b/sys/arch/mac68k/dev/adb.c @@ -1,5 +1,36 @@ -/* $OpenBSD: adb.c,v 1.18 2006/01/13 19:36:43 miod Exp $ */ +/* $OpenBSD: adb.c,v 1.19 2006/01/18 23:21:16 miod Exp $ */ /* $NetBSD: adb.c,v 1.47 2005/06/16 22:43:36 jmc Exp $ */ +/* $NetBSD: adb_direct.c,v 1.51 2005/06/16 22:43:36 jmc Exp $ */ + +/* + * Copyright (C) 1996, 1997 John P. Wittkoski + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by John P. Wittkoski. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ /* * Copyright (C) 1994 Bradley A. Grantham @@ -31,6 +62,33 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* + * This code is rather messy, but I don't have time right now + * to clean it up as much as I would like. + * But it works, so I'm happy. :-) jpw + */ + +/* + * TO DO: + * - We could reduce the time spent in the adb_intr_* routines + * by having them save the incoming and outgoing data directly + * in the adbInbound and adbOutbound queues, as it would reduce + * the number of times we need to copy the data around. It + * would also make the code more readable and easier to follow. + * - (Related to above) Use the header part of adbCommand to + * reduce the number of copies we have to do of the data. + * - (Related to above) Actually implement the adbOutbound queue. + * This is fairly easy once you switch all the intr routines + * over to using adbCommand structs directly. + * - There is a bug in the state machine of adb_intr_cuda + * code that causes hangs, especially on 030 machines, probably + * because of some timing issues. Because I have been unable to + * determine the exact cause of this bug, I used the timeout function + * to check for and recover from this condition. If anyone finds + * the actual cause of this bug, the calls to timeout and the + * adb_cuda_tickle routine can be removed. + */ + #include <sys/param.h> #include <sys/device.h> #include <sys/fcntl.h> @@ -38,174 +96,2368 @@ #include <sys/selinfo.h> #include <sys/proc.h> #include <sys/signalvar.h> +#include <sys/timeout.h> #include <sys/systm.h> #include <machine/autoconf.h> #include <machine/cpu.h> +#include <machine/viareg.h> +#include <dev/adb/adb.h> #include <mac68k/dev/adbvar.h> +#define printf_intr printf + +int adb_polling; /* Are we polling? (Debugger mode) */ +#ifdef ADB_DEBUG +int adb_debug; /* Output debugging messages */ +#endif /* ADB_DEBUG */ + +/* some misc. leftovers */ +#define vPB 0x0000 +#define vPB3 0x08 +#define vPB4 0x10 +#define vPB5 0x20 +#define vSR_INT 0x04 +#define vSR_OUT 0x10 + +/* the type of ADB action that we are currently preforming */ +#define ADB_ACTION_NOTREADY 0x1 /* has not been initialized yet */ +#define ADB_ACTION_IDLE 0x2 /* the bus is currently idle */ +#define ADB_ACTION_OUT 0x3 /* sending out a command */ +#define ADB_ACTION_IN 0x4 /* receiving data */ +#define ADB_ACTION_POLLING 0x5 /* polling - II only */ + /* - * Function declarations. + * These describe the state of the ADB bus itself, although they + * don't necessarily correspond directly to ADB states. + * Note: these are not really used in the IIsi code. */ -int adbmatch(struct device *, void *, void *); -void adbattach(struct device *, struct device *, void *); -int adbprint(void *, const char *); -void adb_attach_deferred(void *); +#define ADB_BUS_UNKNOWN 0x1 /* we don't know yet - all models */ +#define ADB_BUS_IDLE 0x2 /* bus is idle - all models */ +#define ADB_BUS_CMD 0x3 /* starting a command - II models */ +#define ADB_BUS_ODD 0x4 /* the "odd" state - II models */ +#define ADB_BUS_EVEN 0x5 /* the "even" state - II models */ +#define ADB_BUS_ACTIVE 0x6 /* active state - IIsi models */ +#define ADB_BUS_ACK 0x7 /* currently ACKing - IIsi models */ + +/* + * Shortcuts for setting or testing the VIA bit states. + * Not all shortcuts are used for every type of ADB hardware. + */ +#define ADB_SET_STATE_IDLE_II() via_reg(VIA1, vBufB) |= (vPB4 | vPB5) +#define ADB_SET_STATE_IDLE_IISI() via_reg(VIA1, vBufB) &= ~(vPB4 | vPB5) +#define ADB_SET_STATE_IDLE_CUDA() via_reg(VIA1, vBufB) |= (vPB4 | vPB5) +#define ADB_SET_STATE_CMD() via_reg(VIA1, vBufB) &= ~(vPB4 | vPB5) +#define ADB_SET_STATE_EVEN() via_reg(VIA1, vBufB) = ((via_reg(VIA1, \ + vBufB) | vPB4) & ~vPB5) +#define ADB_SET_STATE_ODD() via_reg(VIA1, vBufB) = ((via_reg(VIA1, \ + vBufB) | vPB5) & ~vPB4) +#define ADB_SET_STATE_ACTIVE() via_reg(VIA1, vBufB) |= vPB5 +#define ADB_SET_STATE_INACTIVE() via_reg(VIA1, vBufB) &= ~vPB5 +#define ADB_SET_STATE_TIP() via_reg(VIA1, vBufB) &= ~vPB5 +#define ADB_CLR_STATE_TIP() via_reg(VIA1, vBufB) |= vPB5 +#define ADB_SET_STATE_ACKON() via_reg(VIA1, vBufB) |= vPB4 +#define ADB_SET_STATE_ACKOFF() via_reg(VIA1, vBufB) &= ~vPB4 +#define ADB_TOGGLE_STATE_ACK_CUDA() via_reg(VIA1, vBufB) ^= vPB4 +#define ADB_SET_STATE_ACKON_CUDA() via_reg(VIA1, vBufB) &= ~vPB4 +#define ADB_SET_STATE_ACKOFF_CUDA() via_reg(VIA1, vBufB) |= vPB4 +#define ADB_SET_SR_INPUT() via_reg(VIA1, vACR) &= ~vSR_OUT +#define ADB_SET_SR_OUTPUT() via_reg(VIA1, vACR) |= vSR_OUT +#define ADB_SR() via_reg(VIA1, vSR) +#define ADB_VIA_INTR_ENABLE() via_reg(VIA1, vIER) = 0x84 +#define ADB_VIA_INTR_DISABLE() via_reg(VIA1, vIER) = 0x04 +#define ADB_VIA_CLR_INTR() via_reg(VIA1, vIFR) = 0x04 +#define ADB_INTR_IS_OFF (vPB3 == (via_reg(VIA1, vBufB) & vPB3)) +#define ADB_INTR_IS_ON (0 == (via_reg(VIA1, vBufB) & vPB3)) +#define ADB_SR_INTR_IS_OFF (0 == (via_reg(VIA1, vIFR) & vSR_INT)) +#define ADB_SR_INTR_IS_ON (vSR_INT == (via_reg(VIA1, \ + vIFR) & vSR_INT)) -extern void adb_jadbproc(void); +/* + * This is the delay that is required (in uS) between certain + * ADB transactions. The actual timing delay for for each uS is + * calculated at boot time to account for differences in machine speed. + */ +#define ADB_DELAY 150 /* - * Global variables. + * Maximum ADB message length; includes space for data, result, and + * device code - plus a little for safety. */ -int adb_polling = 0; /* Are we polling? (Debugger mode) */ -#ifdef ADB_DEBUG -int adb_debug = 0; /* Output debugging messages */ -#endif /* ADB_DEBUG */ +#define ADB_MAX_MSG_LENGTH 16 +#define ADB_MAX_HDR_LENGTH 8 -extern struct mac68k_machine_S mac68k_machine; -extern int adbHardware; -extern char *adbHardwareDescr[]; +#define ADB_QUEUE 32 +#define ADB_TICKLE_TICKS 4 /* - * Driver definition. + * A structure for storing information about each ADB device. */ -struct cfattach adb_ca = { - sizeof(struct device), adbmatch, adbattach +struct ADBDevEntry { + void (*ServiceRtPtr)(void); + void *DataAreaAddr; + int devType; + int origAddr; + int currentAddr; }; -struct cfdriver adb_cd = { - NULL, "adb", DV_DULL + +/* + * Used to hold ADB commands that are waiting to be sent out. + */ +struct adbCmdHoldEntry { + u_char outBuf[ADB_MAX_MSG_LENGTH]; /* our message */ + u_char *saveBuf; /* buffer to know where to save result */ + u_char *compRout; /* completion routine pointer */ + u_char *data; /* completion routine data pointer */ }; -int -adbmatch(struct device *parent, void *vcf, void *aux) -{ - static int adb_matched = 0; +/* + * Eventually used for two separate queues, the queue between + * the upper and lower halves, and the outgoing packet queue. + * TO DO: adbCommand can replace all of adbCmdHoldEntry eventually + */ +struct adbCommand { + u_char header[ADB_MAX_HDR_LENGTH]; /* not used yet */ + u_char data[ADB_MAX_MSG_LENGTH]; /* packet data only */ + u_char *saveBuf; /* where to save result */ + u_char *compRout; /* completion routine pointer */ + u_char *compData; /* completion routine data pointer */ + u_int cmd; /* the original command for this data */ + u_int unsol; /* 1 if packet was unsolicited */ + u_int ack_only; /* 1 for no special processing */ +}; - /* Allow only one instance. */ - if (adb_matched) - return (0); +/* + * Text representations of each hardware class + */ +const char *adbHardwareDescr[MAX_ADB_HW + 1] = { + "unknown", + "II series", + "IIsi series", + "PowerBook", + "Cuda", +}; - adb_matched = 1; - return (1); -} +/* + * A few variables that we need and their initial values. + */ +int adbHardware = ADB_HW_UNKNOWN; +int adbActionState = ADB_ACTION_NOTREADY; +int adbBusState = ADB_BUS_UNKNOWN; +int adbWaiting = 0; /* waiting for return data from the device */ +int adbWriteDelay = 0; /* working on (or waiting to do) a write */ +int adbOutQueueHasData = 0; /* something in the queue waiting to go out */ +int adbNextEnd = 0; /* the next incoming bute is the last (II) */ +int adbSoftPower = 0; /* machine supports soft power */ + +int adbWaitingCmd = 0; /* ADB command we are waiting for */ +u_char *adbBuffer = (long)0; /* pointer to user data area */ +void *adbCompRout = (long)0; /* pointer to the completion routine */ +void *adbCompData = (long)0; /* pointer to the completion routine data */ +long adbFakeInts = 0; /* keeps track of fake ADB interrupts for + * timeouts (II) */ +int adbStarting = 1; /* doing adb_reinit so do polling differently */ +int adbSendTalk = 0; /* the intr routine is sending the talk, not + * the user (II) */ +int adbPolling = 0; /* we are polling for service request */ +int adbPollCmd = 0; /* the last poll command we sent */ + +u_char adbInputBuffer[ADB_MAX_MSG_LENGTH]; /* data input buffer */ +u_char adbOutputBuffer[ADB_MAX_MSG_LENGTH]; /* data output buffer */ +struct adbCmdHoldEntry adbOutQueue; /* our 1 entry output queue */ + +int adbSentChars = 0; /* how many characters we have sent */ +int adbLastDevice = 0; /* last ADB dev we heard from (II ONLY) */ +int adbLastDevIndex = 0; /* last ADB dev loc in dev table (II ONLY) */ +int adbLastCommand = 0; /* the last ADB command we sent (II) */ +struct ADBDevEntry ADBDevTable[16]; /* our ADB device table */ +int ADBNumDevices; /* num. of ADB devices found with adb_reinit */ + +struct adbCommand adbInbound[ADB_QUEUE]; /* incoming queue */ +volatile int adbInCount = 0; /* how many packets in in queue */ +int adbInHead = 0; /* head of in queue */ +int adbInTail = 0; /* tail of in queue */ +struct adbCommand adbOutbound[ADB_QUEUE]; /* outgoing queue - not used yet */ +int adbOutCount = 0; /* how many packets in out queue */ +int adbOutHead = 0; /* head of out queue */ +int adbOutTail = 0; /* tail of out queue */ + +int tickle_count = 0; /* how many tickles seen for this packet? */ +int tickle_serial = 0; /* the last packet tickled */ +int adb_cuda_serial = 0; /* the current packet */ + +struct timeout adb_cuda_timeout; + +void pm_setup_adb(void); +void pm_hw_setup(void); +void pm_check_adb_devices(int); +int pm_adb_op(u_char *, void *, void *, int); +void pm_init_adb_device(void); + +/* + * The following are private routines. + */ +#ifdef ADB_DEBUG +void print_single(u_char *); +#endif +int adb_intr(void *); +int adb_intr_II(void *); +int adb_intr_IIsi(void *); +int adb_intr_cuda(void *); +void adb_soft_intr(void); +int send_adb_II(u_char *, u_char *, void *, void *, int); +int send_adb_IIsi(u_char *, u_char *, void *, void *, int); +int send_adb_cuda(u_char *, u_char *, void *, void *, int); +void adb_intr_cuda_test(void); +void adb_cuda_tickle(void); +void adb_pass_up(struct adbCommand *); +void adb_op_comprout(caddr_t, caddr_t, int); +void adb_reinit(void); +int count_adbs(void); +int get_ind_adb_info(ADBDataBlock *, int); +int get_adb_info(ADBDataBlock *, int); +int set_adb_info(ADBSetInfoBlock *, int); +void adb_setup_hw_type(void); +int adb_op(Ptr, Ptr, Ptr, short); +void adb_read_II(u_char *); +void adb_hw_setup(void); +void adb_hw_setup_IIsi(u_char *); +int adb_cmd_result(u_char *); +int adb_cmd_extra(u_char *); +int adb_guess_next_device(void); +int adb_prog_switch_enable(void); +int adb_prog_switch_disable(void); +/* we should create this and it will be the public version */ +int send_adb(u_char *, void *, void *); + +#ifdef ADB_DEBUG +/* + * print_single + * Diagnostic display routine. Displays the hex values of the + * specified elements of the u_char. The length of the "string" + * is in [0]. + */ void -adbattach(struct device *parent, struct device *self, void *aux) +print_single(u_char *str) { - printf("\n"); - startuphook_establish(adb_attach_deferred, self); + int x; + + if (str == 0) { + printf_intr("no data - null pointer\n"); + return; + } + if (*str == 0) { + printf_intr("nothing returned\n"); + return; + } + if (*str > 20) { + printf_intr("ADB: ACK > 20 no way!\n"); + *str = (u_char)20; + } + printf_intr("(length=0x%x):", (u_int)*str); + for (x = 1; x <= *str; x++) + printf_intr(" 0x%02x", (u_int)*(str + x)); + printf_intr("\n"); } +#endif void -adb_attach_deferred(void *v) +adb_cuda_tickle(void) { - struct device *self = v; - ADBDataBlock adbdata; - struct adb_attach_args aa_args; - int totaladbs; - int adbindex, adbaddr; + volatile int s; - printf("%s", self->dv_xname); - adb_polling = 1; + if (adbActionState == ADB_ACTION_IN) { + if (tickle_serial == adb_cuda_serial) { + if (++tickle_count > 0) { + s = splhigh(); + adbActionState = ADB_ACTION_IDLE; + adbInputBuffer[0] = 0; + ADB_SET_STATE_IDLE_CUDA(); + splx(s); + } + } else { + tickle_serial = adb_cuda_serial; + tickle_count = 0; + } + } else { + tickle_serial = adb_cuda_serial; + tickle_count = 0; + } - ADBReInit(); - printf(": %s", adbHardwareDescr[adbHardware]); + timeout_add(&adb_cuda_timeout, ADB_TICKLE_TICKS); +} + +/* + * called when when an adb interrupt happens + * + * Cuda version of adb_intr + * TO DO: do we want to add some calls to intr_dispatch() here to + * grab serial interrupts? + */ +int +adb_intr_cuda(void *arg) +{ + volatile int i, ending; + volatile unsigned int s; + struct adbCommand packet; + + s = splhigh(); /* can't be too careful - might be called */ + /* from a routine, NOT an interrupt */ + + ADB_VIA_CLR_INTR(); /* clear interrupt */ + ADB_VIA_INTR_DISABLE(); /* disable ADB interrupt on IIs. */ + +switch_start: + switch (adbActionState) { + case ADB_ACTION_IDLE: + /* + * This is an unexpected packet, so grab the first (dummy) + * byte, set up the proper vars, and tell the chip we are + * starting to receive the packet by setting the TIP bit. + */ + adbInputBuffer[1] = ADB_SR(); + adb_cuda_serial++; + if (ADB_INTR_IS_OFF) /* must have been a fake start */ + break; + + ADB_SET_SR_INPUT(); + ADB_SET_STATE_TIP(); + + adbInputBuffer[0] = 1; + adbActionState = ADB_ACTION_IN; +#ifdef ADB_DEBUG + if (adb_debug) + printf_intr("idle 0x%02x ", adbInputBuffer[1]); +#endif + break; + + case ADB_ACTION_IN: + adbInputBuffer[++adbInputBuffer[0]] = ADB_SR(); + /* intr off means this is the last byte (end of frame) */ + if (ADB_INTR_IS_OFF) + ending = 1; + else + ending = 0; + + if (1 == ending) { /* end of message? */ +#ifdef ADB_DEBUG + if (adb_debug) { + printf_intr("in end 0x%02x ", + adbInputBuffer[adbInputBuffer[0]]); + print_single(adbInputBuffer); + } +#endif + + /* + * Are we waiting AND does this packet match what we + * are waiting for AND is it coming from either the + * ADB or RTC/PRAM sub-device? This section _should_ + * recognize all ADB and RTC/PRAM type commands, but + * there may be more... NOTE: commands are always at + * [4], even for RTC/PRAM commands. + */ + /* set up data for adb_pass_up */ + memcpy(packet.data, adbInputBuffer, adbInputBuffer[0] + 1); + + if ((adbWaiting == 1) && + (adbInputBuffer[4] == adbWaitingCmd) && + ((adbInputBuffer[2] == 0x00) || + (adbInputBuffer[2] == 0x01))) { + packet.saveBuf = adbBuffer; + packet.compRout = adbCompRout; + packet.compData = adbCompData; + packet.unsol = 0; + packet.ack_only = 0; + adb_pass_up(&packet); + + adbWaitingCmd = 0; /* reset "waiting" vars */ + adbWaiting = 0; + adbBuffer = (long)0; + adbCompRout = (long)0; + adbCompData = (long)0; + } else { + packet.unsol = 1; + packet.ack_only = 0; + adb_pass_up(&packet); + } + + + /* reset vars and signal the end of this frame */ + adbActionState = ADB_ACTION_IDLE; + adbInputBuffer[0] = 0; + ADB_SET_STATE_IDLE_CUDA(); + /*ADB_SET_SR_INPUT();*/ + + /* + * If there is something waiting to be sent out, + * the set everything up and send the first byte. + */ + if (adbWriteDelay == 1) { + delay(ADB_DELAY); /* required */ + adbSentChars = 0; + adbActionState = ADB_ACTION_OUT; + /* + * If the interrupt is on, we were too slow + * and the chip has already started to send + * something to us, so back out of the write + * and start a read cycle. + */ + if (ADB_INTR_IS_ON) { + ADB_SET_SR_INPUT(); + ADB_SET_STATE_IDLE_CUDA(); + adbSentChars = 0; + adbActionState = ADB_ACTION_IDLE; + adbInputBuffer[0] = 0; + break; + } + /* + * If we got here, it's ok to start sending + * so load the first byte and tell the chip + * we want to send. + */ + ADB_SET_STATE_TIP(); + ADB_SET_SR_OUTPUT(); + ADB_SR() = adbOutputBuffer[adbSentChars + 1]; + } + } else { + ADB_TOGGLE_STATE_ACK_CUDA(); +#ifdef ADB_DEBUG + if (adb_debug) + printf_intr("in 0x%02x ", + adbInputBuffer[adbInputBuffer[0]]); +#endif + } + break; + + case ADB_ACTION_OUT: + i = ADB_SR(); /* reset SR-intr in IFR */ +#ifdef ADB_DEBUG + if (adb_debug) + printf_intr("intr out 0x%02x ", i); +#endif + + adbSentChars++; + if (ADB_INTR_IS_ON) { /* ADB intr low during write */ +#ifdef ADB_DEBUG + if (adb_debug) + printf_intr("intr was on "); +#endif + ADB_SET_SR_INPUT(); /* make sure SR is set to IN */ + ADB_SET_STATE_IDLE_CUDA(); + adbSentChars = 0; /* must start all over */ + adbActionState = ADB_ACTION_IDLE; /* new state */ + adbInputBuffer[0] = 0; + adbWriteDelay = 1; /* must retry when done with + * read */ + delay(ADB_DELAY); + goto switch_start; /* process next state right + * now */ + break; + } + if (adbOutputBuffer[0] == adbSentChars) { /* check for done */ + if (0 == adb_cmd_result(adbOutputBuffer)) { /* do we expect data + * back? */ + adbWaiting = 1; /* signal waiting for return */ + adbWaitingCmd = adbOutputBuffer[2]; /* save waiting command */ + } else { /* no talk, so done */ + /* set up stuff for adb_pass_up */ + memcpy(packet.data, adbInputBuffer, adbInputBuffer[0] + 1); + packet.saveBuf = adbBuffer; + packet.compRout = adbCompRout; + packet.compData = adbCompData; + packet.cmd = adbWaitingCmd; + packet.unsol = 0; + packet.ack_only = 1; + adb_pass_up(&packet); + + /* reset "waiting" vars, just in case */ + adbWaitingCmd = 0; + adbBuffer = (long)0; + adbCompRout = (long)0; + adbCompData = (long)0; + } + + adbWriteDelay = 0; /* done writing */ + adbActionState = ADB_ACTION_IDLE; /* signal bus is idle */ + ADB_SET_SR_INPUT(); + ADB_SET_STATE_IDLE_CUDA(); +#ifdef ADB_DEBUG + if (adb_debug) + printf_intr("write done "); +#endif + } else { + ADB_SR() = adbOutputBuffer[adbSentChars + 1]; /* send next byte */ + ADB_TOGGLE_STATE_ACK_CUDA(); /* signal byte ready to + * shift */ +#ifdef ADB_DEBUG + if (adb_debug) + printf_intr("toggle "); +#endif + } + break; + + case ADB_ACTION_NOTREADY: +#ifdef ADB_DEBUG + if (adb_debug) + printf_intr("adb: not yet initialized\n"); +#endif + break; + + default: +#ifdef ADB_DEBUG + if (adb_debug) + printf_intr("intr: unknown ADB state\n"); +#endif + break; + } + + ADB_VIA_INTR_ENABLE(); /* enable ADB interrupt on IIs. */ + + splx(s); /* restore */ + + return (1); +} /* end adb_intr_cuda */ + + +int +send_adb_cuda(u_char *in, u_char *buffer, void *compRout, void *data, int + command) +{ + int s, len; #ifdef ADB_DEBUG if (adb_debug) - printf("adb: done with ADBReInit\n"); + printf_intr("SEND\n"); #endif - totaladbs = CountADBs(); + if (adbActionState == ADB_ACTION_NOTREADY) + return 1; - printf(", %d target%s\n", totaladbs, (totaladbs == 1) ? "" : "s"); + /* Don't interrupt while we are messing with the ADB */ + s = splhigh(); - /* for each ADB device */ - for (adbindex = 1; adbindex <= totaladbs; adbindex++) { - /* Get the ADB information */ - adbaddr = GetIndADB(&adbdata, adbindex); + if ((adbActionState == ADB_ACTION_IDLE) && /* ADB available? */ + (ADB_INTR_IS_OFF)) { /* and no incoming interrupt? */ + } else + if (adbWriteDelay == 0) /* it's busy, but is anything waiting? */ + adbWriteDelay = 1; /* if no, then we'll "queue" + * it up */ + else { + splx(s); + return 1; /* really busy! */ + } - aa_args.origaddr = (int)(adbdata.origADBAddr); - aa_args.adbaddr = adbaddr; - aa_args.handler_id = (int)(adbdata.devType); +#ifdef ADB_DEBUG + if (adb_debug) + printf_intr("QUEUE\n"); +#endif + if ((long)in == (long)0) { /* need to convert? */ + /* + * Don't need to use adb_cmd_extra here because this section + * will be called ONLY when it is an ADB command (no RTC or + * PRAM) + */ + if ((command & 0x0c) == 0x08) /* copy addl data ONLY if + * doing a listen! */ + len = buffer[0]; /* length of additional data */ + else + len = 0;/* no additional data */ - (void)config_found(self, &aa_args, adbprint); + adbOutputBuffer[0] = 2 + len; /* dev. type + command + addl. + * data */ + adbOutputBuffer[1] = 0x00; /* mark as an ADB command */ + adbOutputBuffer[2] = (u_char)command; /* load command */ + + /* copy additional output data, if any */ + memcpy(adbOutputBuffer + 3, buffer + 1, len); + } else + /* if data ready, just copy over */ + memcpy(adbOutputBuffer, in, in[0] + 2); + + adbSentChars = 0; /* nothing sent yet */ + adbBuffer = buffer; /* save buffer to know where to save result */ + adbCompRout = compRout; /* save completion routine pointer */ + adbCompData = data; /* save completion routine data pointer */ + adbWaitingCmd = adbOutputBuffer[2]; /* save wait command */ + + if (adbWriteDelay != 1) { /* start command now? */ +#ifdef ADB_DEBUG + if (adb_debug) + printf_intr("out start NOW"); +#endif + delay(ADB_DELAY); + adbActionState = ADB_ACTION_OUT; /* set next state */ + ADB_SET_SR_OUTPUT(); /* set shift register for OUT */ + ADB_SR() = adbOutputBuffer[adbSentChars + 1]; /* load byte for output */ + ADB_SET_STATE_ACKOFF_CUDA(); + ADB_SET_STATE_TIP(); /* tell ADB that we want to send */ } - adb_polling = 0; -} + adbWriteDelay = 1; /* something in the write "queue" */ + + splx(s); + + if (0x0100 <= (s & 0x0700)) /* were VIA1 interrupts blocked? */ + /* poll until byte done */ + while ((adbActionState != ADB_ACTION_IDLE) || (ADB_INTR_IS_ON) + || (adbWaiting == 1)) + if (ADB_SR_INTR_IS_ON) { /* wait for "interrupt" */ + adb_intr_cuda(NULL); /* go process it */ + if (adb_polling) + adb_soft_intr(); + } + + return 0; +} /* send_adb_cuda */ int -adbprint(void *args, const char *name) +adb_intr_II(void *arg) { - struct adb_attach_args *aa_args = (struct adb_attach_args *)args; - int rv = UNCONF; + struct adbCommand packet; + int i, intr_on = 0; + int send = 0; + unsigned int s; + + s = splhigh(); /* can't be too careful - might be called */ + /* from a routine, NOT an interrupt */ + + ADB_VIA_CLR_INTR(); /* clear interrupt */ + + ADB_VIA_INTR_DISABLE(); /* disable ADB interrupt on IIs. */ + + delay(ADB_DELAY); /* yuck (don't remove) */ + + (void)intr_dispatch(0x70); /* grab any serial interrupts */ - if (name) { /* no configured device matched */ - rv = UNSUPP; /* most ADB device types are unsupported */ + if (ADB_INTR_IS_ON) + intr_on = 1; /* save for later */ + +switch_start: + switch (adbActionState) { + case ADB_ACTION_POLLING: + if (!intr_on) { + if (adbOutQueueHasData) { +#ifdef ADB_DEBUG + if (adb_debug & 0x80) + printf_intr("POLL-doing-out-queue. "); +#endif + ADB_SET_STATE_IDLE_II(); + delay(ADB_DELAY); - /* print out what kind of ADB device we have found */ - switch(aa_args->origaddr) { -#ifdef ADBVERBOSE - case ADBADDR_SECURE: - printf("security dongle (%d)", - aa_args->handler_id); + /* copy over data */ + memcpy(adbOutputBuffer, adbOutQueue.outBuf, + adbOutQueue.outBuf[0] + 2); + + adbBuffer = adbOutQueue.saveBuf; /* user data area */ + adbCompRout = adbOutQueue.compRout; /* completion routine */ + adbCompData = adbOutQueue.data; /* comp. rout. data */ + adbOutQueueHasData = 0; /* currently processing + * "queue" entry */ + adbSentChars = 0; /* nothing sent yet */ + adbActionState = ADB_ACTION_OUT; /* set next state */ + ADB_SET_SR_OUTPUT(); /* set shift register for OUT */ + ADB_SR() = adbOutputBuffer[1]; /* load byte for output */ + adbBusState = ADB_BUS_CMD; /* set bus to cmd state */ + ADB_SET_STATE_CMD(); /* tell ADB that we want to send */ + break; + } else { +#ifdef ADB_DEBUG + if (adb_debug) + printf_intr("pIDLE "); +#endif + adbActionState = ADB_ACTION_IDLE; + } + } else { +#ifdef ADB_DEBUG + if (adb_debug & 0x80) + printf_intr("pIN "); +#endif + adbActionState = ADB_ACTION_IN; + } + delay(ADB_DELAY); + (void)intr_dispatch(0x70); /* grab any serial interrupts */ + goto switch_start; + break; + case ADB_ACTION_IDLE: + if (!intr_on) { + i = ADB_SR(); + adbBusState = ADB_BUS_IDLE; + adbActionState = ADB_ACTION_IDLE; + ADB_SET_STATE_IDLE_II(); break; + } + adbInputBuffer[0] = 1; + adbInputBuffer[1] = ADB_SR(); /* get first byte */ +#ifdef ADB_DEBUG + if (adb_debug & 0x80) + printf_intr("idle 0x%02x ", adbInputBuffer[1]); +#endif + ADB_SET_SR_INPUT(); /* make sure SR is set to IN */ + adbActionState = ADB_ACTION_IN; /* set next state */ + ADB_SET_STATE_EVEN(); /* set bus state to even */ + adbBusState = ADB_BUS_EVEN; + break; + + case ADB_ACTION_IN: + adbInputBuffer[++adbInputBuffer[0]] = ADB_SR(); /* get byte */ +#ifdef ADB_DEBUG + if (adb_debug & 0x80) + printf_intr("in 0x%02x ", + adbInputBuffer[adbInputBuffer[0]]); +#endif + ADB_SET_SR_INPUT(); /* make sure SR is set to IN */ + + if (intr_on) { /* process last byte of packet */ + adbInputBuffer[0]--; /* minus one */ + /* + * If intr_on was true, and it's the second byte, then + * the byte we just discarded is really valid, so + * adjust the count + */ + if (adbInputBuffer[0] == 2) { + adbInputBuffer[0]++; + } + +#ifdef ADB_DEBUG + if (adb_debug & 0x80) { + printf_intr("done: "); + print_single(adbInputBuffer); + } #endif - case ADBADDR_MAP: - printf("mapped device (%d)", - aa_args->handler_id); - rv = UNCONF; + + adbLastDevice = ADB_CMDADDR(adbInputBuffer[1]); + + if (adbInputBuffer[0] == 1 && !adbWaiting) { /* SRQ!!!*/ +#ifdef ADB_DEBUG + if (adb_debug & 0x80) + printf_intr(" xSRQ! "); +#endif + adb_guess_next_device(); +#ifdef ADB_DEBUG + if (adb_debug & 0x80) + printf_intr("try 0x%0x ", + adbLastDevice); +#endif + adbOutputBuffer[0] = 1; + adbOutputBuffer[1] = ADBTALK(adbLastDevice, 0); + + adbSentChars = 0; /* nothing sent yet */ + adbActionState = ADB_ACTION_POLLING; /* set next state */ + ADB_SET_SR_OUTPUT(); /* set shift register for OUT */ + ADB_SR() = adbOutputBuffer[1]; /* load byte for output */ + adbBusState = ADB_BUS_CMD; /* set bus to cmd state */ + ADB_SET_STATE_CMD(); /* tell ADB that we want to */ + break; + } + + /* set up data for adb_pass_up */ + memcpy(packet.data, adbInputBuffer, adbInputBuffer[0] + 1); + + if (!adbWaiting && (adbInputBuffer[0] != 0)) { + packet.unsol = 1; + packet.ack_only = 0; + adb_pass_up(&packet); + } else { + packet.saveBuf = adbBuffer; + packet.compRout = adbCompRout; + packet.compData = adbCompData; + packet.unsol = 0; + packet.ack_only = 0; + adb_pass_up(&packet); + } + + adbWaiting = 0; + adbInputBuffer[0] = 0; + adbBuffer = (long)0; + adbCompRout = (long)0; + adbCompData = (long)0; + /* + * Since we are done, check whether there is any data + * waiting to do out. If so, start the sending the data. + */ + if (adbOutQueueHasData == 1) { +#ifdef ADB_DEBUG + if (adb_debug & 0x80) + printf_intr("XXX: DOING OUT QUEUE\n"); +#endif + /* copy over data */ + memcpy(adbOutputBuffer, adbOutQueue.outBuf, + adbOutQueue.outBuf[0] + 2); + adbBuffer = adbOutQueue.saveBuf; /* user data area */ + adbCompRout = adbOutQueue.compRout; /* completion routine */ + adbCompData = adbOutQueue.data; /* comp. rout. data */ + adbOutQueueHasData = 0; /* currently processing + * "queue" entry */ + send = 1; + } else { +#ifdef ADB_DEBUG + if (adb_debug & 0x80) + printf_intr("XXending "); +#endif + adb_guess_next_device(); + adbOutputBuffer[0] = 1; + adbOutputBuffer[1] = ((adbLastDevice & 0x0f) << 4) | 0x0c; + adbSentChars = 0; /* nothing sent yet */ + adbActionState = ADB_ACTION_POLLING; /* set next state */ + ADB_SET_SR_OUTPUT(); /* set shift register for OUT */ + ADB_SR() = adbOutputBuffer[1]; /* load byte for output */ + adbBusState = ADB_BUS_CMD; /* set bus to cmd state */ + ADB_SET_STATE_CMD(); /* tell ADB that we want to */ + break; + } + } + + /* + * If send is true then something above determined that + * the message has ended and we need to start sending out + * a new message immediately. This could be because there + * is data waiting to go out or because an SRQ was seen. + */ + if (send) { + adbSentChars = 0; /* nothing sent yet */ + adbActionState = ADB_ACTION_OUT; /* set next state */ + ADB_SET_SR_OUTPUT(); /* set shift register for OUT */ + ADB_SR() = adbOutputBuffer[1]; /* load byte for output */ + adbBusState = ADB_BUS_CMD; /* set bus to cmd state */ + ADB_SET_STATE_CMD(); /* tell ADB that we want to + * send */ + break; + } + /* We only get this far if the message hasn't ended yet. */ + switch (adbBusState) { /* set to next state */ + case ADB_BUS_EVEN: + ADB_SET_STATE_ODD(); /* set state to odd */ + adbBusState = ADB_BUS_ODD; + break; + + case ADB_BUS_ODD: + ADB_SET_STATE_EVEN(); /* set state to even */ + adbBusState = ADB_BUS_EVEN; + break; + default: + printf_intr("strange state!!!\n"); /* huh? */ break; - case ADBADDR_REL: - printf("relative positioning device (%d)", - aa_args->handler_id); - rv = UNCONF; + } + break; + + case ADB_ACTION_OUT: + i = ADB_SR(); /* clear interrupt */ + adbSentChars++; + /* + * If the outgoing data was a TALK, we must + * switch to input mode to get the result. + */ + if ((adbOutputBuffer[1] & 0x0c) == 0x0c) { + adbInputBuffer[0] = 1; + adbInputBuffer[1] = i; + adbActionState = ADB_ACTION_IN; + ADB_SET_SR_INPUT(); + adbBusState = ADB_BUS_EVEN; + ADB_SET_STATE_EVEN(); +#ifdef ADB_DEBUG + if (adb_debug & 0x80) + printf_intr("talk out 0x%02x ", i); +#endif + /* we want something back */ + adbWaiting = 1; break; -#ifdef ADBVERBOSE - case ADBADDR_ABS: - switch (aa_args->handler_id) { - case ADB_ARTPAD: - printf("WACOM ArtPad II"); + } + /* + * If it's not a TALK, check whether all data has been sent. + * If so, call the completion routine and clean up. If not, + * advance to the next state. + */ +#ifdef ADB_DEBUG + if (adb_debug & 0x80) + printf_intr("non-talk out 0x%0x ", i); +#endif + ADB_SET_SR_OUTPUT(); + if (adbOutputBuffer[0] == adbSentChars) { /* check for done */ +#ifdef ADB_DEBUG + if (adb_debug & 0x80) + printf_intr("done \n"); +#endif + /* set up stuff for adb_pass_up */ + memcpy(packet.data, adbOutputBuffer, adbOutputBuffer[0] + 1); + packet.saveBuf = adbBuffer; + packet.compRout = adbCompRout; + packet.compData = adbCompData; + packet.cmd = adbWaitingCmd; + packet.unsol = 0; + packet.ack_only = 1; + adb_pass_up(&packet); + + /* reset "waiting" vars, just in case */ + adbBuffer = (long)0; + adbCompRout = (long)0; + adbCompData = (long)0; + if (adbOutQueueHasData == 1) { + /* copy over data */ + memcpy(adbOutputBuffer, adbOutQueue.outBuf, + adbOutQueue.outBuf[0] + 2); + adbBuffer = adbOutQueue.saveBuf; /* user data area */ + adbCompRout = adbOutQueue.compRout; /* completion routine */ + adbCompData = adbOutQueue.data; /* comp. rout. data */ + adbOutQueueHasData = 0; /* currently processing + * "queue" entry */ + adbSentChars = 0; /* nothing sent yet */ + adbActionState = ADB_ACTION_OUT; /* set next state */ + ADB_SET_SR_OUTPUT(); /* set shift register for OUT */ + ADB_SR() = adbOutputBuffer[1]; /* load byte for output */ + adbBusState = ADB_BUS_CMD; /* set bus to cmd state */ + ADB_SET_STATE_CMD(); /* tell ADB that we want to + * send */ break; - default: - printf("absolute positioning device (%d)", - aa_args->handler_id); + } else { + /* send talk to last device instead */ + adbOutputBuffer[0] = 1; + adbOutputBuffer[1] = + ADBTALK(ADB_CMDADDR(adbOutputBuffer[1]), 0); + + adbSentChars = 0; /* nothing sent yet */ + adbActionState = ADB_ACTION_IDLE; /* set next state */ + ADB_SET_SR_OUTPUT(); /* set shift register for OUT */ + ADB_SR() = adbOutputBuffer[1]; /* load byte for output */ + adbBusState = ADB_BUS_CMD; /* set bus to cmd state */ + ADB_SET_STATE_CMD(); /* tell ADB that we want to */ break; } + } + ADB_SR() = adbOutputBuffer[adbSentChars + 1]; + switch (adbBusState) { /* advance to next state */ + case ADB_BUS_EVEN: + ADB_SET_STATE_ODD(); /* set state to odd */ + adbBusState = ADB_BUS_ODD; break; - case ADBADDR_DATATX: - printf("data transfer device (modem?) (%d)", - aa_args->handler_id); + + case ADB_BUS_CMD: + case ADB_BUS_ODD: + ADB_SET_STATE_EVEN(); /* set state to even */ + adbBusState = ADB_BUS_EVEN; + break; + + default: +#ifdef ADB_DEBUG + if (adb_debug) { + printf_intr("strange state!!! (0x%x)\n", + adbBusState); + } +#endif break; - case ADBADDR_MISC: - switch (aa_args->handler_id) { - case ADB_POWERKEY: - printf("Sophisticated Circuits PowerKey"); + } + break; + + default: +#ifdef ADB_DEBUG + if (adb_debug) + printf_intr("adb: unknown ADB state (during intr)\n"); +#endif + break; + } + + ADB_VIA_INTR_ENABLE(); /* enable ADB interrupt on IIs. */ + + splx(s); /* restore */ + + return (1); + +} + + +/* + * send_adb version for II series machines + */ +int +send_adb_II(u_char *in, u_char *buffer, void *compRout, void *data, int command) +{ + int s, len; + + if (adbActionState == ADB_ACTION_NOTREADY) /* return if ADB not + * available */ + return 1; + + /* Don't interrupt while we are messing with the ADB */ + s = splhigh(); + + if (0 != adbOutQueueHasData) { /* right now, "has data" means "full" */ + splx(s); /* sorry, try again later */ + return 1; + } + if ((long)in == (long)0) { /* need to convert? */ + /* + * Don't need to use adb_cmd_extra here because this section + * will be called ONLY when it is an ADB command (no RTC or + * PRAM), especially on II series! + */ + if ((command & 0x0c) == 0x08) /* copy addl data ONLY if + * doing a listen! */ + len = buffer[0]; /* length of additional data */ + else + len = 0;/* no additional data */ + + adbOutQueue.outBuf[0] = 1 + len; /* command + addl. data */ + adbOutQueue.outBuf[1] = (u_char)command; /* load command */ + + /* copy additional output data, if any */ + memcpy(adbOutQueue.outBuf + 2, buffer + 1, len); + } else + /* if data ready, just copy over */ + memcpy(adbOutQueue.outBuf, in, in[0] + 2); + + adbOutQueue.saveBuf = buffer; /* save buffer to know where to save + * result */ + adbOutQueue.compRout = compRout; /* save completion routine + * pointer */ + adbOutQueue.data = data;/* save completion routine data pointer */ + + if ((adbActionState == ADB_ACTION_IDLE) && /* is ADB available? */ + (ADB_INTR_IS_OFF)) { /* and no incoming interrupts? */ + /* then start command now */ + memcpy(adbOutputBuffer, adbOutQueue.outBuf, + adbOutQueue.outBuf[0] + 2); /* copy over data */ + + adbBuffer = adbOutQueue.saveBuf; /* pointer to user data + * area */ + adbCompRout = adbOutQueue.compRout; /* pointer to the + * completion routine */ + adbCompData = adbOutQueue.data; /* pointer to the completion + * routine data */ + + adbSentChars = 0; /* nothing sent yet */ + adbActionState = ADB_ACTION_OUT; /* set next state */ + adbBusState = ADB_BUS_CMD; /* set bus to cmd state */ + + ADB_SET_SR_OUTPUT(); /* set shift register for OUT */ + + ADB_SR() = adbOutputBuffer[adbSentChars + 1]; /* load byte for output */ + ADB_SET_STATE_CMD(); /* tell ADB that we want to send */ + adbOutQueueHasData = 0; /* currently processing "queue" entry */ + } else + adbOutQueueHasData = 1; /* something in the write "queue" */ + + splx(s); + + if (0x0100 <= (s & 0x0700)) /* were VIA1 interrupts blocked? */ + /* poll until message done */ + while ((adbActionState != ADB_ACTION_IDLE) || (ADB_INTR_IS_ON) + || (adbWaiting == 1)) + if (ADB_SR_INTR_IS_ON) { /* wait for "interrupt" */ + adb_intr_II(NULL); /* go process it */ + if (adb_polling) + adb_soft_intr(); + } + + return 0; +} + + +/* + * This routine is called from the II series interrupt routine + * to determine what the "next" device is that should be polled. + */ +int +adb_guess_next_device(void) +{ + int last, i, dummy; + + if (adbStarting) { + /* + * Start polling EVERY device, since we can't be sure there is + * anything in the device table yet + */ + if (adbLastDevice < 1 || adbLastDevice > 15) + adbLastDevice = 1; + if (++adbLastDevice > 15) /* point to next one */ + adbLastDevice = 1; + } else { + /* find the next device using the device table */ + if (adbLastDevice < 1 || adbLastDevice > 15) /* let's be parinoid */ + adbLastDevice = 2; + last = 1; /* default index location */ + + for (i = 1; i < 16; i++) /* find index entry */ + if (ADBDevTable[i].currentAddr == adbLastDevice) { /* look for device */ + last = i; /* found it */ break; - default: - printf("misc. device (remote control?) (%d)", - aa_args->handler_id); + } + dummy = last; /* index to start at */ + for (;;) { /* find next device in index */ + if (++dummy > 15) /* wrap around if needed */ + dummy = 1; + if (dummy == last) { /* didn't find any other + * device! This can happen if + * there are no devices on the + * bus */ + dummy = 1; break; } + /* found the next device */ + if (ADBDevTable[dummy].devType != 0) + break; + } + adbLastDevice = ADBDevTable[dummy].currentAddr; + } + return adbLastDevice; +} + + +/* + * Called when when an adb interrupt happens. + * This routine simply transfers control over to the appropriate + * code for the machine we are running on. + */ +int +adb_intr(void *arg) +{ + switch (adbHardware) { + case ADB_HW_II: + return adb_intr_II(arg); + break; + + case ADB_HW_IISI: + return adb_intr_IIsi(arg); + break; + + case ADB_HW_PB: /* Should not come through here. */ + break; + + case ADB_HW_CUDA: + return adb_intr_cuda(arg); + break; + + case ADB_HW_UNKNOWN: + break; + } + + return (-1); +} + + +/* + * called when when an adb interrupt happens + * + * IIsi version of adb_intr + * + */ +int +adb_intr_IIsi(void *arg) +{ + struct adbCommand packet; + int i, ending; + unsigned int s; + + s = splhigh(); /* can't be too careful - might be called */ + /* from a routine, NOT an interrupt */ + + ADB_VIA_CLR_INTR(); /* clear interrupt */ + + ADB_VIA_INTR_DISABLE(); /* disable ADB interrupt on IIs. */ + +switch_start: + switch (adbActionState) { + case ADB_ACTION_IDLE: + delay(ADB_DELAY); /* short delay is required before the + * first byte */ + + ADB_SET_SR_INPUT(); /* make sure SR is set to IN */ + ADB_SET_STATE_ACTIVE(); /* signal start of data frame */ + adbInputBuffer[1] = ADB_SR(); /* get byte */ + adbInputBuffer[0] = 1; + adbActionState = ADB_ACTION_IN; /* set next state */ + + ADB_SET_STATE_ACKON(); /* start ACK to ADB chip */ + delay(ADB_DELAY); /* delay */ + ADB_SET_STATE_ACKOFF(); /* end ACK to ADB chip */ + (void)intr_dispatch(0x70); /* grab any serial interrupts */ + break; + + case ADB_ACTION_IN: + ADB_SET_SR_INPUT(); /* make sure SR is set to IN */ + adbInputBuffer[++adbInputBuffer[0]] = ADB_SR(); /* get byte */ + if (ADB_INTR_IS_OFF) /* check for end of frame */ + ending = 1; + else + ending = 0; + + ADB_SET_STATE_ACKON(); /* start ACK to ADB chip */ + delay(ADB_DELAY); /* delay */ + ADB_SET_STATE_ACKOFF(); /* end ACK to ADB chip */ + (void)intr_dispatch(0x70); /* grab any serial interrupts */ + + if (1 == ending) { /* end of message? */ + ADB_SET_STATE_INACTIVE(); /* signal end of frame */ + /* + * This section _should_ handle all ADB and RTC/PRAM + * type commands, but there may be more... Note: + * commands are always at [4], even for rtc/pram + * commands + */ + /* set up data for adb_pass_up */ + memcpy(packet.data, adbInputBuffer, adbInputBuffer[0] + 1); + + if ((adbWaiting == 1) && /* are we waiting AND */ + (adbInputBuffer[4] == adbWaitingCmd) && /* the cmd we sent AND */ + ((adbInputBuffer[2] == 0x00) || /* it's from the ADB + * device OR */ + (adbInputBuffer[2] == 0x01))) { /* it's from the + * PRAM/RTC device */ + + packet.saveBuf = adbBuffer; + packet.compRout = adbCompRout; + packet.compData = adbCompData; + packet.unsol = 0; + packet.ack_only = 0; + adb_pass_up(&packet); + + adbWaitingCmd = 0; /* reset "waiting" vars */ + adbWaiting = 0; + adbBuffer = (long)0; + adbCompRout = (long)0; + adbCompData = (long)0; + } else { + packet.unsol = 1; + packet.ack_only = 0; + adb_pass_up(&packet); + } + + adbActionState = ADB_ACTION_IDLE; + adbInputBuffer[0] = 0; /* reset length */ + + if (adbWriteDelay == 1) { /* were we waiting to + * write? */ + adbSentChars = 0; /* nothing sent yet */ + adbActionState = ADB_ACTION_OUT; /* set next state */ + + delay(ADB_DELAY); /* delay */ + (void)intr_dispatch(0x70); /* grab any serial interrupts */ + + if (ADB_INTR_IS_ON) { /* ADB intr low during + * write */ + ADB_SET_STATE_IDLE_IISI(); /* reset */ + ADB_SET_SR_INPUT(); /* make sure SR is set + * to IN */ + adbSentChars = 0; /* must start all over */ + adbActionState = ADB_ACTION_IDLE; /* new state */ + adbInputBuffer[0] = 0; + /* may be able to take this out later */ + delay(ADB_DELAY); /* delay */ + break; + } + ADB_SET_STATE_ACTIVE(); /* tell ADB that we want + * to send */ + ADB_SET_STATE_ACKOFF(); /* make sure */ + ADB_SET_SR_OUTPUT(); /* set shift register + * for OUT */ + ADB_SR() = adbOutputBuffer[adbSentChars + 1]; + ADB_SET_STATE_ACKON(); /* tell ADB byte ready + * to shift */ + } + } + break; + + case ADB_ACTION_OUT: + i = ADB_SR(); /* reset SR-intr in IFR */ + ADB_SET_SR_OUTPUT(); /* set shift register for OUT */ + + ADB_SET_STATE_ACKOFF(); /* finish ACK */ + adbSentChars++; + if (ADB_INTR_IS_ON) { /* ADB intr low during write */ + ADB_SET_STATE_IDLE_IISI(); /* reset */ + ADB_SET_SR_INPUT(); /* make sure SR is set to IN */ + adbSentChars = 0; /* must start all over */ + adbActionState = ADB_ACTION_IDLE; /* new state */ + adbInputBuffer[0] = 0; + adbWriteDelay = 1; /* must retry when done with + * read */ + delay(ADB_DELAY); /* delay */ + (void)intr_dispatch(0x70); /* grab any serial interrupts */ + goto switch_start; /* process next state right + * now */ break; - default: - printf("unknown type %d device, (handler %d)", - aa_args->origaddr, aa_args->handler_id); + } + delay(ADB_DELAY); /* required delay */ + (void)intr_dispatch(0x70); /* grab any serial interrupts */ + + if (adbOutputBuffer[0] == adbSentChars) { /* check for done */ + if (0 == adb_cmd_result(adbOutputBuffer)) { /* do we expect data + * back? */ + adbWaiting = 1; /* signal waiting for return */ + adbWaitingCmd = adbOutputBuffer[2]; /* save waiting command */ + } else {/* no talk, so done */ + /* set up stuff for adb_pass_up */ + memcpy(packet.data, adbInputBuffer, + adbInputBuffer[0] + 1); + packet.saveBuf = adbBuffer; + packet.compRout = adbCompRout; + packet.compData = adbCompData; + packet.cmd = adbWaitingCmd; + packet.unsol = 0; + packet.ack_only = 1; + adb_pass_up(&packet); + + /* reset "waiting" vars, just in case */ + adbWaitingCmd = 0; + adbBuffer = (long)0; + adbCompRout = (long)0; + adbCompData = (long)0; + } + + adbWriteDelay = 0; /* done writing */ + adbActionState = ADB_ACTION_IDLE; /* signal bus is idle */ + ADB_SET_SR_INPUT(); /* make sure SR is set to IN */ + ADB_SET_STATE_INACTIVE(); /* end of frame */ + } else { + ADB_SR() = adbOutputBuffer[adbSentChars + 1]; /* send next byte */ + ADB_SET_STATE_ACKON(); /* signal byte ready to shift */ + } + break; + + case ADB_ACTION_NOTREADY: +#ifdef ADB_DEBUG + if (adb_debug) + printf_intr("adb: not yet initialized\n"); +#endif + break; + + default: +#ifdef ADB_DEBUG + if (adb_debug) + printf_intr("intr: unknown ADB state\n"); +#endif + break; + } + + ADB_VIA_INTR_ENABLE(); /* enable ADB interrupt on IIs. */ + + splx(s); /* restore */ + + return (1); +} /* end adb_intr_IIsi */ + + +/***************************************************************************** + * if the device is currently busy, and there is no data waiting to go out, then + * the data is "queued" in the outgoing buffer. If we are already waiting, then + * we return. + * in: if (in == 0) then the command string is built from command and buffer + * if (in != 0) then in is used as the command string + * buffer: additional data to be sent (used only if in == 0) + * this is also where return data is stored + * compRout: the completion routine that is called when then return value + * is received (if a return value is expected) + * data: a data pointer that can be used by the completion routine + * command: an ADB command to be sent (used only if in == 0) + * + */ +int +send_adb_IIsi(u_char *in, u_char *buffer, void *compRout, void *data, int + command) +{ + int s, len; + + if (adbActionState == ADB_ACTION_NOTREADY) + return 1; + + /* Don't interrupt while we are messing with the ADB */ + s = splhigh(); + + if ((adbActionState == ADB_ACTION_IDLE) && /* ADB available? */ + (ADB_INTR_IS_OFF)) {/* and no incoming interrupt? */ + + } else + if (adbWriteDelay == 0) /* it's busy, but is anything waiting? */ + adbWriteDelay = 1; /* if no, then we'll "queue" + * it up */ + else { + splx(s); + return 1; /* really busy! */ + } + + if ((long)in == (long)0) { /* need to convert? */ + /* + * Don't need to use adb_cmd_extra here because this section + * will be called ONLY when it is an ADB command (no RTC or + * PRAM) + */ + if ((command & 0x0c) == 0x08) /* copy addl data ONLY if + * doing a listen! */ + len = buffer[0]; /* length of additional data */ + else + len = 0;/* no additional data */ + + adbOutputBuffer[0] = 2 + len; /* dev. type + command + addl. + * data */ + adbOutputBuffer[1] = 0x00; /* mark as an ADB command */ + adbOutputBuffer[2] = (u_char)command; /* load command */ + + /* copy additional output data, if any */ + memcpy(adbOutputBuffer + 3, buffer + 1, len); + } else + /* if data ready, just copy over */ + memcpy(adbOutputBuffer, in, in[0] + 2); + + adbSentChars = 0; /* nothing sent yet */ + adbBuffer = buffer; /* save buffer to know where to save result */ + adbCompRout = compRout; /* save completion routine pointer */ + adbCompData = data; /* save completion routine data pointer */ + adbWaitingCmd = adbOutputBuffer[2]; /* save wait command */ + + if (adbWriteDelay != 1) { /* start command now? */ + adbActionState = ADB_ACTION_OUT; /* set next state */ + + ADB_SET_STATE_ACTIVE(); /* tell ADB that we want to send */ + ADB_SET_STATE_ACKOFF(); /* make sure */ + + ADB_SET_SR_OUTPUT(); /* set shift register for OUT */ + + ADB_SR() = adbOutputBuffer[adbSentChars + 1]; /* load byte for output */ + + ADB_SET_STATE_ACKON(); /* tell ADB byte ready to shift */ + } + adbWriteDelay = 1; /* something in the write "queue" */ + + splx(s); + + if (0x0100 <= (s & 0x0700)) /* were VIA1 interrupts blocked? */ + /* poll until byte done */ + while ((adbActionState != ADB_ACTION_IDLE) || (ADB_INTR_IS_ON) + || (adbWaiting == 1)) + if (ADB_SR_INTR_IS_ON) { /* wait for "interrupt" */ + adb_intr_IIsi(NULL); /* go process it */ + if (adb_polling) + adb_soft_intr(); + } + + return 0; +} /* send_adb_IIsi */ + +/* + * adb_pass_up is called by the interrupt-time routines. + * It takes the raw packet data that was received from the + * device and puts it into the queue that the upper half + * processes. It then signals for a soft ADB interrupt which + * will eventually call the upper half routine (adb_soft_intr). + * + * If in->unsol is 0, then this is either the notification + * that the packet was sent (on a LISTEN, for example), or the + * response from the device (on a TALK). The completion routine + * is called only if the user specified one. + * + * If in->unsol is 1, then this packet was unsolicited and + * so we look up the device in the ADB device table to determine + * what it's default service routine is. + * + * If in->ack_only is 1, then we really only need to call + * the completion routine, so don't do any other stuff. + * + * Note that in->data contains the packet header AND data, + * while adbInbound[]->data contains ONLY data. + * + * Note: Called only at interrupt time. Assumes this. + */ +void +adb_pass_up(struct adbCommand *in) +{ + int start = 0, len = 0, cmd = 0; + ADBDataBlock block; + + /* temp for testing */ + /*u_char *buffer = 0;*/ + /*u_char *compdata = 0;*/ + /*u_char *comprout = 0;*/ + + if (adbInCount >= ADB_QUEUE) { +#ifdef ADB_DEBUG + if (adb_debug) + printf_intr("adb: ring buffer overflow\n"); +#endif + return; + } + + if (in->ack_only) { + len = in->data[0]; + cmd = in->cmd; + start = 0; + } else { + switch (adbHardware) { + case ADB_HW_II: + cmd = in->data[1]; + if (in->data[0] < 2) + len = 0; + else + len = in->data[0]-1; + start = 1; break; -#endif /* ADBVERBOSE */ + + case ADB_HW_IISI: + case ADB_HW_CUDA: + /* If it's unsolicited, accept only ADB data for now */ + if (in->unsol) + if (0 != in->data[2]) + return; + cmd = in->data[4]; + if (in->data[0] < 5) + len = 0; + else + len = in->data[0]-4; + start = 4; + break; + + case ADB_HW_PB: + cmd = in->data[1]; + if (in->data[0] < 2) + len = 0; + else + len = in->data[0]-1; + start = 1; + break; + + case ADB_HW_UNKNOWN: + return; + } + + /* Make sure there is a valid device entry for this device */ + if (in->unsol) { + /* ignore unsolicited data during adbreinit */ + if (adbStarting) + return; + /* get device's comp. routine and data area */ + if (-1 == get_adb_info(&block, ADB_CMDADDR(cmd))) + return; + } + } + + /* + * If this is an unsolicited packet, we need to fill in + * some info so adb_soft_intr can process this packet + * properly. If it's not unsolicited, then use what + * the caller sent us. + */ + if (in->unsol) { + adbInbound[adbInTail].compRout = (void *)block.dbServiceRtPtr; + adbInbound[adbInTail].compData = (void *)block.dbDataAreaAddr; + adbInbound[adbInTail].saveBuf = (void *)adbInbound[adbInTail].data; + } else { + adbInbound[adbInTail].compRout = (void *)in->compRout; + adbInbound[adbInTail].compData = (void *)in->compData; + adbInbound[adbInTail].saveBuf = (void *)in->saveBuf; + } + +#ifdef ADB_DEBUG + if (adb_debug && in->data[1] == 2) + printf_intr("adb: caught error\n"); +#endif + + /* copy the packet data over */ + /* + * TO DO: If the *_intr routines fed their incoming data + * directly into an adbCommand struct, which is passed to + * this routine, then we could eliminate this copy. + */ + memcpy(adbInbound[adbInTail].data + 1, in->data + start + 1, len); + adbInbound[adbInTail].data[0] = len; + adbInbound[adbInTail].cmd = cmd; + + adbInCount++; + if (++adbInTail >= ADB_QUEUE) + adbInTail = 0; + + /* + * If the debugger is running, call upper half manually. + * Otherwise, trigger a soft interrupt to handle the rest later. + */ + if (adb_polling) + adb_soft_intr(); + else + setsoftadb(); + + return; +} + + +/* + * Called to process the packets after they have been + * placed in the incoming queue. + * + */ +void +adb_soft_intr(void) +{ + int s; + int cmd = 0; + u_char *buffer = 0; + u_char *comprout = 0; + u_char *compdata = 0; + +/*delay(2*ADB_DELAY);*/ + + while (adbInCount) { +#ifdef ADB_DEBUG + if (adb_debug & 0x80) + printf_intr("%x %x %x ", + adbInCount, adbInHead, adbInTail); +#endif + /* get the data we need from the queue */ + buffer = adbInbound[adbInHead].saveBuf; + comprout = adbInbound[adbInHead].compRout; + compdata = adbInbound[adbInHead].compData; + cmd = adbInbound[adbInHead].cmd; + + /* copy over data to data area if it's valid */ + /* + * Note that for unsol packets we don't want to copy the + * data anywhere, so buffer was already set to 0. + * For ack_only buffer was set to 0, so don't copy. + */ + if (buffer) + memcpy(buffer, adbInbound[adbInHead].data, + adbInbound[adbInHead].data[0] + 1); + +#ifdef ADB_DEBUG + if (adb_debug & 0x80) { + printf_intr("%p %p %p %x ", + buffer, comprout, compdata, (short)cmd); + printf_intr("buf: "); + print_single(adbInbound[adbInHead].data); + } +#endif + + /* call default completion routine if it's valid */ + if (comprout) { + (void)((int (*)(u_char *, u_char *, int))comprout) + (buffer, compdata, cmd); } - printf(" at %s", name); + + s = splhigh(); + adbInCount--; + if (++adbInHead >= ADB_QUEUE) + adbInHead = 0; + splx(s); + } + return; +} + + +/* + * This is my version of the ADBOp routine. It mainly just calls the + * hardware-specific routine. + * + * data : pointer to data area to be used by compRout + * compRout : completion routine + * buffer : for LISTEN: points to data to send - MAX 8 data bytes, + * byte 0 = # of bytes + * : for TALK: points to place to save return data + * command : the adb command to send + * result : 0 = success + * : -1 = could not complete + */ +int +adb_op(Ptr buffer, Ptr compRout, Ptr data, short command) +{ + int result; + + switch (adbHardware) { + case ADB_HW_II: + result = send_adb_II((u_char *)0, (u_char *)buffer, + (void *)compRout, (void *)data, (int)command); + if (result == 0) + return 0; + else + return -1; + break; + + case ADB_HW_IISI: + result = send_adb_IIsi((u_char *)0, (u_char *)buffer, + (void *)compRout, (void *)data, (int)command); + /* + * I wish I knew why this delay is needed. It usually needs to + * be here when several commands are sent in close succession, + * especially early in device probes when doing collision + * detection. It must be some race condition. Sigh. - jpw + */ + delay(100); + if (result == 0) + return 0; + else + return -1; + break; + + case ADB_HW_PB: + result = pm_adb_op((u_char *)buffer, (void *)compRout, + (void *)data, (int)command); + + if (result == 0) + return 0; + else + return -1; + break; - printf(" addr %d", aa_args->adbaddr); + case ADB_HW_CUDA: + result = send_adb_cuda((u_char *)0, (u_char *)buffer, + (void *)compRout, (void *)data, (int)command); + if (result == 0) + return 0; + else + return -1; + break; - return (rv); + case ADB_HW_UNKNOWN: + default: + return -1; + } } /* + * adb_hw_setup + * This routine sets up the possible machine specific hardware + * config (mainly VIA settings) for the various models. + */ +void +adb_hw_setup(void) +{ + volatile int i; + u_char send_string[ADB_MAX_MSG_LENGTH]; + + switch (adbHardware) { + case ADB_HW_II: + via1_register_irq(2, adb_intr_II, NULL, NULL); + + via_reg(VIA1, vDirB) |= 0x30; /* register B bits 4 and 5: + * outputs */ + via_reg(VIA1, vDirB) &= 0xf7; /* register B bit 3: input */ + via_reg(VIA1, vACR) &= ~vSR_OUT; /* make sure SR is set + * to IN (II, IIsi) */ + adbActionState = ADB_ACTION_IDLE; /* used by all types of + * hardware (II, IIsi) */ + adbBusState = ADB_BUS_IDLE; /* this var. used in II-series + * code only */ + via_reg(VIA1, vIER) = 0x84; /* make sure VIA interrupts + * are on (II, IIsi) */ + ADB_SET_STATE_IDLE_II(); /* set ADB bus state to idle */ + + ADB_VIA_CLR_INTR(); /* clear interrupt */ + break; + + case ADB_HW_IISI: + via1_register_irq(2, adb_intr_IIsi, NULL, NULL); + via_reg(VIA1, vDirB) |= 0x30; /* register B bits 4 and 5: + * outputs */ + via_reg(VIA1, vDirB) &= 0xf7; /* register B bit 3: input */ + via_reg(VIA1, vACR) &= ~vSR_OUT; /* make sure SR is set + * to IN (II, IIsi) */ + adbActionState = ADB_ACTION_IDLE; /* used by all types of + * hardware (II, IIsi) */ + adbBusState = ADB_BUS_IDLE; /* this var. used in II-series + * code only */ + via_reg(VIA1, vIER) = 0x84; /* make sure VIA interrupts + * are on (II, IIsi) */ + ADB_SET_STATE_IDLE_IISI(); /* set ADB bus state to idle */ + + /* get those pesky clock ticks we missed while booting */ + for (i = 0; i < 30; i++) { + delay(ADB_DELAY); + adb_hw_setup_IIsi(send_string); +#ifdef ADB_DEBUG + if (adb_debug) { + printf_intr("adb: cleanup: "); + print_single(send_string); + } +#endif + delay(ADB_DELAY); + if (ADB_INTR_IS_OFF) + break; + } + break; + + case ADB_HW_PB: + /* + * XXX - really PM_VIA_CLR_INTR - should we put it in + * pm_direct.h? + */ + pm_hw_setup(); + break; + + case ADB_HW_CUDA: + via1_register_irq(2, adb_intr_cuda, NULL, NULL); + via_reg(VIA1, vDirB) |= 0x30; /* register B bits 4 and 5: + * outputs */ + via_reg(VIA1, vDirB) &= 0xf7; /* register B bit 3: input */ + via_reg(VIA1, vACR) &= ~vSR_OUT; /* make sure SR is set + * to IN */ + via_reg(VIA1, vACR) = (via_reg(VIA1, vACR) | 0x0c) & ~0x10; + adbActionState = ADB_ACTION_IDLE; /* used by all types of + * hardware */ + adbBusState = ADB_BUS_IDLE; /* this var. used in II-series + * code only */ + via_reg(VIA1, vIER) = 0x84; /* make sure VIA interrupts + * are on */ + ADB_SET_STATE_IDLE_CUDA(); /* set ADB bus state to idle */ + + /* sort of a device reset */ + i = ADB_SR(); /* clear interrupt */ + ADB_VIA_INTR_DISABLE(); /* no interrupts while clearing */ + ADB_SET_STATE_IDLE_CUDA(); /* reset state to idle */ + delay(ADB_DELAY); + ADB_SET_STATE_TIP(); /* signal start of frame */ + delay(ADB_DELAY); + ADB_TOGGLE_STATE_ACK_CUDA(); + delay(ADB_DELAY); + ADB_CLR_STATE_TIP(); + delay(ADB_DELAY); + ADB_SET_STATE_IDLE_CUDA(); /* back to idle state */ + i = ADB_SR(); /* clear interrupt */ + ADB_VIA_INTR_ENABLE(); /* ints ok now */ + break; + + case ADB_HW_UNKNOWN: + default: + via_reg(VIA1, vIER) = 0x04; /* turn interrupts off - TO + * DO: turn PB ints off? */ + return; + break; + } +} + + +/* + * adb_hw_setup_IIsi + * This is sort of a "read" routine that forces the adb hardware through a read cycle + * if there is something waiting. This helps "clean up" any commands that may have gotten + * stuck or stopped during the boot process. + * + */ +void +adb_hw_setup_IIsi(u_char *buffer) +{ + int i; + int dummy; + int s; + long my_time; + int endofframe; + + delay(ADB_DELAY); + + i = 1; /* skip over [0] */ + s = splhigh(); /* block ALL interrupts while we are working */ + ADB_SET_SR_INPUT(); /* make sure SR is set to IN */ + ADB_VIA_INTR_DISABLE(); /* disable ADB interrupt on IIs. */ + /* this is required, especially on faster machines */ + delay(ADB_DELAY); + + if (ADB_INTR_IS_ON) { + ADB_SET_STATE_ACTIVE(); /* signal start of data frame */ + + endofframe = 0; + while (0 == endofframe) { + /* + * Poll for ADB interrupt and watch for timeout. + * If time out, keep going in hopes of not hanging + * the ADB chip - I think + */ + my_time = ADB_DELAY * 5; + while ((ADB_SR_INTR_IS_OFF) && (my_time-- > 0)) + dummy = via_reg(VIA1, vBufB); + + buffer[i++] = ADB_SR(); /* reset interrupt flag by + * reading vSR */ + /* + * Perhaps put in a check here that ignores all data + * after the first ADB_MAX_MSG_LENGTH bytes ??? + */ + if (ADB_INTR_IS_OFF) /* check for end of frame */ + endofframe = 1; + + ADB_SET_STATE_ACKON(); /* send ACK to ADB chip */ + delay(ADB_DELAY); /* delay */ + ADB_SET_STATE_ACKOFF(); /* send ACK to ADB chip */ + } + ADB_SET_STATE_INACTIVE(); /* signal end of frame and + * delay */ + + /* probably don't need to delay this long */ + delay(ADB_DELAY); + } + buffer[0] = --i; /* [0] is length of message */ + ADB_VIA_INTR_ENABLE(); /* enable ADB interrupt on IIs. */ + splx(s); /* restore interrupts */ + + return; +} /* adb_hw_setup_IIsi */ + + + +/* + * adb_reinit sets up the adb stuff + * + */ +void +adb_reinit(void) +{ + u_char send_string[ADB_MAX_MSG_LENGTH]; + ADBDataBlock data; /* temp. holder for getting device info */ + volatile int i, x; + int s; + int command; + int result; + int saveptr; /* point to next free relocation address */ + int device; + int nonewtimes; /* times thru loop w/o any new devices */ + + via1_register_irq(2, adb_intr, NULL, "adb"); + adb_setup_hw_type(); /* setup hardware type */ + + /* Make sure we are not interrupted while building the table. */ + /* ints must be on for PB & IOP (at least, for now) */ + if (adbHardware != ADB_HW_PB) + s = splhigh(); + else + s = 0; /* XXX shut the compiler up*/ + + ADBNumDevices = 0; /* no devices yet */ + + /* Let intr routines know we are running reinit */ + adbStarting = 1; + + /* + * Initialize the ADB table. For now, we'll always use the same table + * that is defined at the beginning of this file - no mallocs. + */ + for (i = 0; i < 16; i++) { + ADBDevTable[i].devType = 0; + ADBDevTable[i].origAddr = ADBDevTable[i].currentAddr = 0; + } + + adb_hw_setup(); /* init the VIA bits and hard reset ADB */ + + delay(1000); + + /* send an ADB reset first */ + (void)adb_op_sync((Ptr)0, (Ptr)0, (Ptr)0, (short)0x00); + delay(3000); + + /* + * Probe for ADB devices. Probe devices 1-15 quickly to determine + * which device addresses are in use and which are free. For each + * address that is in use, move the device at that address to a higher + * free address. Continue doing this at that address until no device + * responds at that address. Then move the last device that was moved + * back to the original address. Do this for the remaining addresses + * that we determined were in use. + * + * When finished, do this entire process over again with the updated + * list of in use addresses. Do this until no new devices have been + * found in 20 passes though the in use address list. (This probably + * seems long and complicated, but it's the best way to detect multiple + * devices at the same address - sometimes it takes a couple of tries + * before the collision is detected.) + */ + + /* initial scan through the devices */ + for (i = 1; i < 16; i++) { + command = ADBTALK(i, 3); + result = adb_op_sync((Ptr)send_string, (Ptr)0, + (Ptr)0, (short)command); + + if (result == 0 && send_string[0] != 0) { + /* found a device */ + ++ADBNumDevices; + KASSERT(ADBNumDevices < 16); + ADBDevTable[ADBNumDevices].devType = + (int)(send_string[2]); + ADBDevTable[ADBNumDevices].origAddr = i; + ADBDevTable[ADBNumDevices].currentAddr = i; + ADBDevTable[ADBNumDevices].DataAreaAddr = + (long)0; + ADBDevTable[ADBNumDevices].ServiceRtPtr = (void *)0; + pm_check_adb_devices(i); /* tell pm driver device + * is here */ + } + } + + /* find highest unused address */ + for (saveptr = 15; saveptr > 0; saveptr--) + if (-1 == get_adb_info(&data, saveptr)) + break; + +#ifdef ADB_DEBUG + if (adb_debug & 0x80) { + printf_intr("first free is: 0x%02x\n", saveptr); + printf_intr("devices: %i\n", ADBNumDevices); + } +#endif + + nonewtimes = 0; /* no loops w/o new devices */ + while (saveptr > 0 && nonewtimes++ < 11) { + for (i = 1;saveptr > 0 && i <= ADBNumDevices; i++) { + device = ADBDevTable[i].currentAddr; +#ifdef ADB_DEBUG + if (adb_debug & 0x80) + printf_intr("moving device 0x%02x to 0x%02x " + "(index 0x%02x) ", device, saveptr, i); +#endif + + /* send TALK R3 to address */ + command = ADBTALK(device, 3); + (void)adb_op_sync((Ptr)send_string, (Ptr)0, + (Ptr)0, (short)command); + + /* move device to higher address */ + command = ADBLISTEN(device, 3); + send_string[0] = 2; + send_string[1] = (u_char)(saveptr | 0x60); + send_string[2] = 0xfe; + (void)adb_op_sync((Ptr)send_string, (Ptr)0, + (Ptr)0, (short)command); + delay(1000); + + /* send TALK R3 - anthing at new address? */ + command = ADBTALK(saveptr, 3); + send_string[0] = 0; + result = adb_op_sync((Ptr)send_string, (Ptr)0, + (Ptr)0, (short)command); + delay(1000); + + if (result != 0 || send_string[0] == 0) { + /* + * maybe there's a communication breakdown; + * just in case, move it back from whence it + * came, and we'll try again later + */ + command = ADBLISTEN(saveptr, 3); + send_string[0] = 2; + send_string[1] = (u_char)(device | 0x60); + send_string[2] = 0x00; + (void)adb_op_sync((Ptr)send_string, (Ptr)0, + (Ptr)0, (short)command); +#ifdef ADB_DEBUG + if (adb_debug & 0x80) + printf_intr("failed, continuing\n"); +#endif + delay(1000); + continue; + } + + /* send TALK R3 - anything at old address? */ + command = ADBTALK(device, 3); + send_string[0] = 0; + result = adb_op_sync((Ptr)send_string, (Ptr)0, + (Ptr)0, (short)command); + if (result == 0 && send_string[0] != 0) { + /* new device found */ + /* update data for previously moved device */ + ADBDevTable[i].currentAddr = saveptr; +#ifdef ADB_DEBUG + if (adb_debug & 0x80) + printf_intr("old device at index %i\n",i); +#endif + /* add new device in table */ +#ifdef ADB_DEBUG + if (adb_debug & 0x80) + printf_intr("new device found\n"); +#endif + if (saveptr > ADBNumDevices) { + ++ADBNumDevices; + KASSERT(ADBNumDevices < 16); + } + ADBDevTable[ADBNumDevices].devType = + (int)(send_string[2]); + ADBDevTable[ADBNumDevices].origAddr = device; + ADBDevTable[ADBNumDevices].currentAddr = device; + /* These will be set correctly in adbsys.c */ + /* Until then, unsol. data will be ignored. */ + ADBDevTable[ADBNumDevices].DataAreaAddr = + (long)0; + ADBDevTable[ADBNumDevices].ServiceRtPtr = + (void *)0; + /* find next unused address */ + for (x = saveptr; x > 0; x--) { + if (-1 == get_adb_info(&data, x)) { + saveptr = x; + break; + } + } + if (x == 0) + saveptr = 0; +#ifdef ADB_DEBUG + if (adb_debug & 0x80) + printf_intr("new free is 0x%02x\n", + saveptr); +#endif + nonewtimes = 0; + /* tell pm driver device is here */ + pm_check_adb_devices(device); + } else { +#ifdef ADB_DEBUG + if (adb_debug & 0x80) + printf_intr("moving back...\n"); +#endif + /* move old device back */ + command = ADBLISTEN(saveptr, 3); + send_string[0] = 2; + send_string[1] = (u_char)(device | 0x60); + send_string[2] = 0xfe; + (void)adb_op_sync((Ptr)send_string, (Ptr)0, + (Ptr)0, (short)command); + delay(1000); + } + } + } + +#ifdef ADB_DEBUG + if (adb_debug) { + for (i = 1; i <= ADBNumDevices; i++) { + x = get_ind_adb_info(&data, i); + if (x != -1) + printf_intr("index 0x%x, addr 0x%x, type 0x%hx\n", + i, x, data.devType); + } + } +#endif + + /* enable the programmer's switch, if we have one */ + adb_prog_switch_enable(); + +#ifdef ADB_DEBUG + if (adb_debug) { + if (0 == ADBNumDevices) /* tell user if no devices found */ + printf_intr("adb: no devices found\n"); + } +#endif + + adbStarting = 0; /* not starting anymore */ +#ifdef ADB_DEBUG + if (adb_debug) + printf_intr("adb: adb_reinit complete\n"); +#endif + + if (adbHardware == ADB_HW_CUDA) { + timeout_set(&adb_cuda_timeout, (void *)adb_cuda_tickle, NULL); + timeout_add(&adb_cuda_timeout, ADB_TICKLE_TICKS); + } + + /* ints must be on for PB & IOP (at least, for now) */ + if (adbHardware != ADB_HW_PB) + splx(s); + + return; +} + + +/* + * adb_cmd_result + * + * This routine lets the caller know whether the specified adb command string + * should expect a returned result, such as a TALK command. + * + * returns: 0 if a result should be expected + * 1 if a result should NOT be expected + */ +int +adb_cmd_result(u_char *in) +{ + switch (adbHardware) { + case ADB_HW_II: + /* was it an ADB talk command? */ + if ((in[1] & 0x0c) == 0x0c) + return 0; + return 1; + + case ADB_HW_IISI: + case ADB_HW_CUDA: + /* was it an ADB talk command? */ + if ((in[1] == 0x00) && ((in[2] & 0x0c) == 0x0c)) + return 0; + /* was it an RTC/PRAM read date/time? */ + if ((in[1] == 0x01) && (in[2] == 0x03)) + return 0; + return 1; + + case ADB_HW_PB: + return 1; + + case ADB_HW_UNKNOWN: + default: + return 1; + } +} + + +/* + * adb_cmd_extra + * + * This routine lets the caller know whether the specified adb command string + * may have extra data appended to the end of it, such as a LISTEN command. + * + * returns: 0 if extra data is allowed + * 1 if extra data is NOT allowed + */ +int +adb_cmd_extra(u_char *in) +{ + switch (adbHardware) { + case ADB_HW_II: + if ((in[1] & 0x0c) == 0x08) /* was it a listen command? */ + return 0; + return 1; + + case ADB_HW_IISI: + case ADB_HW_CUDA: + /* + * TO DO: support needs to be added to recognize RTC and PRAM + * commands + */ + if ((in[2] & 0x0c) == 0x08) /* was it a listen command? */ + return 0; + /* add others later */ + return 1; + + case ADB_HW_PB: + return 1; + + case ADB_HW_UNKNOWN: + default: + return 1; + } +} + + +void +adb_setup_hw_type(void) +{ + long response; + + response = mac68k_machine.machineid; + + /* + * Determine what type of ADB hardware we are running on. + */ + switch (response) { + case MACH_MACC610: /* Centris 610 */ + case MACH_MACC650: /* Centris 650 */ + case MACH_MACII: /* II */ + case MACH_MACIICI: /* IIci */ + case MACH_MACIICX: /* IIcx */ + case MACH_MACIIX: /* IIx */ + case MACH_MACQ610: /* Quadra 610 */ + case MACH_MACQ650: /* Quadra 650 */ + case MACH_MACQ700: /* Quadra 700 */ + case MACH_MACQ800: /* Quadra 800 */ + case MACH_MACSE30: /* SE/30 */ + adbHardware = ADB_HW_II; +#ifdef ADB_DEBUG + if (adb_debug) + printf_intr("adb: using II series hardware support\n"); +#endif + break; + + case MACH_MACCLASSICII: /* Classic II */ + case MACH_MACLCII: /* LC II, Performa 400/405/430 */ + case MACH_MACLCIII: /* LC III, Performa 450 */ + case MACH_MACIISI: /* IIsi */ + case MACH_MACIIVI: /* IIvi */ + case MACH_MACIIVX: /* IIvx */ + case MACH_MACP460: /* Performa 460/465/467 */ + case MACH_MACP600: /* Performa 600 */ + adbHardware = ADB_HW_IISI; +#ifdef ADB_DEBUG + if (adb_debug) + printf_intr("adb: using IIsi series hardware support\n"); +#endif + break; + + case MACH_MACPB140: /* PowerBook 140 */ + case MACH_MACPB145: /* PowerBook 145 */ + case MACH_MACPB160: /* PowerBook 160 */ + case MACH_MACPB165: /* PowerBook 165 */ + case MACH_MACPB165C: /* PowerBook 165c */ + case MACH_MACPB170: /* PowerBook 170 */ + case MACH_MACPB180: /* PowerBook 180 */ + case MACH_MACPB180C: /* PowerBook 180c */ + adbHardware = ADB_HW_PB; + pm_setup_adb(); +#ifdef ADB_DEBUG + if (adb_debug) + printf_intr("adb: using PowerBook 100-series hardware support\n"); +#endif + break; + + case MACH_MACPB150: /* PowerBook 150 */ + case MACH_MACPB210: /* PowerBook Duo 210 */ + case MACH_MACPB230: /* PowerBook Duo 230 */ + case MACH_MACPB250: /* PowerBook Duo 250 */ + case MACH_MACPB270: /* PowerBook Duo 270 */ + case MACH_MACPB280: /* PowerBook Duo 280 */ + case MACH_MACPB280C: /* PowerBook Duo 280c */ + case MACH_MACPB500: /* PowerBook 500 series */ + case MACH_MACPB190: /* PowerBook 190 */ + case MACH_MACPB190CS: /* PowerBook 190cs */ + adbHardware = ADB_HW_PB; + pm_setup_adb(); +#ifdef ADB_DEBUG + if (adb_debug) + printf_intr("adb: using PowerBook Duo-series and PowerBook 500-series hardware support\n"); +#endif + break; + + case MACH_MACC660AV: /* Centris 660AV */ + case MACH_MACCCLASSIC: /* Color Classic */ + case MACH_MACCCLASSICII: /* Color Classic II */ + case MACH_MACLC475: /* LC 475, Performa 475/476 */ + case MACH_MACLC475_33: /* Clock-chipped 47x */ + case MACH_MACLC520: /* LC 520 */ + case MACH_MACLC575: /* LC 575, Performa 575/577/578 */ + case MACH_MACP550: /* LC 550, Performa 550 */ + case MACH_MACTV: /* Macintosh TV */ + case MACH_MACP580: /* Performa 580/588 */ + case MACH_MACQ605: /* Quadra 605 */ + case MACH_MACQ605_33: /* Clock-chipped Quadra 605 */ + case MACH_MACQ630: /* LC 630, Performa 630, Quadra 630 */ + case MACH_MACQ840AV: /* Quadra 840AV */ + adbHardware = ADB_HW_CUDA; +#ifdef ADB_DEBUG + if (adb_debug) + printf_intr("adb: using Cuda series hardware support\n"); +#endif + break; + + default: + adbHardware = ADB_HW_UNKNOWN; +#ifdef ADB_DEBUG + if (adb_debug) { + printf_intr("adb: hardware type unknown for this machine\n"); + printf_intr("adb: ADB support is disabled\n"); + } +#endif + break; + } + + /* + * Determine whether this machine has ADB based soft power. + */ + switch (response) { + case MACH_MACCCLASSIC: /* Color Classic */ + case MACH_MACCCLASSICII: /* Color Classic II */ + case MACH_MACIISI: /* IIsi */ + case MACH_MACIIVI: /* IIvi */ + case MACH_MACIIVX: /* IIvx */ + case MACH_MACLC520: /* LC 520 */ + case MACH_MACLC575: /* LC 575, Performa 575/577/578 */ + case MACH_MACP550: /* LC 550, Performa 550 */ + case MACH_MACTV: /* Macintosh TV */ + case MACH_MACP580: /* Performa 580/588 */ + case MACH_MACP600: /* Performa 600 */ + case MACH_MACQ630: /* LC 630, Performa 630, Quadra 630 */ + case MACH_MACQ840AV: /* Quadra 840AV */ + adbSoftPower = 1; + break; + } +} + +/* * adb_op_sync * * This routine does exactly what the adb_op routine does, except that after @@ -223,7 +2475,7 @@ adb_op_sync(Ptr buffer, Ptr compRout, Ptr data, short command) int result; volatile int flag = 0; - result = ADBOp(buffer, (void *)adb_op_comprout, (Ptr)&flag, + result = adb_op(buffer, (void *)adb_op_comprout, (Ptr)&flag, command); /* send command */ if (result == 0) { /* send ok? */ /* @@ -254,7 +2506,6 @@ adb_op_sync(Ptr buffer, Ptr compRout, Ptr data, short command) return result; } - /* * adb_op_comprout * @@ -266,3 +2517,380 @@ adb_op_comprout(caddr_t buffer, caddr_t data_area, int adb_command) { *(u_short *)data_area = 0x01; /* update flag value */ } + +int +count_adbs(void) +{ + int i; + int found; + + found = 0; + + for (i = 1; i < 16; i++) + if (0 != ADBDevTable[i].currentAddr) + found++; + + return found; +} + +int +get_ind_adb_info(ADBDataBlock *info, int index) +{ + if ((index < 1) || (index > 15)) /* check range 1-15 */ + return (-1); + +#ifdef ADB_DEBUG + if (adb_debug & 0x80) + printf_intr("index 0x%x devType is: 0x%x\n", index, + ADBDevTable[index].devType); +#endif + if (0 == ADBDevTable[index].devType) /* make sure it's a valid entry */ + return (-1); + + info->devType = (unsigned char)(ADBDevTable[index].devType); + info->origADBAddr = (unsigned char)(ADBDevTable[index].origAddr); + info->dbServiceRtPtr = (Ptr)ADBDevTable[index].ServiceRtPtr; + info->dbDataAreaAddr = (Ptr)ADBDevTable[index].DataAreaAddr; + + return (ADBDevTable[index].currentAddr); +} + +int +get_adb_info(ADBDataBlock *info, int adbAddr) +{ + int i; + + if ((adbAddr < 1) || (adbAddr > 15)) /* check range 1-15 */ + return (-1); + + for (i = 1; i < 15; i++) + if (ADBDevTable[i].currentAddr == adbAddr) { + info->devType = (unsigned char)(ADBDevTable[i].devType); + info->origADBAddr = (unsigned char)(ADBDevTable[i].origAddr); + info->dbServiceRtPtr = (Ptr)ADBDevTable[i].ServiceRtPtr; + info->dbDataAreaAddr = ADBDevTable[i].DataAreaAddr; + return 0; /* found */ + } + + return (-1); /* not found */ +} + +int +set_adb_info(ADBSetInfoBlock *info, int adbAddr) +{ + int i; + + if ((adbAddr < 1) || (adbAddr > 15)) /* check range 1-15 */ + return (-1); + + for (i = 1; i < 15; i++) + if (ADBDevTable[i].currentAddr == adbAddr) { + ADBDevTable[i].ServiceRtPtr = + (void *)(info->siServiceRtPtr); + ADBDevTable[i].DataAreaAddr = info->siDataAreaAddr; + return 0; /* found */ + } + + return (-1); /* not found */ + +} + +/* caller should really use machine-independant version: getPramTime */ +/* this version does pseudo-adb access only */ +int +adb_read_date_time(unsigned long *time) +{ + u_char output[ADB_MAX_MSG_LENGTH]; + int result; + volatile int flag = 0; + + switch (adbHardware) { + case ADB_HW_II: + return -1; + + case ADB_HW_IISI: + output[0] = 0x02; /* 2 byte message */ + output[1] = 0x01; /* to pram/rtc device */ + output[2] = 0x03; /* read date/time */ + result = send_adb_IIsi((u_char *)output, (u_char *)output, + (void *)adb_op_comprout, (void *)&flag, (int)0); + if (result != 0) /* exit if not sent */ + return -1; + + while (0 == flag) /* wait for result */ + ; + + *time = (long)(*(long *)(output + 1)); + return 0; + + case ADB_HW_PB: + return -1; + + case ADB_HW_CUDA: + output[0] = 0x02; /* 2 byte message */ + output[1] = 0x01; /* to pram/rtc device */ + output[2] = 0x03; /* read date/time */ + result = send_adb_cuda((u_char *)output, (u_char *)output, + (void *)adb_op_comprout, (void *)&flag, (int)0); + if (result != 0) /* exit if not sent */ + return -1; + + while (0 == flag) /* wait for result */ + ; + + *time = (long)(*(long *)(output + 1)); + return 0; + + case ADB_HW_UNKNOWN: + default: + return -1; + } +} + +/* caller should really use machine-independant version: setPramTime */ +/* this version does pseudo-adb access only */ +int +adb_set_date_time(unsigned long time) +{ + u_char output[ADB_MAX_MSG_LENGTH]; + int result; + volatile int flag = 0; + + switch (adbHardware) { + case ADB_HW_II: + return -1; + + case ADB_HW_IISI: + output[0] = 0x06; /* 6 byte message */ + output[1] = 0x01; /* to pram/rtc device */ + output[2] = 0x09; /* set date/time */ + output[3] = (u_char)(time >> 24); + output[4] = (u_char)(time >> 16); + output[5] = (u_char)(time >> 8); + output[6] = (u_char)(time); + result = send_adb_IIsi((u_char *)output, (u_char *)0, + (void *)adb_op_comprout, (void *)&flag, (int)0); + if (result != 0) /* exit if not sent */ + return -1; + + while (0 == flag) /* wait for send to finish */ + ; + + return 0; + + case ADB_HW_PB: + return -1; + + case ADB_HW_CUDA: + output[0] = 0x06; /* 6 byte message */ + output[1] = 0x01; /* to pram/rtc device */ + output[2] = 0x09; /* set date/time */ + output[3] = (u_char)(time >> 24); + output[4] = (u_char)(time >> 16); + output[5] = (u_char)(time >> 8); + output[6] = (u_char)(time); + result = send_adb_cuda((u_char *)output, (u_char *)0, + (void *)adb_op_comprout, (void *)&flag, (int)0); + if (result != 0) /* exit if not sent */ + return -1; + + while (0 == flag) /* wait for send to finish */ + ; + + return 0; + + case ADB_HW_UNKNOWN: + default: + return -1; + } +} + + +int +adb_poweroff(void) +{ + u_char output[ADB_MAX_MSG_LENGTH]; + int result; + + if (!adbSoftPower) + return -1; + + adb_polling = 1; + + switch (adbHardware) { + case ADB_HW_IISI: + output[0] = 0x02; /* 2 byte message */ + output[1] = 0x01; /* to pram/rtc/soft-power device */ + output[2] = 0x0a; /* set date/time */ + result = send_adb_IIsi((u_char *)output, (u_char *)0, + (void *)0, (void *)0, (int)0); + if (result != 0) /* exit if not sent */ + return -1; + + for (;;); /* wait for power off */ + + return 0; + + case ADB_HW_PB: + return -1; + + case ADB_HW_CUDA: + output[0] = 0x02; /* 2 byte message */ + output[1] = 0x01; /* to pram/rtc/soft-power device */ + output[2] = 0x0a; /* set date/time */ + result = send_adb_cuda((u_char *)output, (u_char *)0, + (void *)0, (void *)0, (int)0); + if (result != 0) /* exit if not sent */ + return -1; + + for (;;); /* wait for power off */ + + return 0; + + case ADB_HW_II: /* II models don't do ADB soft power */ + case ADB_HW_UNKNOWN: + default: + return -1; + } +} + +int +adb_prog_switch_enable(void) +{ + u_char output[ADB_MAX_MSG_LENGTH]; + int result; + volatile int flag = 0; + + switch (adbHardware) { + case ADB_HW_IISI: + output[0] = 0x03; /* 3 byte message */ + output[1] = 0x01; /* to pram/rtc/soft-power device */ + output[2] = 0x1c; /* prog. switch control */ + output[3] = 0x01; /* enable */ + result = send_adb_IIsi((u_char *)output, (u_char *)0, + (void *)adb_op_comprout, (void *)&flag, (int)0); + if (result != 0) /* exit if not sent */ + return -1; + + while (0 == flag) /* wait for send to finish */ + ; + + return 0; + + case ADB_HW_PB: + return -1; + + case ADB_HW_II: /* II models don't do prog. switch */ + case ADB_HW_CUDA: /* cuda doesn't do prog. switch TO DO: verify this */ + case ADB_HW_UNKNOWN: + default: + return -1; + } +} + +int +adb_prog_switch_disable(void) +{ + u_char output[ADB_MAX_MSG_LENGTH]; + int result; + volatile int flag = 0; + + switch (adbHardware) { + case ADB_HW_IISI: + output[0] = 0x03; /* 3 byte message */ + output[1] = 0x01; /* to pram/rtc/soft-power device */ + output[2] = 0x1c; /* prog. switch control */ + output[3] = 0x01; /* disable */ + result = send_adb_IIsi((u_char *)output, (u_char *)0, + (void *)adb_op_comprout, (void *)&flag, (int)0); + if (result != 0) /* exit if not sent */ + return -1; + + while (0 == flag) /* wait for send to finish */ + ; + + return 0; + + case ADB_HW_PB: + return -1; + + case ADB_HW_II: /* II models don't do prog. switch */ + case ADB_HW_CUDA: /* cuda doesn't do prog. switch */ + case ADB_HW_UNKNOWN: + default: + return -1; + } +} + +/* + * Function declarations. + */ +int adbmatch(struct device *, void *, void *); +void adbattach(struct device *, struct device *, void *); +void adb_attach_deferred(void *); + +/* + * Driver definition. + */ +struct cfattach adb_ca = { + sizeof(struct device), adbmatch, adbattach +}; + +int +adbmatch(struct device *parent, void *vcf, void *aux) +{ + static int adb_matched = 0; + + /* Allow only one instance. */ + if (adb_matched) + return (0); + + adb_matched = 1; + return (1); +} + +void +adbattach(struct device *parent, struct device *self, void *aux) +{ + printf("\n"); + startuphook_establish(adb_attach_deferred, self); +} + +void +adb_attach_deferred(void *v) +{ + struct device *self = v; + ADBDataBlock adbdata; + struct adb_attach_args aa_args; + int totaladbs; + int adbindex, adbaddr; + + printf("%s", self->dv_xname); + + adb_polling = 1; + adb_reinit(); + + printf(": %s", adbHardwareDescr[adbHardware]); + +#ifdef ADB_DEBUG + if (adb_debug) + printf("adb: done with adb_reinit\n"); +#endif + + totaladbs = count_adbs(); + + printf(", %d target%s\n", totaladbs, (totaladbs == 1) ? "" : "s"); + + /* for each ADB device */ + for (adbindex = 1; adbindex <= totaladbs; adbindex++) { + /* Get the ADB information */ + adbaddr = get_ind_adb_info(&adbdata, adbindex); + + aa_args.origaddr = (int)(adbdata.origADBAddr); + aa_args.adbaddr = adbaddr; + aa_args.handler_id = (int)(adbdata.devType); + + (void)config_found(self, &aa_args, adbprint); + } + adb_polling = 0; +} diff --git a/sys/arch/mac68k/dev/adb_direct.c b/sys/arch/mac68k/dev/adb_direct.c deleted file mode 100644 index a4a74300deb..00000000000 --- a/sys/arch/mac68k/dev/adb_direct.c +++ /dev/null @@ -1,2759 +0,0 @@ -/* $OpenBSD: adb_direct.c,v 1.19 2006/01/16 21:48:20 miod Exp $ */ -/* $NetBSD: adb_direct.c,v 1.51 2005/06/16 22:43:36 jmc Exp $ */ - -/* From: adb_direct.c 2.02 4/18/97 jpw */ - -/* - * Copyright (C) 1996, 1997 John P. Wittkoski - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by John P. Wittkoski. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * This code is rather messy, but I don't have time right now - * to clean it up as much as I would like. - * But it works, so I'm happy. :-) jpw - */ - -/* - * TO DO: - * - We could reduce the time spent in the adb_intr_* routines - * by having them save the incoming and outgoing data directly - * in the adbInbound and adbOutbound queues, as it would reduce - * the number of times we need to copy the data around. It - * would also make the code more readable and easier to follow. - * - (Related to above) Use the header part of adbCommand to - * reduce the number of copies we have to do of the data. - * - (Related to above) Actually implement the adbOutbound queue. - * This is fairly easy once you switch all the intr routines - * over to using adbCommand structs directly. - * - There is a bug in the state machine of adb_intr_cuda - * code that causes hangs, especially on 030 machines, probably - * because of some timing issues. Because I have been unable to - * determine the exact cause of this bug, I used the timeout function - * to check for and recover from this condition. If anyone finds - * the actual cause of this bug, the calls to timeout and the - * adb_cuda_tickle routine can be removed. - */ - -#include <sys/param.h> -#include <sys/cdefs.h> -#include <sys/pool.h> -#include <sys/queue.h> -#include <sys/systm.h> -#include <sys/timeout.h> - -#include <machine/viareg.h> -#include <machine/param.h> -#include <machine/cpu.h> -#include <mac68k/dev/adbvar.h> -#define printf_intr printf - -/* some misc. leftovers */ -#define vPB 0x0000 -#define vPB3 0x08 -#define vPB4 0x10 -#define vPB5 0x20 -#define vSR_INT 0x04 -#define vSR_OUT 0x10 - -/* the type of ADB action that we are currently preforming */ -#define ADB_ACTION_NOTREADY 0x1 /* has not been initialized yet */ -#define ADB_ACTION_IDLE 0x2 /* the bus is currently idle */ -#define ADB_ACTION_OUT 0x3 /* sending out a command */ -#define ADB_ACTION_IN 0x4 /* receiving data */ -#define ADB_ACTION_POLLING 0x5 /* polling - II only */ - -/* - * These describe the state of the ADB bus itself, although they - * don't necessarily correspond directly to ADB states. - * Note: these are not really used in the IIsi code. - */ -#define ADB_BUS_UNKNOWN 0x1 /* we don't know yet - all models */ -#define ADB_BUS_IDLE 0x2 /* bus is idle - all models */ -#define ADB_BUS_CMD 0x3 /* starting a command - II models */ -#define ADB_BUS_ODD 0x4 /* the "odd" state - II models */ -#define ADB_BUS_EVEN 0x5 /* the "even" state - II models */ -#define ADB_BUS_ACTIVE 0x6 /* active state - IIsi models */ -#define ADB_BUS_ACK 0x7 /* currently ACKing - IIsi models */ - -/* - * Shortcuts for setting or testing the VIA bit states. - * Not all shortcuts are used for every type of ADB hardware. - */ -#define ADB_SET_STATE_IDLE_II() via_reg(VIA1, vBufB) |= (vPB4 | vPB5) -#define ADB_SET_STATE_IDLE_IISI() via_reg(VIA1, vBufB) &= ~(vPB4 | vPB5) -#define ADB_SET_STATE_IDLE_CUDA() via_reg(VIA1, vBufB) |= (vPB4 | vPB5) -#define ADB_SET_STATE_CMD() via_reg(VIA1, vBufB) &= ~(vPB4 | vPB5) -#define ADB_SET_STATE_EVEN() via_reg(VIA1, vBufB) = ((via_reg(VIA1, \ - vBufB) | vPB4) & ~vPB5) -#define ADB_SET_STATE_ODD() via_reg(VIA1, vBufB) = ((via_reg(VIA1, \ - vBufB) | vPB5) & ~vPB4) -#define ADB_SET_STATE_ACTIVE() via_reg(VIA1, vBufB) |= vPB5 -#define ADB_SET_STATE_INACTIVE() via_reg(VIA1, vBufB) &= ~vPB5 -#define ADB_SET_STATE_TIP() via_reg(VIA1, vBufB) &= ~vPB5 -#define ADB_CLR_STATE_TIP() via_reg(VIA1, vBufB) |= vPB5 -#define ADB_SET_STATE_ACKON() via_reg(VIA1, vBufB) |= vPB4 -#define ADB_SET_STATE_ACKOFF() via_reg(VIA1, vBufB) &= ~vPB4 -#define ADB_TOGGLE_STATE_ACK_CUDA() via_reg(VIA1, vBufB) ^= vPB4 -#define ADB_SET_STATE_ACKON_CUDA() via_reg(VIA1, vBufB) &= ~vPB4 -#define ADB_SET_STATE_ACKOFF_CUDA() via_reg(VIA1, vBufB) |= vPB4 -#define ADB_SET_SR_INPUT() via_reg(VIA1, vACR) &= ~vSR_OUT -#define ADB_SET_SR_OUTPUT() via_reg(VIA1, vACR) |= vSR_OUT -#define ADB_SR() via_reg(VIA1, vSR) -#define ADB_VIA_INTR_ENABLE() via_reg(VIA1, vIER) = 0x84 -#define ADB_VIA_INTR_DISABLE() via_reg(VIA1, vIER) = 0x04 -#define ADB_VIA_CLR_INTR() via_reg(VIA1, vIFR) = 0x04 -#define ADB_INTR_IS_OFF (vPB3 == (via_reg(VIA1, vBufB) & vPB3)) -#define ADB_INTR_IS_ON (0 == (via_reg(VIA1, vBufB) & vPB3)) -#define ADB_SR_INTR_IS_OFF (0 == (via_reg(VIA1, vIFR) & vSR_INT)) -#define ADB_SR_INTR_IS_ON (vSR_INT == (via_reg(VIA1, \ - vIFR) & vSR_INT)) - -/* - * This is the delay that is required (in uS) between certain - * ADB transactions. The actual timing delay for for each uS is - * calculated at boot time to account for differences in machine speed. - */ -#define ADB_DELAY 150 - -/* - * Maximum ADB message length; includes space for data, result, and - * device code - plus a little for safety. - */ -#define ADB_MAX_MSG_LENGTH 16 -#define ADB_MAX_HDR_LENGTH 8 - -#define ADB_QUEUE 32 -#define ADB_TICKLE_TICKS 4 - -/* - * A structure for storing information about each ADB device. - */ -struct ADBDevEntry { - void (*ServiceRtPtr)(void); - void *DataAreaAddr; - int devType; - int origAddr; - int currentAddr; -}; - -/* - * Used to hold ADB commands that are waiting to be sent out. - */ -struct adbCmdHoldEntry { - u_char outBuf[ADB_MAX_MSG_LENGTH]; /* our message */ - u_char *saveBuf; /* buffer to know where to save result */ - u_char *compRout; /* completion routine pointer */ - u_char *data; /* completion routine data pointer */ -}; - -/* - * Eventually used for two separate queues, the queue between - * the upper and lower halves, and the outgoing packet queue. - * TO DO: adbCommand can replace all of adbCmdHoldEntry eventually - */ -struct adbCommand { - u_char header[ADB_MAX_HDR_LENGTH]; /* not used yet */ - u_char data[ADB_MAX_MSG_LENGTH]; /* packet data only */ - u_char *saveBuf; /* where to save result */ - u_char *compRout; /* completion routine pointer */ - u_char *compData; /* completion routine data pointer */ - u_int cmd; /* the original command for this data */ - u_int unsol; /* 1 if packet was unsolicited */ - u_int ack_only; /* 1 for no special processing */ -}; - -/* - * Text representations of each hardware class - */ -const char *adbHardwareDescr[MAX_ADB_HW + 1] = { - "unknown", - "II series", - "IIsi series", - "PowerBook", - "Cuda", -}; - -/* - * A few variables that we need and their initial values. - */ -int adbHardware = ADB_HW_UNKNOWN; -int adbActionState = ADB_ACTION_NOTREADY; -int adbBusState = ADB_BUS_UNKNOWN; -int adbWaiting = 0; /* waiting for return data from the device */ -int adbWriteDelay = 0; /* working on (or waiting to do) a write */ -int adbOutQueueHasData = 0; /* something in the queue waiting to go out */ -int adbNextEnd = 0; /* the next incoming bute is the last (II) */ -int adbSoftPower = 0; /* machine supports soft power */ - -int adbWaitingCmd = 0; /* ADB command we are waiting for */ -u_char *adbBuffer = (long)0; /* pointer to user data area */ -void *adbCompRout = (long)0; /* pointer to the completion routine */ -void *adbCompData = (long)0; /* pointer to the completion routine data */ -long adbFakeInts = 0; /* keeps track of fake ADB interrupts for - * timeouts (II) */ -int adbStarting = 1; /* doing ADBReInit so do polling differently */ -int adbSendTalk = 0; /* the intr routine is sending the talk, not - * the user (II) */ -int adbPolling = 0; /* we are polling for service request */ -int adbPollCmd = 0; /* the last poll command we sent */ - -u_char adbInputBuffer[ADB_MAX_MSG_LENGTH]; /* data input buffer */ -u_char adbOutputBuffer[ADB_MAX_MSG_LENGTH]; /* data output buffer */ -struct adbCmdHoldEntry adbOutQueue; /* our 1 entry output queue */ - -int adbSentChars = 0; /* how many characters we have sent */ -int adbLastDevice = 0; /* last ADB dev we heard from (II ONLY) */ -int adbLastDevIndex = 0; /* last ADB dev loc in dev table (II ONLY) */ -int adbLastCommand = 0; /* the last ADB command we sent (II) */ - -struct ADBDevEntry ADBDevTable[16]; /* our ADB device table */ -int ADBNumDevices; /* num. of ADB devices found with ADBReInit */ - -struct adbCommand adbInbound[ADB_QUEUE]; /* incoming queue */ -volatile int adbInCount = 0; /* how many packets in in queue */ -int adbInHead = 0; /* head of in queue */ -int adbInTail = 0; /* tail of in queue */ -struct adbCommand adbOutbound[ADB_QUEUE]; /* outgoing queue - not used yet */ -int adbOutCount = 0; /* how many packets in out queue */ -int adbOutHead = 0; /* head of out queue */ -int adbOutTail = 0; /* tail of out queue */ - -int tickle_count = 0; /* how many tickles seen for this packet? */ -int tickle_serial = 0; /* the last packet tickled */ -int adb_cuda_serial = 0; /* the current packet */ - -struct timeout adb_cuda_timeout; - -extern struct mac68k_machine_S mac68k_machine; - -void pm_setup_adb(void); -void pm_hw_setup(void); -void pm_check_adb_devices(int); -int pm_adb_op(u_char *, void *, void *, int); -void pm_init_adb_device(void); - -/* - * The following are private routines. - */ -#ifdef ADB_DEBUG -void print_single(u_char *); -#endif -int adb_intr(void *); -int adb_intr_II(void *); -int adb_intr_IIsi(void *); -int adb_intr_cuda(void *); -void adb_soft_intr(void); -int send_adb_II(u_char *, u_char *, void *, void *, int); -int send_adb_IIsi(u_char *, u_char *, void *, void *, int); -int send_adb_cuda(u_char *, u_char *, void *, void *, int); -void adb_intr_cuda_test(void); -void adb_cuda_tickle(void); -void adb_pass_up(struct adbCommand *); -void adb_reinit(void); -int count_adbs(void); -int get_ind_adb_info(ADBDataBlock *, int); -int get_adb_info(ADBDataBlock *, int); -int set_adb_info(ADBSetInfoBlock *, int); -void adb_setup_hw_type(void); -int adb_op(Ptr, Ptr, Ptr, short); -void adb_read_II(u_char *); -void adb_hw_setup(void); -void adb_hw_setup_IIsi(u_char *); -int adb_cmd_result(u_char *); -int adb_cmd_extra(u_char *); -int adb_guess_next_device(void); -int adb_prog_switch_enable(void); -int adb_prog_switch_disable(void); -/* we should create this and it will be the public version */ -int send_adb(u_char *, void *, void *); - -#ifdef ADB_DEBUG -/* - * print_single - * Diagnostic display routine. Displays the hex values of the - * specified elements of the u_char. The length of the "string" - * is in [0]. - */ -void -print_single(u_char *str) -{ - int x; - - if (str == 0) { - printf_intr("no data - null pointer\n"); - return; - } - if (*str == 0) { - printf_intr("nothing returned\n"); - return; - } - if (*str > 20) { - printf_intr("ADB: ACK > 20 no way!\n"); - *str = (u_char)20; - } - printf_intr("(length=0x%x):", (u_int)*str); - for (x = 1; x <= *str; x++) - printf_intr(" 0x%02x", (u_int)*(str + x)); - printf_intr("\n"); -} -#endif - -void -adb_cuda_tickle(void) -{ - volatile int s; - - if (adbActionState == ADB_ACTION_IN) { - if (tickle_serial == adb_cuda_serial) { - if (++tickle_count > 0) { - s = splhigh(); - adbActionState = ADB_ACTION_IDLE; - adbInputBuffer[0] = 0; - ADB_SET_STATE_IDLE_CUDA(); - splx(s); - } - } else { - tickle_serial = adb_cuda_serial; - tickle_count = 0; - } - } else { - tickle_serial = adb_cuda_serial; - tickle_count = 0; - } - - timeout_add(&adb_cuda_timeout, ADB_TICKLE_TICKS); -} - -/* - * called when when an adb interrupt happens - * - * Cuda version of adb_intr - * TO DO: do we want to add some calls to intr_dispatch() here to - * grab serial interrupts? - */ -int -adb_intr_cuda(void *arg) -{ - volatile int i, ending; - volatile unsigned int s; - struct adbCommand packet; - - s = splhigh(); /* can't be too careful - might be called */ - /* from a routine, NOT an interrupt */ - - ADB_VIA_CLR_INTR(); /* clear interrupt */ - ADB_VIA_INTR_DISABLE(); /* disable ADB interrupt on IIs. */ - -switch_start: - switch (adbActionState) { - case ADB_ACTION_IDLE: - /* - * This is an unexpected packet, so grab the first (dummy) - * byte, set up the proper vars, and tell the chip we are - * starting to receive the packet by setting the TIP bit. - */ - adbInputBuffer[1] = ADB_SR(); - adb_cuda_serial++; - if (ADB_INTR_IS_OFF) /* must have been a fake start */ - break; - - ADB_SET_SR_INPUT(); - ADB_SET_STATE_TIP(); - - adbInputBuffer[0] = 1; - adbActionState = ADB_ACTION_IN; -#ifdef ADB_DEBUG - if (adb_debug) - printf_intr("idle 0x%02x ", adbInputBuffer[1]); -#endif - break; - - case ADB_ACTION_IN: - adbInputBuffer[++adbInputBuffer[0]] = ADB_SR(); - /* intr off means this is the last byte (end of frame) */ - if (ADB_INTR_IS_OFF) - ending = 1; - else - ending = 0; - - if (1 == ending) { /* end of message? */ -#ifdef ADB_DEBUG - if (adb_debug) { - printf_intr("in end 0x%02x ", - adbInputBuffer[adbInputBuffer[0]]); - print_single(adbInputBuffer); - } -#endif - - /* - * Are we waiting AND does this packet match what we - * are waiting for AND is it coming from either the - * ADB or RTC/PRAM sub-device? This section _should_ - * recognize all ADB and RTC/PRAM type commands, but - * there may be more... NOTE: commands are always at - * [4], even for RTC/PRAM commands. - */ - /* set up data for adb_pass_up */ - memcpy(packet.data, adbInputBuffer, adbInputBuffer[0] + 1); - - if ((adbWaiting == 1) && - (adbInputBuffer[4] == adbWaitingCmd) && - ((adbInputBuffer[2] == 0x00) || - (adbInputBuffer[2] == 0x01))) { - packet.saveBuf = adbBuffer; - packet.compRout = adbCompRout; - packet.compData = adbCompData; - packet.unsol = 0; - packet.ack_only = 0; - adb_pass_up(&packet); - - adbWaitingCmd = 0; /* reset "waiting" vars */ - adbWaiting = 0; - adbBuffer = (long)0; - adbCompRout = (long)0; - adbCompData = (long)0; - } else { - packet.unsol = 1; - packet.ack_only = 0; - adb_pass_up(&packet); - } - - - /* reset vars and signal the end of this frame */ - adbActionState = ADB_ACTION_IDLE; - adbInputBuffer[0] = 0; - ADB_SET_STATE_IDLE_CUDA(); - /*ADB_SET_SR_INPUT();*/ - - /* - * If there is something waiting to be sent out, - * the set everything up and send the first byte. - */ - if (adbWriteDelay == 1) { - delay(ADB_DELAY); /* required */ - adbSentChars = 0; - adbActionState = ADB_ACTION_OUT; - /* - * If the interrupt is on, we were too slow - * and the chip has already started to send - * something to us, so back out of the write - * and start a read cycle. - */ - if (ADB_INTR_IS_ON) { - ADB_SET_SR_INPUT(); - ADB_SET_STATE_IDLE_CUDA(); - adbSentChars = 0; - adbActionState = ADB_ACTION_IDLE; - adbInputBuffer[0] = 0; - break; - } - /* - * If we got here, it's ok to start sending - * so load the first byte and tell the chip - * we want to send. - */ - ADB_SET_STATE_TIP(); - ADB_SET_SR_OUTPUT(); - ADB_SR() = adbOutputBuffer[adbSentChars + 1]; - } - } else { - ADB_TOGGLE_STATE_ACK_CUDA(); -#ifdef ADB_DEBUG - if (adb_debug) - printf_intr("in 0x%02x ", - adbInputBuffer[adbInputBuffer[0]]); -#endif - } - break; - - case ADB_ACTION_OUT: - i = ADB_SR(); /* reset SR-intr in IFR */ -#ifdef ADB_DEBUG - if (adb_debug) - printf_intr("intr out 0x%02x ", i); -#endif - - adbSentChars++; - if (ADB_INTR_IS_ON) { /* ADB intr low during write */ -#ifdef ADB_DEBUG - if (adb_debug) - printf_intr("intr was on "); -#endif - ADB_SET_SR_INPUT(); /* make sure SR is set to IN */ - ADB_SET_STATE_IDLE_CUDA(); - adbSentChars = 0; /* must start all over */ - adbActionState = ADB_ACTION_IDLE; /* new state */ - adbInputBuffer[0] = 0; - adbWriteDelay = 1; /* must retry when done with - * read */ - delay(ADB_DELAY); - goto switch_start; /* process next state right - * now */ - break; - } - if (adbOutputBuffer[0] == adbSentChars) { /* check for done */ - if (0 == adb_cmd_result(adbOutputBuffer)) { /* do we expect data - * back? */ - adbWaiting = 1; /* signal waiting for return */ - adbWaitingCmd = adbOutputBuffer[2]; /* save waiting command */ - } else { /* no talk, so done */ - /* set up stuff for adb_pass_up */ - memcpy(packet.data, adbInputBuffer, adbInputBuffer[0] + 1); - packet.saveBuf = adbBuffer; - packet.compRout = adbCompRout; - packet.compData = adbCompData; - packet.cmd = adbWaitingCmd; - packet.unsol = 0; - packet.ack_only = 1; - adb_pass_up(&packet); - - /* reset "waiting" vars, just in case */ - adbWaitingCmd = 0; - adbBuffer = (long)0; - adbCompRout = (long)0; - adbCompData = (long)0; - } - - adbWriteDelay = 0; /* done writing */ - adbActionState = ADB_ACTION_IDLE; /* signal bus is idle */ - ADB_SET_SR_INPUT(); - ADB_SET_STATE_IDLE_CUDA(); -#ifdef ADB_DEBUG - if (adb_debug) - printf_intr("write done "); -#endif - } else { - ADB_SR() = adbOutputBuffer[adbSentChars + 1]; /* send next byte */ - ADB_TOGGLE_STATE_ACK_CUDA(); /* signal byte ready to - * shift */ -#ifdef ADB_DEBUG - if (adb_debug) - printf_intr("toggle "); -#endif - } - break; - - case ADB_ACTION_NOTREADY: -#ifdef ADB_DEBUG - if (adb_debug) - printf_intr("adb: not yet initialized\n"); -#endif - break; - - default: -#ifdef ADB_DEBUG - if (adb_debug) - printf_intr("intr: unknown ADB state\n"); -#endif - break; - } - - ADB_VIA_INTR_ENABLE(); /* enable ADB interrupt on IIs. */ - - splx(s); /* restore */ - - return (1); -} /* end adb_intr_cuda */ - - -int -send_adb_cuda(u_char *in, u_char *buffer, void *compRout, void *data, int - command) -{ - int s, len; - -#ifdef ADB_DEBUG - if (adb_debug) - printf_intr("SEND\n"); -#endif - - if (adbActionState == ADB_ACTION_NOTREADY) - return 1; - - /* Don't interrupt while we are messing with the ADB */ - s = splhigh(); - - if ((adbActionState == ADB_ACTION_IDLE) && /* ADB available? */ - (ADB_INTR_IS_OFF)) { /* and no incoming interrupt? */ - } else - if (adbWriteDelay == 0) /* it's busy, but is anything waiting? */ - adbWriteDelay = 1; /* if no, then we'll "queue" - * it up */ - else { - splx(s); - return 1; /* really busy! */ - } - -#ifdef ADB_DEBUG - if (adb_debug) - printf_intr("QUEUE\n"); -#endif - if ((long)in == (long)0) { /* need to convert? */ - /* - * Don't need to use adb_cmd_extra here because this section - * will be called ONLY when it is an ADB command (no RTC or - * PRAM) - */ - if ((command & 0x0c) == 0x08) /* copy addl data ONLY if - * doing a listen! */ - len = buffer[0]; /* length of additional data */ - else - len = 0;/* no additional data */ - - adbOutputBuffer[0] = 2 + len; /* dev. type + command + addl. - * data */ - adbOutputBuffer[1] = 0x00; /* mark as an ADB command */ - adbOutputBuffer[2] = (u_char)command; /* load command */ - - /* copy additional output data, if any */ - memcpy(adbOutputBuffer + 3, buffer + 1, len); - } else - /* if data ready, just copy over */ - memcpy(adbOutputBuffer, in, in[0] + 2); - - adbSentChars = 0; /* nothing sent yet */ - adbBuffer = buffer; /* save buffer to know where to save result */ - adbCompRout = compRout; /* save completion routine pointer */ - adbCompData = data; /* save completion routine data pointer */ - adbWaitingCmd = adbOutputBuffer[2]; /* save wait command */ - - if (adbWriteDelay != 1) { /* start command now? */ -#ifdef ADB_DEBUG - if (adb_debug) - printf_intr("out start NOW"); -#endif - delay(ADB_DELAY); - adbActionState = ADB_ACTION_OUT; /* set next state */ - ADB_SET_SR_OUTPUT(); /* set shift register for OUT */ - ADB_SR() = adbOutputBuffer[adbSentChars + 1]; /* load byte for output */ - ADB_SET_STATE_ACKOFF_CUDA(); - ADB_SET_STATE_TIP(); /* tell ADB that we want to send */ - } - adbWriteDelay = 1; /* something in the write "queue" */ - - splx(s); - - if (0x0100 <= (s & 0x0700)) /* were VIA1 interrupts blocked? */ - /* poll until byte done */ - while ((adbActionState != ADB_ACTION_IDLE) || (ADB_INTR_IS_ON) - || (adbWaiting == 1)) - if (ADB_SR_INTR_IS_ON) { /* wait for "interrupt" */ - adb_intr_cuda(NULL); /* go process it */ - if (adb_polling) - adb_soft_intr(); - } - - return 0; -} /* send_adb_cuda */ - - -int -adb_intr_II(void *arg) -{ - struct adbCommand packet; - int i, intr_on = 0; - int send = 0; - unsigned int s; - - s = splhigh(); /* can't be too careful - might be called */ - /* from a routine, NOT an interrupt */ - - ADB_VIA_CLR_INTR(); /* clear interrupt */ - - ADB_VIA_INTR_DISABLE(); /* disable ADB interrupt on IIs. */ - - delay(ADB_DELAY); /* yuck (don't remove) */ - - (void)intr_dispatch(0x70); /* grab any serial interrupts */ - - if (ADB_INTR_IS_ON) - intr_on = 1; /* save for later */ - -switch_start: - switch (adbActionState) { - case ADB_ACTION_POLLING: - if (!intr_on) { - if (adbOutQueueHasData) { -#ifdef ADB_DEBUG - if (adb_debug & 0x80) - printf_intr("POLL-doing-out-queue. "); -#endif - ADB_SET_STATE_IDLE_II(); - delay(ADB_DELAY); - - /* copy over data */ - memcpy(adbOutputBuffer, adbOutQueue.outBuf, - adbOutQueue.outBuf[0] + 2); - - adbBuffer = adbOutQueue.saveBuf; /* user data area */ - adbCompRout = adbOutQueue.compRout; /* completion routine */ - adbCompData = adbOutQueue.data; /* comp. rout. data */ - adbOutQueueHasData = 0; /* currently processing - * "queue" entry */ - adbSentChars = 0; /* nothing sent yet */ - adbActionState = ADB_ACTION_OUT; /* set next state */ - ADB_SET_SR_OUTPUT(); /* set shift register for OUT */ - ADB_SR() = adbOutputBuffer[1]; /* load byte for output */ - adbBusState = ADB_BUS_CMD; /* set bus to cmd state */ - ADB_SET_STATE_CMD(); /* tell ADB that we want to send */ - break; - } else { -#ifdef ADB_DEBUG - if (adb_debug) - printf_intr("pIDLE "); -#endif - adbActionState = ADB_ACTION_IDLE; - } - } else { -#ifdef ADB_DEBUG - if (adb_debug & 0x80) - printf_intr("pIN "); -#endif - adbActionState = ADB_ACTION_IN; - } - delay(ADB_DELAY); - (void)intr_dispatch(0x70); /* grab any serial interrupts */ - goto switch_start; - break; - case ADB_ACTION_IDLE: - if (!intr_on) { - i = ADB_SR(); - adbBusState = ADB_BUS_IDLE; - adbActionState = ADB_ACTION_IDLE; - ADB_SET_STATE_IDLE_II(); - break; - } - adbInputBuffer[0] = 1; - adbInputBuffer[1] = ADB_SR(); /* get first byte */ -#ifdef ADB_DEBUG - if (adb_debug & 0x80) - printf_intr("idle 0x%02x ", adbInputBuffer[1]); -#endif - ADB_SET_SR_INPUT(); /* make sure SR is set to IN */ - adbActionState = ADB_ACTION_IN; /* set next state */ - ADB_SET_STATE_EVEN(); /* set bus state to even */ - adbBusState = ADB_BUS_EVEN; - break; - - case ADB_ACTION_IN: - adbInputBuffer[++adbInputBuffer[0]] = ADB_SR(); /* get byte */ -#ifdef ADB_DEBUG - if (adb_debug & 0x80) - printf_intr("in 0x%02x ", - adbInputBuffer[adbInputBuffer[0]]); -#endif - ADB_SET_SR_INPUT(); /* make sure SR is set to IN */ - - if (intr_on) { /* process last byte of packet */ - adbInputBuffer[0]--; /* minus one */ - /* - * If intr_on was true, and it's the second byte, then - * the byte we just discarded is really valid, so - * adjust the count - */ - if (adbInputBuffer[0] == 2) { - adbInputBuffer[0]++; - } - -#ifdef ADB_DEBUG - if (adb_debug & 0x80) { - printf_intr("done: "); - print_single(adbInputBuffer); - } -#endif - - adbLastDevice = ADB_CMDADDR(adbInputBuffer[1]); - - if (adbInputBuffer[0] == 1 && !adbWaiting) { /* SRQ!!!*/ -#ifdef ADB_DEBUG - if (adb_debug & 0x80) - printf_intr(" xSRQ! "); -#endif - adb_guess_next_device(); -#ifdef ADB_DEBUG - if (adb_debug & 0x80) - printf_intr("try 0x%0x ", - adbLastDevice); -#endif - adbOutputBuffer[0] = 1; - adbOutputBuffer[1] = ADBTALK(adbLastDevice, 0); - - adbSentChars = 0; /* nothing sent yet */ - adbActionState = ADB_ACTION_POLLING; /* set next state */ - ADB_SET_SR_OUTPUT(); /* set shift register for OUT */ - ADB_SR() = adbOutputBuffer[1]; /* load byte for output */ - adbBusState = ADB_BUS_CMD; /* set bus to cmd state */ - ADB_SET_STATE_CMD(); /* tell ADB that we want to */ - break; - } - - /* set up data for adb_pass_up */ - memcpy(packet.data, adbInputBuffer, adbInputBuffer[0] + 1); - - if (!adbWaiting && (adbInputBuffer[0] != 0)) { - packet.unsol = 1; - packet.ack_only = 0; - adb_pass_up(&packet); - } else { - packet.saveBuf = adbBuffer; - packet.compRout = adbCompRout; - packet.compData = adbCompData; - packet.unsol = 0; - packet.ack_only = 0; - adb_pass_up(&packet); - } - - adbWaiting = 0; - adbInputBuffer[0] = 0; - adbBuffer = (long)0; - adbCompRout = (long)0; - adbCompData = (long)0; - /* - * Since we are done, check whether there is any data - * waiting to do out. If so, start the sending the data. - */ - if (adbOutQueueHasData == 1) { -#ifdef ADB_DEBUG - if (adb_debug & 0x80) - printf_intr("XXX: DOING OUT QUEUE\n"); -#endif - /* copy over data */ - memcpy(adbOutputBuffer, adbOutQueue.outBuf, - adbOutQueue.outBuf[0] + 2); - adbBuffer = adbOutQueue.saveBuf; /* user data area */ - adbCompRout = adbOutQueue.compRout; /* completion routine */ - adbCompData = adbOutQueue.data; /* comp. rout. data */ - adbOutQueueHasData = 0; /* currently processing - * "queue" entry */ - send = 1; - } else { -#ifdef ADB_DEBUG - if (adb_debug & 0x80) - printf_intr("XXending "); -#endif - adb_guess_next_device(); - adbOutputBuffer[0] = 1; - adbOutputBuffer[1] = ((adbLastDevice & 0x0f) << 4) | 0x0c; - adbSentChars = 0; /* nothing sent yet */ - adbActionState = ADB_ACTION_POLLING; /* set next state */ - ADB_SET_SR_OUTPUT(); /* set shift register for OUT */ - ADB_SR() = adbOutputBuffer[1]; /* load byte for output */ - adbBusState = ADB_BUS_CMD; /* set bus to cmd state */ - ADB_SET_STATE_CMD(); /* tell ADB that we want to */ - break; - } - } - - /* - * If send is true then something above determined that - * the message has ended and we need to start sending out - * a new message immediately. This could be because there - * is data waiting to go out or because an SRQ was seen. - */ - if (send) { - adbSentChars = 0; /* nothing sent yet */ - adbActionState = ADB_ACTION_OUT; /* set next state */ - ADB_SET_SR_OUTPUT(); /* set shift register for OUT */ - ADB_SR() = adbOutputBuffer[1]; /* load byte for output */ - adbBusState = ADB_BUS_CMD; /* set bus to cmd state */ - ADB_SET_STATE_CMD(); /* tell ADB that we want to - * send */ - break; - } - /* We only get this far if the message hasn't ended yet. */ - switch (adbBusState) { /* set to next state */ - case ADB_BUS_EVEN: - ADB_SET_STATE_ODD(); /* set state to odd */ - adbBusState = ADB_BUS_ODD; - break; - - case ADB_BUS_ODD: - ADB_SET_STATE_EVEN(); /* set state to even */ - adbBusState = ADB_BUS_EVEN; - break; - default: - printf_intr("strange state!!!\n"); /* huh? */ - break; - } - break; - - case ADB_ACTION_OUT: - i = ADB_SR(); /* clear interrupt */ - adbSentChars++; - /* - * If the outgoing data was a TALK, we must - * switch to input mode to get the result. - */ - if ((adbOutputBuffer[1] & 0x0c) == 0x0c) { - adbInputBuffer[0] = 1; - adbInputBuffer[1] = i; - adbActionState = ADB_ACTION_IN; - ADB_SET_SR_INPUT(); - adbBusState = ADB_BUS_EVEN; - ADB_SET_STATE_EVEN(); -#ifdef ADB_DEBUG - if (adb_debug & 0x80) - printf_intr("talk out 0x%02x ", i); -#endif - /* we want something back */ - adbWaiting = 1; - break; - } - /* - * If it's not a TALK, check whether all data has been sent. - * If so, call the completion routine and clean up. If not, - * advance to the next state. - */ -#ifdef ADB_DEBUG - if (adb_debug & 0x80) - printf_intr("non-talk out 0x%0x ", i); -#endif - ADB_SET_SR_OUTPUT(); - if (adbOutputBuffer[0] == adbSentChars) { /* check for done */ -#ifdef ADB_DEBUG - if (adb_debug & 0x80) - printf_intr("done \n"); -#endif - /* set up stuff for adb_pass_up */ - memcpy(packet.data, adbOutputBuffer, adbOutputBuffer[0] + 1); - packet.saveBuf = adbBuffer; - packet.compRout = adbCompRout; - packet.compData = adbCompData; - packet.cmd = adbWaitingCmd; - packet.unsol = 0; - packet.ack_only = 1; - adb_pass_up(&packet); - - /* reset "waiting" vars, just in case */ - adbBuffer = (long)0; - adbCompRout = (long)0; - adbCompData = (long)0; - if (adbOutQueueHasData == 1) { - /* copy over data */ - memcpy(adbOutputBuffer, adbOutQueue.outBuf, - adbOutQueue.outBuf[0] + 2); - adbBuffer = adbOutQueue.saveBuf; /* user data area */ - adbCompRout = adbOutQueue.compRout; /* completion routine */ - adbCompData = adbOutQueue.data; /* comp. rout. data */ - adbOutQueueHasData = 0; /* currently processing - * "queue" entry */ - adbSentChars = 0; /* nothing sent yet */ - adbActionState = ADB_ACTION_OUT; /* set next state */ - ADB_SET_SR_OUTPUT(); /* set shift register for OUT */ - ADB_SR() = adbOutputBuffer[1]; /* load byte for output */ - adbBusState = ADB_BUS_CMD; /* set bus to cmd state */ - ADB_SET_STATE_CMD(); /* tell ADB that we want to - * send */ - break; - } else { - /* send talk to last device instead */ - adbOutputBuffer[0] = 1; - adbOutputBuffer[1] = - ADBTALK(ADB_CMDADDR(adbOutputBuffer[1]), 0); - - adbSentChars = 0; /* nothing sent yet */ - adbActionState = ADB_ACTION_IDLE; /* set next state */ - ADB_SET_SR_OUTPUT(); /* set shift register for OUT */ - ADB_SR() = adbOutputBuffer[1]; /* load byte for output */ - adbBusState = ADB_BUS_CMD; /* set bus to cmd state */ - ADB_SET_STATE_CMD(); /* tell ADB that we want to */ - break; - } - } - ADB_SR() = adbOutputBuffer[adbSentChars + 1]; - switch (adbBusState) { /* advance to next state */ - case ADB_BUS_EVEN: - ADB_SET_STATE_ODD(); /* set state to odd */ - adbBusState = ADB_BUS_ODD; - break; - - case ADB_BUS_CMD: - case ADB_BUS_ODD: - ADB_SET_STATE_EVEN(); /* set state to even */ - adbBusState = ADB_BUS_EVEN; - break; - - default: -#ifdef ADB_DEBUG - if (adb_debug) { - printf_intr("strange state!!! (0x%x)\n", - adbBusState); - } -#endif - break; - } - break; - - default: -#ifdef ADB_DEBUG - if (adb_debug) - printf_intr("adb: unknown ADB state (during intr)\n"); -#endif - break; - } - - ADB_VIA_INTR_ENABLE(); /* enable ADB interrupt on IIs. */ - - splx(s); /* restore */ - - return (1); - -} - - -/* - * send_adb version for II series machines - */ -int -send_adb_II(u_char *in, u_char *buffer, void *compRout, void *data, int command) -{ - int s, len; - - if (adbActionState == ADB_ACTION_NOTREADY) /* return if ADB not - * available */ - return 1; - - /* Don't interrupt while we are messing with the ADB */ - s = splhigh(); - - if (0 != adbOutQueueHasData) { /* right now, "has data" means "full" */ - splx(s); /* sorry, try again later */ - return 1; - } - if ((long)in == (long)0) { /* need to convert? */ - /* - * Don't need to use adb_cmd_extra here because this section - * will be called ONLY when it is an ADB command (no RTC or - * PRAM), especially on II series! - */ - if ((command & 0x0c) == 0x08) /* copy addl data ONLY if - * doing a listen! */ - len = buffer[0]; /* length of additional data */ - else - len = 0;/* no additional data */ - - adbOutQueue.outBuf[0] = 1 + len; /* command + addl. data */ - adbOutQueue.outBuf[1] = (u_char)command; /* load command */ - - /* copy additional output data, if any */ - memcpy(adbOutQueue.outBuf + 2, buffer + 1, len); - } else - /* if data ready, just copy over */ - memcpy(adbOutQueue.outBuf, in, in[0] + 2); - - adbOutQueue.saveBuf = buffer; /* save buffer to know where to save - * result */ - adbOutQueue.compRout = compRout; /* save completion routine - * pointer */ - adbOutQueue.data = data;/* save completion routine data pointer */ - - if ((adbActionState == ADB_ACTION_IDLE) && /* is ADB available? */ - (ADB_INTR_IS_OFF)) { /* and no incoming interrupts? */ - /* then start command now */ - memcpy(adbOutputBuffer, adbOutQueue.outBuf, - adbOutQueue.outBuf[0] + 2); /* copy over data */ - - adbBuffer = adbOutQueue.saveBuf; /* pointer to user data - * area */ - adbCompRout = adbOutQueue.compRout; /* pointer to the - * completion routine */ - adbCompData = adbOutQueue.data; /* pointer to the completion - * routine data */ - - adbSentChars = 0; /* nothing sent yet */ - adbActionState = ADB_ACTION_OUT; /* set next state */ - adbBusState = ADB_BUS_CMD; /* set bus to cmd state */ - - ADB_SET_SR_OUTPUT(); /* set shift register for OUT */ - - ADB_SR() = adbOutputBuffer[adbSentChars + 1]; /* load byte for output */ - ADB_SET_STATE_CMD(); /* tell ADB that we want to send */ - adbOutQueueHasData = 0; /* currently processing "queue" entry */ - } else - adbOutQueueHasData = 1; /* something in the write "queue" */ - - splx(s); - - if (0x0100 <= (s & 0x0700)) /* were VIA1 interrupts blocked? */ - /* poll until message done */ - while ((adbActionState != ADB_ACTION_IDLE) || (ADB_INTR_IS_ON) - || (adbWaiting == 1)) - if (ADB_SR_INTR_IS_ON) { /* wait for "interrupt" */ - adb_intr_II(NULL); /* go process it */ - if (adb_polling) - adb_soft_intr(); - } - - return 0; -} - - -/* - * This routine is called from the II series interrupt routine - * to determine what the "next" device is that should be polled. - */ -int -adb_guess_next_device(void) -{ - int last, i, dummy; - - if (adbStarting) { - /* - * Start polling EVERY device, since we can't be sure there is - * anything in the device table yet - */ - if (adbLastDevice < 1 || adbLastDevice > 15) - adbLastDevice = 1; - if (++adbLastDevice > 15) /* point to next one */ - adbLastDevice = 1; - } else { - /* find the next device using the device table */ - if (adbLastDevice < 1 || adbLastDevice > 15) /* let's be parinoid */ - adbLastDevice = 2; - last = 1; /* default index location */ - - for (i = 1; i < 16; i++) /* find index entry */ - if (ADBDevTable[i].currentAddr == adbLastDevice) { /* look for device */ - last = i; /* found it */ - break; - } - dummy = last; /* index to start at */ - for (;;) { /* find next device in index */ - if (++dummy > 15) /* wrap around if needed */ - dummy = 1; - if (dummy == last) { /* didn't find any other - * device! This can happen if - * there are no devices on the - * bus */ - dummy = 1; - break; - } - /* found the next device */ - if (ADBDevTable[dummy].devType != 0) - break; - } - adbLastDevice = ADBDevTable[dummy].currentAddr; - } - return adbLastDevice; -} - - -/* - * Called when when an adb interrupt happens. - * This routine simply transfers control over to the appropriate - * code for the machine we are running on. - */ -int -adb_intr(void *arg) -{ - switch (adbHardware) { - case ADB_HW_II: - return adb_intr_II(arg); - break; - - case ADB_HW_IISI: - return adb_intr_IIsi(arg); - break; - - case ADB_HW_PB: /* Should not come through here. */ - break; - - case ADB_HW_CUDA: - return adb_intr_cuda(arg); - break; - - case ADB_HW_UNKNOWN: - break; - } - - return (-1); -} - - -/* - * called when when an adb interrupt happens - * - * IIsi version of adb_intr - * - */ -int -adb_intr_IIsi(void *arg) -{ - struct adbCommand packet; - int i, ending; - unsigned int s; - - s = splhigh(); /* can't be too careful - might be called */ - /* from a routine, NOT an interrupt */ - - ADB_VIA_CLR_INTR(); /* clear interrupt */ - - ADB_VIA_INTR_DISABLE(); /* disable ADB interrupt on IIs. */ - -switch_start: - switch (adbActionState) { - case ADB_ACTION_IDLE: - delay(ADB_DELAY); /* short delay is required before the - * first byte */ - - ADB_SET_SR_INPUT(); /* make sure SR is set to IN */ - ADB_SET_STATE_ACTIVE(); /* signal start of data frame */ - adbInputBuffer[1] = ADB_SR(); /* get byte */ - adbInputBuffer[0] = 1; - adbActionState = ADB_ACTION_IN; /* set next state */ - - ADB_SET_STATE_ACKON(); /* start ACK to ADB chip */ - delay(ADB_DELAY); /* delay */ - ADB_SET_STATE_ACKOFF(); /* end ACK to ADB chip */ - (void)intr_dispatch(0x70); /* grab any serial interrupts */ - break; - - case ADB_ACTION_IN: - ADB_SET_SR_INPUT(); /* make sure SR is set to IN */ - adbInputBuffer[++adbInputBuffer[0]] = ADB_SR(); /* get byte */ - if (ADB_INTR_IS_OFF) /* check for end of frame */ - ending = 1; - else - ending = 0; - - ADB_SET_STATE_ACKON(); /* start ACK to ADB chip */ - delay(ADB_DELAY); /* delay */ - ADB_SET_STATE_ACKOFF(); /* end ACK to ADB chip */ - (void)intr_dispatch(0x70); /* grab any serial interrupts */ - - if (1 == ending) { /* end of message? */ - ADB_SET_STATE_INACTIVE(); /* signal end of frame */ - /* - * This section _should_ handle all ADB and RTC/PRAM - * type commands, but there may be more... Note: - * commands are always at [4], even for rtc/pram - * commands - */ - /* set up data for adb_pass_up */ - memcpy(packet.data, adbInputBuffer, adbInputBuffer[0] + 1); - - if ((adbWaiting == 1) && /* are we waiting AND */ - (adbInputBuffer[4] == adbWaitingCmd) && /* the cmd we sent AND */ - ((adbInputBuffer[2] == 0x00) || /* it's from the ADB - * device OR */ - (adbInputBuffer[2] == 0x01))) { /* it's from the - * PRAM/RTC device */ - - packet.saveBuf = adbBuffer; - packet.compRout = adbCompRout; - packet.compData = adbCompData; - packet.unsol = 0; - packet.ack_only = 0; - adb_pass_up(&packet); - - adbWaitingCmd = 0; /* reset "waiting" vars */ - adbWaiting = 0; - adbBuffer = (long)0; - adbCompRout = (long)0; - adbCompData = (long)0; - } else { - packet.unsol = 1; - packet.ack_only = 0; - adb_pass_up(&packet); - } - - adbActionState = ADB_ACTION_IDLE; - adbInputBuffer[0] = 0; /* reset length */ - - if (adbWriteDelay == 1) { /* were we waiting to - * write? */ - adbSentChars = 0; /* nothing sent yet */ - adbActionState = ADB_ACTION_OUT; /* set next state */ - - delay(ADB_DELAY); /* delay */ - (void)intr_dispatch(0x70); /* grab any serial interrupts */ - - if (ADB_INTR_IS_ON) { /* ADB intr low during - * write */ - ADB_SET_STATE_IDLE_IISI(); /* reset */ - ADB_SET_SR_INPUT(); /* make sure SR is set - * to IN */ - adbSentChars = 0; /* must start all over */ - adbActionState = ADB_ACTION_IDLE; /* new state */ - adbInputBuffer[0] = 0; - /* may be able to take this out later */ - delay(ADB_DELAY); /* delay */ - break; - } - ADB_SET_STATE_ACTIVE(); /* tell ADB that we want - * to send */ - ADB_SET_STATE_ACKOFF(); /* make sure */ - ADB_SET_SR_OUTPUT(); /* set shift register - * for OUT */ - ADB_SR() = adbOutputBuffer[adbSentChars + 1]; - ADB_SET_STATE_ACKON(); /* tell ADB byte ready - * to shift */ - } - } - break; - - case ADB_ACTION_OUT: - i = ADB_SR(); /* reset SR-intr in IFR */ - ADB_SET_SR_OUTPUT(); /* set shift register for OUT */ - - ADB_SET_STATE_ACKOFF(); /* finish ACK */ - adbSentChars++; - if (ADB_INTR_IS_ON) { /* ADB intr low during write */ - ADB_SET_STATE_IDLE_IISI(); /* reset */ - ADB_SET_SR_INPUT(); /* make sure SR is set to IN */ - adbSentChars = 0; /* must start all over */ - adbActionState = ADB_ACTION_IDLE; /* new state */ - adbInputBuffer[0] = 0; - adbWriteDelay = 1; /* must retry when done with - * read */ - delay(ADB_DELAY); /* delay */ - (void)intr_dispatch(0x70); /* grab any serial interrupts */ - goto switch_start; /* process next state right - * now */ - break; - } - delay(ADB_DELAY); /* required delay */ - (void)intr_dispatch(0x70); /* grab any serial interrupts */ - - if (adbOutputBuffer[0] == adbSentChars) { /* check for done */ - if (0 == adb_cmd_result(adbOutputBuffer)) { /* do we expect data - * back? */ - adbWaiting = 1; /* signal waiting for return */ - adbWaitingCmd = adbOutputBuffer[2]; /* save waiting command */ - } else {/* no talk, so done */ - /* set up stuff for adb_pass_up */ - memcpy(packet.data, adbInputBuffer, - adbInputBuffer[0] + 1); - packet.saveBuf = adbBuffer; - packet.compRout = adbCompRout; - packet.compData = adbCompData; - packet.cmd = adbWaitingCmd; - packet.unsol = 0; - packet.ack_only = 1; - adb_pass_up(&packet); - - /* reset "waiting" vars, just in case */ - adbWaitingCmd = 0; - adbBuffer = (long)0; - adbCompRout = (long)0; - adbCompData = (long)0; - } - - adbWriteDelay = 0; /* done writing */ - adbActionState = ADB_ACTION_IDLE; /* signal bus is idle */ - ADB_SET_SR_INPUT(); /* make sure SR is set to IN */ - ADB_SET_STATE_INACTIVE(); /* end of frame */ - } else { - ADB_SR() = adbOutputBuffer[adbSentChars + 1]; /* send next byte */ - ADB_SET_STATE_ACKON(); /* signal byte ready to shift */ - } - break; - - case ADB_ACTION_NOTREADY: -#ifdef ADB_DEBUG - if (adb_debug) - printf_intr("adb: not yet initialized\n"); -#endif - break; - - default: -#ifdef ADB_DEBUG - if (adb_debug) - printf_intr("intr: unknown ADB state\n"); -#endif - break; - } - - ADB_VIA_INTR_ENABLE(); /* enable ADB interrupt on IIs. */ - - splx(s); /* restore */ - - return (1); -} /* end adb_intr_IIsi */ - - -/***************************************************************************** - * if the device is currently busy, and there is no data waiting to go out, then - * the data is "queued" in the outgoing buffer. If we are already waiting, then - * we return. - * in: if (in == 0) then the command string is built from command and buffer - * if (in != 0) then in is used as the command string - * buffer: additional data to be sent (used only if in == 0) - * this is also where return data is stored - * compRout: the completion routine that is called when then return value - * is received (if a return value is expected) - * data: a data pointer that can be used by the completion routine - * command: an ADB command to be sent (used only if in == 0) - * - */ -int -send_adb_IIsi(u_char *in, u_char *buffer, void *compRout, void *data, int - command) -{ - int s, len; - - if (adbActionState == ADB_ACTION_NOTREADY) - return 1; - - /* Don't interrupt while we are messing with the ADB */ - s = splhigh(); - - if ((adbActionState == ADB_ACTION_IDLE) && /* ADB available? */ - (ADB_INTR_IS_OFF)) {/* and no incoming interrupt? */ - - } else - if (adbWriteDelay == 0) /* it's busy, but is anything waiting? */ - adbWriteDelay = 1; /* if no, then we'll "queue" - * it up */ - else { - splx(s); - return 1; /* really busy! */ - } - - if ((long)in == (long)0) { /* need to convert? */ - /* - * Don't need to use adb_cmd_extra here because this section - * will be called ONLY when it is an ADB command (no RTC or - * PRAM) - */ - if ((command & 0x0c) == 0x08) /* copy addl data ONLY if - * doing a listen! */ - len = buffer[0]; /* length of additional data */ - else - len = 0;/* no additional data */ - - adbOutputBuffer[0] = 2 + len; /* dev. type + command + addl. - * data */ - adbOutputBuffer[1] = 0x00; /* mark as an ADB command */ - adbOutputBuffer[2] = (u_char)command; /* load command */ - - /* copy additional output data, if any */ - memcpy(adbOutputBuffer + 3, buffer + 1, len); - } else - /* if data ready, just copy over */ - memcpy(adbOutputBuffer, in, in[0] + 2); - - adbSentChars = 0; /* nothing sent yet */ - adbBuffer = buffer; /* save buffer to know where to save result */ - adbCompRout = compRout; /* save completion routine pointer */ - adbCompData = data; /* save completion routine data pointer */ - adbWaitingCmd = adbOutputBuffer[2]; /* save wait command */ - - if (adbWriteDelay != 1) { /* start command now? */ - adbActionState = ADB_ACTION_OUT; /* set next state */ - - ADB_SET_STATE_ACTIVE(); /* tell ADB that we want to send */ - ADB_SET_STATE_ACKOFF(); /* make sure */ - - ADB_SET_SR_OUTPUT(); /* set shift register for OUT */ - - ADB_SR() = adbOutputBuffer[adbSentChars + 1]; /* load byte for output */ - - ADB_SET_STATE_ACKON(); /* tell ADB byte ready to shift */ - } - adbWriteDelay = 1; /* something in the write "queue" */ - - splx(s); - - if (0x0100 <= (s & 0x0700)) /* were VIA1 interrupts blocked? */ - /* poll until byte done */ - while ((adbActionState != ADB_ACTION_IDLE) || (ADB_INTR_IS_ON) - || (adbWaiting == 1)) - if (ADB_SR_INTR_IS_ON) { /* wait for "interrupt" */ - adb_intr_IIsi(NULL); /* go process it */ - if (adb_polling) - adb_soft_intr(); - } - - return 0; -} /* send_adb_IIsi */ - -/* - * adb_pass_up is called by the interrupt-time routines. - * It takes the raw packet data that was received from the - * device and puts it into the queue that the upper half - * processes. It then signals for a soft ADB interrupt which - * will eventually call the upper half routine (adb_soft_intr). - * - * If in->unsol is 0, then this is either the notification - * that the packet was sent (on a LISTEN, for example), or the - * response from the device (on a TALK). The completion routine - * is called only if the user specified one. - * - * If in->unsol is 1, then this packet was unsolicited and - * so we look up the device in the ADB device table to determine - * what it's default service routine is. - * - * If in->ack_only is 1, then we really only need to call - * the completion routine, so don't do any other stuff. - * - * Note that in->data contains the packet header AND data, - * while adbInbound[]->data contains ONLY data. - * - * Note: Called only at interrupt time. Assumes this. - */ -void -adb_pass_up(struct adbCommand *in) -{ - int start = 0, len = 0, cmd = 0; - ADBDataBlock block; - - /* temp for testing */ - /*u_char *buffer = 0;*/ - /*u_char *compdata = 0;*/ - /*u_char *comprout = 0;*/ - - if (adbInCount >= ADB_QUEUE) { -#ifdef ADB_DEBUG - if (adb_debug) - printf_intr("adb: ring buffer overflow\n"); -#endif - return; - } - - if (in->ack_only) { - len = in->data[0]; - cmd = in->cmd; - start = 0; - } else { - switch (adbHardware) { - case ADB_HW_II: - cmd = in->data[1]; - if (in->data[0] < 2) - len = 0; - else - len = in->data[0]-1; - start = 1; - break; - - case ADB_HW_IISI: - case ADB_HW_CUDA: - /* If it's unsolicited, accept only ADB data for now */ - if (in->unsol) - if (0 != in->data[2]) - return; - cmd = in->data[4]; - if (in->data[0] < 5) - len = 0; - else - len = in->data[0]-4; - start = 4; - break; - - case ADB_HW_PB: - cmd = in->data[1]; - if (in->data[0] < 2) - len = 0; - else - len = in->data[0]-1; - start = 1; - break; - - case ADB_HW_UNKNOWN: - return; - } - - /* Make sure there is a valid device entry for this device */ - if (in->unsol) { - /* ignore unsolicited data during adbreinit */ - if (adbStarting) - return; - /* get device's comp. routine and data area */ - if (-1 == get_adb_info(&block, ADB_CMDADDR(cmd))) - return; - } - } - - /* - * If this is an unsolicited packet, we need to fill in - * some info so adb_soft_intr can process this packet - * properly. If it's not unsolicited, then use what - * the caller sent us. - */ - if (in->unsol) { - adbInbound[adbInTail].compRout = (void *)block.dbServiceRtPtr; - adbInbound[adbInTail].compData = (void *)block.dbDataAreaAddr; - adbInbound[adbInTail].saveBuf = (void *)adbInbound[adbInTail].data; - } else { - adbInbound[adbInTail].compRout = (void *)in->compRout; - adbInbound[adbInTail].compData = (void *)in->compData; - adbInbound[adbInTail].saveBuf = (void *)in->saveBuf; - } - -#ifdef ADB_DEBUG - if (adb_debug && in->data[1] == 2) - printf_intr("adb: caught error\n"); -#endif - - /* copy the packet data over */ - /* - * TO DO: If the *_intr routines fed their incoming data - * directly into an adbCommand struct, which is passed to - * this routine, then we could eliminate this copy. - */ - memcpy(adbInbound[adbInTail].data + 1, in->data + start + 1, len); - adbInbound[adbInTail].data[0] = len; - adbInbound[adbInTail].cmd = cmd; - - adbInCount++; - if (++adbInTail >= ADB_QUEUE) - adbInTail = 0; - - /* - * If the debugger is running, call upper half manually. - * Otherwise, trigger a soft interrupt to handle the rest later. - */ - if (adb_polling) - adb_soft_intr(); - else - setsoftadb(); - - return; -} - - -/* - * Called to process the packets after they have been - * placed in the incoming queue. - * - */ -void -adb_soft_intr(void) -{ - int s; - int cmd = 0; - u_char *buffer = 0; - u_char *comprout = 0; - u_char *compdata = 0; - -/*delay(2*ADB_DELAY);*/ - - while (adbInCount) { -#ifdef ADB_DEBUG - if (adb_debug & 0x80) - printf_intr("%x %x %x ", - adbInCount, adbInHead, adbInTail); -#endif - /* get the data we need from the queue */ - buffer = adbInbound[adbInHead].saveBuf; - comprout = adbInbound[adbInHead].compRout; - compdata = adbInbound[adbInHead].compData; - cmd = adbInbound[adbInHead].cmd; - - /* copy over data to data area if it's valid */ - /* - * Note that for unsol packets we don't want to copy the - * data anywhere, so buffer was already set to 0. - * For ack_only buffer was set to 0, so don't copy. - */ - if (buffer) - memcpy(buffer, adbInbound[adbInHead].data, - adbInbound[adbInHead].data[0] + 1); - -#ifdef ADB_DEBUG - if (adb_debug & 0x80) { - printf_intr("%p %p %p %x ", - buffer, comprout, compdata, (short)cmd); - printf_intr("buf: "); - print_single(adbInbound[adbInHead].data); - } -#endif - - /* call default completion routine if it's valid */ - if (comprout) { - (void)((int (*)(u_char *, u_char *, int))comprout) - (buffer, compdata, cmd); - } - - s = splhigh(); - adbInCount--; - if (++adbInHead >= ADB_QUEUE) - adbInHead = 0; - splx(s); - - } - return; -} - - -/* - * This is my version of the ADBOp routine. It mainly just calls the - * hardware-specific routine. - * - * data : pointer to data area to be used by compRout - * compRout : completion routine - * buffer : for LISTEN: points to data to send - MAX 8 data bytes, - * byte 0 = # of bytes - * : for TALK: points to place to save return data - * command : the adb command to send - * result : 0 = success - * : -1 = could not complete - */ -int -adb_op(Ptr buffer, Ptr compRout, Ptr data, short command) -{ - int result; - - switch (adbHardware) { - case ADB_HW_II: - result = send_adb_II((u_char *)0, (u_char *)buffer, - (void *)compRout, (void *)data, (int)command); - if (result == 0) - return 0; - else - return -1; - break; - - case ADB_HW_IISI: - result = send_adb_IIsi((u_char *)0, (u_char *)buffer, - (void *)compRout, (void *)data, (int)command); - /* - * I wish I knew why this delay is needed. It usually needs to - * be here when several commands are sent in close succession, - * especially early in device probes when doing collision - * detection. It must be some race condition. Sigh. - jpw - */ - delay(100); - if (result == 0) - return 0; - else - return -1; - break; - - case ADB_HW_PB: - result = pm_adb_op((u_char *)buffer, (void *)compRout, - (void *)data, (int)command); - - if (result == 0) - return 0; - else - return -1; - break; - - case ADB_HW_CUDA: - result = send_adb_cuda((u_char *)0, (u_char *)buffer, - (void *)compRout, (void *)data, (int)command); - if (result == 0) - return 0; - else - return -1; - break; - - case ADB_HW_UNKNOWN: - default: - return -1; - } -} - - -/* - * adb_hw_setup - * This routine sets up the possible machine specific hardware - * config (mainly VIA settings) for the various models. - */ -void -adb_hw_setup(void) -{ - volatile int i; - u_char send_string[ADB_MAX_MSG_LENGTH]; - - switch (adbHardware) { - case ADB_HW_II: - via1_register_irq(2, adb_intr_II, NULL, NULL); - - via_reg(VIA1, vDirB) |= 0x30; /* register B bits 4 and 5: - * outputs */ - via_reg(VIA1, vDirB) &= 0xf7; /* register B bit 3: input */ - via_reg(VIA1, vACR) &= ~vSR_OUT; /* make sure SR is set - * to IN (II, IIsi) */ - adbActionState = ADB_ACTION_IDLE; /* used by all types of - * hardware (II, IIsi) */ - adbBusState = ADB_BUS_IDLE; /* this var. used in II-series - * code only */ - via_reg(VIA1, vIER) = 0x84; /* make sure VIA interrupts - * are on (II, IIsi) */ - ADB_SET_STATE_IDLE_II(); /* set ADB bus state to idle */ - - ADB_VIA_CLR_INTR(); /* clear interrupt */ - break; - - case ADB_HW_IISI: - via1_register_irq(2, adb_intr_IIsi, NULL, NULL); - via_reg(VIA1, vDirB) |= 0x30; /* register B bits 4 and 5: - * outputs */ - via_reg(VIA1, vDirB) &= 0xf7; /* register B bit 3: input */ - via_reg(VIA1, vACR) &= ~vSR_OUT; /* make sure SR is set - * to IN (II, IIsi) */ - adbActionState = ADB_ACTION_IDLE; /* used by all types of - * hardware (II, IIsi) */ - adbBusState = ADB_BUS_IDLE; /* this var. used in II-series - * code only */ - via_reg(VIA1, vIER) = 0x84; /* make sure VIA interrupts - * are on (II, IIsi) */ - ADB_SET_STATE_IDLE_IISI(); /* set ADB bus state to idle */ - - /* get those pesky clock ticks we missed while booting */ - for (i = 0; i < 30; i++) { - delay(ADB_DELAY); - adb_hw_setup_IIsi(send_string); -#ifdef ADB_DEBUG - if (adb_debug) { - printf_intr("adb: cleanup: "); - print_single(send_string); - } -#endif - delay(ADB_DELAY); - if (ADB_INTR_IS_OFF) - break; - } - break; - - case ADB_HW_PB: - /* - * XXX - really PM_VIA_CLR_INTR - should we put it in - * pm_direct.h? - */ - pm_hw_setup(); - break; - - case ADB_HW_CUDA: - via1_register_irq(2, adb_intr_cuda, NULL, NULL); - via_reg(VIA1, vDirB) |= 0x30; /* register B bits 4 and 5: - * outputs */ - via_reg(VIA1, vDirB) &= 0xf7; /* register B bit 3: input */ - via_reg(VIA1, vACR) &= ~vSR_OUT; /* make sure SR is set - * to IN */ - via_reg(VIA1, vACR) = (via_reg(VIA1, vACR) | 0x0c) & ~0x10; - adbActionState = ADB_ACTION_IDLE; /* used by all types of - * hardware */ - adbBusState = ADB_BUS_IDLE; /* this var. used in II-series - * code only */ - via_reg(VIA1, vIER) = 0x84; /* make sure VIA interrupts - * are on */ - ADB_SET_STATE_IDLE_CUDA(); /* set ADB bus state to idle */ - - /* sort of a device reset */ - i = ADB_SR(); /* clear interrupt */ - ADB_VIA_INTR_DISABLE(); /* no interrupts while clearing */ - ADB_SET_STATE_IDLE_CUDA(); /* reset state to idle */ - delay(ADB_DELAY); - ADB_SET_STATE_TIP(); /* signal start of frame */ - delay(ADB_DELAY); - ADB_TOGGLE_STATE_ACK_CUDA(); - delay(ADB_DELAY); - ADB_CLR_STATE_TIP(); - delay(ADB_DELAY); - ADB_SET_STATE_IDLE_CUDA(); /* back to idle state */ - i = ADB_SR(); /* clear interrupt */ - ADB_VIA_INTR_ENABLE(); /* ints ok now */ - break; - - case ADB_HW_UNKNOWN: - default: - via_reg(VIA1, vIER) = 0x04; /* turn interrupts off - TO - * DO: turn PB ints off? */ - return; - break; - } -} - - -/* - * adb_hw_setup_IIsi - * This is sort of a "read" routine that forces the adb hardware through a read cycle - * if there is something waiting. This helps "clean up" any commands that may have gotten - * stuck or stopped during the boot process. - * - */ -void -adb_hw_setup_IIsi(u_char *buffer) -{ - int i; - int dummy; - int s; - long my_time; - int endofframe; - - delay(ADB_DELAY); - - i = 1; /* skip over [0] */ - s = splhigh(); /* block ALL interrupts while we are working */ - ADB_SET_SR_INPUT(); /* make sure SR is set to IN */ - ADB_VIA_INTR_DISABLE(); /* disable ADB interrupt on IIs. */ - /* this is required, especially on faster machines */ - delay(ADB_DELAY); - - if (ADB_INTR_IS_ON) { - ADB_SET_STATE_ACTIVE(); /* signal start of data frame */ - - endofframe = 0; - while (0 == endofframe) { - /* - * Poll for ADB interrupt and watch for timeout. - * If time out, keep going in hopes of not hanging - * the ADB chip - I think - */ - my_time = ADB_DELAY * 5; - while ((ADB_SR_INTR_IS_OFF) && (my_time-- > 0)) - dummy = via_reg(VIA1, vBufB); - - buffer[i++] = ADB_SR(); /* reset interrupt flag by - * reading vSR */ - /* - * Perhaps put in a check here that ignores all data - * after the first ADB_MAX_MSG_LENGTH bytes ??? - */ - if (ADB_INTR_IS_OFF) /* check for end of frame */ - endofframe = 1; - - ADB_SET_STATE_ACKON(); /* send ACK to ADB chip */ - delay(ADB_DELAY); /* delay */ - ADB_SET_STATE_ACKOFF(); /* send ACK to ADB chip */ - } - ADB_SET_STATE_INACTIVE(); /* signal end of frame and - * delay */ - - /* probably don't need to delay this long */ - delay(ADB_DELAY); - } - buffer[0] = --i; /* [0] is length of message */ - ADB_VIA_INTR_ENABLE(); /* enable ADB interrupt on IIs. */ - splx(s); /* restore interrupts */ - - return; -} /* adb_hw_setup_IIsi */ - - - -/* - * adb_reinit sets up the adb stuff - * - */ -void -adb_reinit(void) -{ - u_char send_string[ADB_MAX_MSG_LENGTH]; - ADBDataBlock data; /* temp. holder for getting device info */ - volatile int i, x; - int s; - int command; - int result; - int saveptr; /* point to next free relocation address */ - int device; - int nonewtimes; /* times thru loop w/o any new devices */ - - via1_register_irq(2, adb_intr, NULL, "adb"); - adb_setup_hw_type(); /* setup hardware type */ - - /* Make sure we are not interrupted while building the table. */ - /* ints must be on for PB & IOP (at least, for now) */ - if (adbHardware != ADB_HW_PB) - s = splhigh(); - else - s = 0; /* XXX shut the compiler up*/ - - ADBNumDevices = 0; /* no devices yet */ - - /* Let intr routines know we are running reinit */ - adbStarting = 1; - - /* - * Initialize the ADB table. For now, we'll always use the same table - * that is defined at the beginning of this file - no mallocs. - */ - for (i = 0; i < 16; i++) { - ADBDevTable[i].devType = 0; - ADBDevTable[i].origAddr = ADBDevTable[i].currentAddr = 0; - } - - adb_hw_setup(); /* init the VIA bits and hard reset ADB */ - - delay(1000); - - /* send an ADB reset first */ - (void)adb_op_sync((Ptr)0, (Ptr)0, (Ptr)0, (short)0x00); - delay(3000); - - /* - * Probe for ADB devices. Probe devices 1-15 quickly to determine - * which device addresses are in use and which are free. For each - * address that is in use, move the device at that address to a higher - * free address. Continue doing this at that address until no device - * responds at that address. Then move the last device that was moved - * back to the original address. Do this for the remaining addresses - * that we determined were in use. - * - * When finished, do this entire process over again with the updated - * list of in use addresses. Do this until no new devices have been - * found in 20 passes though the in use address list. (This probably - * seems long and complicated, but it's the best way to detect multiple - * devices at the same address - sometimes it takes a couple of tries - * before the collision is detected.) - */ - - /* initial scan through the devices */ - for (i = 1; i < 16; i++) { - command = ADBTALK(i, 3); - result = adb_op_sync((Ptr)send_string, (Ptr)0, - (Ptr)0, (short)command); - - if (result == 0 && send_string[0] != 0) { - /* found a device */ - ++ADBNumDevices; - KASSERT(ADBNumDevices < 16); - ADBDevTable[ADBNumDevices].devType = - (int)(send_string[2]); - ADBDevTable[ADBNumDevices].origAddr = i; - ADBDevTable[ADBNumDevices].currentAddr = i; - ADBDevTable[ADBNumDevices].DataAreaAddr = - (long)0; - ADBDevTable[ADBNumDevices].ServiceRtPtr = (void *)0; - pm_check_adb_devices(i); /* tell pm driver device - * is here */ - } - } - - /* find highest unused address */ - for (saveptr = 15; saveptr > 0; saveptr--) - if (-1 == get_adb_info(&data, saveptr)) - break; - -#ifdef ADB_DEBUG - if (adb_debug & 0x80) { - printf_intr("first free is: 0x%02x\n", saveptr); - printf_intr("devices: %i\n", ADBNumDevices); - } -#endif - - nonewtimes = 0; /* no loops w/o new devices */ - while (saveptr > 0 && nonewtimes++ < 11) { - for (i = 1;saveptr > 0 && i <= ADBNumDevices; i++) { - device = ADBDevTable[i].currentAddr; -#ifdef ADB_DEBUG - if (adb_debug & 0x80) - printf_intr("moving device 0x%02x to 0x%02x " - "(index 0x%02x) ", device, saveptr, i); -#endif - - /* send TALK R3 to address */ - command = ADBTALK(device, 3); - (void)adb_op_sync((Ptr)send_string, (Ptr)0, - (Ptr)0, (short)command); - - /* move device to higher address */ - command = ADBLISTEN(device, 3); - send_string[0] = 2; - send_string[1] = (u_char)(saveptr | 0x60); - send_string[2] = 0xfe; - (void)adb_op_sync((Ptr)send_string, (Ptr)0, - (Ptr)0, (short)command); - delay(1000); - - /* send TALK R3 - anthing at new address? */ - command = ADBTALK(saveptr, 3); - send_string[0] = 0; - result = adb_op_sync((Ptr)send_string, (Ptr)0, - (Ptr)0, (short)command); - delay(1000); - - if (result != 0 || send_string[0] == 0) { - /* - * maybe there's a communication breakdown; - * just in case, move it back from whence it - * came, and we'll try again later - */ - command = ADBLISTEN(saveptr, 3); - send_string[0] = 2; - send_string[1] = (u_char)(device | 0x60); - send_string[2] = 0x00; - (void)adb_op_sync((Ptr)send_string, (Ptr)0, - (Ptr)0, (short)command); -#ifdef ADB_DEBUG - if (adb_debug & 0x80) - printf_intr("failed, continuing\n"); -#endif - delay(1000); - continue; - } - - /* send TALK R3 - anything at old address? */ - command = ADBTALK(device, 3); - send_string[0] = 0; - result = adb_op_sync((Ptr)send_string, (Ptr)0, - (Ptr)0, (short)command); - if (result == 0 && send_string[0] != 0) { - /* new device found */ - /* update data for previously moved device */ - ADBDevTable[i].currentAddr = saveptr; -#ifdef ADB_DEBUG - if (adb_debug & 0x80) - printf_intr("old device at index %i\n",i); -#endif - /* add new device in table */ -#ifdef ADB_DEBUG - if (adb_debug & 0x80) - printf_intr("new device found\n"); -#endif - if (saveptr > ADBNumDevices) { - ++ADBNumDevices; - KASSERT(ADBNumDevices < 16); - } - ADBDevTable[ADBNumDevices].devType = - (int)(send_string[2]); - ADBDevTable[ADBNumDevices].origAddr = device; - ADBDevTable[ADBNumDevices].currentAddr = device; - /* These will be set correctly in adbsys.c */ - /* Until then, unsol. data will be ignored. */ - ADBDevTable[ADBNumDevices].DataAreaAddr = - (long)0; - ADBDevTable[ADBNumDevices].ServiceRtPtr = - (void *)0; - /* find next unused address */ - for (x = saveptr; x > 0; x--) { - if (-1 == get_adb_info(&data, x)) { - saveptr = x; - break; - } - } - if (x == 0) - saveptr = 0; -#ifdef ADB_DEBUG - if (adb_debug & 0x80) - printf_intr("new free is 0x%02x\n", - saveptr); -#endif - nonewtimes = 0; - /* tell pm driver device is here */ - pm_check_adb_devices(device); - } else { -#ifdef ADB_DEBUG - if (adb_debug & 0x80) - printf_intr("moving back...\n"); -#endif - /* move old device back */ - command = ADBLISTEN(saveptr, 3); - send_string[0] = 2; - send_string[1] = (u_char)(device | 0x60); - send_string[2] = 0xfe; - (void)adb_op_sync((Ptr)send_string, (Ptr)0, - (Ptr)0, (short)command); - delay(1000); - } - } - } - -#ifdef ADB_DEBUG - if (adb_debug) { - for (i = 1; i <= ADBNumDevices; i++) { - x = get_ind_adb_info(&data, i); - if (x != -1) - printf_intr("index 0x%x, addr 0x%x, type 0x%hx\n", - i, x, data.devType); - } - } -#endif - - /* enable the programmer's switch, if we have one */ - adb_prog_switch_enable(); - -#ifdef ADB_DEBUG - if (adb_debug) { - if (0 == ADBNumDevices) /* tell user if no devices found */ - printf_intr("adb: no devices found\n"); - } -#endif - - adbStarting = 0; /* not starting anymore */ -#ifdef ADB_DEBUG - if (adb_debug) - printf_intr("adb: ADBReInit complete\n"); -#endif - - if (adbHardware == ADB_HW_CUDA) { - timeout_set(&adb_cuda_timeout, (void *)adb_cuda_tickle, NULL); - timeout_add(&adb_cuda_timeout, ADB_TICKLE_TICKS); - } - - /* ints must be on for PB & IOP (at least, for now) */ - if (adbHardware != ADB_HW_PB) - splx(s); - - return; -} - - -/* - * adb_cmd_result - * - * This routine lets the caller know whether the specified adb command string - * should expect a returned result, such as a TALK command. - * - * returns: 0 if a result should be expected - * 1 if a result should NOT be expected - */ -int -adb_cmd_result(u_char *in) -{ - switch (adbHardware) { - case ADB_HW_II: - /* was it an ADB talk command? */ - if ((in[1] & 0x0c) == 0x0c) - return 0; - return 1; - - case ADB_HW_IISI: - case ADB_HW_CUDA: - /* was it an ADB talk command? */ - if ((in[1] == 0x00) && ((in[2] & 0x0c) == 0x0c)) - return 0; - /* was it an RTC/PRAM read date/time? */ - if ((in[1] == 0x01) && (in[2] == 0x03)) - return 0; - return 1; - - case ADB_HW_PB: - return 1; - - case ADB_HW_UNKNOWN: - default: - return 1; - } -} - - -/* - * adb_cmd_extra - * - * This routine lets the caller know whether the specified adb command string - * may have extra data appended to the end of it, such as a LISTEN command. - * - * returns: 0 if extra data is allowed - * 1 if extra data is NOT allowed - */ -int -adb_cmd_extra(u_char *in) -{ - switch (adbHardware) { - case ADB_HW_II: - if ((in[1] & 0x0c) == 0x08) /* was it a listen command? */ - return 0; - return 1; - - case ADB_HW_IISI: - case ADB_HW_CUDA: - /* - * TO DO: support needs to be added to recognize RTC and PRAM - * commands - */ - if ((in[2] & 0x0c) == 0x08) /* was it a listen command? */ - return 0; - /* add others later */ - return 1; - - case ADB_HW_PB: - return 1; - - case ADB_HW_UNKNOWN: - default: - return 1; - } -} - - -void -adb_setup_hw_type(void) -{ - long response; - - response = mac68k_machine.machineid; - - /* - * Determine what type of ADB hardware we are running on. - */ - switch (response) { - case MACH_MACC610: /* Centris 610 */ - case MACH_MACC650: /* Centris 650 */ - case MACH_MACII: /* II */ - case MACH_MACIICI: /* IIci */ - case MACH_MACIICX: /* IIcx */ - case MACH_MACIIX: /* IIx */ - case MACH_MACQ610: /* Quadra 610 */ - case MACH_MACQ650: /* Quadra 650 */ - case MACH_MACQ700: /* Quadra 700 */ - case MACH_MACQ800: /* Quadra 800 */ - case MACH_MACSE30: /* SE/30 */ - adbHardware = ADB_HW_II; -#ifdef ADB_DEBUG - if (adb_debug) - printf_intr("adb: using II series hardware support\n"); -#endif - break; - - case MACH_MACCLASSICII: /* Classic II */ - case MACH_MACLCII: /* LC II, Performa 400/405/430 */ - case MACH_MACLCIII: /* LC III, Performa 450 */ - case MACH_MACIISI: /* IIsi */ - case MACH_MACIIVI: /* IIvi */ - case MACH_MACIIVX: /* IIvx */ - case MACH_MACP460: /* Performa 460/465/467 */ - case MACH_MACP600: /* Performa 600 */ - adbHardware = ADB_HW_IISI; -#ifdef ADB_DEBUG - if (adb_debug) - printf_intr("adb: using IIsi series hardware support\n"); -#endif - break; - - case MACH_MACPB140: /* PowerBook 140 */ - case MACH_MACPB145: /* PowerBook 145 */ - case MACH_MACPB160: /* PowerBook 160 */ - case MACH_MACPB165: /* PowerBook 165 */ - case MACH_MACPB165C: /* PowerBook 165c */ - case MACH_MACPB170: /* PowerBook 170 */ - case MACH_MACPB180: /* PowerBook 180 */ - case MACH_MACPB180C: /* PowerBook 180c */ - adbHardware = ADB_HW_PB; - pm_setup_adb(); -#ifdef ADB_DEBUG - if (adb_debug) - printf_intr("adb: using PowerBook 100-series hardware support\n"); -#endif - break; - - case MACH_MACPB150: /* PowerBook 150 */ - case MACH_MACPB210: /* PowerBook Duo 210 */ - case MACH_MACPB230: /* PowerBook Duo 230 */ - case MACH_MACPB250: /* PowerBook Duo 250 */ - case MACH_MACPB270: /* PowerBook Duo 270 */ - case MACH_MACPB280: /* PowerBook Duo 280 */ - case MACH_MACPB280C: /* PowerBook Duo 280c */ - case MACH_MACPB500: /* PowerBook 500 series */ - case MACH_MACPB190: /* PowerBook 190 */ - case MACH_MACPB190CS: /* PowerBook 190cs */ - adbHardware = ADB_HW_PB; - pm_setup_adb(); -#ifdef ADB_DEBUG - if (adb_debug) - printf_intr("adb: using PowerBook Duo-series and PowerBook 500-series hardware support\n"); -#endif - break; - - case MACH_MACC660AV: /* Centris 660AV */ - case MACH_MACCCLASSIC: /* Color Classic */ - case MACH_MACCCLASSICII: /* Color Classic II */ - case MACH_MACLC475: /* LC 475, Performa 475/476 */ - case MACH_MACLC475_33: /* Clock-chipped 47x */ - case MACH_MACLC520: /* LC 520 */ - case MACH_MACLC575: /* LC 575, Performa 575/577/578 */ - case MACH_MACP550: /* LC 550, Performa 550 */ - case MACH_MACTV: /* Macintosh TV */ - case MACH_MACP580: /* Performa 580/588 */ - case MACH_MACQ605: /* Quadra 605 */ - case MACH_MACQ605_33: /* Clock-chipped Quadra 605 */ - case MACH_MACQ630: /* LC 630, Performa 630, Quadra 630 */ - case MACH_MACQ840AV: /* Quadra 840AV */ - adbHardware = ADB_HW_CUDA; -#ifdef ADB_DEBUG - if (adb_debug) - printf_intr("adb: using Cuda series hardware support\n"); -#endif - break; - - default: - adbHardware = ADB_HW_UNKNOWN; -#ifdef ADB_DEBUG - if (adb_debug) { - printf_intr("adb: hardware type unknown for this machine\n"); - printf_intr("adb: ADB support is disabled\n"); - } -#endif - break; - } - - /* - * Determine whether this machine has ADB based soft power. - */ - switch (response) { - case MACH_MACCCLASSIC: /* Color Classic */ - case MACH_MACCCLASSICII: /* Color Classic II */ - case MACH_MACIISI: /* IIsi */ - case MACH_MACIIVI: /* IIvi */ - case MACH_MACIIVX: /* IIvx */ - case MACH_MACLC520: /* LC 520 */ - case MACH_MACLC575: /* LC 575, Performa 575/577/578 */ - case MACH_MACP550: /* LC 550, Performa 550 */ - case MACH_MACTV: /* Macintosh TV */ - case MACH_MACP580: /* Performa 580/588 */ - case MACH_MACP600: /* Performa 600 */ - case MACH_MACQ630: /* LC 630, Performa 630, Quadra 630 */ - case MACH_MACQ840AV: /* Quadra 840AV */ - adbSoftPower = 1; - break; - } -} - -int -count_adbs(void) -{ - int i; - int found; - - found = 0; - - for (i = 1; i < 16; i++) - if (0 != ADBDevTable[i].currentAddr) - found++; - - return found; -} - -int -get_ind_adb_info(ADBDataBlock *info, int index) -{ - if ((index < 1) || (index > 15)) /* check range 1-15 */ - return (-1); - -#ifdef ADB_DEBUG - if (adb_debug & 0x80) - printf_intr("index 0x%x devType is: 0x%x\n", index, - ADBDevTable[index].devType); -#endif - if (0 == ADBDevTable[index].devType) /* make sure it's a valid entry */ - return (-1); - - info->devType = (unsigned char)(ADBDevTable[index].devType); - info->origADBAddr = (unsigned char)(ADBDevTable[index].origAddr); - info->dbServiceRtPtr = (Ptr)ADBDevTable[index].ServiceRtPtr; - info->dbDataAreaAddr = (Ptr)ADBDevTable[index].DataAreaAddr; - - return (ADBDevTable[index].currentAddr); -} - -int -get_adb_info(ADBDataBlock *info, int adbAddr) -{ - int i; - - if ((adbAddr < 1) || (adbAddr > 15)) /* check range 1-15 */ - return (-1); - - for (i = 1; i < 15; i++) - if (ADBDevTable[i].currentAddr == adbAddr) { - info->devType = (unsigned char)(ADBDevTable[i].devType); - info->origADBAddr = (unsigned char)(ADBDevTable[i].origAddr); - info->dbServiceRtPtr = (Ptr)ADBDevTable[i].ServiceRtPtr; - info->dbDataAreaAddr = ADBDevTable[i].DataAreaAddr; - return 0; /* found */ - } - - return (-1); /* not found */ -} - -int -set_adb_info(ADBSetInfoBlock *info, int adbAddr) -{ - int i; - - if ((adbAddr < 1) || (adbAddr > 15)) /* check range 1-15 */ - return (-1); - - for (i = 1; i < 15; i++) - if (ADBDevTable[i].currentAddr == adbAddr) { - ADBDevTable[i].ServiceRtPtr = - (void *)(info->siServiceRtPtr); - ADBDevTable[i].DataAreaAddr = info->siDataAreaAddr; - return 0; /* found */ - } - - return (-1); /* not found */ - -} - -/* caller should really use machine-independant version: getPramTime */ -/* this version does pseudo-adb access only */ -int -adb_read_date_time(unsigned long *time) -{ - u_char output[ADB_MAX_MSG_LENGTH]; - int result; - volatile int flag = 0; - - switch (adbHardware) { - case ADB_HW_II: - return -1; - - case ADB_HW_IISI: - output[0] = 0x02; /* 2 byte message */ - output[1] = 0x01; /* to pram/rtc device */ - output[2] = 0x03; /* read date/time */ - result = send_adb_IIsi((u_char *)output, (u_char *)output, - (void *)adb_op_comprout, (void *)&flag, (int)0); - if (result != 0) /* exit if not sent */ - return -1; - - while (0 == flag) /* wait for result */ - ; - - *time = (long)(*(long *)(output + 1)); - return 0; - - case ADB_HW_PB: - return -1; - - case ADB_HW_CUDA: - output[0] = 0x02; /* 2 byte message */ - output[1] = 0x01; /* to pram/rtc device */ - output[2] = 0x03; /* read date/time */ - result = send_adb_cuda((u_char *)output, (u_char *)output, - (void *)adb_op_comprout, (void *)&flag, (int)0); - if (result != 0) /* exit if not sent */ - return -1; - - while (0 == flag) /* wait for result */ - ; - - *time = (long)(*(long *)(output + 1)); - return 0; - - case ADB_HW_UNKNOWN: - default: - return -1; - } -} - -/* caller should really use machine-independant version: setPramTime */ -/* this version does pseudo-adb access only */ -int -adb_set_date_time(unsigned long time) -{ - u_char output[ADB_MAX_MSG_LENGTH]; - int result; - volatile int flag = 0; - - switch (adbHardware) { - case ADB_HW_II: - return -1; - - case ADB_HW_IISI: - output[0] = 0x06; /* 6 byte message */ - output[1] = 0x01; /* to pram/rtc device */ - output[2] = 0x09; /* set date/time */ - output[3] = (u_char)(time >> 24); - output[4] = (u_char)(time >> 16); - output[5] = (u_char)(time >> 8); - output[6] = (u_char)(time); - result = send_adb_IIsi((u_char *)output, (u_char *)0, - (void *)adb_op_comprout, (void *)&flag, (int)0); - if (result != 0) /* exit if not sent */ - return -1; - - while (0 == flag) /* wait for send to finish */ - ; - - return 0; - - case ADB_HW_PB: - return -1; - - case ADB_HW_CUDA: - output[0] = 0x06; /* 6 byte message */ - output[1] = 0x01; /* to pram/rtc device */ - output[2] = 0x09; /* set date/time */ - output[3] = (u_char)(time >> 24); - output[4] = (u_char)(time >> 16); - output[5] = (u_char)(time >> 8); - output[6] = (u_char)(time); - result = send_adb_cuda((u_char *)output, (u_char *)0, - (void *)adb_op_comprout, (void *)&flag, (int)0); - if (result != 0) /* exit if not sent */ - return -1; - - while (0 == flag) /* wait for send to finish */ - ; - - return 0; - - case ADB_HW_UNKNOWN: - default: - return -1; - } -} - - -int -adb_poweroff(void) -{ - u_char output[ADB_MAX_MSG_LENGTH]; - int result; - - if (!adbSoftPower) - return -1; - - adb_polling = 1; - - switch (adbHardware) { - case ADB_HW_IISI: - output[0] = 0x02; /* 2 byte message */ - output[1] = 0x01; /* to pram/rtc/soft-power device */ - output[2] = 0x0a; /* set date/time */ - result = send_adb_IIsi((u_char *)output, (u_char *)0, - (void *)0, (void *)0, (int)0); - if (result != 0) /* exit if not sent */ - return -1; - - for (;;); /* wait for power off */ - - return 0; - - case ADB_HW_PB: - return -1; - - case ADB_HW_CUDA: - output[0] = 0x02; /* 2 byte message */ - output[1] = 0x01; /* to pram/rtc/soft-power device */ - output[2] = 0x0a; /* set date/time */ - result = send_adb_cuda((u_char *)output, (u_char *)0, - (void *)0, (void *)0, (int)0); - if (result != 0) /* exit if not sent */ - return -1; - - for (;;); /* wait for power off */ - - return 0; - - case ADB_HW_II: /* II models don't do ADB soft power */ - case ADB_HW_UNKNOWN: - default: - return -1; - } -} - -int -adb_prog_switch_enable(void) -{ - u_char output[ADB_MAX_MSG_LENGTH]; - int result; - volatile int flag = 0; - - switch (adbHardware) { - case ADB_HW_IISI: - output[0] = 0x03; /* 3 byte message */ - output[1] = 0x01; /* to pram/rtc/soft-power device */ - output[2] = 0x1c; /* prog. switch control */ - output[3] = 0x01; /* enable */ - result = send_adb_IIsi((u_char *)output, (u_char *)0, - (void *)adb_op_comprout, (void *)&flag, (int)0); - if (result != 0) /* exit if not sent */ - return -1; - - while (0 == flag) /* wait for send to finish */ - ; - - return 0; - - case ADB_HW_PB: - return -1; - - case ADB_HW_II: /* II models don't do prog. switch */ - case ADB_HW_CUDA: /* cuda doesn't do prog. switch TO DO: verify this */ - case ADB_HW_UNKNOWN: - default: - return -1; - } -} - -int -adb_prog_switch_disable(void) -{ - u_char output[ADB_MAX_MSG_LENGTH]; - int result; - volatile int flag = 0; - - switch (adbHardware) { - case ADB_HW_IISI: - output[0] = 0x03; /* 3 byte message */ - output[1] = 0x01; /* to pram/rtc/soft-power device */ - output[2] = 0x1c; /* prog. switch control */ - output[3] = 0x01; /* disable */ - result = send_adb_IIsi((u_char *)output, (u_char *)0, - (void *)adb_op_comprout, (void *)&flag, (int)0); - if (result != 0) /* exit if not sent */ - return -1; - - while (0 == flag) /* wait for send to finish */ - ; - - return 0; - - case ADB_HW_PB: - return -1; - - case ADB_HW_II: /* II models don't do prog. switch */ - case ADB_HW_CUDA: /* cuda doesn't do prog. switch */ - case ADB_HW_UNKNOWN: - default: - return -1; - } -} - -int -CountADBs(void) -{ - return (count_adbs()); -} - -void -ADBReInit(void) -{ - adb_reinit(); -} - -int -GetIndADB(ADBDataBlock *info, int index) -{ - return (get_ind_adb_info(info, index)); -} - -int -GetADBInfo(ADBDataBlock *info, int adbAddr) -{ - return (get_adb_info(info, adbAddr)); -} - -int -SetADBInfo(ADBSetInfoBlock *info, int adbAddr) -{ - return (set_adb_info(info, adbAddr)); -} - -int -ADBOp(Ptr buffer, Ptr compRout, Ptr data, short commandNum) -{ - return (adb_op(buffer, compRout, data, commandNum)); -} diff --git a/sys/arch/mac68k/dev/adbvar.h b/sys/arch/mac68k/dev/adbvar.h index 60a681be10a..fb41204d969 100644 --- a/sys/arch/mac68k/dev/adbvar.h +++ b/sys/arch/mac68k/dev/adbvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: adbvar.h,v 1.11 2006/01/13 19:36:43 miod Exp $ */ +/* $OpenBSD: adbvar.h,v 1.12 2006/01/18 23:21:16 miod Exp $ */ /* $NetBSD: adbvar.h,v 1.22 2005/01/15 16:00:59 chs Exp $ */ /* @@ -31,34 +31,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <machine/adbsys.h> - -/* - * Arguments used to attach a device to the Apple Desktop Bus - */ -struct adb_attach_args { - int origaddr; - int adbaddr; - int handler_id; -}; - -extern int adb_polling; - -#ifdef DEBUG -#ifndef ADB_DEBUG -#define ADB_DEBUG -#endif -#endif - -#ifdef ADB_DEBUG -extern int adb_debug; -#endif - -typedef caddr_t Ptr; - -/* adb.c */ -int adb_op_sync(Ptr, Ptr, Ptr, short); -void adb_op_comprout(caddr_t, caddr_t, int); +extern int adbHardware; /* types of adb hardware that we support */ #define ADB_HW_UNKNOWN 0x0 /* don't know */ @@ -68,31 +41,6 @@ void adb_op_comprout(caddr_t, caddr_t, int); #define ADB_HW_CUDA 0x4 /* Machines with a Cuda chip */ #define MAX_ADB_HW 4 /* Number of ADB hardware types */ -#define ADB_CMDADDR(cmd) ((u_int8_t)(cmd & 0xf0) >> 4) -#define ADBFLUSH(dev) ((((u_int8_t)dev & 0x0f) << 4) | 0x01) -#define ADBLISTEN(dev, reg) ((((u_int8_t)dev & 0x0f) << 4) | 0x08 | reg) -#define ADBTALK(dev, reg) ((((u_int8_t)dev & 0x0f) << 4) | 0x0c | reg) - -/* ADB Manager */ -typedef struct { - Ptr siServiceRtPtr; - Ptr siDataAreaAddr; -} ADBSetInfoBlock; - -typedef struct { - unsigned char devType; - unsigned char origADBAddr; - Ptr dbServiceRtPtr; - Ptr dbDataAreaAddr; -} ADBDataBlock; - -/* adb_direct.c */ int adb_poweroff(void); -int CountADBs(void); -void ADBReInit(void); -int GetIndADB(ADBDataBlock *, int); -int GetADBInfo(ADBDataBlock *, int); -int SetADBInfo(ADBSetInfoBlock *, int); -int ADBOp(Ptr, Ptr, Ptr, short); int adb_read_date_time(unsigned long *); int adb_set_date_time(unsigned long); diff --git a/sys/arch/mac68k/dev/akbd.c b/sys/arch/mac68k/dev/akbd.c deleted file mode 100644 index aa778e2fd06..00000000000 --- a/sys/arch/mac68k/dev/akbd.c +++ /dev/null @@ -1,550 +0,0 @@ -/* $OpenBSD: akbd.c,v 1.6 2006/01/13 19:36:43 miod Exp $ */ -/* $NetBSD: akbd.c,v 1.17 2005/01/15 16:00:59 chs Exp $ */ - -/* - * Copyright (C) 1998 Colin Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Colin Wood. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/param.h> -#include <sys/timeout.h> -#include <sys/kernel.h> -#include <sys/device.h> -#include <sys/fcntl.h> -#include <sys/poll.h> -#include <sys/selinfo.h> -#include <sys/proc.h> -#include <sys/signalvar.h> -#include <sys/systm.h> - -#include "wskbd.h" - -#include <dev/wscons/wsconsio.h> -#include <dev/wscons/wskbdvar.h> -#include <dev/wscons/wsksymdef.h> -#include <dev/wscons/wsksymvar.h> - -#include <machine/autoconf.h> -#include <machine/cpu.h> -#include <machine/viareg.h> - -#include <mac68k/dev/adbvar.h> -#include <mac68k/dev/akbdmap.h> -#include <mac68k/dev/akbdvar.h> - -#define KEYBOARD_ARRAY -#include <machine/keyboard.h> - -/* - * Function declarations. - */ -int akbdmatch(struct device *, void *, void *); -void akbdattach(struct device *, struct device *, void *); -void kbd_adbcomplete(caddr_t, caddr_t, int); -void kbd_processevent(adb_event_t *, struct akbd_softc *); -int akbd_is_console(void); - -/* Driver definition. */ -struct cfattach akbd_ca = { - sizeof(struct akbd_softc), akbdmatch, akbdattach -}; -struct cfdriver akbd_cd = { - NULL, "akbd", DV_DULL -}; - -int akbd_enable(void *, int); -void akbd_set_leds(void *, int); -int akbd_ioctl(void *, u_long, caddr_t, int, struct proc *); -int akbd_intr(adb_event_t *, struct akbd_softc *); -void akbd_rawrepeat(void *v); - - -struct wskbd_accessops akbd_accessops = { - akbd_enable, - akbd_set_leds, - akbd_ioctl, -}; - -struct wskbd_mapdata akbd_keymapdata = { - akbd_keydesctab, -#ifdef AKBD_LAYOUT - AKBD_LAYOUT, -#else - KB_US, -#endif -}; - -int -akbdmatch(struct device *parent, void *vcf, void *aux) -{ - struct adb_attach_args *aa_args = (struct adb_attach_args *)aux; - - if (aa_args->origaddr == ADBADDR_KBD) - return 1; - else - return 0; -} - -void -akbdattach(struct device *parent, struct device *self, void *aux) -{ - ADBSetInfoBlock adbinfo; - struct akbd_softc *sc = (struct akbd_softc *)self; - struct adb_attach_args *aa_args = (struct adb_attach_args *)aux; - int error, kbd_done; - short cmd; - u_char buffer[9]; -#if NWSKBD > 0 - struct wskbddev_attach_args a; - static int akbd_console_initted; - int wskbd_eligible; - - wskbd_eligible = 1; -#endif - - sc->origaddr = aa_args->origaddr; - sc->adbaddr = aa_args->adbaddr; - sc->handler_id = aa_args->handler_id; - - sc->sc_leds = (u_int8_t)0x00; /* initially off */ - - adbinfo.siServiceRtPtr = (Ptr)kbd_adbcomplete; - adbinfo.siDataAreaAddr = (caddr_t)sc; - - printf(": "); - switch (sc->handler_id) { - case ADB_STDKBD: - printf("standard keyboard\n"); - break; - case ADB_ISOKBD: - printf("standard keyboard (ISO layout)\n"); - break; - case ADB_EXTKBD: - cmd = ADBTALK(sc->adbaddr, 1); - kbd_done = - (adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd) == 0); - - /* Ignore Logitech MouseMan/Trackman pseudo keyboard */ - if (kbd_done && buffer[1] == 0x9a && buffer[2] == 0x20) { - printf("Mouseman (non-EMP) pseudo keyboard\n"); - adbinfo.siServiceRtPtr = (Ptr)0; - adbinfo.siDataAreaAddr = (Ptr)0; -#if NWSKBD > 0 - wskbd_eligible = 0; -#endif /* NWSKBD > 0 */ - } else if (kbd_done && buffer[1] == 0x9a && buffer[2] == 0x21) { - printf("Trackman (non-EMP) pseudo keyboard\n"); - adbinfo.siServiceRtPtr = (Ptr)0; - adbinfo.siDataAreaAddr = (Ptr)0; -#if NWSKBD > 0 - wskbd_eligible = 0; -#endif /* NWSKBD > 0 */ - } else { - printf("extended keyboard\n"); -#ifdef notyet - blinkleds(sc); -#endif - } - break; - case ADB_EXTISOKBD: - printf("extended keyboard (ISO layout)\n"); -#ifdef notyet - blinkleds(sc); -#endif - break; - case ADB_KBDII: - printf("keyboard II\n"); - break; - case ADB_ISOKBDII: - printf("keyboard II (ISO layout)\n"); - break; - case ADB_PBKBD: - printf("PowerBook keyboard\n"); - break; - case ADB_PBISOKBD: - printf("PowerBook keyboard (ISO layout)\n"); - break; - case ADB_ADJKPD: - printf("adjustable keypad\n"); -#if NWSKBD > 0 - wskbd_eligible = 0; -#endif /* NWSKBD > 0 */ - break; - case ADB_ADJKBD: - printf("adjustable keyboard\n"); - break; - case ADB_ADJISOKBD: - printf("adjustable keyboard (ISO layout)\n"); - break; - case ADB_ADJJAPKBD: - printf("adjustable keyboard (Japanese layout)\n"); - break; - case ADB_PBEXTISOKBD: - printf("PowerBook extended keyboard (ISO layout)\n"); - break; - case ADB_PBEXTJAPKBD: - printf("PowerBook extended keyboard (Japanese layout)\n"); - break; - case ADB_JPKBDII: - printf("keyboard II (Japanese layout)\n"); - break; - case ADB_PBEXTKBD: - printf("PowerBook extended keyboard\n"); - break; - case ADB_DESIGNKBD: - printf("extended keyboard\n"); -#ifdef notyet - blinkleds(sc); -#endif - break; - case ADB_PBJPKBD: - printf("PowerBook keyboard (Japanese layout)\n"); - break; - case ADB_PBG3JPKBD: - printf("PowerBook G3 keyboard (Japanese layout)\n"); - break; - case ADB_PBG4KBD: - printf("PowerBook G4 keyboard (Inverted T)\n"); - break; - case ADB_IBITISOKBD: - printf("iBook keyboard with inverted T (ISO layout)\n"); - break; - default: - printf("mapped device (%d)\n", sc->handler_id); -#if NWSKBD > 0 - wskbd_eligible = 0; -#endif /* NWSKBD > 0 */ - break; - } - error = SetADBInfo(&adbinfo, sc->adbaddr); -#ifdef ADB_DEBUG - if (adb_debug) - printf("akbd: returned %d from SetADBInfo\n", error); -#endif - -#ifdef WSDISPLAY_COMPAT_RAWKBD - timeout_set(&sc->sc_rawrepeat_ch, akbd_rawrepeat, sc); -#endif - -#if NWSKBD > 0 - if (akbd_is_console() && wskbd_eligible) - a.console = (++akbd_console_initted == 1); - else - a.console = 0; - a.keymap = &akbd_keymapdata; - a.accessops = &akbd_accessops; - a.accesscookie = sc; - - sc->sc_wskbddev = config_found(self, &a, wskbddevprint); -#endif -} - - -/* - * Handle putting the keyboard data received from the ADB into - * an ADB event record. - */ -void -kbd_adbcomplete(caddr_t buffer, caddr_t data_area, int adb_command) -{ - adb_event_t event; - struct akbd_softc *ksc; - int adbaddr; -#ifdef ADB_DEBUG - int i; - - if (adb_debug) - printf("adb: transaction completion\n"); -#endif - - adbaddr = ADB_CMDADDR(adb_command); - ksc = (struct akbd_softc *)data_area; - - event.addr = adbaddr; - event.hand_id = ksc->handler_id; - event.def_addr = ksc->origaddr; - event.byte_count = buffer[0]; - memcpy(event.bytes, buffer + 1, event.byte_count); - -#ifdef ADB_DEBUG - if (adb_debug) { - printf("akbd: from %d at %d (org %d) %d:", event.addr, - event.hand_id, event.def_addr, buffer[0]); - for (i = 1; i <= buffer[0]; i++) - printf(" %x", buffer[i]); - printf("\n"); - } -#endif - - microtime(&event.timestamp); - - kbd_processevent(&event, ksc); -} - -/* - * Given a keyboard ADB event, record the keycodes and call the key - * repeat handler, optionally passing the event through the mouse - * button emulation handler first. - */ -void -kbd_processevent(adb_event_t *event, struct akbd_softc *ksc) -{ - adb_event_t new_event; - - new_event = *event; - new_event.u.k.key = event->bytes[0]; - new_event.bytes[1] = 0xff; -#if NWSKBD > 0 - if (ksc->sc_wskbddev != NULL) /* wskbd is attached? */ - akbd_intr(&new_event, ksc); -#endif - if (event->bytes[1] != 0xff) { - new_event.u.k.key = event->bytes[1]; - new_event.bytes[0] = event->bytes[1]; - new_event.bytes[1] = 0xff; -#if NWSKBD > 0 - if (ksc->sc_wskbddev != NULL) /* wskbd is attached? */ - akbd_intr(&new_event, ksc); -#endif - } - -} - -int -akbd_enable(void *v, int on) -{ - return 0; -} - -void -akbd_set_leds(void *v, int on) -{ -} - -int -akbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) -{ -#ifdef WSDISPLAY_COMPAT_RAWKBD - struct akbd_softc *sc = v; -#endif - - switch (cmd) { - - case WSKBDIO_GTYPE: - *(int *)data = WSKBD_TYPE_ADB; - return 0; - case WSKBDIO_SETLEDS: - return 0; - case WSKBDIO_GETLEDS: - *(int *)data = 0; - return 0; -#ifdef WSDISPLAY_COMPAT_RAWKBD - case WSKBDIO_SETMODE: - sc->sc_rawkbd = *(int *)data == WSKBD_RAW; - timeout_del(&sc->sc_rawrepeat_ch); - return (0); -#endif - case WSKBDIO_BELL: - case WSKBDIO_COMPLEXBELL: -#define d ((struct wskbd_bell_data *)data) - mac68k_ring_bell(d->pitch, d->period * hz / 1000, d->volume); -#undef d - return (0); - - default: - return (-1); - } -} - -#ifdef WSDISPLAY_COMPAT_RAWKBD -void -akbd_rawrepeat(void *v) -{ - struct akbd_softc *sc = v; - int s; - - s = spltty(); - wskbd_rawinput(sc->sc_wskbddev, sc->sc_rep, sc->sc_nrep); - splx(s); - timeout_add(&sc->sc_rawrepeat_ch, hz * REP_DELAYN / 1000); -} -#endif - -int adb_polledkey; -int -akbd_intr(adb_event_t *event, struct akbd_softc *sc) -{ - int key, press, val; - int type; - static int shift; - - key = event->u.k.key; - - /* - * Caps lock is weird. The key sequence generated is: - * press: down(57) [57] (LED turns on) - * release: up(127) [255] - * press: up(127) [255] - * release: up(57) [185] (LED turns off) - */ - if (ADBK_KEYVAL(key) == ADBK_CAPSLOCK) - shift = 0; - - if (key == 255) { - if (shift == 0) { - key = ADBK_KEYUP(ADBK_CAPSLOCK); - shift = 1; - } else { - key = ADBK_KEYDOWN(ADBK_CAPSLOCK); - shift = 0; - } - } - - press = ADBK_PRESS(key); - val = ADBK_KEYVAL(key); - - type = press ? WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP; - - if (adb_polling) { - adb_polledkey = key; -#ifdef WSDISPLAY_COMPAT_RAWKBD - } else if (sc->sc_rawkbd) { - char cbuf[MAXKEYS *2]; - int c, j, s; - int npress; - - j = npress = 0; - - c = keyboard[val][3]; - if (c == 0) { - return 0; /* XXX */ - } - if (c & 0x80) - cbuf[j++] = 0xe0; - cbuf[j] = c & 0x7f; - if (type == WSCONS_EVENT_KEY_UP) { - cbuf[j] |= 0x80; - } else { - /* this only records last key pressed */ - if (c & 0x80) - sc->sc_rep[npress++] = 0xe0; - sc->sc_rep[npress++] = c & 0x7f; - } - j++; - s = spltty(); - wskbd_rawinput(sc->sc_wskbddev, cbuf, j); - splx(s); - timeout_del(&sc->sc_rawrepeat_ch); - sc->sc_nrep = npress; - if (npress != 0) - timeout_add(&sc->sc_rawrepeat_ch, hz * REP_DELAY1/1000); - return 0; -#endif - } else { - wskbd_input(sc->sc_wskbddev, type, val); - } - - return 0; -} - -int -akbd_is_console(void) -{ - extern struct mac68k_machine_S mac68k_machine; - - return ((mac68k_machine.serial_console & 0x03) == 0); -} - -void akbd_cnbell(void *, u_int, u_int, u_int); -void akbd_cngetc(void *, u_int *, int *); -void akbd_cnpollc(void *, int); - -struct wskbd_consops akbd_consops = { - akbd_cngetc, - akbd_cnpollc, - akbd_cnbell -}; - -int -akbd_cnattach(void) -{ - extern struct wskbd_mapdata akbd_keymapdata; - - wskbd_cnattach(&akbd_consops, NULL, &akbd_keymapdata); - - return 0; -} - -void -akbd_cngetc(void *v, u_int *type, int *data) -{ - int intbits, key, press, val; - int s; - extern int adb_polledkey; - extern int adb_intr(void *); - extern void pm_intr(void *); - - s = splhigh(); - - adb_polledkey = -1; - adb_polling = 1; - - while (adb_polledkey == -1) { - intbits = via_reg(VIA1, vIFR); - - if (intbits & V1IF_ADBRDY) { - adb_intr(NULL); - via_reg(VIA1, vIFR) = V1IF_ADBRDY; - } - if (intbits & 0x10) { - pm_intr(NULL); - via_reg(VIA1, vIFR) = 0x10; - } - } - - adb_polling = 0; - splx(s); - - key = adb_polledkey; - press = ADBK_PRESS(key); - val = ADBK_KEYVAL(key); - - *data = val; - *type = press ? WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP; -} - -void -akbd_cnpollc(void *v, int on) -{ -} - -void -akbd_cnbell(void *v, u_int pitch, u_int period, u_int volume) -{ - mac68k_ring_bell(pitch, period * hz / 1000, volume); -} diff --git a/sys/arch/mac68k/dev/akbd_machdep.c b/sys/arch/mac68k/dev/akbd_machdep.c new file mode 100644 index 00000000000..2d8e588bbc0 --- /dev/null +++ b/sys/arch/mac68k/dev/akbd_machdep.c @@ -0,0 +1,136 @@ +/* $OpenBSD: akbd_machdep.c,v 1.1 2006/01/18 23:21:17 miod Exp $ */ +/* $NetBSD: akbd.c,v 1.17 2005/01/15 16:00:59 chs Exp $ */ + +/* + * Copyright (C) 1998 Colin Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Colin Wood. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/timeout.h> +#include <sys/kernel.h> +#include <sys/device.h> +#include <sys/fcntl.h> +#include <sys/poll.h> +#include <sys/selinfo.h> +#include <sys/proc.h> +#include <sys/signalvar.h> +#include <sys/systm.h> + +#include <dev/wscons/wsconsio.h> +#include <dev/wscons/wskbdvar.h> + +#include <machine/cpu.h> +#include <machine/viareg.h> + +#include <dev/adb/adb.h> +#include <dev/adb/akbdvar.h> +#include <dev/adb/keyboard.h> + +#if 0 + case WSKBDIO_BELL: + case WSKBDIO_COMPLEXBELL: +#define d ((struct wskbd_bell_data *)data) + mac68k_ring_bell(d->pitch, d->period * hz / 1000, d->volume); +#undef d + return (0); + + default: + return (-1); +#endif + +void akbd_cnbell(void *, u_int, u_int, u_int); +void akbd_cngetc(void *, u_int *, int *); +void akbd_cnpollc(void *, int); + +struct wskbd_consops akbd_consops = { + akbd_cngetc, + akbd_cnpollc, + akbd_cnbell +}; + +int +akbd_is_console(void) +{ + return ((mac68k_machine.serial_console & 0x03) == 0); +} + +int +akbd_cnattach(void) +{ + wskbd_cnattach(&akbd_consops, NULL, &akbd_keymapdata); + return 0; +} + +void +akbd_cngetc(void *v, u_int *type, int *data) +{ + int intbits, key, press, val; + int s; + extern int adb_intr(void *); + extern void pm_intr(void *); + + s = splhigh(); + + adb_polledkey = -1; + adb_polling = 1; + + while (adb_polledkey == -1) { + intbits = via_reg(VIA1, vIFR); + + if (intbits & V1IF_ADBRDY) { + adb_intr(NULL); + via_reg(VIA1, vIFR) = V1IF_ADBRDY; + } + if (intbits & V1IF_ADBCLK) { + pm_intr(NULL); + via_reg(VIA1, vIFR) = 0x10; + } + } + + adb_polling = 0; + splx(s); + + key = adb_polledkey; + press = ADBK_PRESS(key); + val = ADBK_KEYVAL(key); + + *data = val; + *type = press ? WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP; +} + +void +akbd_cnpollc(void *v, int on) +{ +} + +void +akbd_cnbell(void *v, u_int pitch, u_int period, u_int volume) +{ + mac68k_ring_bell(pitch, period * hz / 1000, volume); +} diff --git a/sys/arch/mac68k/dev/akbdmap.h b/sys/arch/mac68k/dev/akbdmap.h deleted file mode 100644 index 8e0c01f0523..00000000000 --- a/sys/arch/mac68k/dev/akbdmap.h +++ /dev/null @@ -1,431 +0,0 @@ -/* $NetBSD: akbdmap.h,v 1.7 2005/05/05 22:29:41 abs Exp $ */ - -/*- - * Copyright (c) 1997 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Juergen Hannken-Illjes. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* XXX This list is incomplete. */ - -#define KC(n) KS_KEYCODE(n) - -static const keysym_t akbd_keydesc_us[] = { -/* pos command normal shifted */ - KC(0), KS_a, - KC(1), KS_s, - KC(2), KS_d, - KC(3), KS_f, - KC(4), KS_h, - KC(5), KS_g, - KC(6), KS_z, - KC(7), KS_x, - KC(8), KS_c, - KC(9), KS_v, - - KC(11), KS_b, - KC(12), KS_q, - KC(13), KS_w, - KC(14), KS_e, - KC(15), KS_r, - KC(16), KS_y, - KC(17), KS_t, - KC(18), KS_1, KS_exclam, - KC(19), KS_2, KS_at, - KC(20), KS_3, KS_numbersign, - KC(21), KS_4, KS_dollar, - KC(22), KS_6, KS_asciicircum, - KC(23), KS_5, KS_percent, - KC(24), KS_equal, KS_plus, - KC(25), KS_9, KS_parenleft, - KC(26), KS_7, KS_ampersand, - KC(27), KS_minus, KS_underscore, - KC(28), KS_8, KS_asterisk, - KC(29), KS_0, KS_parenright, - KC(30), KS_bracketright, KS_braceright, - KC(31), KS_o, - KC(32), KS_u, - KC(33), KS_bracketleft, KS_braceleft, - KC(34), KS_i, - KC(35), KS_p, - KC(36), KS_Return, - KC(37), KS_l, - KC(38), KS_j, - KC(39), KS_apostrophe, KS_quotedbl, - KC(40), KS_k, - KC(41), KS_semicolon, KS_colon, - KC(42), KS_backslash, KS_bar, - KC(43), KS_comma, KS_less, - KC(44), KS_slash, KS_question, - KC(45), KS_n, - KC(46), KS_m, - KC(47), KS_period, KS_greater, - KC(48), KS_Tab, - KC(49), KS_space, - KC(50), KS_grave, KS_asciitilde, - KC(51), KS_Delete, - KC(52), KS_KP_Enter, /* Pretend this is alt-R ? */ - KC(53), KS_Escape, - KC(54), KS_Control_L, - KC(55), KS_Cmd, /* Command */ - KC(56), KS_Shift_L, - KC(57), KS_Caps_Lock, - KC(58), KS_Cmd1, /* Option */ - KC(59), KS_Left, - KC(60), KS_Right, - KC(61), KS_Down, - KC(62), KS_Up, - - KC(65), KS_KP_Decimal, - KC(67), KS_KP_Multiply, - KC(69), KS_KP_Add, - KC(71), KS_Num_Lock, - KC(75), KS_KP_Divide, - KC(76), KS_KP_Enter, - KC(78), KS_KP_Subtract, - - KC(81), KS_KP_Equal, - KC(82), KS_KP_Insert, KS_KP_0, - KC(83), KS_KP_End, KS_KP_1, - KC(84), KS_KP_Down, KS_KP_2, - KC(85), KS_KP_Next, KS_KP_3, - KC(86), KS_KP_Left, KS_KP_4, - KC(87), KS_KP_Begin, KS_KP_5, - KC(88), KS_KP_Right, KS_KP_6, - KC(89), KS_KP_Home, KS_KP_7, - - KC(91), KS_KP_Up, KS_KP_8, - KC(92), KS_KP_Prior, KS_KP_9, - - KC(95), KS_KP_Delete, KS_KP_Decimal, - KC(96), KS_f5, - KC(97), KS_f6, - KC(98), KS_f7, - KC(99), KS_f3, - KC(100), KS_f8, - - KC(101), KS_f9, - - KC(103), KS_f11, - - KC(105), KS_Print_Screen, - KC(106), KS_KP_Enter, - KC(107), KS_Hold_Screen, - - KC(109), KS_f10, - - KC(111), KS_f12, - - KC(113), KS_Pause, - KC(114), KS_Insert, - KC(115), KS_Home, - KC(116), KS_Prior, - KC(117), KS_Delete, - KC(118), KS_f4, - KC(119), KS_End, - KC(120), KS_f2, - KC(121), KS_Next, - KC(122), KS_f1, - - KC(127), KS_Cmd_Debugger, -}; - -static const keysym_t akbd_keydesc_fr[] = { -/* pos normal shifted altgr shift-altgr */ - KC(0), KS_q, - KC(1), KS_s, KS_S, KS_Ograve, - KC(4), KS_h, KS_H, KS_Igrave, KS_Icircumflex, - KC(6), KS_w, KS_W, KS_less, KS_greater, - KC(8), KS_c, KS_C, KS_copyright, KS_cent, - KC(10), KS_at, KS_numbersign, - KC(11), KS_b, KS_B, KS_ssharp, - KC(12), KS_a, KS_A, KS_ae, KS_AE, - KC(13), KS_z, KS_Z, KS_Acircumflex, KS_Aring, - KC(14), KS_e, KS_E, KS_ecircumflex, KS_Ecircumflex, - KC(15), KS_r, KS_R, KS_registered, /* Euro */ - KC(16), KS_y, KS_Y, KS_Uacute, - KC(18), KS_ampersand, KS_1, KS_voidSymbol, KS_dead_acute, - KC(19), KS_eacute, KS_2, KS_ediaeresis, - KC(20), KS_quotedbl, KS_3, - KC(21), KS_apostrophe, KS_4, KS_braceleft, KS_bracketleft, - KC(22), KS_section, KS_6, KS_paragraph, - KC(23), KS_parenleft, KS_5, KS_braceleft, KS_bracketleft, - KC(24), KS_minus, KS_underscore, KS_braceright, - KC(25), KS_ccedilla, KS_9, KS_Ccedilla, KS_Agrave, - KC(26), KS_egrave, KS_7, KS_guillemotleft,KS_guillemotright, - KC(27), KS_parenright, KS_degree, KS_braceright, KS_bracketright, - KC(28), KS_exclam, KS_8, KS_exclamdown, KS_Ucircumflex, - KC(29), KS_agrave, KS_0, KS_oslash, - KC(30), KS_dollar, KS_asterisk, KS_comma, KS_yen, - KC(33), KS_dead_circumflex, KS_dead_diaeresis,KS_ocircumflex,KS_Ocircumflex, - KC(34), KS_i, KS_I, KS_icircumflex, KS_Icircumflex, - KC(37), KS_l, KS_L, KS_notsign, KS_bar, - KC(38), KS_j, KS_J, KS_Idiaeresis, KS_Igrave, - KC(39), KS_ugrave, KS_percent, KS_Ugrave, - KC(40), KS_k, KS_K, KS_Egrave, KS_Ediaeresis, - KC(41), KS_m, KS_M, KS_mu, KS_Ograve, - KC(42), KS_dead_grave, KS_sterling, KS_at, KS_numbersign, - KC(43), KS_semicolon, KS_period, - KC(44), KS_equal, KS_plus, KS_voidSymbol, KS_plusminus, - KC(45), KS_n, KS_N, KS_dead_tilde, - KC(46), KS_comma, KS_question, KS_voidSymbol, KS_questiondown, - KC(47), KS_colon, KS_slash, KS_division, KS_backslash, - KC(50), KS_less, KS_greater, - KC(52), KS_Alt_R, - KC(55), KS_Meta_L, /* Command */ - KC(58), KS_Mode_switch, KS_Multi_key, /* Option */ -}; - -static const keysym_t akbd_keydesc_fr_nodead[] = { - KC(18), KS_ampersand, KS_1, KS_voidSymbol, KS_acute, - KC(33), KS_asciicircum, KS_diaeresis, KS_ocircumflex, KS_Ocircumflex, - KC(42), KS_grave, KS_sterling, KS_at, KS_numbersign, - KC(45), KS_n, KS_N, KS_asciitilde, -}; - -static const keysym_t akbd_keydesc_jp[] = { -/* pos command normal shifted */ - KC(19), KS_2, KS_quotedbl, - KC(22), KS_6, KS_ampersand, - KC(24), KS_asciicircum, KS_asciitilde, - KC(25), KS_9, KS_parenright, - KC(26), KS_7, KS_apostrophe, - KC(27), KS_minus, KS_equal, - KC(28), KS_8, KS_parenleft, - KC(29), KS_0, - KC(30), KS_bracketleft, KS_braceleft, - KC(33), KS_at, KS_grave, - KC(39), KS_colon, KS_asterisk, - - KC(41), KS_semicolon, KS_plus, - KC(42), KS_bracketright,KS_braceright, - KC(93), KS_backslash, KS_bar, - KC(94), KS_underscore, -}; - -static const keysym_t akbd_keydesc_uk[] = { -/* pos normal shifted altgr shift-altgr */ - KC(10), KS_section, KS_plusminus, - KC(20), KS_3, KS_sterling, KS_numbersign, - KC(52), KS_KP_Enter, - KC(58), KS_Mode_switch, KS_Multi_key, /* Option */ -}; - -static const keysym_t akbd_keydesc_sv[] = { -/* pos normal shifted altgr shift-altgr */ - KC(10), KS_section, KS_degree, - KC(19), KS_2, KS_quotedbl, KS_at, - KC(21), KS_4, KS_dollar, - KC(22), KS_6, KS_ampersand, - KC(24), KS_dead_acute, KS_dead_grave, - KC(25), KS_9, KS_parenright, KS_bracketright, - KC(26), KS_7, KS_slash, KS_braceleft, - KC(27), KS_plus, KS_question, KS_backslash, - KC(28), KS_8, KS_parenleft, KS_bracketleft, - KC(29), KS_0, KS_equal, KS_braceright, - KC(30), KS_dead_diaeresis,KS_dead_circumflex,KS_dead_tilde, - KC(33), KS_aring, - KC(39), KS_adiaeresis, - KC(41), KS_odiaeresis, - KC(42), KS_apostrophe, KS_asterisk, - KC(43), KS_comma, KS_semicolon, - KC(44), KS_minus, KS_underscore, - KC(47), KS_period, KS_colon, - KC(50), KS_less, KS_greater, KS_bar, - KC(58), KS_Mode_switch,KS_Multi_key, -}; - -static const keysym_t akbd_keydesc_sv_nodead[] = { -/* pos normal shifted altgr shift-altgr */ - KC(24), KS_apostrophe, KS_grave, - KC(30), KS_diaeresis, KS_asciicircum, KS_asciitilde, -}; - -static const keysym_t akbd_keydesc_de[] = { -/* pos normal shifted altgr shift-altgr */ - KC(0), KS_a, KS_A, KS_aring, KS_Aring, - KC(1), KS_s, KS_S, KS_voidSymbol, KS_Iacute, - KC(3), KS_f, KS_F, KS_voidSymbol, KS_Idiaeresis, - KC(4), KS_h, KS_H, KS_ordfeminine, KS_Oacute, - KC(5), KS_g, KS_G, KS_copyright, KS_Igrave, - KC(6), KS_y, KS_Y, KS_yen, - KC(7), KS_x, KS_X, KS_voidSymbol, KS_Ugrave, - KC(8), KS_c, KS_C, KS_ccedilla, KS_Ccedilla, - KC(10), KS_dead_circumflex,KS_degree, - KC(12), KS_q, KS_Q, KS_guillemotleft,KS_guillemotright, - KC(15), KS_r, KS_R, KS_registered, KS_cedilla, - KC(16), KS_z, KS_Z, - KC(18), KS_1, KS_exclam, KS_exclamdown, KS_notsign, - KC(19), KS_2, KS_quotedbl, - KC(20), KS_3, KS_section, KS_paragraph, KS_numbersign, - KC(21), KS_4, KS_dollar, KS_cent, KS_sterling, - KC(22), KS_6, KS_ampersand, KS_bracketright,KS_dead_circumflex, - KC(23), KS_5, KS_percent, KS_bracketleft, - KC(24), KS_dead_acute, KS_dead_grave, KS_apostrophe, - KC(25), KS_9, KS_parenright, KS_braceright, KS_periodcentered, - KC(26), KS_7, KS_slash, KS_bar, KS_backslash, - KC(27), KS_ssharp, KS_question, KS_questiondown, - KC(28), KS_8, KS_parenleft, KS_braceleft, - KC(29), KS_0, KS_equal, KS_voidSymbol, KS_macron, - KC(30), KS_plus, KS_asterisk, KS_plusminus, - KC(31), KS_o, KS_O, KS_oslash, KS_Ooblique, - KC(32), KS_u, KS_U, KS_dead_diaeresis,KS_Aacute, - KC(33), KS_udiaeresis, KS_Udiaeresis, KS_voidSymbol, KS_degree, - KC(34), KS_i, KS_I, KS_voidSymbol, KS_Ucircumflex, - KC(37), KS_l, KS_L, KS_at, - KC(38), KS_j, KS_J, KS_masculine, - KC(39), KS_adiaeresis, KS_Adiaeresis, KS_ae, KS_AE, - KC(41), KS_odiaeresis, KS_Odiaeresis, - KC(42), KS_numbersign, KS_apostrophe, - KC(43), KS_comma, KS_semicolon, - KC(44), KS_minus, KS_underscore, - KC(45), KS_n, KS_N, KS_dead_tilde, - KC(46), KS_m, KS_M, KS_mu, - KC(47), KS_period, KS_colon, - KC(50), KS_less, KS_greater, - KC(52), KS_Multi_key, - KC(58), KS_Mode_switch, -}; - -static const keysym_t akbd_keydesc_de_nodead[] = { -/* pos normal shifted altgr shift-altgr */ - KC(10), KS_asciicircum, KS_degree, - KC(22), KS_6, KS_ampersand, KS_bracketright,KS_asciicircum, - KC(24), KS_acute, KS_grave, KS_apostrophe, - KC(32), KS_u, KS_U, KS_diaeresis, KS_Aacute, - KC(45), KS_n, KS_N, KS_asciitilde, -}; - -static const keysym_t akbd_keydesc_sf[] = { -/* pos normal shifted altgr shift-altgr */ - KC(6), KS_y, - KC(10), KS_paragraph, KS_degree, - KC(16), KS_z, - KC(18), KS_plus, KS_1, - KC(19), KS_quotedbl, KS_2, - KC(20), KS_asterisk, KS_3, - KC(21), KS_ccedilla, KS_4, KS_Ccedilla, - KC(22), KS_ampersand, KS_6, - KC(23), KS_percent, KS_5, - KC(24), KS_dead_circumflex,KS_grave, - KC(25), KS_parenright, KS_9, - KC(26), KS_slash, KS_7, - KC(27), KS_apostrophe, KS_question, - KC(28), KS_parenleft, KS_8, - KC(29), KS_equal, KS_0, - KC(30), KS_dead_diaeresis,KS_exclam, - KC(33), KS_egrave, KS_udiaeresis, - KC(39), KS_agrave, KS_adiaeresis, - KC(41), KS_eacute, KS_odiaeresis, - KC(42), KS_dollar, KS_sterling, - KC(43), KS_period, KS_colon, - KC(46), KS_comma, KS_semicolon, - KC(47), KS_minus, KS_underscore, - KC(50), KS_less, KS_greater, -}; - -static const keysym_t akbd_keydesc_es[] = { -/* pos normal shifted altgr shift-altgr */ - KC(10), KS_degree, KS_ordfeminine, KS_backslash, - KC(18), KS_1, KS_exclam, KS_bar, - KC(19), KS_2, KS_quotedbl, KS_at, - KC(20), KS_3, KS_periodcentered, KS_numbersign, - KC(21), KS_4, KS_dollar, KS_asciitilde, - KC(22), KS_6, KS_ampersand, KS_notsign, - KC(23), KS_5, KS_percent, - KC(24), KS_exclamdown, KS_questiondown, - KC(25), KS_9, KS_parenright, - KC(26), KS_7, KS_slash, - KC(27), KS_apostrophe, KS_question, - KC(28), KS_8, KS_parenleft, - KC(29), KS_0, KS_equal, - KC(30), KS_plus, KS_asterisk, KS_bracketright, - KC(33), KS_dead_grave, KS_dead_circumflex, KS_bracketleft, - KC(39), KS_dead_acute, KS_dead_diaeresis, KS_braceleft, - KC(41), KS_ntilde, - KC(42), KS_ccedilla, KS_Ccedilla, KS_braceright, - KC(43), KS_comma, KS_semicolon, - KC(44), KS_minus, KS_underscore, - KC(47), KS_period, KS_colon, - KC(50), KS_less, KS_greater, - KC(55), KS_Alt_L, /* Command */ - KC(58), KS_Mode_switch, KS_Multi_key, /* Option */ -}; - -static const keysym_t akbd_keydesc_pt[] = { -/* pos normal shifted altgr shift-altgr */ - KC(7), KS_x, KS_X, KS_guillemotleft, KS_guillemotright, - KC(10), KS_section, KS_plusminus, - KC(19), KS_2, KS_quotedbl, KS_at, - KC(20), KS_3, KS_numbersign, KS_sterling, - KC(22), KS_6, KS_ampersand, - KC(24), KS_plus, KS_asterisk, - KC(25), KS_9, KS_parenright, KS_bracketright, KS_braceright, - KC(26), KS_7, KS_slash, - KC(27), KS_apostrophe, KS_question, - KC(28), KS_8, KS_parenleft, KS_bracketleft, KS_braceleft, - KC(29), KS_0, KS_equal, - KC(30), KS_dead_acute, KS_dead_grave, - KC(33), KS_masculine, KS_ordfeminine, - KC(39), KS_dead_tilde, KS_dead_circumflex, - KC(41), KS_ccedilla, KS_Ccedilla, - KC(43), KS_comma, KS_semicolon, - KC(44), KS_minus, KS_underscore, - KC(47), KS_period, KS_colon, - KC(50), KS_less, KS_greater, - KC(58), KS_Mode_switch, - KC(81), KS_KP_Equal, -}; - -#define KBD_MAP(name, base, map) \ - { name, base, sizeof(map)/sizeof(keysym_t), map } - -static const struct wscons_keydesc akbd_keydesctab[] = { - KBD_MAP(KB_US, 0, akbd_keydesc_us), - KBD_MAP(KB_FR, KB_US, akbd_keydesc_fr), - KBD_MAP(KB_JP, KB_US, akbd_keydesc_jp), - KBD_MAP(KB_FR | KB_NODEAD, KB_FR, akbd_keydesc_fr_nodead), - KBD_MAP(KB_SF, KB_US, akbd_keydesc_sf), - KBD_MAP(KB_SV, KB_US, akbd_keydesc_sv), - KBD_MAP(KB_SV | KB_NODEAD, KB_SV, akbd_keydesc_sv_nodead), - KBD_MAP(KB_DE, KB_US, akbd_keydesc_de), - KBD_MAP(KB_DE | KB_NODEAD, KB_DE, akbd_keydesc_de_nodead), - KBD_MAP(KB_UK, KB_US, akbd_keydesc_uk), - KBD_MAP(KB_ES, KB_US, akbd_keydesc_es), - KBD_MAP(KB_PT, KB_US, akbd_keydesc_pt), - {0, 0, 0, 0} -}; - -#undef KBD_MAP -#undef KC - diff --git a/sys/arch/mac68k/dev/akbdvar.h b/sys/arch/mac68k/dev/akbdvar.h deleted file mode 100644 index 9688e8b421c..00000000000 --- a/sys/arch/mac68k/dev/akbdvar.h +++ /dev/null @@ -1,71 +0,0 @@ -/* $OpenBSD: akbdvar.h,v 1.1 2006/01/04 20:39:04 miod Exp $ */ -/* $NetBSD: akbdvar.h,v 1.4 1999/02/17 14:56:56 tsubai Exp $ */ - -/* - * Copyright (C) 1998 Colin Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Colin Wood. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _MAC68K_KBDVAR_H_ -#define _MAC68K_KBDVAR_H_ - -#include <machine/adbsys.h> - -/* - * State info, per keyboard instance. - */ -struct akbd_softc { - struct device sc_dev; - - /* ADB info */ - int origaddr; /* ADB device type (ADBADDR_KBD) */ - int adbaddr; /* current ADB address */ - int handler_id; /* type of keyboard */ - - u_int8_t sc_leds; /* current LED state */ - struct device *sc_wskbddev; -#ifdef WSDISPLAY_COMPAT_RAWKBD -#define MAXKEYS 20 -#define REP_DELAY1 400 -#define REP_DELAYN 100 - int sc_rawkbd; - int sc_nrep; - char sc_rep[MAXKEYS]; - struct timeout sc_rawrepeat_ch; -#endif /* defined(WSDISPLAY_COMPAT_RAWKBD) */ -}; - -/* LED register bits, inverse of actual register value */ -#define LED_NUMLOCK 0x1 -#define LED_CAPSLOCK 0x2 -#define LED_SCROLL_LOCK 0x4 - -void kbd_adbcomplete(caddr_t buffer, caddr_t data_area, int adb_command); -int akbd_cnattach(void); - -#endif /* _MAC68K_KBDVAR_H_ */ diff --git a/sys/arch/mac68k/dev/ams.c b/sys/arch/mac68k/dev/ams.c deleted file mode 100644 index a5f5e43bb0c..00000000000 --- a/sys/arch/mac68k/dev/ams.c +++ /dev/null @@ -1,534 +0,0 @@ -/* $OpenBSD: ams.c,v 1.4 2006/01/13 19:36:44 miod Exp $ */ -/* $NetBSD: ams.c,v 1.11 2000/12/19 03:13:40 tsubai Exp $ */ - -/* - * Copyright (C) 1998 Colin Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Colin Wood. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/param.h> -#include <sys/device.h> -#include <sys/fcntl.h> -#include <sys/poll.h> -#include <sys/selinfo.h> -#include <sys/proc.h> -#include <sys/signalvar.h> -#include <sys/systm.h> - -#include <machine/autoconf.h> - -#include <dev/wscons/wsconsio.h> -#include <dev/wscons/wsmousevar.h> - -#include <mac68k/dev/adbvar.h> -#include <mac68k/dev/amsvar.h> - -/* - * Function declarations. - */ -int amsmatch(struct device *, void *, void *); -void amsattach(struct device *, struct device *, void *); -void ems_init(struct ams_softc *); -void ms_processevent(adb_event_t *event, struct ams_softc *); - -/* Driver definition. */ -struct cfattach ams_ca = { - sizeof(struct ams_softc), amsmatch, amsattach -}; -/* Driver definition. */ -struct cfdriver ams_cd = { - NULL, "ams", DV_DULL -}; - - -int ams_enable(void *); -int ams_ioctl(void *, u_long, caddr_t, int, struct proc *); -void ams_disable(void *); - -const struct wsmouse_accessops ams_accessops = { - ams_enable, - ams_ioctl, - ams_disable, -}; - -int -amsmatch(struct device *parent, void *cf, void *aux) -{ - struct adb_attach_args *aa_args = aux; - - if (aa_args->origaddr == ADBADDR_MS) - return 1; - else - return 0; -} - -void -amsattach(struct device *parent, struct device *self, void *aux) -{ - ADBSetInfoBlock adbinfo; - struct ams_softc *sc = (struct ams_softc *)self; - struct adb_attach_args *aa_args = aux; - int error; - struct wsmousedev_attach_args a; - - sc->origaddr = aa_args->origaddr; - sc->adbaddr = aa_args->adbaddr; - sc->handler_id = aa_args->handler_id; - - sc->sc_class = MSCLASS_MOUSE; - sc->sc_buttons = 1; - sc->sc_res = 100; - sc->sc_devid[0] = 0; - sc->sc_devid[4] = 0; - - adbinfo.siServiceRtPtr = (Ptr)ms_adbcomplete; - adbinfo.siDataAreaAddr = (caddr_t)sc; - - ems_init(sc); - - /* print out the type of mouse we have */ - printf(": "); - switch (sc->handler_id) { - case ADBMS_200DPI: - sc->sc_res = 200; - /* FALLTHROUGH */ - case ADBMS_100DPI: - printf("%d-button, %d dpi mouse\n", sc->sc_buttons, - (int)(sc->sc_res)); - break; - case ADBMS_MSA3: - printf("Mouse Systems A3 mouse, %d-button, %d dpi\n", - sc->sc_buttons, (int)(sc->sc_res)); - break; - case ADBMS_USPEED: - printf("MicroSpeed mouse, default parameters\n"); - break; - case ADBMS_UCONTOUR: - printf("Contour mouse, default parameters\n"); - break; - case ADBMS_TURBO: - printf("Kensington Turbo Mouse\n"); - break; - case ADBMS_EXTENDED: - if (sc->sc_devid[0] == '\0') { - printf("Logitech "); - switch (sc->sc_class) { - case MSCLASS_MOUSE: - printf("MouseMan (non-EMP) mouse"); - break; - case MSCLASS_TRACKBALL: - printf("TrackMan (non-EMP) trackball"); - break; - default: - printf("non-EMP relative positioning device"); - break; - } - printf("\n"); - } else { - printf("EMP "); - switch (sc->sc_class) { - case MSCLASS_TABLET: - printf("tablet"); - break; - case MSCLASS_MOUSE: - printf("mouse"); - break; - case MSCLASS_TRACKBALL: - printf("trackball"); - break; - case MSCLASS_TRACKPAD: - printf("trackpad"); - break; - default: - printf("unknown device"); - break; - } - printf(" <%s> %d-button, %d dpi\n", sc->sc_devid, - sc->sc_buttons, (int)(sc->sc_res)); - } - break; - default: - printf("relative positioning device (mouse?) (%d)\n", - sc->handler_id); - break; - } - error = SetADBInfo(&adbinfo, sc->adbaddr); -#ifdef ADB_DEBUG - if (adb_debug) - printf("ams: returned %d from SetADBInfo\n", error); -#endif - - a.accessops = &ams_accessops; - a.accesscookie = sc; - sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint); -} - - -/* - * Initialize extended mouse support -- probes devices as described - * in Inside Macintosh: Devices, Chapter 5 "ADB Manager". - * - * Extended Mouse Protocol is documented in TechNote HW1: - * "ADB - The Untold Story: Space Aliens Ate My Mouse" - * - * Supports: Extended Mouse Protocol, MicroSpeed Mouse Deluxe, - * Mouse Systems A^3 Mouse, Logitech non-EMP MouseMan - */ -void -ems_init(struct ams_softc *sc) -{ - int adbaddr; - short cmd; - u_char buffer[9]; - - adbaddr = sc->adbaddr; - if (sc->origaddr != ADBADDR_MS) - return; - if (sc->handler_id == ADBMS_USPEED || - sc->handler_id == ADBMS_UCONTOUR) { - /* Found MicroSpeed Mouse Deluxe Mac or Contour Mouse */ - cmd = ADBLISTEN(adbaddr, 1); - - /* - * To setup the MicroSpeed or the Contour, it appears - * that we can send the following command to the mouse - * and then expect data back in the form: - * buffer[0] = 4 (bytes) - * buffer[1], buffer[2] as std. mouse - * buffer[3] = buffer[4] = 0xff when no buttons - * are down. When button N down, bit N is clear. - * buffer[4]'s locking mask enables a - * click to toggle the button down state--sort of - * like the "Easy Access" shift/control/etc. keys. - * buffer[3]'s alternative speed mask enables using - * different speed when the corr. button is down - */ - buffer[0] = 4; - buffer[1] = 0x00; /* Alternative speed */ - buffer[2] = 0x00; /* speed = maximum */ - buffer[3] = 0x10; /* enable extended protocol, - * lower bits = alt. speed mask - * = 0000b - */ - buffer[4] = 0x07; /* Locking mask = 0000b, - * enable buttons = 0111b - */ - adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd); - - sc->sc_buttons = 3; - sc->sc_res = 200; - return; - } - if (sc->handler_id == ADBMS_TURBO) { - /* Found Kensington Turbo Mouse */ - static u_char data1[] = - { 8, 0xe7, 0x8c, 0, 0, 0, 0xff, 0xff, 0x94 }; - static u_char data2[] = - { 8, 0xa5, 0x14, 0, 0, 0x69, 0xff, 0xff, 0x27 }; - - buffer[0] = 0; - adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, ADBFLUSH(adbaddr)); - - adb_op_sync((Ptr)data1, (Ptr)0, (Ptr)0, ADBLISTEN(adbaddr, 2)); - - buffer[0] = 0; - adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, ADBFLUSH(adbaddr)); - - adb_op_sync((Ptr)data2, (Ptr)0, (Ptr)0, ADBLISTEN(adbaddr, 2)); - return; - } - if ((sc->handler_id == ADBMS_100DPI) || - (sc->handler_id == ADBMS_200DPI)) { - /* found a mouse */ - cmd = ADBTALK(adbaddr, 3); - if (adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd)) { -#ifdef ADB_DEBUG - if (adb_debug) - printf("adb: ems_init timed out\n"); -#endif - return; - } - - /* Attempt to initialize Extended Mouse Protocol */ - buffer[2] = 4; /* make handler ID 4 */ - cmd = ADBLISTEN(adbaddr, 3); - if (adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd)) { -#ifdef ADB_DEBUG - if (adb_debug) - printf("adb: ems_init timed out\n"); -#endif - return; - } - - /* - * Check to see if successful, if not - * try to initialize it as other types - */ - cmd = ADBTALK(adbaddr, 3); - if (adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd) == 0 && - buffer[2] == ADBMS_EXTENDED) { - sc->handler_id = ADBMS_EXTENDED; - cmd = ADBTALK(adbaddr, 1); - if (adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd)) { -#ifdef ADB_DEBUG - if (adb_debug) - printf("adb: ems_init timed out\n"); -#endif - } else if (buffer[0] == 8) { - /* we have a true EMP device */ - sc->sc_class = buffer[7]; - sc->sc_buttons = buffer[8]; - sc->sc_res = (int)*(short *)&buffer[5]; - bcopy(&(buffer[1]), sc->sc_devid, 4); - } else if (buffer[1] == 0x9a && - ((buffer[2] == 0x20) || (buffer[2] == 0x21))) { - /* - * Set up non-EMP Mouseman/Trackman to put - * button bits in 3rd byte instead of sending - * via pseudo keyboard device. - */ - cmd = ADBLISTEN(adbaddr, 1); - buffer[0]=2; - buffer[1]=0x00; - buffer[2]=0x81; - adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd); - - cmd = ADBLISTEN(adbaddr, 1); - buffer[0]=2; - buffer[1]=0x01; - buffer[2]=0x81; - adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd); - - cmd = ADBLISTEN(adbaddr, 1); - buffer[0]=2; - buffer[1]=0x02; - buffer[2]=0x81; - adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd); - - cmd = ADBLISTEN(adbaddr, 1); - buffer[0]=2; - buffer[1]=0x03; - buffer[2]=0x38; - adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd); - - sc->sc_buttons = 3; - sc->sc_res = 400; - if (buffer[2] == 0x21) - sc->sc_class = MSCLASS_TRACKBALL; - else - sc->sc_class = MSCLASS_MOUSE; - } else - /* unknown device? */; - } else { - /* Attempt to initialize as an A3 mouse */ - buffer[2] = 0x03; /* make handler ID 3 */ - cmd = ADBLISTEN(adbaddr, 3); - if (adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd)) { -#ifdef ADB_DEBUG - if (adb_debug) - printf("adb: ems_init timed out\n"); -#endif - return; - } - - /* - * Check to see if successful, if not - * try to initialize it as other types - */ - cmd = ADBTALK(adbaddr, 3); - if (adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd) == 0 - && buffer[2] == ADBMS_MSA3) { - sc->handler_id = ADBMS_MSA3; - /* Initialize as above */ - cmd = ADBLISTEN(adbaddr, 2); - /* listen 2 */ - buffer[0] = 3; - buffer[1] = 0x00; - /* Irrelevant, buffer has 0x77 */ - buffer[2] = 0x07; - /* - * enable 3 button mode = 0111b, - * speed = normal - */ - adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd); - sc->sc_buttons = 3; - sc->sc_res = 300; - } else { - /* No special support for this mouse */ - } - } - } -} - -/* - * Handle putting the mouse data received from the ADB into - * an ADB event record. - */ -void -ms_adbcomplete(caddr_t buffer, caddr_t data_area, int adb_command) -{ - adb_event_t event; - struct ams_softc *sc; - int adbaddr; -#ifdef ADB_DEBUG - int i; - - if (adb_debug) - printf("adb: transaction completion\n"); -#endif - - adbaddr = ADB_CMDADDR(adb_command); - sc = (struct ams_softc *)data_area; - - if ((sc->handler_id == ADBMS_EXTENDED) && (sc->sc_devid[0] == 0)) { - /* massage the data to look like EMP data */ - if ((buffer[3] & 0x04) == 0x04) - buffer[1] &= 0x7f; - else - buffer[1] |= 0x80; - if ((buffer[3] & 0x02) == 0x02) - buffer[2] &= 0x7f; - else - buffer[2] |= 0x80; - if ((buffer[3] & 0x01) == 0x01) - buffer[3] = 0x00; - else - buffer[3] = 0x80; - } - - event.addr = adbaddr; - event.hand_id = sc->handler_id; - event.def_addr = sc->origaddr; - event.byte_count = buffer[0]; - memcpy(event.bytes, buffer + 1, event.byte_count); - -#ifdef ADB_DEBUG - if (adb_debug) { - printf("ams: from %d at %d (org %d) %d:", event.addr, - event.hand_id, event.def_addr, buffer[0]); - for (i = 1; i <= buffer[0]; i++) - printf(" %x", buffer[i]); - printf("\n"); - } -#endif - - microtime(&event.timestamp); - - ms_processevent(&event, sc); -} - -/* - * Given a mouse ADB event, record the button settings, calculate the - * x- and y-axis motion, and handoff the event to the appropriate subsystem. - */ -void -ms_processevent(adb_event_t *event, struct ams_softc *sc) -{ - adb_event_t new_event; - int i, button_bit, max_byte, mask, buttons; - - new_event = *event; - buttons = 0; - - /* - * This should handle both plain ol' Apple mice and mice - * that claim to support the Extended Apple Mouse Protocol. - */ - max_byte = event->byte_count; - button_bit = 1; - switch (event->hand_id) { - case ADBMS_USPEED: - case ADBMS_UCONTOUR: - /* MicroSpeed mouse and Contour mouse */ - if (max_byte == 4) - buttons = (~event->bytes[2]) & 0xff; - else - buttons = (event->bytes[0] & 0x80) ? 0 : 1; - break; - case ADBMS_MSA3: - /* Mouse Systems A3 mouse */ - if (max_byte == 3) - buttons = (~event->bytes[2]) & 0x07; - else - buttons = (event->bytes[0] & 0x80) ? 0 : 1; - break; - default: - /* Classic Mouse Protocol (up to 2 buttons) */ - for (i = 0; i < 2; i++, button_bit <<= 1) - /* 0 when button down */ - if (!(event->bytes[i] & 0x80)) - buttons |= button_bit; - else - buttons &= ~button_bit; - /* Extended Protocol (up to 6 more buttons) */ - for (mask = 0x80; i < max_byte; - i += (mask == 0x80), button_bit <<= 1) { - /* 0 when button down */ - if (!(event->bytes[i] & mask)) - buttons |= button_bit; - else - buttons &= ~button_bit; - mask = ((mask >> 4) & 0xf) - | ((mask & 0xf) << 4); - } - break; - } - new_event.u.m.buttons = sc->sc_mb | buttons; - new_event.u.m.dx = ((signed int) (event->bytes[1] & 0x3f)) - - ((event->bytes[1] & 0x40) ? 64 : 0); - new_event.u.m.dy = ((signed int) (event->bytes[0] & 0x3f)) - - ((event->bytes[0] & 0x40) ? 64 : 0); - - if (sc->sc_wsmousedev) - wsmouse_input(sc->sc_wsmousedev, new_event.u.m.buttons, - new_event.u.m.dx, -new_event.u.m.dy, 0, - WSMOUSE_INPUT_DELTA); -} - -int -ams_enable(void *v) -{ - return 0; -} - -int -ams_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) -{ - switch (cmd) { - case WSMOUSEIO_GTYPE: - *(u_int *)data = WSMOUSE_TYPE_ADB; - return (0); - } - - return -1; -} - -void -ams_disable(void *v) -{ -} diff --git a/sys/arch/mac68k/dev/amsvar.h b/sys/arch/mac68k/dev/amsvar.h deleted file mode 100644 index a4d7960cbd6..00000000000 --- a/sys/arch/mac68k/dev/amsvar.h +++ /dev/null @@ -1,67 +0,0 @@ -/* $OpenBSD: amsvar.h,v 1.1 2006/01/04 20:39:04 miod Exp $ */ -/* $NetBSD: amsvar.h,v 1.4 1999/06/17 06:59:05 tsubai Exp $ */ - -/* - * Copyright (C) 1998 Colin Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Colin Wood. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _MAC68K_AMSVAR_H_ -#define _MAC68K_AMSVAR_H_ - -/* - * State info, per mouse instance. - */ -struct ams_softc { - struct device sc_dev; - - /* ADB info */ - int origaddr; /* ADB device type (ADBADDR_MS) */ - int adbaddr; /* current ADB address */ - int handler_id; /* type of mouse */ - - /* Extended Mouse Protocol info, faked for non-EMP mice */ - u_int8_t sc_class; /* mouse class (mouse, trackball) */ - u_int8_t sc_buttons; /* number of buttons */ - u_int32_t sc_res; /* mouse resolution (dpi) */ - char sc_devid[5]; /* device indentifier */ - - int sc_mb; /* current button state */ - struct device *sc_wsmousedev; -}; - -/* EMP device classes */ -#define MSCLASS_TABLET 0 -#define MSCLASS_MOUSE 1 -#define MSCLASS_TRACKBALL 2 -#define MSCLASS_TRACKPAD 3 - -void ms_adbcomplete(caddr_t buffer, caddr_t data_area, int adb_command); -void ms_handoff(adb_event_t *event, struct ams_softc *); - -#endif /* _MAC68K_AMSVAR_H_ */ diff --git a/sys/arch/mac68k/dev/pm_direct.c b/sys/arch/mac68k/dev/pm_direct.c index 752200cf96a..84357747750 100644 --- a/sys/arch/mac68k/dev/pm_direct.c +++ b/sys/arch/mac68k/dev/pm_direct.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pm_direct.c,v 1.10 2006/01/13 19:36:44 miod Exp $ */ +/* $OpenBSD: pm_direct.c,v 1.11 2006/01/18 23:21:17 miod Exp $ */ /* $NetBSD: pm_direct.c,v 1.25 2005/10/28 21:54:52 christos Exp $ */ /* @@ -46,6 +46,7 @@ #include <machine/cpu.h> #include <machine/viareg.h> +#include <dev/adb/adb.h> #include <mac68k/dev/adbvar.h> #include <mac68k/dev/pm_direct.h> |