Benjamin Herrenschmidt wrote: [...] > There is no general interface. If you figure out the proper command to send > to the PMU, then we can add the option to /proc/pmu/options
An easy way to get the information is to 'boot' into Open Firmware. First I want to add two hints: Apple's Technotes 'TN2004: Debugging Open Firmware Using Telnet' and 'TN2023: Open Firmware Ethernet Debugging II: Telnet downloading' are very usefull. There is a short Forth tutorial on Apple's pci page: <http://developer.apple.com/hardware/pci/> Here is a fragment of such a session: (It is an iBook 2.2) | Script started on Mon Jun 7 23:43:00 2004 | [EMAIL PROTECTED]:~$ telnet 192.168.0.3 | Trying 192.168.0.3... | Connected to 192.168.0.3. | Escape character is '^]'. | ok | 0 > dev rtc | 0 > pwd | 0 > /[EMAIL PROTECTED]/[EMAIL PROTECTED]/[EMAIL PROTECTED]/rtc ok | 0 > words | More [<space>,<cr>,q,a] ? | open set-time get-time oneminute shutdowntimer | write-pua disableboottimer enableboottimer setboottimer | read-boot disablewakeup write-wake write-rtc write-time | read-wake read-rtc read-time rtc-bfr ok 'oneminute' will set the boot timer one minute in the future and shutdown the Mac. | 0 > see oneminute | : oneminute | 3c shutdowntimer ; ok | 0 > see shutdowntimer | : shutdowntimer | read-rtc + write-pua shut-down ; ok | 0 > see write-pua | : write-pua | enableboottimer ; ok The 'read-rtc' command puts the current time on the data-stack | 0 > read-rtc . [enter] leads to: | 0 > read-rtc bcea937e ok The following line would set the boot timer one minute in the future: | 0 > read-rtc 3c + enableboottimer [enter] | 0 > see enableboottimer | : enableboottimer | 8e rtc-bfr c! 5 rtc-bfr char+ c! 0 rtc-bfr wa1+ c! | rtc-bfr 3 + 4c!-be | rtc-bfr 7 " write" _pmu-ihandle $call-method drop | rtc-bfr 7 + 1 " read" | _pmu-ihandle $call-method drop ; ok [Sorry for the line breaks] In short words: A sequence of 7 bytes is assembled somewhere in the memory (The position is determined by rtc-bfr) and sent to the pmu. These 7 bytes are: '0x8e 0x05 0x00 x3 x2 x1 x0'. An answer of the pmu of length of one byte is then expected. Here 'x3 x2 x1 x0' is a 32-bit value. (Which is the time of which the boot timer will be set.) To read the boot timer (commando 'read-boot') the sequence '0x8e 0x01 0x01' is sent to the pmu and a sequence of 6 bytes is expected as answer. Some more commands: | 0 > see write-wake | : write-time | 80 write-time ; ok | 0 > | 0 > see write-time | : >r rtc-bfr 4c!-be 0 0 rtc-bfr 4 r> " pmu-op" | _pmu-ihandle $call-method drop ; ok Here '0x80 y3 y2 y1 y0' is sent to the pmu. (I haven't looked for the meaning of the other two arguments '00 00'.) | 0 > see read-wake | : 88 read-time ; ok | 0 > | 0 > see read-time | : read-time | >r rtc-bfr 5 0 0 r> " pmu-op" _pmu-ihandle $call-method drop | >rtc-bfr [EMAIL PROTECTED] ; ok Here '0x88' is send to the pmu. There is also a command 'setboottimer' in this node, but it is not clear to me what the command will do. One node above '/[EMAIL PROTECTED]/[EMAIL PROTECTED]/[EMAIL PROTECTED]' there are more commands, e.g | 0 > see shutdown | : shutdown | 0 0 " MATT" poweroffcmd pmu-op drop | begin | again | ; ok More interesting a lot of command bytes are defined here, e.g. 'poweroffcmd'. **************************************** There is already a program called 'pmacpow' written by Takashi Oe, which can set the wakeup time for cuda-based Macs. The idea is to write a sequence of command bytes to '/dev/adb'. I have tested to write sequences like: "PMU_PACKET 0x38" ('read-rtc'). [PMU_PACKET is definend in <linux/adb.h>] And then I read back as many bytes as possible from '/dev/adb'. "PMU_PACKET 0x38" 'read-rtc' succesfull "PMU_PACKET 0x88" 'read-wake' succesfull "PMU_PACKET 0x8e 0x01 0x01" 'read-boot' succesfull "PMU_PACKET 0x80 y3 y2 y1 y0" 'write-wake' succesfull "PMU_PACKET 0x8e 0x05 0x00 y3 y2 y1 y0 " 'enableboottimer' no luck In '$linux/drivers/macintosh/via-pmu.c' (I'm using 2.4.22-ben2) there is an array 'pmu_data_len[256][2]' (line 255 ff.) which says something about the length of the data of a command and something about the length of the reply of the pmu. Hence '0x8e ...' is a variable lenght command and the second byte is the count of the bytes _after_ the second byte. So I suppose there is a mistake in the pmu-code or I am using '/dev/adb' in a wrong way. Frank **************** To be complete here is an example: > cat pmu_read_boot.c /* * pmacpow.c - set the next power up time on VIA-CUDA. * * * Copyright (C) 1999 Takashi Oe. All rights reserved. * Parts of the code are from clock.c and bat.c * by Paul Mackerras. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * cc -o pmu_read_boot pmu_read_boot.c */ #include <stdio.h> #include <string.h> #include <fcntl.h> #include <getopt.h> #include <time.h> #include <sys/time.h> #include <linux/adb.h> #include <linux/pmu.h> unsigned char reqt[4] = { PMU_PACKET, 0x8e, 0x01, 0x01}; unsigned char reply[32]; static char *program_name; void dump(unsigned char *buf, int n) { int i; for (i = 0; i < n; ++i) fprintf(stderr, " %.2x", buf[i]); fprintf(stderr, "\n"); } void usage(void) { fprintf(stderr, "%s TBA \n", program_name); exit(1); } int get_rtc_time(int fd) { int n; n = write(fd, reqt, sizeof(reqt)); if (n != sizeof(reqt)) { fprintf(stderr, "%s: write returned %d\n", program_name, n); return -1; } if ((n = read(fd, reply, sizeof(reply))) < 0) { perror("read"); return -1; } dump(reply, n); fprintf(stderr, "%s: command returned\n", program_name); return 0; } int main(int argc, char **argv) { int fd, arg, hour, min; long cur, sec, uptime; char *timestr, *tmp; extern int optind; program_name = (char *)basename(argv[0]); if (getuid()) { fprintf(stderr, "Sorry, must be root to set power up time\n"); return 1; } if ((fd = open("/dev/adb", O_RDWR)) < 0) { perror("open"); return 1; } get_rtc_time(fd); close(fd); return 0; }