pcitool.c revision 09b1eac246a4e627fcbd1ce5bf8005746cbe45ea
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * CDDL HEADER START
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * The contents of this file are subject to the terms of the
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * Common Development and Distribution License (the "License").
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * You may not use this file except in compliance with the License.
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * See the License for the specific language governing permissions
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * and limitations under the License.
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * When distributing Covered Code, include this CDDL HEADER in each
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * If applicable, add the following below this CDDL HEADER, with the
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * fields enclosed by brackets "[]" replaced with your own identifying
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * information: Portions Copyright [yyyy] [name of copyright owner]
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * CDDL HEADER END
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * Use is subject to license terms.
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim/* This file is the main module for the pcitool. */
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim/* First 16 longs of device PCI config header. */
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimtypedef union {
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim/* Used by probe printing functions. */
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimtypedef struct {
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim uint16_t cfg_offset; /* Offset of data within config space. */
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim char *abbrev_hdr; /* Abbreviated header for this data. */
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim char *full_hdr; /* Full header for this data, verbose option. */
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim/* Used to package many args into one arg for probe di_node walk function. */
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimtypedef struct {
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * Read config space in native processor endianness. Endian-neutral
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * processing can then take place. On big endian machines, MSB and LSB
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * of little endian data end up switched if read as little endian.
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * They are in correct order if read as big endian.
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim/* status error lookup table. */
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimstatic struct {
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim "No error status returned from driver" },
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim "CPU is non-existent or not online" },
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim "INO is out of range or invalid" },
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim "MSI is out of range or invalid" },
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim "Timeout waiting for pending interrupts to clear" },
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim "Reg property has invalid format" },
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim "Address out of range or invalid" },
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim "Improper address alignment for access attempted" },
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim "Argument out of range" },
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim "End of address range" },
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim "Device ROM is disabled. Cannot read" },
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim "Write to ROM not allowed" },
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim "IO error encountered" },
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim "Size is invalid for this platform" },
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim/* Used with ^C handler to stop looping in repeat mode in do_device_or_nexus. */
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimstatic char *strstatus(pcitool_errno_t pcitool_status);
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimstatic int open_node(char *device, pcitool_uiargs_t *input_args_p);
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimstatic void print_probe_value(pci_conf_hdr_t *config_hdr_p, uint16_t offset,
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimstatic void print_probe_info_verbose(pci_conf_hdr_t *config_hdr_p,
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimstatic void print_probe_info_nonverbose(pci_conf_hdr_t *config_hdr_p,
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimstatic void print_probe_info(pci_conf_hdr_t *config_hdr_p,
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimstatic int get_config_header(int fd, uint8_t bus_no, uint8_t dev_no,
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimstatic int do_probe(int fd, di_node_t di_node, di_prom_handle_t di_phdl,
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimstatic int process_nexus_node(di_node_t node, di_minor_t minor, void *arg);
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimstatic int do_probe_walk(pcitool_uiargs_t *input_args_p, char *pathname);
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimstatic void print_bytedump_header(boolean_t do_chardump);
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimstatic int bytedump_get(int fd, int cmd, pcitool_reg_t *prg_p,
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimstatic uint32_t set_acc_attr(pcitool_uiargs_t *input_args_p);
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimstatic int do_single_access(int fd, int cmd, pcitool_reg_t *prg_p,
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimstatic int do_device_or_nexus(int fd, pcitool_uiargs_t *input_args_p);
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimstatic void print_intr_info(pcitool_intr_get_t *iget_p);
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimstatic int get_single_interrupt(int fd, pcitool_intr_get_t **iget_pp,
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimstatic int get_interrupts(int fd, pcitool_uiargs_t *input_args_p);
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimstatic int set_interrupts(int fd, pcitool_uiargs_t *input_args_p);
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimstatic int do_interrupts(int fd, pcitool_uiargs_t *input_args_p);
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim/* *************** General ************** */
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * Handler for ^C to stop looping.
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim/*ARGSUSED*/
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim * Print string based on PCItool status returned from driver.
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimstatic char *
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim for (i = 0; pcitool_stat_str[i].string != NULL; i++) {
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim return ("Unknown status returned from driver.");
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kimopen_node(char *device, pcitool_uiargs_t *input_args_p)
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim char *path; /* For building full nexus pathname. */
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim /* Check for names starting with /devices. */
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim prefix = (strstr(device, slash_devices) == device) ? "" : slash_devices;
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim device + (strlen(device) - strlen(PCI_MINOR_INTR))) {
9e86db79b7d1bbc5f2f04e99954cbd5eae0e22bbHyon Kim device + (strlen(device) - strlen(PCI_MINOR_REG))) {
return (fd);
while (size-- > 0) {
if (!verbose) {
if (verbose) {
if ((rval =
return (rval);
int func;
int first_func = 0;
func++) {
SUCCESS) {
return (rval);
int bus;
int dev;
int first_bus = 0;
int first_dev = 0;
int len;
if (len <= 0) {
if (len > 0) {
return (rval);
int fd;
char *trunc;
return (DI_WALK_CONTINUE);
return (DI_WALK_CONTINUE);
return (rval);
if (do_chardump) {
if (do_chardump) {
} buffer_t;
int skip_begin;
int skip_end = 0;
int skip_begin2;
int skip_end2;
int lines_since_header = 0;
int next;
(!(continue_on_errs))) {
if (print_addr == 0) {
error_mask |=
switch (read_size) {
next++;
if (next != 0) {
if (next == 0) {
if (skip_end) {
skip_end--;
} else if (skip_begin > i) {
skip_begin--;
if (do_chardump) {
for (i = 0; i < DUMP_BUF_SIZE; i++) {
if (skip_begin2) {
skip_begin2--;
lines_since_header = 0;
error_mask = 0;
return (rval);
static uint32_t
return (access_attrs);
int rval;
switch (cmd) {
case PCITOOL_NEXUS_SET_REG:
case PCITOOL_DEVICE_SET_REG:
return (rval);
} else if (!(is_write)) {
return (rval);
(void) printf(
if (write_cmd != 0) {
(keep_looping));
return (SUCCESS);
return (errno);
return (SUCCESS);
return (errno);
return (SUCCESS);
#define INIT_NUM_DEVS 0
int msi;
for (msi = 0;
msi++) {
int ino;
for (ino = 0;
ino++) {
return (rval);
case PCITOOL_CTLR_TYPE_RISC:
case PCITOOL_CTLR_TYPE_UPPC:
#ifdef __x86
return (rval);
return (rval);
int gic_rval;
int gi_rval;
return (EINVAL);
return (SUCCESS);
return (rval);