rtc again...
Takashi Oe
toe at unlserve.unl.edu
Thu Aug 10 09:12:48 EST 2000
On Wed, 9 Aug 2000, Benjamin Herrenschmidt wrote:
> Saving the timezone value to xpram is another issue. It could be done
> from userland but we currently don't have userland tool that properly
> access the xpram portion of the nvram. I did plan to add some ioctls to /
> dev/nvram for it to return the location of the various nvram partitions,
> looks like it will be time to actually implement them... Also, the
> userland tool will have to be written...
I had a xpram manipulation tool, so I modified it a bit. Also, I added an
ioctl to drivers/macintosh/nvram.c.
Please have a look at them. Are these what you had in mind?
Takashi Oe
Kernel mods:
--- linux-2.4.0-test4/include/asm-ppc/nvram.h Tue May 2 15:05:40 2000
+++ linux-nubus/include/asm-ppc/nvram.h Wed Aug 9 17:44:23 2000
@@ -38,12 +38,14 @@
pmac_nvram_NR /* MacOS Name Registry partition */
};
+#ifdef __KERNEL__
/* Return partition offset in nvram */
extern int pmac_get_partition(int partition);
/* Direct access to XPRAM */
extern u8 pmac_xpram_read(int xpaddr);
extern void pmac_xpram_write(int xpaddr, u8 data);
+#endif /* __KERNEL__ */
/* Some offsets in XPRAM */
#define PMAC_XPRAM_MACHINE_LOC 0xe4
@@ -51,9 +53,12 @@
/* Machine location structure in XPRAM */
struct pmac_machine_location {
- u32 latitude; /* 2+30 bit Fractional number */
- u32 longitude; /* 2+30 bit Fractional number */
- u32 delta; /* mix of GMT delta and DLS */
+ unsigned int latitude; /* 2+30 bit Fractional number */
+ unsigned int longitude; /* 2+30 bit Fractional number */
+ unsigned int delta; /* mix of GMT delta and DLS */
};
+
+/* /dev/nvram ioctls */
+#define PMAC_NVRAM_GET_OFFSET _IOWR('p', 0x40, int) /* Get NVRAM partition offset */
#endif
--- linux-2.4.0-test4/drivers/macintosh/nvram.c Tue Jun 20 15:58:42 2000
+++ linux-nubus/drivers/macintosh/nvram.c Wed Aug 9 16:44:50 2000
@@ -14,6 +14,7 @@
#include <linux/nvram.h>
#include <linux/init.h>
#include <asm/uaccess.h>
+#include <asm/nvram.h>
#define NVRAM_SIZE 8192
@@ -70,11 +71,36 @@
return p - buf;
}
+static int nvram_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ switch(cmd) {
+ case PMAC_NVRAM_GET_OFFSET:
+ {
+ int part, offset;
+ if (copy_from_user(&part,(void*)arg,sizeof(part))!=0)
+ return -EFAULT;
+ if (part < pmac_nvram_OF || part > pmac_nvram_NR)
+ return -EINVAL;
+ offset = pmac_get_partition(part);
+ if (copy_to_user((void*)arg,&offset,sizeof(offset))!=0)
+ return -EFAULT;
+ break;
+ }
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
struct file_operations nvram_fops = {
owner: THIS_MODULE,
llseek: nvram_llseek,
read: read_nvram,
write: write_nvram,
+ ioctl: nvram_ioctl,
};
static struct miscdevice nvram_dev = {
Userland utilitity: xpram.c
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <fcntl.h>
#include <getopt.h>
#include <sys/ioctl.h>
#include <asm/nvram.h>
/* Globals */
int set_timezone = 0;
void
usage (char *str)
{
fprintf (stderr,
"%s offset [val]\n"
"%s -t\n"
" t: update XPRAM timezone info\n", str, str);
exit(EXIT_FAILURE);
}
int nvram_fd;
static void
nvram_init ( int rw_flag )
{
if (rw_flag && getuid () != 0) {
fprintf (stderr, "Sorry, must be root to set XPRAM value\n");
exit(EXIT_FAILURE);
}
nvram_fd = open ("/dev/nvram", rw_flag? O_RDWR: O_RDONLY);
if (nvram_fd < 0) {
fprintf (stderr, "unable to open /dev/nvram read/write : %s\n",
rw_flag? "read/write": "read only", strerror(errno));
exit(EXIT_FAILURE);
}
}
int
main (int argc, char **argv )
{
int i, arg, rw = 0;
unsigned long address;
unsigned char val;
char *p;
extern int optind;
while ((arg = getopt (argc, argv, "t")) != -1) {
switch (arg) {
case 't':
set_timezone = 1;
break;
default:
usage (argv[0]);
}
}
if (set_timezone) {
address = PMAC_XPRAM_MACHINE_LOC;
rw = 1;
} else {
if (!argv[optind])
usage(argv[0]);
address = strtoul(argv[optind], &p, 0);
if (p == argv[optind])
usage(argv[0]);
if (argv[++optind]) {
val = (unsigned char)strtoul(argv[optind], &p, 0);
if (p == argv[optind])
usage(argv[0]);
rw = 1;
}
}
nvram_init (rw);
i = pmac_nvram_XPRAM;
if (ioctl(nvram_fd, PMAC_NVRAM_GET_OFFSET, &i) < 0) {
fprintf(stderr, "ioctl PMAC_NVRAM_GET_OFFSET: %s\n",
strerror(errno));
exit(EXIT_FAILURE);
}
address += i;
if (set_timezone) {
unsigned char buf[4];
time_t gmt;
int utc_offset;
gmt = time( NULL );
(void )localtime( &gmt );
utc_offset = -timezone + (daylight? 3600: 0);
if (lseek(nvram_fd, address + 8, 0) < 0
|| read(nvram_fd, buf, 1) != 1) {
fprintf(stderr, "Error reading from /dev/nvram: %s",
strerror(errno));
exit(EXIT_FAILURE);
}
buf[0] = (buf[0] & 0x7f) | ((daylight)? 0x80: 0);
buf[1] = ((unsigned)(utc_offset) >> 16) & 0xff;
buf[2] = ((unsigned)(utc_offset) >> 8) & 0xff;
buf[3] = (unsigned)(utc_offset) & 0xff;
if (lseek(nvram_fd, address + 8, 0) < 0
|| write(nvram_fd, buf, 4) != 4) {
fprintf(stderr, "Error writing to /dev/nvram: %s",
strerror(errno));
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
if (!rw) {
if (lseek(nvram_fd, address, 0) < 0
|| read(nvram_fd, &val, 1) != 1) {
fprintf(stderr, "Error reading from /dev/nvram: %s",
strerror(errno));
exit(EXIT_FAILURE);
}
printf("0x%02X\n", val);
} else {
if (lseek(nvram_fd, address, 0) < 0
|| write(nvram_fd, &val, 1) != 1) {
fprintf(stderr, "Error writing to /dev/nvram: %s",
strerror(errno));
exit(EXIT_FAILURE);
}
}
exit(EXIT_SUCCESS);
}
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
More information about the Linuxppc-dev
mailing list