mirror of
https://github.com/lm-sensors/lm-sensors.git
synced 2026-10-29 12:50:43 +00:00
Written value can be masked, preserving unmasked bits at the
written location. Similar to what I did for i2cset some times
ago.
git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@2739 7894878c-1315-0410-8ee3-d5d059ff63e0
This commit is contained in:
1 parent
5691e2d947
commit
3eb8495004
2 files changed
+80
-20
No files matched your search
+8
-3
@@ -9,12 +9,14 @@ i2cset \- set ISA registers
|
||||
.I datareg
|
||||
.I address
|
||||
.I value
|
||||
.RI [ mask ]
|
||||
#for I2C-like access
|
||||
.br
|
||||
.B isaset
|
||||
.RB [ -y ]
|
||||
.BI "-f " address
|
||||
.I value
|
||||
.RI [ mask ]
|
||||
#for flat address space
|
||||
|
||||
.SH DESCRIPTION
|
||||
@@ -33,24 +35,27 @@ will perform the operation directly. This is mainly meant to be used in
|
||||
scripts.
|
||||
|
||||
.SH OPTIONS (I2C-like access mode)
|
||||
Exactly four options must be provided to isaset. \fIaddrreg\fR contains the
|
||||
Four options must be provided to isaset. \fIaddrreg\fR contains the
|
||||
ISA address of the address register for the chip to probe; \fIdatareg\fR
|
||||
contains the address of the data register. Both addresses are integers between
|
||||
0x0000 and 0x3FFF. Usually, if the chip's base address is 0x0nn0, the
|
||||
address register is at 0x0nn5 and the data register is at 0x0nn6. The most
|
||||
common base address for hardware monitoring chips is 0x0290.
|
||||
.PP
|
||||
For Super-I/O chips, address register is typically at 0x2E with data
|
||||
register at 0x2F.
|
||||
The \fIaddress\fR and \fIvalue\fR parameters are two integers between
|
||||
0x00 and 0xFF. isaset will write value \fIvalue\fR to address \fIaddress\fR.
|
||||
An optional \fImask\fR can be provided as a fifth parameter, preserving
|
||||
unmasked bits at the written location.
|
||||
|
||||
.SH OPTIONS (flat address space mode)
|
||||
In flat mode, exactly two parameters must
|
||||
In flat mode, two parameters must
|
||||
be provided. \fIaddress\fR contains the ISA address of the register to
|
||||
write to; it is an integer between 0x0000 and 0xFFFF. Basically, it is
|
||||
the sum of the chip's base address and the chip register's address. isaset
|
||||
will write value \fIvalue\fR at this address.
|
||||
An optional \fImask\fR can be provided as a third parameter, preserving
|
||||
unmasked bits at the written location.
|
||||
|
||||
.SH WARNING
|
||||
Poking around in ISA data space is extremely dangerous.
|
||||
|
||||
+72
-17
@@ -46,14 +46,14 @@ void help(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Syntax for I2C-like access:\n"
|
||||
" isaset [-y] ADDRREG DATAREG ADDRESS VALUE\n"
|
||||
" isaset [-y] ADDRREG DATAREG ADDRESS VALUE [MASK]\n"
|
||||
"Syntax for flat address space:\n"
|
||||
" isaset [-y] -f ADDRESS VALUE\n");
|
||||
" isaset [-y] -f ADDRESS VALUE [MASK]\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int addrreg, datareg = 0, value, addr = 0;
|
||||
int addrreg, datareg = 0, value, addr = 0, vmask = 0;
|
||||
unsigned char res;
|
||||
int flags = 0;
|
||||
int flat = 0, yes = 0;
|
||||
@@ -74,8 +74,8 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
/* verify that the argument count is correct */
|
||||
if ((!flat && argc != 1+flags+4)
|
||||
|| (flat && argc != 1+flags+2)) {
|
||||
if ((!flat && (argc < 1+flags+4 || argc > 1+flags+5))
|
||||
|| (flat && (argc < 1+flags+2 || argc > 1+flags+3))) {
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
@@ -122,7 +122,11 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
value = strtol(argv[flat?1+flags+1:1+flags+3], &end, 0);
|
||||
/* rest is the same for both modes so we cheat on flags */
|
||||
if (!flat)
|
||||
flags += 2;
|
||||
|
||||
value = strtol(argv[flags+2], &end, 0);
|
||||
if (*end) {
|
||||
fprintf(stderr, "Error: Invalid value!\n");
|
||||
help();
|
||||
@@ -135,6 +139,21 @@ int main(int argc, char *argv[])
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (flags+3 < argc) {
|
||||
vmask = strtol(argv[flags+3], &end, 0);
|
||||
if (*end) {
|
||||
fprintf(stderr, "Error: Invalid mask!\n");
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
if (vmask < 0 || vmask > 0xff) {
|
||||
fprintf(stderr, "Error: Mask out of range "
|
||||
"(0x00-0xff)!\n");
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (getuid()) {
|
||||
fprintf(stderr, "Error: Can only be run as root "
|
||||
"(or make it suid root)\n");
|
||||
@@ -148,13 +167,15 @@ int main(int argc, char *argv[])
|
||||
"system crashes, data loss and worse!\n");
|
||||
|
||||
if (flat)
|
||||
fprintf(stderr, "I will write value 0x%02x to address "
|
||||
"0x%x.\n", value, addrreg);
|
||||
fprintf(stderr, "I will write value 0x%02x%s to address "
|
||||
"0x%x.\n", value, vmask ? " (masked)" : "",
|
||||
addrreg);
|
||||
else
|
||||
fprintf(stderr, "I will write value 0x%02x to address "
|
||||
fprintf(stderr, "I will write value 0x%02x%s to address "
|
||||
"0x%02x of chip with address register 0x%x\n"
|
||||
"and data register 0x%x.\n",
|
||||
value, addr, addrreg, datareg);
|
||||
value, vmask ? " (masked)" : "", addr,
|
||||
addrreg, datareg);
|
||||
|
||||
fprintf(stderr, "Continue? [Y/n] ");
|
||||
fflush(stderr);
|
||||
@@ -185,19 +206,53 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
#endif
|
||||
|
||||
/* write */
|
||||
if (flat) {
|
||||
outb(value, addrreg);
|
||||
} else {
|
||||
outb(addr, addrreg);
|
||||
outb(value, datareg);
|
||||
if (vmask) {
|
||||
int oldvalue;
|
||||
|
||||
if (flat) {
|
||||
oldvalue = inb(addrreg);
|
||||
} else {
|
||||
outb(addr, addrreg);
|
||||
oldvalue = inb(datareg);
|
||||
}
|
||||
|
||||
if (oldvalue < 0) {
|
||||
fprintf(stderr, "Error: Failed to read old value\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
value = (value & vmask) | (oldvalue & ~vmask);
|
||||
|
||||
if (!yes) {
|
||||
char s[2];
|
||||
|
||||
fprintf(stderr, "Old value 0x%02x, write mask "
|
||||
"0x%02x: Will write 0x%02x to %s "
|
||||
"0x%02x\n", oldvalue, vmask, value,
|
||||
flat ? "address" : "register",
|
||||
flat ? addrreg : addr);
|
||||
|
||||
fprintf(stderr, "Continue? [Y/n] ");
|
||||
fflush(stderr);
|
||||
fgets(s, 2, stdin);
|
||||
if (s[0] != '\n' && s[0] != 'y' && s[0] != 'Y') {
|
||||
fprintf(stderr, "Aborting on user request.\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* readback */
|
||||
/* do the real thing */
|
||||
if (flat) {
|
||||
/* write */
|
||||
outb(value, addrreg);
|
||||
/* readback */
|
||||
res = inb(addrreg);
|
||||
} else {
|
||||
/* write */
|
||||
outb(addr, addrreg);
|
||||
outb(value, datareg);
|
||||
/* readback */
|
||||
res = inb(datareg);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user