tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: ixg(4) performances
Date: Tue, 26 Aug 2014 10:25:52 -0400
From: christos%zoulas.com@localhost (Christos Zoulas)
On Aug 26, 2:23pm, manu%netbsd.org@localhost (Emmanuel Dreyfus) wrote:
-- Subject: Re: ixg(4) performances
| I see <dev/pci/pciio.h> has a PCI_IOC_CFGREAD / PCI_IOC_CFGWRITE ioctl,
| does that means Linux's setpci can be easily reproduced?
I would probably extend pcictl with cfgread and cfgwrite commands.
How about the attached patch? I've been sitting on this for months.
Index: usr.sbin/pcictl/pcictl.8
===================================================================
RCS file: /cvsroot/src/usr.sbin/pcictl/pcictl.8,v
retrieving revision 1.10
diff -p -u -r1.10 pcictl.8
--- usr.sbin/pcictl/pcictl.8 25 Feb 2011 21:40:48 -0000 1.10
+++ usr.sbin/pcictl/pcictl.8 26 Aug 2014 15:38:55 -0000
@@ -33,7 +33,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd February 25, 2011
+.Dd June 12, 2014
.Dt PCICTL 8
.Os
.Sh NAME
@@ -79,6 +79,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: usr.sbin/pcictl/pcictl.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/pcictl/pcictl.c,v
retrieving revision 1.18
diff -p -u -r1.18 pcictl.c
--- usr.sbin/pcictl/pcictl.c 30 Aug 2011 20:08:38 -0000 1.18
+++ usr.sbin/pcictl/pcictl.c 26 Aug 2014 15:38:55 -0000
@@ -76,6 +76,8 @@ static int print_numbers = 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",
@@ -88,10 +90,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));
@@ -230,6 +243,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)
{
@@ -240,9 +334,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;
}
Home |
Main Index |
Thread Index |
Old Index