Module Name:    src
Committed By:   manu
Date:           Mon Sep  1 07:11:19 UTC 2014

Modified Files:
        src/usr.sbin/pcictl: pcictl.8 pcictl.c

Log Message:
read and write commands for pcictl, from riastradh@ and wiz@
http://mail-index.netbsd.org/tech-kern/2014/08/26/msg017572.html


To generate a diff of this commit:
cvs rdiff -u -r1.13 -r1.14 src/usr.sbin/pcictl/pcictl.8
cvs rdiff -u -r1.20 -r1.21 src/usr.sbin/pcictl/pcictl.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.sbin/pcictl/pcictl.8
diff -u src/usr.sbin/pcictl/pcictl.8:1.13 src/usr.sbin/pcictl/pcictl.8:1.14
--- src/usr.sbin/pcictl/pcictl.8:1.13	Sun Aug 31 09:59:08 2014
+++ src/usr.sbin/pcictl/pcictl.8	Mon Sep  1 07:11:19 2014
@@ -1,4 +1,4 @@
-.\"	$NetBSD: pcictl.8,v 1.13 2014/08/31 09:59:08 wiz Exp $
+.\"	$NetBSD: pcictl.8,v 1.14 2014/09/01 07:11:19 manu Exp $
 .\"
 .\" Copyright 2001 Wasabi Systems, Inc.
 .\" All rights reserved.
@@ -83,6 +83,31 @@ at the specified bus, device, and functi
 If the bus is not specified, it defaults to the bus number of the
 PCI bus specified on the command line.
 If the function is not specified, it defaults to 0.
+.Pp
+.Nm read
+.Op Fl b Ar bus
+.Fl d Ar device
+.Op Fl f Ar function
+.Ar reg
+.Pp
+Read the specified 32-bit aligned PCI configuration register and print
+it in hexadecimal to standard output.
+If the bus is not specified, it defaults to the bus number of the
+PCI bus specified on the command line.
+If the function is not specified, it defaults to 0.
+.Pp
+.Nm write
+.Op Fl b Ar bus
+.Fl d Ar device
+.Op Fl f Ar function
+.Ar reg
+.Ar value
+.Pp
+Write the specified value to the specified 32-bit aligned PCI
+configuration register.
+If the bus is not specified, it defaults to the bus number of the
+PCI bus specified on the command line.
+If the function is not specified, it defaults to 0.
 .Sh FILES
 .Pa /dev/pci*
 - PCI bus device nodes

Index: src/usr.sbin/pcictl/pcictl.c
diff -u src/usr.sbin/pcictl/pcictl.c:1.20 src/usr.sbin/pcictl/pcictl.c:1.21
--- src/usr.sbin/pcictl/pcictl.c:1.20	Sun Aug 31 09:59:08 2014
+++ src/usr.sbin/pcictl/pcictl.c	Mon Sep  1 07:11:19 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: pcictl.c,v 1.20 2014/08/31 09:59:08 wiz Exp $	*/
+/*	$NetBSD: pcictl.c,v 1.21 2014/09/01 07:11:19 manu Exp $	*/
 
 /*
  * Copyright 2001 Wasabi Systems, Inc.
@@ -77,6 +77,8 @@ static int	print_names = 0;
 
 static void	cmd_list(int, char *[]);
 static void	cmd_dump(int, char *[]);
+static void	cmd_read(int, char *[]);
+static void	cmd_write(int, char *[]);
 
 static const struct command commands[] = {
 	{ "list",
@@ -89,10 +91,21 @@ static const struct command commands[] =
 	  cmd_dump,
 	  O_RDONLY },
 
+	{ "read",
+	  "[-b bus] -d device [-f function] reg",
+	  cmd_read,
+	  O_RDONLY },
+
+	{ "write",
+	  "[-b bus] -d device [-f function] reg value",
+	  cmd_write,
+	  O_WRONLY },
+
 	{ 0, 0, 0, 0 },
 };
 
 static int	parse_bdf(const char *);
+static u_int	parse_reg(const char *);
 
 static void	scan_pci(int, int, int, void (*)(u_int, u_int, u_int));
 
@@ -234,6 +247,87 @@ cmd_dump(int argc, char *argv[])
 	scan_pci(bus, dev, func, scan_pci_dump);
 }
 
+static void
+cmd_read(int argc, char *argv[])
+{
+	int bus, dev, func;
+	u_int reg;
+	pcireg_t value;
+	int ch;
+
+	bus = pci_businfo.busno;
+	func = 0;
+	dev = -1;
+
+	while ((ch = getopt(argc, argv, "b:d:f:")) != -1) {
+		switch (ch) {
+		case 'b':
+			bus = parse_bdf(optarg);
+			break;
+		case 'd':
+			dev = parse_bdf(optarg);
+			break;
+		case 'f':
+			func = parse_bdf(optarg);
+			break;
+		default:
+			usage();
+		}
+	}
+	argv += optind;
+	argc -= optind;
+
+	if (argc != 1)
+		usage();
+	reg = parse_reg(argv[0]);
+	if (pcibus_conf_read(pcifd, bus, dev, func, reg, &value) == -1)
+		err(EXIT_FAILURE, "pcibus_conf_read"
+		    "(bus %d dev %d func %d reg %u)", bus, dev, func, reg);
+	if (printf("%08x\n", value) < 0)
+		err(EXIT_FAILURE, "printf");
+}
+
+static void
+cmd_write(int argc, char *argv[])
+{
+	int bus, dev, func;
+	u_int reg;
+	pcireg_t value;
+	int ch;
+
+	bus = pci_businfo.busno;
+	func = 0;
+	dev = -1;
+
+	while ((ch = getopt(argc, argv, "b:d:f:")) != -1) {
+		switch (ch) {
+		case 'b':
+			bus = parse_bdf(optarg);
+			break;
+		case 'd':
+			dev = parse_bdf(optarg);
+			break;
+		case 'f':
+			func = parse_bdf(optarg);
+			break;
+		default:
+			usage();
+		}
+	}
+	argv += optind;
+	argc -= optind;
+
+	if (argc != 2)
+		usage();
+	reg = parse_reg(argv[0]);
+	__CTASSERT(sizeof(value) == sizeof(u_int));
+	value = parse_reg(argv[1]);
+	if (pcibus_conf_write(pcifd, bus, dev, func, reg, value) == -1)
+		err(EXIT_FAILURE, "pcibus_conf_write"
+		    "(bus %d dev %d func %d reg %u value 0x%x)",
+		    bus, dev, func, reg, value);
+}
+
 static int
 parse_bdf(const char *str)
 {
@@ -244,9 +338,32 @@ parse_bdf(const char *str)
 	    strcmp(str, "any") == 0)
 		return (-1);
 
+	errno = 0;
 	value = strtol(str, &end, 0);
-	if (*end != '\0') 
+	if ((str[0] == '\0') || (*end != '\0'))
+		errx(EXIT_FAILURE, "\"%s\" is not a number", str);
+	if ((errno == ERANGE) && ((value == LONG_MIN) || (value == LONG_MAX)))
+		errx(EXIT_FAILURE, "out of range: %s", str);
+	if ((value < INT_MIN) || (INT_MAX < value))
+		errx(EXIT_FAILURE, "out of range: %lu", value);
+
+	return value;
+}
+
+static u_int
+parse_reg(const char *str)
+{
+	unsigned long value;
+	char *end;
+
+	errno = 0;
+	value = strtoul(str, &end, 0);
+	if (*end != '\0')
 		errx(EXIT_FAILURE, "\"%s\" is not a number", str);
+	if ((errno == ERANGE) && (value == ULONG_MAX))
+		errx(EXIT_FAILURE, "out of range: %s", str);
+	if (UINT_MAX < value)
+		errx(EXIT_FAILURE, "out of range: %lu", value);
 
 	return value;
 }

Reply via email to