Blame prog/dump/isaset.c

Packit Service 23242a
/*
Packit Service 23242a
    isaset.c - isaset, a user-space program to write ISA registers
Packit Service 23242a
    Copyright (C) 2000  Frodo Looijaard <frodol@dds.nl>, and
Packit Service 23242a
                        Mark D. Studebaker <mdsxyz123@yahoo.com>
Packit Service 23242a
    Copyright (C) 2004-2011  Jean Delvare <jdelvare@suse.de>
Packit Service 23242a
Packit Service 23242a
    This program is free software; you can redistribute it and/or modify
Packit Service 23242a
    it under the terms of the GNU General Public License as published by
Packit Service 23242a
    the Free Software Foundation; either version 2 of the License, or
Packit Service 23242a
    (at your option) any later version.
Packit Service 23242a
Packit Service 23242a
    This program is distributed in the hope that it will be useful,
Packit Service 23242a
    but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 23242a
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 23242a
    GNU General Public License for more details.
Packit Service 23242a
Packit Service 23242a
    You should have received a copy of the GNU General Public License
Packit Service 23242a
    along with this program; if not, write to the Free Software
Packit Service 23242a
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
Packit Service 23242a
    MA 02110-1301 USA.
Packit Service 23242a
*/
Packit Service 23242a
Packit Service 23242a
/*
Packit Service 23242a
	Typical usage:
Packit Service 23242a
	isaset 0x295 0x296 0x10 0x12	Write 0x12 to address 0x10 using address/data registers
Packit Service 23242a
	isaset -f 0x5010 0x12		Write 0x12 to location 0x5010
Packit Service 23242a
*/
Packit Service 23242a
Packit Service 23242a
#include <sys/io.h>
Packit Service 23242a
#include <stdio.h>
Packit Service 23242a
#include <stdlib.h>
Packit Service 23242a
#include <unistd.h>
Packit Service 23242a
#include <string.h>
Packit Service 23242a
#include "util.h"
Packit Service 23242a
Packit Service 23242a
#ifdef __powerpc__
Packit Service 23242a
unsigned long isa_io_base = 0; /* XXX for now */
Packit Service 23242a
#endif /* __powerpc__ */
Packit Service 23242a
Packit Service 23242a
static void help(void)
Packit Service 23242a
{
Packit Service 23242a
	fprintf(stderr,
Packit Service 23242a
	        "Syntax for I2C-like access:\n"
Packit Service 23242a
	        "  isaset [OPTIONS] ADDRREG DATAREG ADDRESS VALUE [MASK]\n"
Packit Service 23242a
	        "Syntax for flat address space:\n"
Packit Service 23242a
	        "  isaset -f [OPTIONS] ADDRESS VALUE [MASK]\n"
Packit Service 23242a
		"Options:\n"
Packit Service 23242a
		"  -f	Enable flat address space mode\n"
Packit Service 23242a
		"  -y	Assume affirmative answer to all questions\n"
Packit Service 23242a
		"  -W	Write a word (16-bit) value\n"
Packit Service 23242a
		"  -L	Write a long (32-bit) value\n");
Packit Service 23242a
}
Packit Service 23242a
Packit Service 23242a
int main(int argc, char *argv[])
Packit Service 23242a
{
Packit Service 23242a
	int addrreg, datareg = 0, addr = 0;
Packit Service 23242a
	unsigned long value, vmask = 0, maxval = 0xff, res;
Packit Service 23242a
	int flags = 0;
Packit Service 23242a
	int flat = 0, yes = 0, width = 1;
Packit Service 23242a
	char *end;
Packit Service 23242a
Packit Service 23242a
	/* handle (optional) flags first */
Packit Service 23242a
	while (1+flags < argc && argv[1+flags][0] == '-') {
Packit Service 23242a
		switch (argv[1+flags][1]) {
Packit Service 23242a
		case 'f': flat = 1; break;
Packit Service 23242a
		case 'y': yes = 1; break;
Packit Service 23242a
		case 'W': width = 2; maxval = 0xffff; break;
Packit Service 23242a
		case 'L': width = 4; maxval = 0xffffffff; break;
Packit Service 23242a
		default:
Packit Service 23242a
			fprintf(stderr, "Warning: Unsupported flag "
Packit Service 23242a
				"\"-%c\"!\n", argv[1+flags][1]);
Packit Service 23242a
			help();
Packit Service 23242a
			exit(1);
Packit Service 23242a
		}
Packit Service 23242a
		flags++;
Packit Service 23242a
	}
Packit Service 23242a
Packit Service 23242a
	/* verify that the argument count is correct */
Packit Service 23242a
	if ((!flat && (argc < 1+flags+4 || argc > 1+flags+5))
Packit Service 23242a
	 || (flat && (argc < 1+flags+2 || argc > 1+flags+3))) {
Packit Service 23242a
		help();
Packit Service 23242a
		exit(1);
Packit Service 23242a
	}
Packit Service 23242a
Packit Service 23242a
	addrreg = strtol(argv[1+flags], &end, 0);
Packit Service 23242a
	if (*end) {
Packit Service 23242a
		fprintf(stderr, "Error: Invalid address!\n");
Packit Service 23242a
		help();
Packit Service 23242a
		exit(1);
Packit Service 23242a
	}
Packit Service 23242a
	if (addrreg < 0 || addrreg > (flat?0xffff:0x3fff)) {
Packit Service 23242a
		fprintf(stderr,
Packit Service 23242a
		        "Error: Address out of range (0x0000-0x%04x)!\n",
Packit Service 23242a
			flat?0xffff:0x3fff);
Packit Service 23242a
		help();
Packit Service 23242a
		exit(1);
Packit Service 23242a
	}
Packit Service 23242a
Packit Service 23242a
	if (!flat) {
Packit Service 23242a
		datareg = strtol(argv[1+flags+1], &end, 0);
Packit Service 23242a
		if (*end) {
Packit Service 23242a
			fprintf(stderr, "Error: Invalid data register!\n");
Packit Service 23242a
			help();
Packit Service 23242a
			exit(1);
Packit Service 23242a
		}
Packit Service 23242a
		if (datareg < 0 || datareg > 0x3fff) {
Packit Service 23242a
			fprintf(stderr, "Error: Data register out of range "
Packit Service 23242a
			        "(0x0000-0x3fff)!\n");
Packit Service 23242a
			help();
Packit Service 23242a
			exit(1);
Packit Service 23242a
		}
Packit Service 23242a
Packit Service 23242a
		addr = strtol(argv[1+flags+2], &end, 0);
Packit Service 23242a
		if (*end) {
Packit Service 23242a
			fprintf(stderr, "Error: Invalid address!\n");
Packit Service 23242a
			help();
Packit Service 23242a
			exit(1);
Packit Service 23242a
		}
Packit Service 23242a
		if (addr < 0 || addr > 0xff) {
Packit Service 23242a
			fprintf(stderr, "Error: Address out of range "
Packit Service 23242a
			        "(0x00-0xff)!\n");
Packit Service 23242a
			help();
Packit Service 23242a
			exit(1);
Packit Service 23242a
		}
Packit Service 23242a
	}
Packit Service 23242a
Packit Service 23242a
	/* rest is the same for both modes so we cheat on flags */
Packit Service 23242a
	if (!flat)
Packit Service 23242a
		flags += 2;
Packit Service 23242a
Packit Service 23242a
	value = strtoul(argv[flags+2], &end, 0);
Packit Service 23242a
	if (*end) {
Packit Service 23242a
		fprintf(stderr, "Error: Invalid value!\n");
Packit Service 23242a
		help();
Packit Service 23242a
		exit(1);
Packit Service 23242a
	}
Packit Service 23242a
	if (value > maxval) {
Packit Service 23242a
		fprintf(stderr, "Error: Value out of range "
Packit Service 23242a
			"(0x%0*u-%0*lu)!\n", width * 2, 0, width * 2, maxval);
Packit Service 23242a
		help();
Packit Service 23242a
		exit(1);
Packit Service 23242a
	}
Packit Service 23242a
Packit Service 23242a
	if (flags+3 < argc) {
Packit Service 23242a
		vmask = strtoul(argv[flags+3], &end, 0);
Packit Service 23242a
		if (*end) {
Packit Service 23242a
			fprintf(stderr, "Error: Invalid mask!\n");
Packit Service 23242a
			help();
Packit Service 23242a
			exit(1);
Packit Service 23242a
		}
Packit Service 23242a
		if (vmask > maxval) {
Packit Service 23242a
			fprintf(stderr, "Error: Mask out of range "
Packit Service 23242a
				"(0x%0*u-%0*lu)!\n", width * 2, 0,
Packit Service 23242a
				width * 2, maxval);
Packit Service 23242a
			help();
Packit Service 23242a
			exit(1);
Packit Service 23242a
		}
Packit Service 23242a
	}
Packit Service 23242a
Packit Service 23242a
	if (geteuid()) {
Packit Service 23242a
		fprintf(stderr, "Error: Can only be run as root "
Packit Service 23242a
		        "(or make it suid root)\n");
Packit Service 23242a
		exit(1);
Packit Service 23242a
	}
Packit Service 23242a
Packit Service 23242a
	if (!yes) {
Packit Service 23242a
		fprintf(stderr, "WARNING! Running this program can cause "
Packit Service 23242a
		        "system crashes, data loss and worse!\n");
Packit Service 23242a
Packit Service 23242a
		if (flat)
Packit Service 23242a
			fprintf(stderr,
Packit Service 23242a
				"I will write value 0x%0*lx%s to address "
Packit Service 23242a
		                "0x%x.\n", width * 2, value,
Packit Service 23242a
				vmask ? " (masked)" : "", addrreg);
Packit Service 23242a
		else
Packit Service 23242a
			fprintf(stderr,
Packit Service 23242a
				"I will write value 0x%0*lx%s to address "
Packit Service 23242a
		                "0x%02x of chip with address register 0x%x\n"
Packit Service 23242a
		                "and data register 0x%x.\n", width * 2,
Packit Service 23242a
		                value, vmask ? " (masked)" : "", addr,
Packit Service 23242a
			        addrreg, datareg);
Packit Service 23242a
Packit Service 23242a
		fprintf(stderr, "Continue? [Y/n] ");
Packit Service 23242a
		fflush(stderr);
Packit Service 23242a
		if (!user_ack(1)) {
Packit Service 23242a
			fprintf(stderr, "Aborting on user request.\n");
Packit Service 23242a
			exit(0);
Packit Service 23242a
		}
Packit Service 23242a
	}
Packit Service 23242a
Packit Service 23242a
#ifndef __powerpc__
Packit Service 23242a
	if (!flat && datareg < 0x400 && addrreg < 0x400) {
Packit Service 23242a
		if (ioperm(datareg, 1, 1)) {
Packit Service 23242a
			fprintf(stderr, "Error: Could not ioperm() data "
Packit Service 23242a
			        "register!\n");
Packit Service 23242a
			exit(1);
Packit Service 23242a
		}
Packit Service 23242a
		if (ioperm(addrreg, 1, 1)) {
Packit Service 23242a
			fprintf(stderr, "Error: Could not ioperm() address "
Packit Service 23242a
		        	"register!\n");
Packit Service 23242a
			exit(1);
Packit Service 23242a
		}
Packit Service 23242a
	} else {
Packit Service 23242a
		if (iopl(3)) {
Packit Service 23242a
			fprintf(stderr, "Error: Could not do iopl(3)!\n");
Packit Service 23242a
			exit(1);
Packit Service 23242a
		}
Packit Service 23242a
	}
Packit Service 23242a
#endif
Packit Service 23242a
Packit Service 23242a
	if (vmask) {
Packit Service 23242a
		unsigned long oldvalue;
Packit Service 23242a
Packit Service 23242a
		if (flat) {
Packit Service 23242a
			oldvalue = inx(addrreg, width);
Packit Service 23242a
		} else {	
Packit Service 23242a
			outb(addr, addrreg);
Packit Service 23242a
			oldvalue = inx(datareg, width);
Packit Service 23242a
		}
Packit Service 23242a
Packit Service 23242a
		value = (value & vmask) | (oldvalue & ~vmask);
Packit Service 23242a
Packit Service 23242a
		if (!yes) {
Packit Service 23242a
			fprintf(stderr, "Old value 0x%0*lx, write mask "
Packit Service 23242a
				"0x%0*lx: Will write 0x%0*lx to %s "
Packit Service 23242a
				"0x%02x\n", width * 2, oldvalue,
Packit Service 23242a
				width * 2, vmask, width * 2, value,
Packit Service 23242a
				flat ? "address" : "register",
Packit Service 23242a
				flat ? addrreg : addr);
Packit Service 23242a
Packit Service 23242a
			fprintf(stderr, "Continue? [Y/n] ");
Packit Service 23242a
			fflush(stderr);
Packit Service 23242a
			if (!user_ack(1)) {
Packit Service 23242a
				fprintf(stderr, "Aborting on user request.\n");
Packit Service 23242a
				exit(0);
Packit Service 23242a
			}
Packit Service 23242a
		}
Packit Service 23242a
	}
Packit Service 23242a
Packit Service 23242a
	/* do the real thing */
Packit Service 23242a
	if (flat) {
Packit Service 23242a
		/* write */
Packit Service 23242a
		outx(value, addrreg, width);
Packit Service 23242a
		/* readback */
Packit Service 23242a
		res = inx(addrreg, width);
Packit Service 23242a
	} else {	
Packit Service 23242a
		/* write */
Packit Service 23242a
		outb(addr, addrreg);
Packit Service 23242a
		outx(value, datareg, width);
Packit Service 23242a
		/* readback */
Packit Service 23242a
		res = inx(datareg, width);
Packit Service 23242a
	}
Packit Service 23242a
Packit Service 23242a
	if (res != value) {
Packit Service 23242a
		fprintf(stderr, "Data mismatch, wrote 0x%0*lx, "
Packit Service 23242a
		        "read 0x%0*lx back.\n", width * 2, value,
Packit Service 23242a
			width * 2, res);
Packit Service 23242a
	}
Packit Service 23242a
Packit Service 23242a
	exit(0);
Packit Service 23242a
}