From 6f821d2ad8894cfc5ee9c1b47fa6a80f1ee44273 Mon Sep 17 00:00:00 2001 From: "Mark D. Studebaker" Date: Wed, 28 Apr 2004 23:54:09 +0000 Subject: [PATCH] new isaset program. Warning - lightly tested. Please test and improve as necessary. git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@2488 7894878c-1315-0410-8ee3-d5d059ff63e0 --- CHANGES | 2 + prog/dump/Module.mk | 8 +- prog/dump/isaset.c | 194 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 200 insertions(+), 4 deletions(-) create mode 100644 prog/dump/isaset.c diff --git a/CHANGES b/CHANGES index dad4b5b3..0a7c4088 100644 --- a/CHANGES +++ b/CHANGES @@ -31,6 +31,7 @@ ask CVS about it: Man page i2cdetect.8: document new command line flags Man page i2cdump.8: More details on how i2cdump can write to a chip Modules (all chip drivers): Rework memory allocation scheme. + Module bmcsensors: Fix oops by creating thread for initialization Modules dmi_scan, i2c-piix4: Move IBM detection into dmi_scan Modules w83781d.c, smartbatt.c, lm75.c, gl520sm.c, gl518sm.c, ds1621.c, asb100.c, lm92.c: Use swab16 @@ -50,6 +51,7 @@ ask CVS about it: Program i2cdetect: Adapt probing method to address Add -q and -r flags to force probing methods Program isadump: Misc improvements + Program isaset: New Program mkpatch: Patch dmi_scan.c in kernel instead of adding our own module Include i2c-nforce2 diff --git a/prog/dump/Module.mk b/prog/dump/Module.mk index 6d94f4f1..80caeb78 100644 --- a/prog/dump/Module.mk +++ b/prog/dump/Module.mk @@ -31,12 +31,12 @@ PROGDUMPSOURCES := $(MODULE_DIR)/i2cdump.c $(MODULE_DIR)/i2cset.c \ $(MODULE_DIR)/i2cbusses.c PROGDUMPBININSTALL := $(MODULE_DIR)/i2cdump $(MODULE_DIR)/i2cset -# Only build isadump on x86 machines. +# Only build isadump and isaset on x86 machines. ifneq (,$(findstring $(MACHINE), i386 i486 i586 i686 x86_64)) PROGDUMPMAN8FILES += $(MODULE_DIR)/isadump.8 -PROGDUMPTARGETS += $(MODULE_DIR)/isadump -PROGDUMPSOURCES += $(MODULE_DIR)/isadump.c -PROGDUMPBININSTALL += $(MODULE_DIR)/isadump +PROGDUMPTARGETS += $(MODULE_DIR)/isadump $(MODULE_DIR)/isaset +PROGDUMPSOURCES += $(MODULE_DIR)/isadump.c $(MODULE_DIR)/isaset.c +PROGDUMPBININSTALL += $(MODULE_DIR)/isadump $(MODULE_DIR)/isaset endif # Include all dependency files. We use '.rd' to indicate this will create diff --git a/prog/dump/isaset.c b/prog/dump/isaset.c new file mode 100644 index 00000000..423ea6b1 --- /dev/null +++ b/prog/dump/isaset.c @@ -0,0 +1,194 @@ +/* + isaset.c - isaset, a user-space program to write ISA registers + Copyright (c) 2000 - 2004 Frodo Looijaard , and + Mark D. Studebaker + + 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + Typical usage: + isaset 0x295 0x296 0x10 0x12 Write 0x12 to address 0x10 using address/data registers + isaset -f 0x5000 0x12 Write 0x12 to location 0x5010 +*/ + +#include +#include +#include + + +/* To keep glibc2 happy */ +#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ >= 0 +#include +#else +#include +#endif + +#ifdef __powerpc__ +unsigned long isa_io_base = 0; /* XXX for now */ +#endif /* __powerpc__ */ + +char hexchar(int i) +{ + if ((i >= 0) && (i <= 9)) + return '0' + i; + else if (i <= 15) + return 'a' - 10 + i; + else + return 'X'; +} + +void help(void) +{ + fprintf(stderr,"Syntax: isaset ADDRREG DATAREG ADDR DATA (for chips with addr/data registers)\n"); + fprintf(stderr," isaset -f ADDR DATA (for chips with a flat address space)\n"); +} + +int main(int argc, char *argv[]) +{ + int addrreg, datareg = 0; + unsigned char value, res, addr = 0; + int flat = 0; + char *end; + + if (argc < 4) { + help(); + exit(1); + } + + if(strcmp(argv[1], "-f")) { + addrreg = strtol(argv[1],&end,0); + } else { + if(argc != 4) { + help(); + exit(1); + } + flat = 1; + addrreg = strtol(argv[2],&end,0); + } + if (*end) { + fprintf(stderr,"Error: Invalid address!\n"); + help(); + exit(1); + } + if ((addrreg < 0) || (addrreg > 0xffff)) { + fprintf(stderr,"Error: Address out of range!\n"); + help(); + exit(1); + } + + if(flat) { + value = strtol(argv[3],&end,0); + if (*end) { + fprintf(stderr,"Error: Invalid data!\n"); + help(); + exit(1); + } + } else { + + datareg = strtol(argv[2],&end,0); + if (*end) { + fprintf(stderr,"Error: Invalid data register!\n"); + help(); + exit(1); + } + if ((datareg < 0) || (datareg > 0xffff)) { + fprintf(stderr,"Error: Data register out of range!\n"); + help(); + exit(1); + } + + if(flat) { + value = strtol(argv[3],&end,0); + if (*end) { + fprintf(stderr,"Error: Invalid addr!\n"); + help(); + exit(1); + } + } else { + addr = strtol(argv[3],&end,0); + if (*end) { + fprintf(stderr,"Error: Invalid addr!\n"); + help(); + exit(1); + } + value = strtol(argv[4],&end,0); + if (*end) { + fprintf(stderr,"Error: Invalid data!\n"); + help(); + exit(1); + } + } +} + + if (getuid()) { + fprintf(stderr,"Error: Can only be run as root (or make it suid root)\n"); + exit(1); + } + + fprintf(stderr," WARNING! Running this program can cause system crashes, " + "data loss and worse!\n"); + if(flat) + fprintf(stderr," I will write address 0x%04x with data 0x%02x\n", + addrreg, value); + else + fprintf(stderr," I will write chip address 0x%04x with data 0x%02x\n" + " using address register 0x%04x and " + "data register 0x%04x.\n", + addr, value, addrreg, datareg); + fprintf(stderr," You have five seconds to reconsider and press CTRL-C!\n\n"); + sleep(5); + +#ifndef __powerpc__ + if ((datareg < 0x400) && (addrreg < 0x400) && !flat) { + if(ioperm(datareg,1,1)) { + fprintf(stderr,"Error: Could not ioperm() data register!\n"); + exit(1); + } + if(ioperm(addrreg,1,1)) { + fprintf(stderr,"Error: Could not ioperm() address register!\n"); + exit(1); + } + } else { + if(iopl(3)) { + fprintf(stderr,"Error: Could not do iopl(3)!\n"); + exit(1); + } + } +#endif + +/* write */ + if(flat) { + outb(value, addrreg); + } else { + outb(addr, addrreg); + outb(value,datareg); + } + +/* readback */ + if(flat) { + res = inb(addrreg); + } else { + outb(addr, addrreg); + res = inb(datareg); + } + + if(res != value) { + fprintf(stderr, "Warning - data mismatch - wrote 0x%.2x, read back 0x%.2x\n", value, res); + } else { + fprintf(stderr, "Value 0x%x written, readback matched\n", value); + } + exit(0); +}