Mercurial > ~darius > hgwebdir.cgi > hwmon
diff superio/superio.c @ 0:c34b37680055 default tip
Inital commit of random SuperIO code.
author | Daniel O'Connor <darius@dons.net.au> |
---|---|
date | Thu, 20 Oct 2011 16:48:24 +1030 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/superio/superio.c Thu Oct 20 16:48:24 2011 +1030 @@ -0,0 +1,112 @@ +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <fcntl.h> +#include <stdlib.h> +#include <sys/types.h> +#include <machine/cpufunc.h> +#include <unistd.h> + +void +usage(char *name) { + fprintf(stderr, + "Bad usage\n" + "\t%s [-b base] [-d dev] [-t type] adr [data]\n" + "\n" + "Read/write registers in Winbond SuperIO parts\n" + "base is the base address for the chip (default: 0x2e)\n" + "dev is the sub-device to talk to (default: -1/global)\n" + "type is the chip type (i = ITE, w = WinBond)\n" + "adr is the register to read/write\n" + "data is the data to write to adr\n", name); + exit(1); +} + +int +main(int argc, char **argv) { + int fd, base, dev, type, adr, data, ch; + char *progname; + + type = 'w'; + base = 0x2e; + dev = -1; + + progname = argv[0]; + + while ((ch = getopt(argc, argv, "b:d:t:")) != -1) { + switch (ch) { + case 'b': + base = strtol(optarg, NULL, 0) & 0xffff; + break; + + case 'd': + dev = strtol(optarg, NULL, 0) & 0xff; + break; + + case 't': + if (optarg[0] != 'w' && optarg[0] != 'i') { + fprintf(stderr, "type must be w or i\n\n"); + usage(progname); + } + + type = optarg[0]; + break; + + default: + usage(progname); + break; + } + } + argc -= optind; + argv += optind; + + if (argc != 1 && argc != 2) + usage(progname); + + if ((fd = open("/dev/io", O_RDWR)) == -1) { + fprintf(stderr, "Can't open /dev/io: %s\n", strerror(errno)); + exit(1); + } + + adr = strtol(argv[0], NULL, 0) & 0xff; + + /* Enter extended function mode */ + if (type == 'w') { + outb(base, 0x87); + outb(base, 0x87); + } else { + /* Taken from the Linux driver drivers/hwmon/it87.c */ + outb(base, 0x87); + outb(base, 0x01); + outb(base, 0x55); + outb(base, 0x55); + } + + /* Sub device to select (skip if global) */ + if (dev != -1) { + outb(base, 0x07); /* Logical device select register */ + outb(base + 1, dev & 0xff); + } + + /* Register to access */ + outb(base, adr); + + if (argc == 2) { + data = strtol(argv[1], NULL, 0) & 0xff; + printf("Bank 0x%02x: 0x%02x <- 0x%02x\n", dev, adr, data); + outb(base + 1, data); + } else + printf("Bank 0x%02x: 0x%02x -> 0x%02x\n", dev, adr, inb(base + 1)); + + /* Exit extended function mode */ + if (type == 'w') { + outb(base, 0xaa); + outb(base, 0xaa); + } else { + outb(base, 0x02); + outb(base, 0x02); + } + + exit(0); +} +