Package: util-linux
Version: 2.12p-4
Tags: patch

Here's a patch that takes the code distributed in util-linux source as 
hwclock/clock-ppc.c and modifies it to work with the clock_ops structure.  It 
allows PPC machines running kernels without /dev/rtc support to fall back to 
modifying the hardware click via ADB.

It's lower precision than the /dev/rtc method, but as far as I can tell, all 
the functionality has survived from Paul's code.

The patch applies to 2.12p and 2.12q.

I got no response when I submitted this to [EMAIL PROTECTED] (the address 
mentioned in the INSTALL file)

diff -urN util-linux-2.12q/hwclock/adb.c util-linux-2.12q-new/hwclock/adb.c
--- util-linux-2.12q/hwclock/adb.c      1969-12-31 19:00:00.000000000 -0500
+++ util-linux-2.12q-new/hwclock/adb.c  2005-04-28 18:45:57.000000000 -0400
@@ -0,0 +1,143 @@
+#include <unistd.h>            /* for write(), read() */
+#include <fcntl.h>             /* for O_RDWR */
+#include <errno.h>
+
+#include <linux/adb.h>
+#include <linux/cuda.h>
+
+#include "nls.h"
+
+#include "clock.h"
+
+/* Apparently the RTC on PowerMacs stores seconds since 1 Jan 1904 */
+#define RTC_OFFSET      2082844800
+
+static int adb_fd;
+
+static unsigned char get_packet[2] = { (unsigned char) CUDA_PACKET,
+                                (unsigned char) CUDA_GET_TIME };
+static unsigned char set_packet[6] = { (unsigned char) CUDA_PACKET,
+                                (unsigned char) CUDA_SET_TIME };
+
+static int
+synchronize_to_clock_tick_adb(void) {
+  /* I don't know how to do this via adb */
+  return 0;
+}
+
+static int
+read_hardware_clock_adb(struct tm *tm) {
+  int ii;
+  time_t clock_time;
+  unsigned char reply[16];
+
+  if (write(adb_fd, get_packet, sizeof(get_packet)) < 0) {
+    perror("write adb");
+    exit(EXIT_FAILURE);
+  }
+  ii = (int) read(adb_fd, reply, sizeof(reply));
+  if (ii < 0) {
+    perror("read adb");
+    exit(EXIT_FAILURE);
+  }
+  if (ii != 7)
+    (void) fprintf(stderr,
+                  "Warning: bad reply length from CUDA (%d)\n", ii);
+  clock_time = (time_t) ((reply[3] << 24) + (reply[4] << 16)
+                        + (reply[5] << 8)) + (time_t) reply[6];
+  clock_time -= RTC_OFFSET;
+
+  gmtime_r(&clock_time, tm);            /* Should this be localtime()? */
+  if (debug)
+    (void) printf("time in rtc is %s", asctime(tm));
+  tm->tm_isdst = -1;
+  return 0;
+}
+
+static int
+set_hardware_clock_adb(const struct tm *new_broken_time) {
+  int i;
+  time_t clock_time;
+  char * zone;
+  unsigned char reply[16];
+
+  zone = (char *) getenv ("TZ");        /* save original time zone */
+  (void) putenv ("TZ=");
+  tzset ();
+  clock_time = mktime (new_broken_time);
+  /* now put back the original zone */
+  if (zone) {
+      char *zonebuf;
+      zonebuf = malloc (strlen (zone) + 4);
+      strcpy (zonebuf, "TZ=");
+      strcpy (zonebuf+3, zone);
+      putenv (zonebuf);
+      free (zonebuf);
+  }
+  else {                   /* wasn't one, so clear it */
+      putenv ("TZ");
+  }
+  tzset ();
+
+  clock_time += RTC_OFFSET;
+  set_packet[2] = clock_time >> 24;
+  set_packet[3] = clock_time >> 16;
+  set_packet[4] = clock_time >> 8;
+  set_packet[5] = (unsigned char) clock_time;
+
+  if (write(adb_fd, set_packet, sizeof(set_packet)) < 0) {
+    perror("write adb (set)");
+    exit(EXIT_FAILURE);
+  }
+  i = (int) read(adb_fd, reply, sizeof(reply));
+  if (debug) {
+    int j;
+    (void) printf("set reply %d bytes:", i);
+    for (j = 0; j < i; ++j)
+      (void) printf(" %.2x", (unsigned int) reply[j]);
+    (void) printf("\n");
+  }
+  if (i != 3 || reply[1] != (unsigned char) 0)
+    (void) fprintf(stderr, "Warning: error %d setting RTC\n",
+                  (int) reply[1]);
+
+  if (debug) {
+    clock_time -= RTC_OFFSET;
+    (void) printf("set RTC to %s", asctime(gmtime(&clock_time)));
+  }
+  return 0;
+}
+
+static int
+get_permissions_adb(void) {
+  if ((adb_fd = open ("/dev/adb", O_RDWR)) < 0) {
+    int errsv = errno;
+    fprintf(stderr, _("Cannot open /dev/port: %s"), strerror(errsv));
+    fprintf(stderr, _("Probably you need root priveledges.\n"));
+    return 1;
+  }
+  return 0;
+}
+
+static struct clock_ops adb = {
+       "adb interface to powerpc clock",
+       get_permissions_adb,
+       read_hardware_clock_adb,
+       set_hardware_clock_adb,
+       synchronize_to_clock_tick_adb,
+};
+
+
+/* return &adb if adb clock present, NULL otherwise */
+/* choose this construction to avoid gcc messages about unused variables */
+
+struct clock_ops *
+probe_for_adb_clock(void){
+    int have_adb =
+#if defined(__powerpc__)
+           TRUE;
+#else
+           FALSE;
+#endif
+    return have_adb ? &adb : NULL;
+}
diff -urN util-linux-2.12q/hwclock/clock.h util-linux-2.12q-new/hwclock/clock.h
--- util-linux-2.12q/hwclock/clock.h    2000-12-07 11:39:53.000000000 -0500
+++ util-linux-2.12q-new/hwclock/clock.h        2005-04-28 13:06:20.000000000 
-0400
@@ -15,6 +15,7 @@
 extern struct clock_ops *probe_for_cmos_clock(void);
 extern struct clock_ops *probe_for_rtc_clock(void);
 extern struct clock_ops *probe_for_kd_clock(void);
+extern struct clock_ops *probe_for_adb_clock(void);
 
 typedef int bool;
 #define TRUE 1
diff -urN util-linux-2.12q/hwclock/hwclock.c util-linux-2.12q-new/hwclock/hwclo
ck.c
--- util-linux-2.12q/hwclock/hwclock.c  2004-12-15 14:13:48.000000000 -0500
+++ util-linux-2.12q-new/hwclock/hwclock.c      2005-04-28 12:36:19.000000000 
-0400
@@ -1010,6 +1010,9 @@
   if (!ur && !user_requests_ISA)
          ur = probe_for_cmos_clock();
 
+  if (!ur)
+         ur = probe_for_adb_clock();
+
   if (debug) {
          if (ur)
                  printf(_("Using %s.\n"), ur->interface_name);
diff -urN util-linux-2.12q/hwclock/Makefile util-linux-2.12q-new/hwclock/Makefi
le
--- util-linux-2.12q/hwclock/Makefile   2004-12-15 14:11:59.000000000 -0500
+++ util-linux-2.12q-new/hwclock/Makefile       2005-04-28 12:35:04.000000000 
-0400
@@ -19,7 +19,7 @@
 hwclock.o: hwclock.c
 hwclock.o cmos.o kd.o: ../defines.h
 hwclock.o cmos.o rtc.o kd.o: clock.h
-hwclock: hwclock.o cmos.o rtc.o kd.o
+hwclock: hwclock.o cmos.o rtc.o kd.o adb.o
 
 CWFLAGS := $(subst -Wmissing-prototypes,,$(CFLAGS))
 

Reply via email to