d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * CDDL HEADER START
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur *
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * The contents of this file are subject to the terms of the
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Common Development and Distribution License (the "License").
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * You may not use this file except in compliance with the License.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur *
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * or http://www.opensolaris.org/os/licensing.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * See the License for the specific language governing permissions
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * and limitations under the License.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur *
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * When distributing Covered Code, include this CDDL HEADER in each
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * If applicable, add the following below this CDDL HEADER, with the
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * fields enclosed by brackets "[]" replaced with your own identifying
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * information: Portions Copyright [yyyy] [name of copyright owner]
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur *
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * CDDL HEADER END
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/*
8d7fafffed373567f52062b634e61fd50858b8d9Zhi-Jun Robin Fu * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/* This file is the main module for the pcitool. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#include <stdio.h>
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#include <stdlib.h>
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#include <unistd.h>
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#include <sys/inttypes.h>
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#include <signal.h>
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#include <sys/types.h>
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#include <sys/param.h>
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#include <fcntl.h>
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#include <strings.h>
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#include <ctype.h>
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#include <errno.h>
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#include <libdevinfo.h>
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#include <sys/sunddi.h>
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#ifdef __x86
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#include <sys/apic_ctlr.h>
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#endif
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#include <sys/pci.h>
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#include <sys/pci_tools.h>
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#include "pcitool_ui.h"
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/* First 16 longs of device PCI config header. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurtypedef union {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur uint8_t bytes[16 * sizeof (uint32_t)];
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur uint32_t dwords[16];
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur} pci_conf_hdr_t;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/* Used by probe printing functions. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurtypedef struct {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur uint16_t cfg_offset; /* Offset of data within config space. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur uint8_t size; /* Size of desired data field. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur char *abbrev_hdr; /* Abbreviated header for this data. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur char *full_hdr; /* Full header for this data, verbose option. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur} field_type_t;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/* Used to package many args into one arg for probe di_node walk function. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurtypedef struct {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur pcitool_uiargs_t *input_args_p;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur char *pathname;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur di_prom_handle_t di_phdl;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur} probe_walk_args_t;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Read config space in native processor endianness. Endian-neutral
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * processing can then take place. On big endian machines, MSB and LSB
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * of little endian data end up switched if read as little endian.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * They are in correct order if read as big endian.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#if defined(__sparc)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#define NATIVE_ENDIAN PCITOOL_ACC_ATTR_ENDN_BIG
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#elif defined(__x86)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#define NATIVE_ENDIAN PCITOOL_ACC_ATTR_ENDN_LTL
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#else
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#error "ISA is neither __sparc nor __x86"
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#endif
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/* status error lookup table. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic struct {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur pcitool_errno_t value;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur char *string;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur} pcitool_stat_str[] = {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCITOOL_SUCCESS,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "No error status returned from driver" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCITOOL_INVALID_CPUID,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "CPU is non-existent or not online" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCITOOL_INVALID_INO,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "INO is out of range or invalid" },
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan { PCITOOL_INVALID_MSI,
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan "MSI is out of range or invalid" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCITOOL_PENDING_INTRTIMEOUT,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "Timeout waiting for pending interrupts to clear" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCITOOL_REGPROP_NOTWELLFORMED,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "Reg property has invalid format" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCITOOL_INVALID_ADDRESS,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "Address out of range or invalid" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCITOOL_NOT_ALIGNED,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "Improper address alignment for access attempted" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCITOOL_OUT_OF_RANGE,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "Argument out of range" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCITOOL_END_OF_RANGE,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "End of address range" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCITOOL_ROM_DISABLED,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "Device ROM is disabled. Cannot read" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCITOOL_ROM_WRITE,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "Write to ROM not allowed" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCITOOL_IO_ERROR,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "IO error encountered" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCITOOL_INVALID_SIZE,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "Size is invalid for this platform" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { 0, NULL }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur};
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/* Used with ^C handler to stop looping in repeat mode in do_device_or_nexus. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic boolean_t keep_looping = B_TRUE;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic void signal_handler(int dummy);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic char *strstatus(pcitool_errno_t pcitool_status);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic int open_node(char *device, pcitool_uiargs_t *input_args_p);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic void print_probe_value(pci_conf_hdr_t *config_hdr_p, uint16_t offset,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur uint8_t size);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic void print_probe_info_verbose(pci_conf_hdr_t *config_hdr_p,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur pcitool_reg_t *info_p);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic void print_probe_info_nonverbose(pci_conf_hdr_t *config_hdr_p,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur pcitool_reg_t *info_p);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic void print_probe_info(pci_conf_hdr_t *config_hdr_p,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur pcitool_reg_t *info_p, boolean_t verbose);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic int get_config_header(int fd, uint8_t bus_no, uint8_t dev_no,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur uint8_t func_no, pci_conf_hdr_t *config_hdr_p);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int supports_ari(int fd, uint8_t bus_no);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic int probe_dev(int fd, pcitool_reg_t *prg_p,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur pcitool_uiargs_t *input_args_p);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic int do_probe(int fd, di_node_t di_node, di_prom_handle_t di_phdl,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur pcitool_uiargs_t *input_args_p);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic int process_nexus_node(di_node_t node, di_minor_t minor, void *arg);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic int do_probe_walk(pcitool_uiargs_t *input_args_p, char *pathname);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic void print_bytedump_header(boolean_t do_chardump);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic int bytedump_get(int fd, int cmd, pcitool_reg_t *prg_p,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur pcitool_uiargs_t *input_args_p);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic uint32_t set_acc_attr(pcitool_uiargs_t *input_args_p);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic int do_single_access(int fd, int cmd, pcitool_reg_t *prg_p,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur pcitool_uiargs_t *input_args_p);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic int do_device_or_nexus(int fd, pcitool_uiargs_t *input_args_p);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic void print_intr_info(pcitool_intr_get_t *iget_p);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic int get_single_interrupt(int fd, pcitool_intr_get_t **iget_pp,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur pcitool_uiargs_t *input_args_p);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic int get_interrupts(int fd, pcitool_uiargs_t *input_args_p);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic int set_interrupts(int fd, pcitool_uiargs_t *input_args_p);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic int do_interrupts(int fd, pcitool_uiargs_t *input_args_p);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/* *************** General ************** */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Handler for ^C to stop looping.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/*ARGSUSED*/
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic void
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaursignal_handler(int dummy)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur{
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur keep_looping = B_FALSE;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur}
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Print string based on PCItool status returned from driver.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic char *
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstrstatus(pcitool_errno_t pcitool_status)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur{
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int i;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur for (i = 0; pcitool_stat_str[i].string != NULL; i++) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (pcitool_stat_str[i].value == pcitool_status) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return (pcitool_stat_str[i].string);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return ("Unknown status returned from driver.");
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur}
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic int
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsauropen_node(char *device, pcitool_uiargs_t *input_args_p)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur{
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int fd;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur char *path; /* For building full nexus pathname. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int stringsize; /* Device name size. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur char *prefix;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur char *suffix;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur char *format;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur static char slash_devices[] = {"/devices"};
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur static char wcolon[] = {"%s%s:%s"};
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur static char wocolon[] = {"%s%s%s"};
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Check for names starting with /devices. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur prefix = (strstr(device, slash_devices) == device) ? "" : slash_devices;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur format = wcolon;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (input_args_p->flags & INTR_FLAG) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (strstr(device, PCI_MINOR_INTR) ==
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur device + (strlen(device) - strlen(PCI_MINOR_INTR))) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur suffix = "";
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur format = wocolon;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur suffix = PCI_MINOR_INTR;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (strstr(device, PCI_MINOR_REG) ==
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur device + (strlen(device) - strlen(PCI_MINOR_REG))) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur suffix = "";
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur format = wocolon;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur suffix = PCI_MINOR_REG;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Build nexus pathname.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * User specified /pci@1f,700000 becomes /devices/pci@1f,700000:intr
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * for interrupt nodes, and ...:reg for register nodes.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur *
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * ...The 2 at the end leaves room for a : and the terminating NULL.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur stringsize = strlen(prefix) + strlen(device) + strlen(suffix) + 2;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur path = malloc(stringsize);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*LINTED*/
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) snprintf(path, stringsize, format, prefix, device, suffix);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Open the nexus. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if ((fd = open(path, O_RDWR)) == -1) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (!(IS_QUIET(input_args_p->flags))) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) fprintf(stderr,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "Could not open nexus node %s: %s\n",
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur path, strerror(errno));
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return (fd);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur}
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/* ****************** Probe **************** */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/* The following are used by the probe printing functions. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/* Header 0 and 1 config space headers have these fields. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic field_type_t first_fields[] = {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCI_CONF_VENID, 2, "Vend", "Vendor ID" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCI_CONF_DEVID, 2, "Dev ", "Device ID" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCI_CONF_COMM, 2, "Cmd ", "Command" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCI_CONF_STAT, 2, "Stat", "Status" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCI_CONF_REVID, 1, "Rv", "Revision ID" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCI_CONF_PROGCLASS, 3, "Class ", "Class Code" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCI_CONF_CACHE_LINESZ, 1, "Ca", "Cache Line Size" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCI_CONF_LATENCY_TIMER, 1, "LT", "Latency Timer" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCI_CONF_HEADER, 1, "Hd", "Header Type" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCI_CONF_BIST, 1, "BI", "BIST" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { 0, 0, NULL, NULL }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur};
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/* Header 0 (for regular devices) have these fields. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic field_type_t last_dev_fields[] = {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCI_CONF_BASE0, 4, "BAR0", "Base Address Register 0 (@10)" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCI_CONF_BASE1, 4, "BAR1", "Base Address Register 1 (@14)" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCI_CONF_BASE2, 4, "BAR2", "Base Address Register 2 (@18)" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCI_CONF_BASE3, 4, "BAR3", "Base Address Register 3 (@1C)" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCI_CONF_BASE4, 4, "BAR4", "Base Address Register 4 (@20)" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCI_CONF_BASE5, 4, "BAR5", "Base Address Register 5 (@24)" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCI_CONF_ROM, 4, "ROM", "Expansion ROM Base Address Register (@30)" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { 0, 0, NULL, NULL }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur};
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/* Header 1 (PCI-PCI bridge devices) have these fields. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic field_type_t last_pcibrg_fields[] = {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCI_CONF_BASE0, 4, "BAR0", "Base Address Register 0 (@10)" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCI_CONF_BASE1, 4, "BAR1", "Base Address Register 1 (@14)" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCI_BCNF_ROM, 4, "ROM", "Expansion ROM Base Address Register (@38)" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { 0, 0, NULL, NULL }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur};
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/* Header 2 (PCI-Cardbus bridge devices) have these fields. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic field_type_t last_cbbrg_fields[] = {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { PCI_CBUS_SOCK_REG, 4, "SCKT", "Socket/ExCA Base Address (@10)" },
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur { 0, 0, NULL, NULL }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur};
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#define FMT_SIZE 7
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic void
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurprint_probe_value(pci_conf_hdr_t *config_hdr_p, uint16_t offset, uint8_t size)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur{
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur char format[FMT_SIZE];
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Size cannot be any larger than 4 bytes. This is not checked. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur uint32_t value = 0;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Build format of print, "%<size*2>.<size*2>x" */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) snprintf(format, FMT_SIZE, "%%%d.%dx ", size * 2, size * 2);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur while (size-- > 0) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur value = (value << 8) + config_hdr_p->bytes[offset + size];
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*LINTED*/
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf(format, value);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur}
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic void
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurprint_probe_info_verbose(pci_conf_hdr_t *config_hdr_p, pcitool_reg_t *info_p)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur{
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur field_type_t *last_fields = NULL;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int i;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf("\n"
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "Bus Number: %x Device Number: %x Function Number: %x\n",
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur info_p->bus_no, info_p->dev_no, info_p->func_no);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (info_p->phys_addr != 0) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf("Physical Address: 0x%" PRIx64 " \n",
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur info_p->phys_addr);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur switch (config_hdr_p->bytes[PCI_CONF_HEADER] & PCI_HEADER_TYPE_M) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur case PCI_HEADER_ZERO: /* Header type 0 is a regular device. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur last_fields = last_dev_fields;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur break;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur case PCI_HEADER_PPB: /* Header type 1 is a PCI-PCI bridge. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur last_fields = last_pcibrg_fields;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf("PCI-PCI bridge\n");
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur break;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur case PCI_HEADER_CARDBUS: /* Header type 2 is a cardbus bridge */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur last_fields = last_cbbrg_fields;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf("PCI-Cardbus bridge\n");
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur break;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur default:
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf("Unknown device\n");
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur break;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (last_fields != NULL) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur for (i = 0; first_fields[i].size != 0; i++) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf("%s: ", first_fields[i].full_hdr);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur print_probe_value(config_hdr_p,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur first_fields[i].cfg_offset, first_fields[i].size);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) putchar('\n');
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur for (i = 0; last_fields[i].size != 0; i++) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf("%s: ", last_fields[i].full_hdr);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur print_probe_value(config_hdr_p,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur last_fields[i].cfg_offset, last_fields[i].size);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) putchar('\n');
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur}
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic void
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurprint_probe_info_nonverbose(pci_conf_hdr_t *config_hdr_p, pcitool_reg_t *info_p)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur{
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int i;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf("%2.2x %2.2x %1.1x ",
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur info_p->bus_no, info_p->dev_no, info_p->func_no);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur for (i = 0; first_fields[i].size != 0; i++) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur print_probe_value(config_hdr_p,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur first_fields[i].cfg_offset, first_fields[i].size);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) putchar('\n');
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur}
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Print device information retrieved during probe mode.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Takes the PCI config header, plus address information retrieved from the
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * driver.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur *
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * When called with config_hdr_p == NULL, this function just prints a header
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * when not in verbose mode.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic void
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurprint_probe_info(
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur pci_conf_hdr_t *config_hdr_p, pcitool_reg_t *info_p, boolean_t verbose)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur{
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int i;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Print header if not in verbose mode. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (config_hdr_p == NULL) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (!verbose) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Bus dev func not from tble */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf("B D F ");
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur for (i = 0; first_fields[i].size != 0; i++) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf("%s ",
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur first_fields[i].abbrev_hdr);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) putchar('\n');
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (verbose) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur print_probe_info_verbose(config_hdr_p, info_p);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur print_probe_info_nonverbose(config_hdr_p, info_p);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur}
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Retrieve first 16 dwords of device's config header, except for the first
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * dword. First 16 dwords are defined by the PCI specification.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic int
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurget_config_header(int fd, uint8_t bus_no, uint8_t dev_no, uint8_t func_no,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur pci_conf_hdr_t *config_hdr_p)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur{
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur pcitool_reg_t cfg_prg;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int i;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int rval = SUCCESS;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Prepare a local pcitool_reg_t so as to not disturb the caller's. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur cfg_prg.offset = 0;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur cfg_prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_4 + NATIVE_ENDIAN;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur cfg_prg.bus_no = bus_no;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur cfg_prg.dev_no = dev_no;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur cfg_prg.func_no = func_no;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur cfg_prg.barnum = 0;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur cfg_prg.user_version = PCITOOL_VERSION;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Get dwords 1-15 of config space. They must be read as uint32_t. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur for (i = 1; i < (sizeof (pci_conf_hdr_t) / sizeof (uint32_t)); i++) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur cfg_prg.offset += sizeof (uint32_t);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if ((rval =
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur ioctl(fd, PCITOOL_DEVICE_GET_REG, &cfg_prg)) != SUCCESS) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur break;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur config_hdr_p->dwords[i] = (uint32_t)cfg_prg.data;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return (rval);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur}
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int
269473047d747f7815af570197e4ef7322d3632cEvan Yansupports_ari(int fd, uint8_t bus_no)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan pcitool_reg_t cfg_prg;
269473047d747f7815af570197e4ef7322d3632cEvan Yan int deadcount = 0;
269473047d747f7815af570197e4ef7322d3632cEvan Yan uint32_t data, hdr_next_ptr, hdr_cap_id;
269473047d747f7815af570197e4ef7322d3632cEvan Yan uint8_t dev_no = 0;
269473047d747f7815af570197e4ef7322d3632cEvan Yan uint8_t func_no = 0;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Prepare a local pcitool_reg_t so as to not disturb the caller's. */
269473047d747f7815af570197e4ef7322d3632cEvan Yan cfg_prg.bus_no = bus_no;
269473047d747f7815af570197e4ef7322d3632cEvan Yan cfg_prg.dev_no = dev_no;
269473047d747f7815af570197e4ef7322d3632cEvan Yan cfg_prg.func_no = func_no;
269473047d747f7815af570197e4ef7322d3632cEvan Yan cfg_prg.barnum = 0;
269473047d747f7815af570197e4ef7322d3632cEvan Yan cfg_prg.user_version = PCITOOL_VERSION;
8d7fafffed373567f52062b634e61fd50858b8d9Zhi-Jun Robin Fu cfg_prg.offset = 0;
269473047d747f7815af570197e4ef7322d3632cEvan Yan cfg_prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_4 + PCITOOL_ACC_ATTR_ENDN_LTL;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (ioctl(fd, PCITOOL_DEVICE_GET_REG, &cfg_prg) != SUCCESS) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (FAILURE);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan data = (uint32_t)cfg_prg.data;
8d7fafffed373567f52062b634e61fd50858b8d9Zhi-Jun Robin Fu if (data == (uint32_t)(-1))
8d7fafffed373567f52062b634e61fd50858b8d9Zhi-Jun Robin Fu return (FAILURE);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
8d7fafffed373567f52062b634e61fd50858b8d9Zhi-Jun Robin Fu cfg_prg.offset = PCI_CONF_COMM;
8d7fafffed373567f52062b634e61fd50858b8d9Zhi-Jun Robin Fu if (ioctl(fd, PCITOOL_DEVICE_GET_REG, &cfg_prg) != SUCCESS) {
8d7fafffed373567f52062b634e61fd50858b8d9Zhi-Jun Robin Fu return (FAILURE);
8d7fafffed373567f52062b634e61fd50858b8d9Zhi-Jun Robin Fu }
8d7fafffed373567f52062b634e61fd50858b8d9Zhi-Jun Robin Fu
8d7fafffed373567f52062b634e61fd50858b8d9Zhi-Jun Robin Fu data = (uint32_t)cfg_prg.data;
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (!((data >> 16) & PCI_STAT_CAP))
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (FAILURE);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan cfg_prg.offset = PCI_CONF_CAP_PTR;
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (ioctl(fd, PCITOOL_DEVICE_GET_REG, &cfg_prg) != SUCCESS) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (FAILURE);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan data = (uint32_t)cfg_prg.data;
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdr_next_ptr = data & 0xff;
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdr_cap_id = 0;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Find the PCIe capability.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan while ((hdr_next_ptr != PCI_CAP_NEXT_PTR_NULL) &&
269473047d747f7815af570197e4ef7322d3632cEvan Yan (hdr_cap_id != PCI_CAP_ID_PCI_E)) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (hdr_next_ptr < 0x40)
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan cfg_prg.offset = hdr_next_ptr;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (ioctl(fd, PCITOOL_DEVICE_GET_REG, &cfg_prg) != SUCCESS)
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (FAILURE);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan data = (uint32_t)cfg_prg.data;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdr_next_ptr = (data >> 8) & 0xFF;
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdr_cap_id = data & 0xFF;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (deadcount++ > 100)
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (FAILURE);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (hdr_cap_id != PCI_CAP_ID_PCI_E)
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (FAILURE);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Found a PCIe Capability */
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdr_next_ptr = 0x100;
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdr_cap_id = 0;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Now find the ARI Capability.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan while ((hdr_next_ptr != PCI_CAP_NEXT_PTR_NULL) &&
269473047d747f7815af570197e4ef7322d3632cEvan Yan (hdr_cap_id != 0xe)) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (hdr_next_ptr < 0x40)
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan cfg_prg.offset = hdr_next_ptr;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (ioctl(fd, PCITOOL_DEVICE_GET_REG, &cfg_prg) != SUCCESS) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (FAILURE);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan data = (uint32_t)cfg_prg.data;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdr_next_ptr = (data >> 20) & 0xFFF;
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdr_cap_id = data & 0xFFFF;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (deadcount++ > 100)
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (FAILURE);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (hdr_cap_id != 0xe)
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (FAILURE);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (SUCCESS);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Identify problematic southbridges. These have device id 0x5249 and
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * vendor id 0x10b9. Check for revision ID 0 and class code 060400 as well.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Values are little endian, so they are reversed for SPARC.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur *
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Check for these southbridges on all architectures, as the issue is a
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * southbridge issue, independent of processor.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur *
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * If one of these is found during probing, skip probing other devs/funcs on
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * the rest of the bus, since the southbridge and all devs underneath will
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * otherwise disappear.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#if (NATIVE_ENDIAN == PCITOOL_ACC_ATTR_ENDN_BIG)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#define U45_SB_DEVID_VID 0xb9104952
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#define U45_SB_CLASS_RID 0x00000406
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#else
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#define U45_SB_DEVID_VID 0x524910b9
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#define U45_SB_CLASS_RID 0x06040000
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#endif
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Probe device's functions. Modifies many fields in the prg_p.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic int
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurprobe_dev(int fd, pcitool_reg_t *prg_p, pcitool_uiargs_t *input_args_p)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur{
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur pci_conf_hdr_t config_hdr;
269473047d747f7815af570197e4ef7322d3632cEvan Yan boolean_t multi_function_device = B_FALSE;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int func;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int first_func = 0;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int last_func = PCI_REG_FUNC_M >> PCI_REG_FUNC_SHIFT;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int rval = SUCCESS;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (input_args_p->flags & FUNC_SPEC_FLAG) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur first_func = last_func = input_args_p->function;
269473047d747f7815af570197e4ef7322d3632cEvan Yan } else if (supports_ari(fd, prg_p->bus_no) == SUCCESS) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan multi_function_device = B_TRUE;
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (!(input_args_p->flags & DEV_SPEC_FLAG))
269473047d747f7815af570197e4ef7322d3632cEvan Yan last_func = 255;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Loop through at least func=first_func. Continue looping through
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * functions if there are no errors and the device is a multi-function
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * device.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur *
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * (Note, if first_func == 0, header will show whether multifunction
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * device and set multi_function_device. If first_func != 0, then we
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * will force the loop as the user wants a specific function to be
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * checked.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
269473047d747f7815af570197e4ef7322d3632cEvan Yan for (func = first_func; ((func <= last_func) &&
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur ((func == first_func) || (multi_function_device)));
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur func++) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (last_func > 7) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan prg_p->func_no = func & 0x7;
269473047d747f7815af570197e4ef7322d3632cEvan Yan prg_p->dev_no = (func >> 3) & 0x1f;
269473047d747f7815af570197e4ef7322d3632cEvan Yan } else
269473047d747f7815af570197e4ef7322d3632cEvan Yan prg_p->func_no = func;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Four things can happen here:
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur *
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * 1) ioctl comes back as EFAULT and prg_p->status is
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * PCITOOL_INVALID_ADDRESS. There is no device at this
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * location.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur *
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * 2) ioctl comes back successful and the data comes back as
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * zero. Config space is mapped but no device responded.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur *
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * 3) ioctl comes back successful and the data comes back as
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * non-zero. We've found a device.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur *
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * 4) Some other error occurs in an ioctl.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur prg_p->status = PCITOOL_SUCCESS;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur prg_p->offset = 0;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur prg_p->data = 0;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur prg_p->user_version = PCITOOL_VERSION;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (((rval = ioctl(fd, PCITOOL_DEVICE_GET_REG, prg_p)) != 0) ||
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (prg_p->data == 0xffffffff)) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Accept errno == EINVAL along with status of
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * PCITOOL_OUT_OF_RANGE because some systems
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * don't implement the full range of config space.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Leave the loop quietly in this case.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if ((errno == EINVAL) ||
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (prg_p->status == PCITOOL_OUT_OF_RANGE)) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur break;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Exit silently with ENXIO as this means that there are
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * no devices under the pci root nexus.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur else if ((errno == ENXIO) &&
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (prg_p->status == PCITOOL_IO_ERROR)) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur break;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Expect errno == EFAULT along with status of
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * PCITOOL_INVALID_ADDRESS because there won't be
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * devices at each stop. Quit on any other error.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur else if (((errno != EFAULT) ||
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (prg_p->status != PCITOOL_INVALID_ADDRESS)) &&
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (prg_p->data != 0xffffffff)) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (!(IS_QUIET(input_args_p->flags))) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) fprintf(stderr,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "Ioctl error: %s\n",
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur strerror(errno));
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur break;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * If no function at this location,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * just advance to the next function.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur rval = SUCCESS;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Data came back as 0.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Treat as unresponsive device amd check next device.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else if (prg_p->data == 0) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur rval = SUCCESS;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Found something. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur config_hdr.dwords[0] = (uint32_t)prg_p->data;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Get the rest of the PCI header. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if ((rval = get_config_header(fd, prg_p->bus_no,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur prg_p->dev_no, prg_p->func_no, &config_hdr)) !=
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur SUCCESS) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur break;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Print the found information. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur print_probe_info(&config_hdr, prg_p,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur IS_VERBOSE(input_args_p->flags));
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Special case for the type of Southbridge found on
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Ultra-45 and other sun4u fire workstations.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if ((config_hdr.dwords[0] == U45_SB_DEVID_VID) &&
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (config_hdr.dwords[2] == U45_SB_CLASS_RID)) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur rval = ECANCELED;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur break;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Accomodate devices which state their
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * multi-functionality only in their function 0 config
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * space. Note multi-functionality throughout probing
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * of all of this device's functions.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (config_hdr.bytes[PCI_CONF_HEADER] &
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur PCI_HEADER_MULTI) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur multi_function_device = B_TRUE;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return (rval);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur}
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Probe a given nexus config space for devices.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur *
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * fd is the file descriptor of the nexus.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * input_args contains commandline options as specified by the user.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic int
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurdo_probe(int fd, di_node_t di_node, di_prom_handle_t di_phdl,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur pcitool_uiargs_t *input_args_p)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur{
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur pcitool_reg_t prg;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int bus;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int dev;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int last_bus = PCI_REG_BUS_M >> PCI_REG_BUS_SHIFT;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int last_dev = PCI_REG_DEV_M >> PCI_REG_DEV_SHIFT;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int first_bus = 0;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int first_dev = 0;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int rval = SUCCESS;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur prg.barnum = 0; /* Config space. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Must read in 4-byte quantities. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_4 + NATIVE_ENDIAN;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur prg.data = 0;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* If an explicit bus was specified by the user, go with it. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (input_args_p->flags & BUS_SPEC_FLAG) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur first_bus = last_bus = input_args_p->bus;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else if (input_args_p->flags & PROBERNG_FLAG) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Otherwise get the bus range from properties. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int len;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur uint32_t *rangebuf = NULL;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur len = di_prop_lookup_ints(DDI_DEV_T_ANY, di_node,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "bus-range", (int **)&rangebuf);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Try PROM property */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (len <= 0) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur len = di_prom_prop_lookup_ints(di_phdl, di_node,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "bus-range", (int **)&rangebuf);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Take full range for default if cannot get property. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (len > 0) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur first_bus = rangebuf[0];
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur last_bus = rangebuf[1];
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Take full range for default if not PROBERNG and not BUS_SPEC. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (last_bus == first_bus) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (input_args_p->flags & DEV_SPEC_FLAG) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Explicit device given. Not probing a whole bus. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) puts("");
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf("*********** Probing bus %x "
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "***********\n\n", first_bus);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf("*********** Probing buses %x through %x "
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "***********\n\n", first_bus, last_bus);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Print header. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur print_probe_info(NULL, NULL, IS_VERBOSE(input_args_p->flags));
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Device number explicitly specified. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (input_args_p->flags & DEV_SPEC_FLAG) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur first_dev = last_dev = input_args_p->device;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Loop through all valid bus / dev / func combinations to check for
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * all devices, with the following exceptions:
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur *
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * When nothing is found at function 0 of a bus / dev combination, skip
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * the other functions of that bus / dev combination.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur *
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * When a found device's function 0 is probed and it is determined that
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * it is not a multifunction device, skip probing of that device's
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * other functions.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur for (bus = first_bus; ((bus <= last_bus) && (rval == SUCCESS)); bus++) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur prg.bus_no = bus;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Device number explicitly specified. */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (input_args_p->flags & DEV_SPEC_FLAG) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan first_dev = last_dev = input_args_p->device;
269473047d747f7815af570197e4ef7322d3632cEvan Yan } else if (supports_ari(fd, bus) == SUCCESS) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan last_dev = 0;
269473047d747f7815af570197e4ef7322d3632cEvan Yan first_dev = 0;
269473047d747f7815af570197e4ef7322d3632cEvan Yan } else {
269473047d747f7815af570197e4ef7322d3632cEvan Yan last_dev = PCI_REG_DEV_M >> PCI_REG_DEV_SHIFT;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur for (dev = first_dev;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur ((dev <= last_dev) && (rval == SUCCESS)); dev++) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur prg.dev_no = dev;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur rval = probe_dev(fd, &prg, input_args_p);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Ultra-45 southbridge workaround:
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * ECANCELED tells to skip to the next bus.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (rval == ECANCELED) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur rval = SUCCESS;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return (rval);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur}
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * This function is called-back from di_walk_minor() when any PROBE is processed
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/*ARGSUSED*/
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic int
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurprocess_nexus_node(di_node_t di_node, di_minor_t minor, void *arg)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur{
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int fd;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur char *trunc;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur probe_walk_args_t *walk_args_p = (probe_walk_args_t *)arg;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur char *pathname = walk_args_p->pathname;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur char *nexus_path = di_devfs_minor_path(minor);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (nexus_path == NULL) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) fprintf(stderr, "Error getting nexus path: %s\n",
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur strerror(errno));
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return (DI_WALK_CONTINUE);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Display this node if pathname not specified (as all nodes are
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * displayed) or if the current node matches the single specified
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * pathname. Pathname form: xxx, nexus form: xxx:reg
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if ((pathname != NULL) &&
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur ((strstr(nexus_path, pathname) != nexus_path) ||
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (strlen(nexus_path) !=
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (strlen(pathname) + strlen(PCI_MINOR_REG) + 1)))) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur di_devfs_path_free(nexus_path);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return (DI_WALK_CONTINUE);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if ((fd = open_node(nexus_path, walk_args_p->input_args_p)) >= 0) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Strip off the suffix at the end of the nexus path. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if ((trunc = strstr(nexus_path, PCI_MINOR_REG)) != NULL) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur trunc--; /* Get the : just before too. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur *trunc = '\0';
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Show header only if no explicit nexus node name given. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) puts("");
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (pathname == NULL) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf("********** Devices in tree under %s "
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "**********\n", nexus_path);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Exit silently with ENXIO as this means that there are
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * no devices under the pci root nexus.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if ((do_probe(fd, di_node, walk_args_p->di_phdl,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur walk_args_p->input_args_p) != SUCCESS) &&
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (errno != ENXIO)) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) fprintf(stderr, "Error probing node %s: %s\n",
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur nexus_path, strerror(errno));
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) close(fd);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur di_devfs_path_free(nexus_path);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * If node was explicitly specified, it has just been displayed
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * and no more looping is required.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Otherwise, keep looping for more nodes.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return ((pathname == NULL) ? DI_WALK_CONTINUE : DI_WALK_TERMINATE);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur}
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Start of probe. If pathname is NULL, search all devices.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur *
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * di_walk_minor() walks all DDI_NT_REGACC (PCItool register access) nodes
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * and calls process_nexus_node on them. process_nexus_node will then check
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * the pathname for a match, unless it is NULL which works like a wildcard.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic int
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurdo_probe_walk(pcitool_uiargs_t *input_args_p, char *pathname)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur{
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur di_node_t di_node;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur di_prom_handle_t di_phdl = DI_PROM_HANDLE_NIL;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur probe_walk_args_t walk_args;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int rval = SUCCESS;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if ((di_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) fprintf(stderr, "di_init() failed: %s\n",
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur strerror(errno));
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur rval = errno;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else if ((input_args_p->flags & PROBERNG_FLAG) &&
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur ((di_phdl = di_prom_init()) == DI_PROM_HANDLE_NIL)) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) fprintf(stderr, "di_prom_init failed: %s\n",
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur strerror(errno));
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur rval = errno;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur walk_args.input_args_p = input_args_p;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur walk_args.di_phdl = di_phdl;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur walk_args.pathname = pathname;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) di_walk_minor(di_node, DDI_NT_REGACC, 0,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur &walk_args, process_nexus_node);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (di_phdl != DI_PROM_HANDLE_NIL) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur di_prom_fini(di_phdl);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (di_node != DI_NODE_NIL) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur di_fini(di_node);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return (rval);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur}
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/* **************** Byte dump specific **************** */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic void
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurprint_bytedump_header(boolean_t do_chardump)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur{
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur static char header1[] = {" "
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00"};
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur static char header2[] = {" "
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "-----------------------------------------------"};
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur static char cheader1[] = {" 0123456789ABCDEF"};
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur static char cheader2[] = {" ----------------"};
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) puts("");
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf(header1);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (do_chardump) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf(cheader1);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) puts("");
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf(header2);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (do_chardump) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf(cheader2);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur}
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/* Number of bytes per line in a dump. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#define DUMP_BUF_SIZE 16
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#define LINES_BTWN_HEADER 16
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Retrieve several bytes over several reads, and print a formatted byte-dump
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur *
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * fd is the nexus by which device is accessed.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * prg provided has bus, dev, func, bank, initial offset already specified,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * as well as size and endian attributes.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur *
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * No checking is made that this is a read operation, although only read
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * operations are allowed.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic int
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurbytedump_get(int fd, int cmd, pcitool_reg_t *prg_p,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur pcitool_uiargs_t *input_args_p)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur{
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur typedef union {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur uint8_t bytes[DUMP_BUF_SIZE];
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur uint16_t shorts[DUMP_BUF_SIZE / sizeof (uint16_t)];
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur uint32_t dwords[DUMP_BUF_SIZE / sizeof (uint32_t)];
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur uint64_t longs[DUMP_BUF_SIZE / sizeof (uint64_t)];
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } buffer_t;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Local copy of pcitool_reg_t, since offset and phys_addrs are
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * modified.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur pcitool_reg_t local_prg;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Loop parameters. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur uint32_t dump_end = prg_p->offset + input_args_p->bytedump_amt;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur uint32_t dump_curr = prg_p->offset;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int read_size = input_args_p->size;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* How many stores to the buffer before it is full. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int wrap_size = DUMP_BUF_SIZE / read_size;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Address prints at the beginning of each line. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur uint64_t print_addr = 0;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Skip this num bytes at the beginning of the first dump. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int skip_begin;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Skip this num bytes at the end of the last dump. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int skip_end = 0;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* skip_begin and skip_end are needed twice. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int skip_begin2;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int skip_end2;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Number of lines between headers */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int lines_since_header = 0;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur boolean_t do_chardump = input_args_p->flags & CHARDUMP_FLAG;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur boolean_t continue_on_errs = input_args_p->flags & ERRCONT_FLAG;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int rval = SUCCESS; /* Return status. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int next;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int i;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur buffer_t buffer;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur uint16_t error_mask = 0; /* 1 bit/byte in buf. Err when set */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur bzero(buffer.bytes, sizeof (uint8_t) * DUMP_BUF_SIZE);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur local_prg = *prg_p; /* Make local copy. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Flip the bytes to proper order if reading on a big endian machine.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Do this by reading big as little and vs.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#if (NATIVE_ENDIAN == PCITOOL_ACC_ATTR_ENDN_BIG)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur local_prg.acc_attr =
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (PCITOOL_ACC_IS_BIG_ENDIAN(local_prg.acc_attr) ?
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (local_prg.acc_attr & ~PCITOOL_ACC_ATTR_ENDN_BIG) :
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (local_prg.acc_attr | PCITOOL_ACC_ATTR_ENDN_BIG));
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#endif
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Get offset into buffer for first store. Assumes the buffer size is
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * a multiple of the read size. "next" is the next buffer index to do
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * a store.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur skip_begin = local_prg.offset % DUMP_BUF_SIZE;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur next = skip_begin / read_size;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur print_bytedump_header(do_chardump);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur while (dump_curr < dump_end) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* For reading from the next location. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur local_prg.offset = dump_curr;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Access the device. Abort on error. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (((rval = ioctl(fd, cmd, &local_prg)) != SUCCESS) &&
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (!(continue_on_errs))) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (!(IS_QUIET(input_args_p->flags))) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) fprintf(stderr,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "Ioctl failed:\n errno: %s\n status: %s\n",
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur strerror(errno),
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur strstatus(local_prg.status));
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur break;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Initialize print_addr first time through, in case printing
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * is starting in the middle of the buffer. Also reinitialize
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * when wrap.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (print_addr == 0) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * X86 config space doesn't return phys addr.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Use offset instead in this case.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (local_prg.phys_addr == 0) { /* No phys addr ret */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur print_addr = local_prg.offset -
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (local_prg.offset % DUMP_BUF_SIZE);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur print_addr = local_prg.phys_addr -
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (local_prg.phys_addr % DUMP_BUF_SIZE);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Read error occurred.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Shift the right number of error bits ((1 << read_size) - 1)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * into the right place (next * read_size)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (rval != SUCCESS) { /* Read error occurred */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur error_mask |=
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur ((1 << read_size) - 1) << (next * read_size);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else { /* Save data to the buffer. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur switch (read_size) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur case 1:
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur buffer.bytes[next] = (uint8_t)local_prg.data;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur break;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur case 2:
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur buffer.shorts[next] = (uint16_t)local_prg.data;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur break;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur case 4:
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur buffer.dwords[next] = (uint32_t)local_prg.data;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur break;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur case 8:
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur buffer.longs[next] = (uint64_t)local_prg.data;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur break;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur default:
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur rval = EIO;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur break;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur next++;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Increment index for next store, and wrap. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur next %= wrap_size;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur dump_curr += read_size;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Zero out the remainder of the buffer if done. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (dump_curr >= dump_end) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (next != 0) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur bzero(&buffer.bytes[next * read_size],
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (wrap_size - next) * read_size);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur skip_end = (wrap_size - next) * read_size;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur next = 0; /* For printing below. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Dump the buffer if full or if done. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (next == 0) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur skip_begin2 = skip_begin;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur skip_end2 = skip_end;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf("\n0x%16.16" PRIx64 ":", print_addr);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur for (i = DUMP_BUF_SIZE - 1; i >= 0; i--) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (skip_end) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur skip_end--;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf(" --");
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else if (skip_begin > i) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur skip_begin--;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf(" --");
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else if (error_mask & (1 << i)) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf(" XX");
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf(" %2.2x",
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur buffer.bytes[i]);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (do_chardump) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) putchar(' ');
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur for (i = 0; i < DUMP_BUF_SIZE; i++) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (skip_begin2) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur skip_begin2--;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf("-");
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else if (
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (DUMP_BUF_SIZE - skip_end2) <= i) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf("-");
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else if (error_mask & (1 << i)) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) putchar('X');
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else if (isprint(buffer.bytes[i])) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) putchar(buffer.bytes[i]);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) putchar('@');
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if ((++lines_since_header == LINES_BTWN_HEADER) &&
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (dump_curr < dump_end)) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur lines_since_header = 0;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) puts("");
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur print_bytedump_header(do_chardump);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur print_addr += DUMP_BUF_SIZE;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur error_mask = 0;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf("\n");
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return (rval);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur}
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/* ************** Device and nexus access commands ************** */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Helper function to set access attributes. Assumes size is valid.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic uint32_t
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurset_acc_attr(pcitool_uiargs_t *input_args_p)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur{
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur uint32_t access_attrs;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur switch (input_args_p->size) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur case 1:
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur access_attrs = PCITOOL_ACC_ATTR_SIZE_1;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur break;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur case 2:
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur access_attrs = PCITOOL_ACC_ATTR_SIZE_2;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur break;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur case 4:
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur access_attrs = PCITOOL_ACC_ATTR_SIZE_4;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur break;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur case 8:
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur access_attrs = PCITOOL_ACC_ATTR_SIZE_8;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur break;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (input_args_p->big_endian) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur access_attrs |= PCITOOL_ACC_ATTR_ENDN_BIG;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return (access_attrs);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur}
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic int
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurdo_single_access(int fd, int cmd, pcitool_reg_t *prg_p,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur pcitool_uiargs_t *input_args_p)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur{
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur boolean_t is_write = B_FALSE;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int rval;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur switch (cmd) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur case PCITOOL_NEXUS_SET_REG:
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur case PCITOOL_DEVICE_SET_REG:
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur is_write = B_TRUE;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur break;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur default:
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur break;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Do the access. Return on error. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if ((rval = ioctl(fd, cmd, prg_p)) != SUCCESS) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (!(IS_QUIET(input_args_p->flags))) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) fprintf(stderr,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "%s ioctl failed:\n errno: %s\n status: %s\n",
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur is_write ? "write" : "read",
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur strerror(errno), strstatus(prg_p->status));
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return (rval);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Print on all verbose requests. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (IS_VERBOSE(input_args_p->flags)) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Return offset on platforms which return phys_addr == 0
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * for config space.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (prg_p->phys_addr == 0)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur prg_p->phys_addr = input_args_p->offset;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf("Addr:0x%" PRIx64 ", %d-byte %s endian "
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "register value: 0x%" PRIx64 "\n",
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur prg_p->phys_addr, input_args_p->size,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (input_args_p->big_endian ? "big" : "little"), prg_p->data);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Non-verbose, read requests. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else if (!(is_write)) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf("0x%" PRIx64 "\n", prg_p->data);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return (rval);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur}
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * fd is the file descriptor of the nexus to access, either to get its
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * registers or to access a device through that nexus.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur *
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * input args are commandline arguments specified by the user.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic int
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurdo_device_or_nexus(int fd, pcitool_uiargs_t *input_args_p)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur{
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur pcitool_reg_t prg; /* Request details given to the driver. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur uint32_t write_cmd = 0; /* Command given to the driver. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur uint32_t read_cmd = 0; /* Command given to the driver. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int rval = SUCCESS; /* Return status. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (input_args_p->flags & WRITE_FLAG) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur prg.data = input_args_p->write_value;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (input_args_p->flags & NEXUS_FLAG) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur write_cmd = PCITOOL_NEXUS_SET_REG;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur write_cmd = PCITOOL_DEVICE_SET_REG;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (input_args_p->flags & READ_FLAG) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (input_args_p->flags & NEXUS_FLAG) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur read_cmd = PCITOOL_NEXUS_GET_REG;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur read_cmd = PCITOOL_DEVICE_GET_REG;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Finish initializing access details for driver. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * For nexus, barnum is the exact bank number, unless it is 0xFF, which
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * indicates that it is inactive and a base_address should be read from
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * the input_args instead.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur *
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * For devices, barnum is the offset to the desired BAR, or 0 for
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * config space.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if ((input_args_p->flags & (BASE_SPEC_FLAG | NEXUS_FLAG)) ==
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (BASE_SPEC_FLAG | NEXUS_FLAG)) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur prg.barnum = PCITOOL_BASE;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur prg.phys_addr = input_args_p->base_address;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur prg.barnum = input_args_p->bank;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur prg.offset = input_args_p->offset;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur prg.acc_attr = set_acc_attr(input_args_p);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur prg.bus_no = input_args_p->bus;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur prg.dev_no = input_args_p->device;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur prg.func_no = input_args_p->function;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur prg.user_version = PCITOOL_VERSION;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur do {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Do a bytedump if desired, or else do single ioctl access. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (input_args_p->flags & BYTEDUMP_FLAG) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (IS_VERBOSE(input_args_p->flags)) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf(
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "\nDoing %d-byte %s endian reads:",
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur input_args_p->size,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur input_args_p->big_endian ?
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "big" : "little");
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur rval = bytedump_get(fd, read_cmd, &prg, input_args_p);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Single write and/or read. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (write_cmd != 0) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur rval = do_single_access(
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur fd, write_cmd, &prg, input_args_p);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if ((rval == SUCCESS) && (read_cmd != 0)) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur rval = do_single_access(
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur fd, read_cmd, &prg, input_args_p);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } while ((IS_LOOP(input_args_p->flags)) && (rval == SUCCESS) &&
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (keep_looping));
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return (rval != SUCCESS ? errno : SUCCESS);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur}
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/* *************** Interrupt routing ************** */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Display interrupt information.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * iget is filled in with the info to display
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic void
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurprint_intr_info(pcitool_intr_get_t *iget_p)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur{
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int i;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur for (i = 0; i < iget_p->num_devs; i++) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (iget_p->flags & PCITOOL_INTR_FLAG_GET_MSI)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (void) printf("0x%x,0x%x: %-10s%d\t %s\n",
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases iget_p->cpu_id, iget_p->msi & 0xff,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases iget_p->dev[i].driver_name, iget_p->dev[i].dev_inst,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases iget_p->dev[i].path);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases else
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (void) printf("0x%x,0x%x: %-10s%d\t %s\n",
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases iget_p->cpu_id, iget_p->ino & 0xff,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases iget_p->dev[i].driver_name, iget_p->dev[i].dev_inst,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases iget_p->dev[i].path);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur}
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Interrupt command support.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur *
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * fd is the file descriptor of the nexus being probed.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * input_args are commandline options entered by the user.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic int
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurget_single_interrupt(int fd, pcitool_intr_get_t **iget_pp,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur pcitool_uiargs_t *input_args_p)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur{
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur pcitool_intr_get_t *iget_p = *iget_pp;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan const char *str_type = NULL;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan uint32_t intr;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if (input_args_p->flags & MSI_SPEC_FLAG) {
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan intr = input_args_p->intr_msi;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan str_type = "msi";
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan } else {
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan intr = input_args_p->intr_ino;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan str_type = "ino";
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan * Check if interrupts are active on this ino/msi. Get as much
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan * device info as there is room for at the moment. If there
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * is not enough room for all devices, will call again with a
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * larger buffer.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (ioctl(fd, PCITOOL_DEVICE_GET_INTR, iget_p) != 0) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Let EIO errors silently slip through, as
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * some inos may not be viewable by design.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * We don't want to stop or print an error for these.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (errno == EIO) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return (SUCCESS);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (!(IS_QUIET(input_args_p->flags))) {
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan (void) fprintf(stderr, "Ioctl to get %s 0x%x "
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan "info failed: %s\n", str_type, intr,
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan strerror(errno));
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (errno != EFAULT) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) fprintf(stderr, "Pcitool status: %s\n",
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur strstatus(iget_p->status));
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return (errno);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Nothing to report for this interrupt. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (iget_p->num_devs == 0) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return (SUCCESS);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Need more room to return additional device info. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (iget_p->num_devs_ret < iget_p->num_devs) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur iget_p = *iget_pp =
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur realloc(iget_p, PCITOOL_IGET_SIZE(iget_p->num_devs));
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur iget_p->num_devs_ret = iget_p->num_devs;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (ioctl(fd, PCITOOL_DEVICE_GET_INTR, iget_p) != 0) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (!(IS_QUIET(input_args_p->flags))) {
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan (void) fprintf(stderr, "Ioctl to get %s 0x%x"
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan "device info failed: %s\n", str_type,
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan intr, strerror(errno));
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (errno != EFAULT) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) fprintf(stderr,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "Pcitool status: %s\n",
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur strstatus(iget_p->status));
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return (errno);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur print_intr_info(iget_p);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return (SUCCESS);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur}
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#define INIT_NUM_DEVS 0
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic int
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurget_interrupts(int fd, pcitool_uiargs_t *input_args_p)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur{
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int rval = SUCCESS; /* Return status. */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases int ino, cpu_id;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Start with a struct with space for info of INIT_NUM_DEVS devs
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * to be returned.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur pcitool_intr_get_t *iget_p = malloc(PCITOOL_IGET_SIZE(INIT_NUM_DEVS));
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur iget_p->num_devs_ret = INIT_NUM_DEVS;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur iget_p->user_version = PCITOOL_VERSION;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan /* Explicit MSI requested. */
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if (input_args_p->flags & MSI_SPEC_FLAG) {
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iget_p->msi = input_args_p->intr_msi;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iget_p->flags = PCITOOL_INTR_FLAG_GET_MSI;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur rval = get_single_interrupt(fd, &iget_p, input_args_p);
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan /* Return all MSIs. */
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan } else if (input_args_p->flags & MSI_ALL_FLAG) {
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan pcitool_intr_info_t intr_info;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan intr_info.flags = PCITOOL_INTR_FLAG_GET_MSI;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if (ioctl(fd, PCITOOL_SYSTEM_INTR_INFO, &intr_info) != 0) {
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if (!(IS_QUIET(input_args_p->flags))) {
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan (void) fprintf(stderr,
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan "intr info ioctl failed: %s\n",
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan strerror(errno));
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan }
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan } else {
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan int msi;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan /*
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan * Search through all interrupts.
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan * Display info on enabled ones.
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan */
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan for (msi = 0;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan ((msi < intr_info.num_intr) && (rval == SUCCESS));
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan msi++) {
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan bzero(iget_p, sizeof (pcitool_intr_get_t));
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iget_p->num_devs_ret = INIT_NUM_DEVS;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iget_p->user_version = PCITOOL_VERSION;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iget_p->flags = PCITOOL_INTR_FLAG_GET_MSI;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iget_p->msi = msi;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan rval = get_single_interrupt(
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan fd, &iget_p, input_args_p);
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan }
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan }
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan /* Explicit INO requested. */
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan } else if (input_args_p->flags & INO_SPEC_FLAG) {
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iget_p->ino = input_args_p->intr_ino;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases iget_p->cpu_id = input_args_p->old_cpu;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan rval = get_single_interrupt(fd, &iget_p, input_args_p);
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan /* Return all INOs. */
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan } else if (input_args_p->flags & INO_ALL_FLAG) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur pcitool_intr_info_t intr_info;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan intr_info.flags = 0;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (ioctl(fd, PCITOOL_SYSTEM_INTR_INFO, &intr_info) != 0) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (!(IS_QUIET(input_args_p->flags))) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) fprintf(stderr,
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan "intr info ioctl failed: %s\n",
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur strerror(errno));
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases free(iget_p);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases return (rval);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases /*
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Search through all interrupts.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases * Display info on enabled ones.
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases */
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (intr_info.ctlr_type == PCITOOL_CTLR_TYPE_APIX) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases for (cpu_id = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ((cpu_id < intr_info.num_cpu) && (rval == SUCCESS));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases cpu_id++) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases for (ino = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ((ino < intr_info.num_intr) &&
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (rval == SUCCESS));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ino++) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases bzero(iget_p,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases sizeof (pcitool_intr_get_t));
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases iget_p->num_devs_ret = INIT_NUM_DEVS;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases iget_p->user_version = PCITOOL_VERSION;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases iget_p->cpu_id = cpu_id;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases iget_p->ino = ino;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases rval = get_single_interrupt(
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases fd, &iget_p, input_args_p);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases } else {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur for (ino = 0;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (ino < intr_info.num_intr) && (rval == SUCCESS);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur ino++) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases bzero(iget_p,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases sizeof (pcitool_intr_get_t));
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iget_p->num_devs_ret = INIT_NUM_DEVS;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iget_p->user_version = PCITOOL_VERSION;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases iget_p->cpu_id = input_args_p->old_cpu;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur iget_p->ino = ino;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur rval = get_single_interrupt(
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur fd, &iget_p, input_args_p);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur free(iget_p);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return (rval);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur}
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic int
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurget_interrupt_ctlr(int fd, pcitool_uiargs_t *input_args_p)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur{
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur pcitool_intr_info_t intr_info;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur char *ctlr_type = NULL;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int rval = SUCCESS;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan intr_info.flags = 0;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (ioctl(fd, PCITOOL_SYSTEM_INTR_INFO, &intr_info) != 0) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (!(IS_QUIET(input_args_p->flags))) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) perror("Ioctl to get intr ctlr info failed");
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur rval = errno;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) fputs("Controller type: ", stdout);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur switch (intr_info.ctlr_type) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur case PCITOOL_CTLR_TYPE_RISC:
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur ctlr_type = "RISC";
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur break;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur case PCITOOL_CTLR_TYPE_UPPC:
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur ctlr_type = "UPPC";
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur break;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur case PCITOOL_CTLR_TYPE_PCPLUSMP:
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur ctlr_type = "PCPLUSMP";
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur break;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases case PCITOOL_CTLR_TYPE_APIX:
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases ctlr_type = "APIX";
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases break;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur default:
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur break;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (ctlr_type == NULL) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf("Unknown or new (%d)",
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur intr_info.ctlr_type);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) fputs(ctlr_type, stdout);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#ifdef __x86
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (intr_info.ctlr_type == PCITOOL_CTLR_TYPE_PCPLUSMP)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf(", IO APIC version: 0x%x, "
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur "local APIC version: 0x%x\n",
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur PSMAT_IO_APIC_VER(intr_info.ctlr_version),
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur PSMAT_LOCAL_APIC_VER(intr_info.ctlr_version));
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur else
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur#endif /* __x86 */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) printf(", version: %2.2x.%2.2x.%2.2x.%2.2x\n",
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur ((intr_info.ctlr_version >> 24) & 0xff),
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur ((intr_info.ctlr_version >> 16) & 0xff),
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur ((intr_info.ctlr_version >> 8) & 0xff),
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (intr_info.ctlr_version & 0xff));
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return (rval);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur}
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur *
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * fd is the file descriptor of the nexus being changed.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * input_args are commandline options entered by the user.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic int
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurset_interrupts(int fd, pcitool_uiargs_t *input_args_p)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur{
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan pcitool_intr_set_t iset;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan const char *str_type = NULL;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan uint32_t intr;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan int rval = SUCCESS; /* Return status. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Load interrupt number and cpu from commandline. */
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan if (input_args_p->flags & MSI_SPEC_FLAG) {
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iset.msi = intr = input_args_p->intr_msi;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iset.flags = PCITOOL_INTR_FLAG_SET_MSI;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan str_type = "msi";
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan } else {
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iset.ino = intr = input_args_p->intr_ino;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iset.flags = 0;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan str_type = "ino";
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan }
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur iset.cpu_id = input_args_p->intr_cpu;
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases iset.old_cpu = input_args_p->old_cpu;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur iset.user_version = PCITOOL_VERSION;
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan iset.flags |= (input_args_p->flags & SETGRP_FLAG) ?
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan PCITOOL_INTR_FLAG_SET_GROUP : 0;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Do the deed. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (ioctl(fd, PCITOOL_DEVICE_SET_INTR, &iset) != 0) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (!(IS_QUIET(input_args_p->flags))) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) fprintf(stderr,
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan "Ioctl to set %s 0x%x failed: %s\n",
09b1eac246a4e627fcbd1ce5bf8005746cbe45eaEvan Yan str_type, intr, strerror(errno));
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) fprintf(stderr, "pcitool status: %s\n",
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur strstatus(iset.status));
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur rval = errno;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (input_args_p->flags & SETGRP_FLAG) {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (iset.flags == PCITOOL_INTR_FLAG_SET_MSI)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (void) printf("0x%x,0x%x => 0x%x,0x%x\n",
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases iset.cpu_id,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (input_args_p->intr_msi) & 0xff,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases input_args_p->intr_cpu, iset.msi);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases else
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (void) printf("0x%x,0x%x => 0x%x,0x%x\n",
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases iset.cpu_id,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (input_args_p->intr_ino) & 0xff,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases input_args_p->intr_cpu, iset.ino);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else {
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases if (iset.flags == PCITOOL_INTR_FLAG_SET_MSI)
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (void) printf("0x%x,0x%x -> 0x%x,0x%x\n",
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases iset.cpu_id,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (input_args_p->intr_msi) & 0xff,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases input_args_p->intr_cpu, iset.msi);
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases else
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (void) printf("0x%x,0x%x -> 0x%x,0x%x\n",
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases iset.cpu_id,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases (input_args_p->intr_ino) & 0xff,
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases input_args_p->intr_cpu, iset.ino);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
7ff178cd8db129d385d3177eb20744d3b6efc59bJimmy Vetayases
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return (rval);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur}
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurstatic int
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurdo_interrupts(int fd, pcitool_uiargs_t *input_args_p)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur{
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (input_args_p->flags & READ_FLAG) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
3004e88e8f37eb9b239425b7120cc7d1e47bcb5dlipeng sang - Sun Microsystems - Beijing China int gic_rval = SUCCESS;
3004e88e8f37eb9b239425b7120cc7d1e47bcb5dlipeng sang - Sun Microsystems - Beijing China int gi_rval = SUCCESS;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (input_args_p->flags & SHOWCTLR_FLAG) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur gic_rval = get_interrupt_ctlr(fd, input_args_p);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur gi_rval = get_interrupts(fd, input_args_p);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return ((gi_rval != SUCCESS) ? gi_rval : gic_rval);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return (set_interrupts(fd, input_args_p));
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur}
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur/* *********** Where it all begins... ************* */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurint
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaurmain(int argc, char **argv)
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur{
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur pcitool_uiargs_t input_args; /* Commandline args. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int fd; /* Nexus file descriptor. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur int rval = SUCCESS; /* Return status value. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Get commandline args and options from user. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (get_commandline_args(argc, argv, &input_args) != SUCCESS) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return (EINVAL);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Help. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (!(input_args.flags & ALL_COMMANDS))
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return (SUCCESS);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /*
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Probe mode.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur * Nexus is provided as argv[1] unless PROBEALL mode.
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (input_args.flags & PROBE_FLAGS) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur rval = do_probe_walk(&input_args,
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur ((input_args.flags & PROBEALL_FLAG) ? NULL : argv[1]));
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else if ((fd = open_node(argv[1], &input_args)) >= 0) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur if (input_args.flags & (NEXUS_FLAG | LEAF_FLAG)) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) signal(SIGINT, signal_handler);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) signal(SIGTERM, signal_handler);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur rval = do_device_or_nexus(fd, &input_args);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else if (input_args.flags & INTR_FLAG) {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur rval = do_interrupts(fd, &input_args);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur } else {
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur /* Should never see this. */
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) fprintf(stderr, "Nothing to do.\n");
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur rval = ENOTTY;
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur (void) close(fd);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur }
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur return (rval);
d5ace9454616652a717c9831d949dffa319381f9Erwin T Tsaur}