The following diff is a partial rewrite of the actual adb(4) driver. It
only applies to CUDA-based machines:

$ dmesg |grep via-cuda && echo "Test this diff"

I tried to separate as much as possible the code responsible for the
CUDA chip, more or less like it is done for the PMU. It's a first step
toward creating two different drivers for the two kinds of chips present
in the macppc world, and a common adb interface.

This diff includes:
 - A better initialization sequence based on the xnu & linux drivers.
 - A simpler state machine which doesn't need a timer and shouldn't
   generate collision.

I haven't seen any problem so far with my iMac G3 but I'm very
interested in some more tests especially if you have a machine with an
adb keyboard & mouse.

Comments?

Martin


Index: conf/files.macppc
===================================================================
RCS file: /cvs/src/sys/arch/macppc/conf/files.macppc,v
retrieving revision 1.64
diff -u -p -r1.64 files.macppc
--- conf/files.macppc   25 May 2011 07:42:15 -0000      1.64
+++ conf/files.macppc   22 Jun 2011 13:18:37 -0000
@@ -153,6 +153,7 @@ file        arch/macppc/dev/z8530tty.c                      
zstty 
 device adb {}
 attach adb at macobio
 file   arch/macppc/dev/adb.c                           adb needs-flag
+file   arch/macppc/dev/cuda.c                          adb
 file   arch/macppc/dev/pm_direct.c                     adb
 
 include        "dev/adb/files.adb"
Index: dev/adb.c
===================================================================
RCS file: /cvs/src/sys/arch/macppc/dev/adb.c,v
retrieving revision 1.34
diff -u -p -r1.34 adb.c
--- dev/adb.c   16 Jun 2011 10:51:48 -0000      1.34
+++ dev/adb.c   22 Jun 2011 13:18:37 -0000
@@ -80,13 +80,6 @@
  *  - (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>
@@ -105,6 +98,7 @@
 
 #include <dev/adb/adb.h>
 #include <macppc/dev/adbvar.h>
+#include <macppc/dev/cuda.h>
 #include <macppc/dev/pm_direct.h>
 #include <macppc/dev/viareg.h>
 
@@ -123,56 +117,7 @@ int        adb_polling;            /* Are we polling?  (D
 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 performing */
-#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 */
-
-/*
- * 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_CUDA()   via_reg_or(VIA1, vBufB, (vPB4 | vPB5))
-#define ADB_SET_STATE_TIP()        via_reg_and(VIA1, vBufB, ~vPB5)
-#define ADB_CLR_STATE_TIP()        via_reg_or(VIA1, vBufB, vPB5)
-#define ADB_TOGGLE_STATE_ACK_CUDA() via_reg_xor(VIA1, vBufB, vPB4)
-#define ADB_SET_STATE_ACKOFF_CUDA() via_reg_or(VIA1, vBufB, vPB4)
-#define ADB_SET_SR_INPUT()         via_reg_and(VIA1, vACR, ~vSR_OUT)
-#define ADB_SET_SR_OUTPUT()        via_reg_or(VIA1, vACR, vSR_OUT)
-#define ADB_SR()                   read_via_reg(VIA1, vSR)
-#define ADB_VIA_INTR_ENABLE()      write_via_reg(VIA1, vIER, 0x84)
-#define ADB_VIA_INTR_DISABLE()     write_via_reg(VIA1, vIER, 0x04)
-#define ADB_VIA_CLR_INTR()         write_via_reg(VIA1, vIFR, 0x04)
-#define ADB_INTR_IS_OFF                   (vPB3 == (read_via_reg(VIA1, vBufB) 
& vPB3))
-#define ADB_INTR_IS_ON            (0 == (read_via_reg(VIA1, vBufB) & vPB3))
-#define ADB_SR_INTR_IS_ON         (vSR_INT == (read_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.
@@ -186,27 +131,10 @@ struct ADBDevEntry {
 };
 
 /*
- * Eventually used for two separate queues, the queue between
- * the upper and lower halves, and the outgoing packet queue.
- */
-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 */
-};
-
-/*
  * A few variables that we need and their initial values.
  */
 int    adbHardware = ADB_HW_UNKNOWN;
-int    adbActionState = ADB_ACTION_NOTREADY;
 int    adbWaiting;             /* waiting for return data from the device */
-int    adbWriteDelay;          /* working on (or waiting to do) a write */
 
 int    adbWaitingCmd;          /* ADB command we are waiting for */
 u_char *adbBuffer;             /* pointer to user data area */
@@ -214,11 +142,6 @@ void       *adbCompRout;           /* pointer to the co
 void   *adbCompData;           /* pointer to the completion routine data */
 int    adbStarting = 1;        /* doing adb_reinit so do polling differently */
 
-u_char adbInputBuffer[ADB_MAX_MSG_LENGTH];     /* data input buffer */
-u_char adbOutputBuffer[ADB_MAX_MSG_LENGTH];    /* data output buffer */
-
-int    adbSentChars;           /* how many characters we have sent */
-
 struct ADBDevEntry ADBDevTable[16];    /* our ADB device table */
 int    ADBNumDevices;          /* num. of ADB devices found with adb_reinit */
 
@@ -227,10 +150,6 @@ int        adbInCount;                     /* how many 
packets in
 int    adbInHead;                      /* head of in queue */
 int    adbInTail;                      /* tail of in queue */
 
-int    tickle_count;                   /* how many tickles seen for this 
packet? */
-int    tickle_serial;                  /* the last packet tickled */
-int    adb_cuda_serial;                /* the current packet */
-struct timeout adb_cuda_timeout;
 struct timeout adb_softintr_timeout;
 int    adbempty;                       /* nonzero if no adb devices */
 
@@ -242,24 +161,15 @@ volatile u_char *Via1Base;
 #ifdef ADB_DEBUG
 void   print_single(u_char *);
 #endif
-void   adb_intr_cuda(void);
-void   adb_soft_intr(void);
-int    send_adb_cuda(u_char *, u_char *, void *, void *, int);
-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    adb_op(Ptr, Ptr, Ptr, short);
 void   adb_hw_setup(void);
-int    adb_cmd_result(u_char *);
 void   setsoftadb(void);
 
 int    adb_intr(void *arg);
-void   adb_cuda_autopoll(void);
-void   adb_cuda_fileserver_mode(void);
 
 #ifdef ADB_DEBUG
 /*
@@ -293,348 +203,6 @@ print_single(str)
 }
 #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?
- */
-void
-adb_intr_cuda(void)
-{
-       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 = NULL;
-                               adbCompRout = NULL;
-                               adbCompData = NULL;
-                       } 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();
-                               write_via_reg(VIA1, vSR, 
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 = NULL;
-                               adbCompRout = NULL;
-                               adbCompData = NULL;
-                       }
-
-                       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 {
-                       write_via_reg(VIA1, vSR, 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
-       }
-
-       ADB_VIA_INTR_ENABLE();  /* enable ADB interrupt on IIs. */
-
-       splx(s);                /* restore */
-}
-
-
-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? */
-               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 */
-               write_via_reg(VIA1, vSR, 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 ((s & (1 << 18)) || adb_polling) /* XXX 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();        /* process it */
-                               if (cold)
-                                       delay(ADB_DELAY);
-                               adb_soft_intr();
-                       }
-
-       return 0;
-}
-
 /*
  * Called when when an adb interrupt happens.
  * This routine simply transfers control over to the appropriate
@@ -649,7 +217,7 @@ adb_intr(void *arg)
                break;
 
        case ADB_HW_CUDA:
-               adb_intr_cuda();
+               cuda_intr();
                break;
        }
        return 1;
@@ -797,8 +365,6 @@ adb_soft_intr(void)
        u_char *comprout;
        u_char *compdata;
 
-/*delay(2*ADB_DELAY);*/
-
        while (adbInCount) {
 #ifdef ADB_DEBUG
                if (adb_debug & 0x80)
@@ -868,7 +434,8 @@ adb_soft_intr(void)
 int
 adb_op(Ptr buffer, Ptr compRout, Ptr data, short command)
 {
-       int result;
+       int result, len = 0;
+
 
        switch (adbHardware) {
        case ADB_HW_PMU:
@@ -882,13 +449,32 @@ adb_op(Ptr buffer, Ptr compRout, Ptr dat
                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;
+
+               if (buffer != NULL) {
+                       /* copy addl data ONLY if doing a listen! */
+                       if ((command & 0x0c) == 0x08) {
+                               len = buffer[0];
+
+                               /* 
+                                * XXX - Craft a real ADB packet,
+                                * The ADB code should be updated to *always*
+                                * pass a real packet to the CUDA and PMU send
+                                * methods.
+                                */
+                               memcpy(buffer + 2, buffer + 1, len);
+                       }
+
+                       buffer[1] = (uint8_t)command;
+
+                       result = cuda_send(buffer, len + 2, compRout, data);
+               } else {
+                       uint8_t msg[] = { 0x00, 0x00 };
+
+                       msg[1] = (uint8_t)command; 
+                       result = cuda_send(msg, 2, compRout, data);
+               }
+
+               return (result);
 
        default:
                return -1;
@@ -904,8 +490,6 @@ adb_op(Ptr buffer, Ptr compRout, Ptr dat
 void
 adb_hw_setup(void)
 {
-       volatile int i;
-
        switch (adbHardware) {
 
        case ADB_HW_PMU:
@@ -917,32 +501,7 @@ adb_hw_setup(void)
                break;
 
        case ADB_HW_CUDA:
-               via_reg_or(VIA1, vDirB, 0x30);  /* register B bits 4 and 5:
-                                                * outputs */
-               via_reg_and(VIA1, vDirB, 0xf7); /* register B bit 3: input */
-               via_reg_and(VIA1, vACR, ~vSR_OUT);      /* make sure SR is set
-                                                        * to IN */
-               write_via_reg(VIA1, vACR, (read_via_reg(VIA1, vACR) | 0x0c) & 
~0x10);
-               adbActionState = ADB_ACTION_IDLE;       /* used by all types of
-                                                        * hardware */
-               write_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 */
+               cuda_init();
                break;
 
        case ADB_HW_UNKNOWN:
@@ -1178,48 +737,12 @@ adb_reinit(void)
                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);
-       }
-
        if (adbHardware != ADB_HW_PMU)  /* ints must be on for PB? */
                splx(s);
 }
 
 
 /*
- * 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_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_PMU:
-               return 1;
-
-       default:
-               return 1;
-       }
-}
-
-
-/*
  * adb_op_sync
  *
  * This routine does exactly what the adb_op routine does, except that after
@@ -1359,34 +882,15 @@ set_adb_info(ADBSetInfoBlock * info, int
 int
 adb_read_date_time(time_t *time)
 {
-       u_char output[ADB_MAX_MSG_LENGTH];
-       int result;
-       int retcode;
-       volatile int flag = 0;
+       int retcode = 0;
 
        switch (adbHardware) {
        case ADB_HW_PMU:
                pm_read_date_time(time);
-               retcode = 0;
                break;
 
        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 */
-                       retcode = -1;
-                       break;
-               }
-
-               while (0 == flag)       /* wait for result */
-                       ;
-
-               delay(20); /* completion occurs too soon? */
-               memcpy(time, output + 1, 4);
-               retcode = 0;
+               retcode = cuda_time_read(time);
                break;
 
        case ADB_HW_UNKNOWN:
@@ -1401,38 +905,18 @@ adb_read_date_time(time_t *time)
        } else {
                *time = 0;
        }
+
        return retcode;
 }
 
-/* caller should really use machine-independent version: setPramTime */
-/* this version does pseudo-adb access only */
 int
 adb_set_date_time(time_t time)
 {
-       u_char output[ADB_MAX_MSG_LENGTH];
-       int result;
-       volatile int flag = 0;
-
        time += DIFF19041970;
        switch (adbHardware) {
 
        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;
+               return cuda_time_write(time);
 
        case ADB_HW_PMU:
                pm_set_date_time(time);
@@ -1443,13 +927,9 @@ adb_set_date_time(time_t time)
        }
 }
 
-
 int
 adb_poweroff(void)
 {
-       u_char output[ADB_MAX_MSG_LENGTH];
-       int result;
-
        adb_polling = 1;
 
        switch (adbHardware) {
@@ -1458,20 +938,13 @@ adb_poweroff(void)
                pmu_fileserver_mode(0);
                pm_adb_poweroff();
 
-               for (;;);               /* wait for power off */
+               for (;;)
+                       ;               /* wait for power off */
 
                return 0;
 
        case ADB_HW_CUDA:
-               output[0] = 0x02;       /* 2 byte message */
-               output[1] = 0x01;       /* to pram/rtc/soft-power device */
-               output[2] = 0x0a;       /* set poweroff */
-               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 */
+               cuda_poweroff();
 
                return 0;
 
@@ -1489,63 +962,15 @@ setsoftadb()
 }
 
 void
-adb_cuda_autopoll()
-{
-       volatile int flag = 0;
-       int result;
-       u_char output[16];
-
-       output[0] = 0x03;       /* 3-byte message */
-       output[1] = 0x01;       /* to pram/rtc/soft-power device */
-       output[2] = 0x01;       /* cuda autopoll */
-       output[3] = 0x01;
-       result = send_adb_cuda(output, output, adb_op_comprout,
-           (void *)&flag, 0);
-       if (result != 0)        /* exit if not sent */
-               return;
-
-       while (flag == 0);      /* wait for result */
-}
-
-void
-adb_cuda_fileserver_mode()
-{
-       volatile int flag = 0;
-       int result;
-       u_char output[16];
-
-       output[0] = 0x03;       /* 3-byte message */
-       output[1] = 0x01;       /* to pram/rtc device/soft-power device */
-       output[2] = 0x13;       /* cuda file server mode */
-       output[3] = 0x01;       /* True - Turn on after AC loss */
-
-       result = send_adb_cuda(output, output, adb_op_comprout,
-           (void *)&flag, 0);
-       if (result != 0)
-               return;
-
-       while (flag == 0);
-}
-
-void
 adb_restart()
 {
-       int result;
-       u_char output[16];
-
        adb_polling = 1;
 
        switch (adbHardware) {
        case ADB_HW_CUDA:
-               output[0] = 0x02;       /* 2 byte message */
-               output[1] = 0x01;       /* to pram/rtc/soft-power device */
-               output[2] = 0x11;       /* restart */
-               result = send_adb_cuda((u_char *)output, (u_char *)0,
-                                      (void *)0, (void *)0, (int)0);
-               if (result != 0)        /* exit if not sent */
-                       return;
-               while (1);              /* not return */
+               cuda_restart();
 
+               /* NOTREACHED */
        case ADB_HW_PMU:
                pm_adb_restart();
                while (1);              /* not return */
@@ -1676,11 +1101,11 @@ adbattach(struct device *parent, struct 
        }
 
        if (adbHardware == ADB_HW_CUDA)
-               adb_cuda_fileserver_mode();
+               cuda_fileserver_mode();
        if (adbHardware == ADB_HW_PMU)
                pmu_fileserver_mode(1);
 
        if (adbHardware == ADB_HW_CUDA)
-               adb_cuda_autopoll();
+               cuda_autopoll();
        adb_polling = 0;
 }
Index: dev/adbvar.h
===================================================================
RCS file: /cvs/src/sys/arch/macppc/dev/adbvar.h,v
retrieving revision 1.8
diff -u -p -r1.8 adbvar.h
--- dev/adbvar.h        18 Jan 2006 23:21:17 -0000      1.8
+++ dev/adbvar.h        22 Jun 2011 13:18:37 -0000
@@ -36,12 +36,40 @@ struct adb_softc {
        char *sc_regbase;
 };
 
+extern volatile u_char *Via1Base;
+
+#define ADB_MAX_MSG_LENGTH     16
+#define ADB_MAX_HDR_LENGTH     8
+
+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 */
+};
+
+extern u_char  *adbBuffer;     /* pointer to user data area */
+extern void    *adbCompRout;   /* pointer to the completion routine */
+extern void    *adbCompData;   /* pointer to the completion routine data */
+extern int     adbWaiting;     /* waiting for return data from the device */
+extern int     adbWaitingCmd;  /* ADB command we are waiting for */
+
+
 extern int adbHardware;
+extern int adb_polling;
 
 /* types of adb hardware that we support */
 #define ADB_HW_UNKNOWN         0x01    /* don't know */
 #define ADB_HW_PMU             0x04    /* PowerBook series */
 #define ADB_HW_CUDA            0x05    /* Machines with a Cuda chip */
+
+void   adb_soft_intr(void);
+void   adb_op_comprout(caddr_t, caddr_t, int);
+void   adb_pass_up(struct adbCommand *);
 
 int    adb_poweroff(void);
 void   adb_restart(void);
Index: dev/cuda.c
===================================================================
RCS file: dev/cuda.c
diff -N dev/cuda.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ dev/cuda.c  22 Jun 2011 13:18:37 -0000
@@ -0,0 +1,565 @@
+/*     $OpenBSD$       */
+/*
+ * Copyright (c) 2011 Martin Pieuchot <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/timeout.h>
+
+#include <machine/pio.h>
+#include <machine/autoconf.h>
+
+#include <macppc/dev/cuda.h>
+#include <macppc/dev/adbvar.h>
+
+#define CUDA_DEBUG
+
+#ifdef CUDA_DEBUG
+#define DPRINTF(x...)  printf(x)
+#else
+#define DPRINTF(x...)
+#endif
+
+/*
+struct cuda_softc {
+       struct device    sc_dev;
+       uint8_t         *sc_viaaddr;
+*/
+#define ST_NOTREADY    0
+#define ST_IDLE                1
+#define ST_SENDING     3
+#define ST_RECEIVING   4
+#define ST_RECEIVED    5
+       int              state;         /* interrupt state */
+
+       int              enqueued;      /* bytes are waiting to be send */
+
+       int              received;
+       uint8_t          inqueue[16];
+
+       int              sent;
+       int              length;
+       uint8_t          outqueue[16];
+/*
+};
+*/
+
+
+/*
+ * VIA registers used by Cuda
+ */
+#define DATB           0x0000  /* B-side data register */
+#define DIRB           0x0400  /* B-side direction register (1 for out) */
+#define SR             0x1400  /* Shift register */
+#define ACR            0x1600  /* Auxiliary control register */
+#define IFR            0x1a00  /* Interrupt flag register */
+#define IER            0x1c00  /* Interrupt enable register */
+
+/*
+ * Cuda signals/bits for the B-side data register.
+ */
+#define TREQ           0x08    /* PB3 */
+#define BYTEACK                0x10    /* PB4 */
+#define TIP            0x20    /* PB5 */
+
+/*
+ * Cuda values for the VIA auxillary control
+ */
+#define EXTCLOCK       0x0c
+#define SREG_OUT       0x10
+
+/*
+ * Interrupts bits.
+ */
+#define INTR_DISABLE   0x00
+#define INTR_SR                0x04
+#define INTR_ALL       0x7f
+#define INTR_ENABLE    0x80
+
+
+void   cuda_poll(void);
+
+
+inline void    cuda_write(int, uint8_t);
+inline uint8_t cuda_read(int);
+
+inline void    cuda_set_idle(void);
+inline void    cuda_set_receiving(void);
+inline void    cuda_set_sending(void);
+inline void    cuda_set_tip(void);
+inline void    cuda_toggle_byteack(void);
+
+#define WAIT_FOR(x)                            \
+       do {                                    \
+               int i;                          \
+                                               \
+               for (i = 0; i < 1000; i++)      \
+                       if ((x))                \
+                               break;          \
+       } while (0);
+
+void
+cuda_init(void)
+{
+       /*
+        * Set the signals directions:
+        *     BYTEACK and TIP are outputs and TREQ in input.
+        */
+       cuda_write(DIRB, (cuda_read(DIRB) | BYTEACK | TIP) & ~TREQ);
+       cuda_set_idle();
+
+       /* Clock control, shift data by external clock CB1. */
+       cuda_write(ACR, (cuda_read(ACR) | EXTCLOCK));
+       cuda_set_receiving();
+
+       (void)cuda_read(SR);
+
+       /* Disable all interrupts from VIA */
+       cuda_write(IER, INTR_DISABLE | INTR_ALL);
+       (void)cuda_read(IER);
+
+       /* Reset ADB, it needs 4 mSec to complete. */
+       delay(4000);
+       (void)cuda_read(SR);
+       cuda_write(IFR, INTR_SR);
+
+       /* Sync with CUDA. */
+       cuda_write(DATB, cuda_read(DATB) & ~BYTEACK);
+       WAIT_FOR((cuda_read(DATB) & TREQ) == 0);
+       WAIT_FOR(cuda_read(IFR) & INTR_SR);
+       (void)cuda_read(SR);
+       cuda_write(IFR, INTR_SR);
+
+       /* End the Sync. */
+       cuda_write(DATB, cuda_read(DATB) | BYTEACK);
+       WAIT_FOR(cuda_read(DATB) & TREQ);
+       WAIT_FOR(cuda_read(IFR) & INTR_SR);
+       (void)cuda_read(SR);
+       cuda_write(IFR, INTR_SR);
+
+       /* 
+        * Clear all interrupts, then enable only those from
+        * the shift register.
+        */
+       cuda_write(IFR, INTR_ALL);
+       cuda_write(IER, INTR_ENABLE | INTR_SR);
+
+       state = ST_IDLE;
+       DPRINTF("\ncuda: init OK\n");
+}
+
+int
+cuda_send(uint8_t *cmd, int len, void *func, void *fargs)
+{
+       int s;
+
+       if (state == ST_NOTREADY)
+               return (-1);
+
+       s = splhigh();
+
+       if (state != ST_IDLE || (cuda_read(DATB) & TREQ) == 0) {
+               DPRINTF("cuda: state = %d, enqueued = %d\n", state, enqueued); 
+               if (enqueued == 0) {
+                       enqueued = 1;
+               } else {
+                       splx(s);
+                       return (-1);    
+               }
+       }
+
+       sent = 0;
+       length = len;
+       memcpy(outqueue, cmd, len);
+
+       /* TODO: clean the ADB mess. */
+       if (func != NULL) {
+               adbBuffer = cmd;
+               adbCompRout = func;     
+               adbCompData = fargs;
+               adbWaitingCmd = cmd[1];
+       }
+
+       if (enqueued == 0) {
+               cuda_set_sending();
+               cuda_write(SR, outqueue[0]);
+               cuda_set_tip();
+               state = ST_SENDING;
+               sent = 0;
+               DPRINTF("cuda: send: %02x", outqueue[0]);
+
+               enqueued = 1;
+       }
+
+       splx(s);
+
+       if (adb_polling || cold)
+               cuda_poll();
+
+       return (0);
+}
+
+void
+cuda_poll(void)
+{
+       int s;
+
+       while ((state != ST_IDLE) || (cuda_read(DATB) & TREQ) == 0 || 
adbWaiting)
+               if ((cuda_read(IFR) & INTR_SR) == INTR_SR) {
+                       s = splhigh();
+                       cuda_intr();
+                       splx(s);
+
+                       /* XXX - ADB mess, don't call soft_intr() here. */
+                       if (cold)
+                               delay(150);
+                       adb_soft_intr();
+               }
+}
+
+int
+cuda_intr(void)
+{
+       /* We only deal with the Shift Register interrupts. */
+       if ((cuda_read(IFR) & INTR_SR) == 0)
+               return (0);
+
+       cuda_write(IFR, INTR_SR);
+
+       switch (state) {
+       case ST_IDLE:
+               inqueue[1] = cuda_read(SR);
+
+               if (cuda_read(DATB) & TREQ) {
+                       DPRINTF("cuda: unsolicited byte\n");
+
+                       if (enqueued == 1) {
+                               cuda_set_sending();
+                               cuda_write(SR, outqueue[0]);
+                               cuda_set_tip();
+                               state = ST_SENDING;
+                               sent = 0;
+                               DPRINTF("cuda: send: %02x", outqueue[0]);
+                       }
+                       break;
+               }
+
+               cuda_set_receiving();
+               cuda_set_tip();
+               state = ST_RECEIVING;
+               received = 1;
+               DPRINTF("cuda: recv: %02x", inqueue[1]);
+               break;
+
+       case ST_RECEIVING:
+               inqueue[++received] = cuda_read(SR);
+               DPRINTF(" %02x", inqueue[received]);
+
+               if (cuda_read(DATB) & TREQ) {
+                       cuda_set_idle();
+                       state = ST_RECEIVED;
+               } else {
+                       cuda_toggle_byteack();
+               }
+               break;
+
+       case ST_RECEIVED:
+               (void)cuda_read(SR);
+               DPRINTF(", eof (%d bytes)\n", received);
+
+               /* 
+                * XXX - for compatibility reasons with the actual
+                * ADB system inqueue[0] contains the number of bytes
+                * received.
+                */
+               inqueue[0] = received - 1;
+
+               /* TODO clean the ADB mess. */
+               if ((adbWaiting == 1) && (inqueue[4] == adbWaitingCmd) &&
+                   (inqueue[2] == CUDA_ADDR_ADB || inqueue[2] == 
CUDA_ADDR_PSEUDO)) {
+                       struct adbCommand packet;
+
+                       memcpy(packet.data, inqueue, received);
+                       packet.saveBuf = adbBuffer;
+                       packet.compRout = adbCompRout;
+                       packet.compData = adbCompData;
+                       packet.unsol = 0;
+                       packet.ack_only = 0;
+                       adb_pass_up(&packet);
+
+                       adbWaitingCmd = 0;
+                       adbWaiting = 0;
+                       adbBuffer = NULL;
+                       adbCompRout = NULL;
+                       adbCompData = NULL;
+               } else {
+                       struct adbCommand packet;
+
+                       memcpy(packet.data, inqueue, received);
+                       packet.unsol = 1;
+                       packet.ack_only = 0;
+                       adb_pass_up(&packet);
+               }
+
+               cuda_set_idle();
+               state = ST_IDLE;
+               received = 0;
+
+               if ((enqueued == 1) && (cuda_read(DATB) & TREQ)) {
+                       cuda_set_sending();
+                       cuda_write(SR, outqueue[0]);
+                       cuda_set_tip();
+                       state = ST_SENDING;
+                       sent = 0;
+                       DPRINTF("cuda: send: %02x", outqueue[0]);
+               }
+               break;
+
+       case ST_SENDING:
+               if ((cuda_read(DATB) & TREQ) == 0) {
+                       DPRINTF(", collision, enqueue.\n");
+                       enqueued = 1;
+
+                       cuda_set_receiving();
+                       (void)cuda_read(SR);
+                       cuda_set_idle();
+                       state = ST_IDLE;
+                       received = 0;
+                       break;
+               }
+
+               if (++sent == length) {
+                       DPRINTF(", eof (%d bytes)\n", sent);
+
+                       /* TODO clean the ADB mess. */
+                       if ((outqueue[0] == CUDA_ADDR_ADB && (outqueue[1] & 
0x0c) == 0x0c) ||
+                           (outqueue[0] == CUDA_ADDR_PSEUDO && (outqueue[1] == 
CUDA_CMD_READ_RTC))) {
+                               adbWaiting = 1;
+                               adbWaitingCmd = outqueue[1];
+                       } else {
+                               struct adbCommand packet;
+
+                               /* ack-only, copy the sended msg */
+                               packet.data[0] = sent;
+                               memcpy(packet.data + 1, outqueue, sent);
+
+                               packet.saveBuf = adbBuffer;
+                               packet.compRout = adbCompRout;
+                               packet.compData = adbCompData;
+                               packet.cmd = adbWaitingCmd;
+                               packet.unsol = 0;
+                               packet.ack_only = 1;
+                               adb_pass_up(&packet);
+
+                               adbWaitingCmd = 0;
+                               adbBuffer = NULL;
+                               adbCompRout = NULL;
+                               adbCompData = NULL;
+                       }
+
+                       enqueued = 0;
+                       cuda_set_receiving();
+                       cuda_set_idle();
+                       state = ST_IDLE;
+               } else {
+                       cuda_write(SR, outqueue[sent]);
+                       cuda_toggle_byteack();
+                       DPRINTF(" %02x", outqueue[sent]);
+               }
+
+               break;
+
+       case ST_NOTREADY:
+               DPRINTF("cuda: ADB not yet initialized\n");
+               break;
+
+       default:
+               DPRINTF("cuda: unknown ADB state\n");
+               break;
+       }
+
+       return (1);
+}
+
+inline void
+cuda_write(int offset, uint8_t value)
+{
+       /*
+        * XXX Via1Base shouldn't be global. 
+        */
+       out8(Via1Base + offset, value);
+}
+
+inline uint8_t
+cuda_read(int offset)
+{
+       /*
+        * XXX Via1Base shouldn't be global. 
+        */
+       return in8(Via1Base + offset);
+}
+
+inline void
+cuda_set_idle(void)
+{
+       cuda_write(DATB, cuda_read(DATB) | BYTEACK | TIP);
+}
+
+inline void
+cuda_set_tip(void)
+{
+       cuda_write(DATB, cuda_read(DATB) & ~TIP);
+}
+
+inline void
+cuda_toggle_byteack(void)
+{
+       cuda_write(DATB, cuda_read(DATB) ^ BYTEACK);
+}
+
+inline void
+cuda_set_receiving(void)
+{
+       cuda_write(ACR, cuda_read(ACR) & ~SREG_OUT);
+}
+
+inline void
+cuda_set_sending(void)
+{
+       cuda_write(ACR,  cuda_read(ACR) | SREG_OUT);
+}
+
+void
+cuda_autopoll(void)
+{
+       volatile int flag = 0;
+       uint8_t cmd[16];
+
+       cmd[0] = CUDA_ADDR_PSEUDO;
+       cmd[1] = CUDA_CMD_AUTOPOLL;
+       cmd[2] = 1; /* ON */
+
+       if (cuda_send(cmd, 3, adb_op_comprout, (void *)&flag))
+               return;
+
+       while (flag == 0)
+               ;
+}
+
+int
+cuda_time_read(time_t *time)
+{
+       volatile int flag = 0;
+       uint8_t cmd[16];
+
+       cmd[0] = CUDA_ADDR_PSEUDO;
+       cmd[1] = CUDA_CMD_READ_RTC;
+
+       if (cuda_send(cmd, 2, adb_op_comprout, (void *)&flag))
+               return (-1);
+
+       while (0 == flag)
+               ;
+
+       delay(20);
+
+       /* XXX - ADB mess
+        * For compatibility reasons the first byte
+        * returned is the size of the response.
+        */
+       memcpy(time, cmd + 1, 4);
+
+       return (0);
+}
+
+int
+cuda_time_write(time_t time)
+{
+       volatile int flag = 0;
+       uint8_t cmd[16];
+
+       cmd[0] = CUDA_ADDR_PSEUDO;
+       cmd[1] = CUDA_CMD_WRITE_RTC; 
+       cmd[2] = (uint8_t)(time >> 24);
+       cmd[3] = (uint8_t)(time >> 16);
+       cmd[4] = (uint8_t)(time >> 8);
+       cmd[5] = (uint8_t)(time);
+
+       if (cuda_send(cmd, 6, adb_op_comprout, (void *)&flag));
+               return (-1);
+
+       while (0 == flag)
+               ;
+
+       return (0);
+}
+
+int
+cuda_poweroff(void)
+{
+       uint8_t cmd[16];
+
+       /*
+        * Clean enqueued msg to be sure this one won't fail.
+        */
+       cuda_poll();
+
+       cmd[0] = CUDA_ADDR_PSEUDO;
+       cmd[1] = CUDA_CMD_POWEROFF;
+
+       if (cuda_send(cmd, 2, NULL, NULL))
+               return (-1);
+
+       while (1)
+               ;
+}
+
+void
+cuda_restart(void)
+{
+       uint8_t cmd[16];
+
+       /*
+        * Clean enqueued msg to be sure this one won't fail.
+        */
+       cuda_poll();
+
+       cmd[0] = CUDA_ADDR_PSEUDO; 
+       cmd[1] = CUDA_CMD_RESTART;
+
+       if (cuda_send(cmd, 2, NULL, NULL))
+               return;
+
+       while (1)
+               ;
+}
+
+void
+cuda_fileserver_mode(void)
+{
+       volatile int flag = 0;
+       uint8_t cmd[16];
+
+       cmd[0] = CUDA_ADDR_PSEUDO;
+       cmd[1] = CUDA_CMD_FILESERVER;
+       cmd[2] = 1; /* ON */
+
+       if (cuda_send(cmd, 3, adb_op_comprout, (void *)&flag))
+               return;
+
+       while (flag == 0)
+               ;
+}
Index: dev/cuda.h
===================================================================
RCS file: dev/cuda.h
diff -N dev/cuda.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ dev/cuda.h  22 Jun 2011 13:18:37 -0000
@@ -0,0 +1,44 @@
+/*     $OpenBSD$       */
+/*
+ * Copyright (c) 2011 Martin Pieuchot <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define CUDA_ADDR_ADB          0x00
+#define CUDA_ADDR_PSEUDO       0x01    /* PRAM, rtc, soft-power */
+#define CUDA_ADDR_ERROR                0x02
+#define CUDA_ADDR_TIMER                0x03
+#define CUDA_ADDR_POWER                0x04
+#define CUDA_ADDR_IIC          0x05
+#define CUDA_ADDR_PMU          0x06
+#define CUDA_ADDR_ADB_QUERY    0x07
+
+#define CUDA_CMD_AUTOPOLL      0x01
+#define CUDA_CMD_READ_RTC      0x03
+#define CUDA_CMD_WRITE_RTC     0x09
+#define CUDA_CMD_POWEROFF      0x0a
+#define CUDA_CMD_RESTART       0x11
+#define CUDA_CMD_FILESERVER    0x13
+
+void   cuda_init(void);
+
+int    cuda_intr(void);
+int    cuda_send(uint8_t *, int, void *, void *);
+
+void   cuda_autopoll(void);
+int    cuda_time_read(time_t *);
+int    cuda_time_write(time_t);
+int    cuda_poweroff(void);
+void   cuda_restart(void);
+void   cuda_fileserver_mode(void);
Index: dev/pm_direct.c
===================================================================
RCS file: /cvs/src/sys/arch/macppc/dev/pm_direct.c,v
retrieving revision 1.23
diff -u -p -r1.23 pm_direct.c
--- dev/pm_direct.c     14 May 2011 12:01:16 -0000      1.23
+++ dev/pm_direct.c     22 Jun 2011 13:18:37 -0000
@@ -163,31 +163,6 @@ void       pm_adb_get_TALK_result(PMData *);
 void   pm_adb_get_ADB_data(PMData *);
 
 
-/*
- * These variables are in adb_direct.c.
- */
-extern u_char  *adbBuffer;     /* pointer to user data area */
-extern void    *adbCompRout;   /* pointer to the completion routine */
-extern void    *adbCompData;   /* pointer to the completion routine data */
-extern int     adbWaiting;     /* waiting for return data from the device */
-extern int     adbWaitingCmd;  /* ADB command we are waiting for */
-extern int     adbStarting;    /* doing ADB reinit, so do "polling" 
differently */
-
-#define        ADB_MAX_MSG_LENGTH      16
-#define        ADB_MAX_HDR_LENGTH      8
-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 */
-};
-extern void    adb_pass_up(struct adbCommand *);
-
-
 #ifdef ADB_DEBUG
 /*
  * This function dumps contents of the PMData

Reply via email to