17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
500d0963fSdilpreet * Common Development and Distribution License (the "License").
600d0963fSdilpreet * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
2219397407SSherry Moore * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
25cd21e7c5SGarrett D'Amore /*
26cd21e7c5SGarrett D'Amore * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved.
27cd21e7c5SGarrett D'Amore */
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate * Intel 21554 PCI to PCI bus bridge nexus driver for sun4u platforms.
327c478bd9Sstevel@tonic-gate * Please note that 21554 is not a transparent bridge.
337c478bd9Sstevel@tonic-gate * This driver can be used when the 21554 bridge is used like a
347c478bd9Sstevel@tonic-gate * transparent bridge. The host OBP or the OS PCI Resource Allocator
357c478bd9Sstevel@tonic-gate * (during a hotplug/hotswap operation) must represent this device
367c478bd9Sstevel@tonic-gate * as a nexus and do the device tree representation of the child
377c478bd9Sstevel@tonic-gate * nodes underneath.
387c478bd9Sstevel@tonic-gate * Interrupt routing of the children must be done as per the PCI
397c478bd9Sstevel@tonic-gate * specifications recommendation similar to that of a transparent
407c478bd9Sstevel@tonic-gate * bridge.
417c478bd9Sstevel@tonic-gate * Address translations from secondary across primary can be 1:1
427c478bd9Sstevel@tonic-gate * or non 1:1. Currently only 1:1 translations are supported.
437c478bd9Sstevel@tonic-gate * Configuration cycles are indirect. Memory and IO cycles are direct.
447c478bd9Sstevel@tonic-gate */
457c478bd9Sstevel@tonic-gate
467c478bd9Sstevel@tonic-gate /*
477c478bd9Sstevel@tonic-gate * INCLUDES
487c478bd9Sstevel@tonic-gate */
497c478bd9Sstevel@tonic-gate #include <sys/stat.h>
507c478bd9Sstevel@tonic-gate #include <sys/conf.h>
517c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
527c478bd9Sstevel@tonic-gate #include <sys/debug.h>
537c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
547c478bd9Sstevel@tonic-gate #include <sys/autoconf.h>
557c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
567c478bd9Sstevel@tonic-gate #include <sys/ddi_subrdefs.h>
577c478bd9Sstevel@tonic-gate #include <sys/pci.h>
587c478bd9Sstevel@tonic-gate #include <sys/pci/pci_nexus.h>
597c478bd9Sstevel@tonic-gate #include <sys/pci/pci_regs.h>
607c478bd9Sstevel@tonic-gate #include <sys/pci/db21554_config.h> /* 21554 configuration space registers */
617c478bd9Sstevel@tonic-gate #include <sys/pci/db21554_csr.h> /* 21554 control status register layout */
627c478bd9Sstevel@tonic-gate #include <sys/pci/db21554_ctrl.h> /* driver private control structure */
637c478bd9Sstevel@tonic-gate #include <sys/pci/db21554_debug.h> /* driver debug declarations */
647c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
657c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
667c478bd9Sstevel@tonic-gate #include <sys/sunndi.h>
677c478bd9Sstevel@tonic-gate #include <sys/fm/protocol.h>
687c478bd9Sstevel@tonic-gate #include <sys/ddifm.h>
697c478bd9Sstevel@tonic-gate #include <sys/promif.h>
707c478bd9Sstevel@tonic-gate #include <sys/file.h>
717c478bd9Sstevel@tonic-gate #include <sys/hotplug/pci/pcihp.h>
727c478bd9Sstevel@tonic-gate
737c478bd9Sstevel@tonic-gate /*
747c478bd9Sstevel@tonic-gate * DEFINES.
757c478bd9Sstevel@tonic-gate */
767c478bd9Sstevel@tonic-gate #define DB_DEBUG
7719397407SSherry Moore #define DB_MODINFO_DESCRIPTION "Intel/21554 pci-pci nexus"
787c478bd9Sstevel@tonic-gate #define DB_DVMA_START 0xc0000000
797c478bd9Sstevel@tonic-gate #define DB_DVMA_LEN 0x20000000
807c478bd9Sstevel@tonic-gate
817c478bd9Sstevel@tonic-gate #ifdef DB_DEBUG
827c478bd9Sstevel@tonic-gate /* ioctl definitions */
837c478bd9Sstevel@tonic-gate #define DB_PCI_READ_CONF_HEADER 1
847c478bd9Sstevel@tonic-gate #define DEF_INVALID_REG_VAL -1
857c478bd9Sstevel@tonic-gate
867c478bd9Sstevel@tonic-gate /* Default values for secondary cache line and latency timer */
877c478bd9Sstevel@tonic-gate #define DB_SEC_LATENCY_TIMER_VAL 0x40
887c478bd9Sstevel@tonic-gate #define DB_SEC_CACHELN_SIZE_VAL 0x10
897c478bd9Sstevel@tonic-gate
907c478bd9Sstevel@tonic-gate /* complete chip status information */
917c478bd9Sstevel@tonic-gate typedef struct db_pci_data {
927c478bd9Sstevel@tonic-gate char name[256];
937c478bd9Sstevel@tonic-gate uint32_t instance;
947c478bd9Sstevel@tonic-gate db_pci_header_t pri_hdr;
957c478bd9Sstevel@tonic-gate db_pci_header_t sec_hdr;
967c478bd9Sstevel@tonic-gate db_conf_regs_t conf_regs;
977c478bd9Sstevel@tonic-gate } db_pci_data_t;
987c478bd9Sstevel@tonic-gate #endif
997c478bd9Sstevel@tonic-gate
1007c478bd9Sstevel@tonic-gate /*
1017c478bd9Sstevel@tonic-gate * LOCALS
1027c478bd9Sstevel@tonic-gate */
1037c478bd9Sstevel@tonic-gate
1047c478bd9Sstevel@tonic-gate /*
1057c478bd9Sstevel@tonic-gate * The next set of variables are control parameters for debug purposes only.
1067c478bd9Sstevel@tonic-gate * Changing the default values as assigned below are not recommended.
1077c478bd9Sstevel@tonic-gate * In some cases, the non-default values are mostly application specific and
1087c478bd9Sstevel@tonic-gate * hence may not have been tested yet.
1097c478bd9Sstevel@tonic-gate *
1107c478bd9Sstevel@tonic-gate * db_conf_map_mode : specifies the access method used for generating
1117c478bd9Sstevel@tonic-gate * configuration cycles. Default value indicates
1127c478bd9Sstevel@tonic-gate * the indirect configuration method.
1137c478bd9Sstevel@tonic-gate * db_io_map_mode : specifies the access method used for generating
1147c478bd9Sstevel@tonic-gate * IO cycles. Default value indicates the direct
1157c478bd9Sstevel@tonic-gate * method.
1167c478bd9Sstevel@tonic-gate * db_pci_own_wait : For indirect cycles, indicates the wait period
1177c478bd9Sstevel@tonic-gate * for acquiring the bus, when the bus is busy.
1187c478bd9Sstevel@tonic-gate * db_pci_release_wait:For indirect cycles, indicates the wait period
1197c478bd9Sstevel@tonic-gate * for releasing the bus when the bus is busy.
1207c478bd9Sstevel@tonic-gate * db_pci_max_wait : max. wait time when bus is busy for indirect cycles
1217c478bd9Sstevel@tonic-gate * db_set_latency_timer_register :
1227c478bd9Sstevel@tonic-gate * when 1, the driver overwrites the OBP assigned
1237c478bd9Sstevel@tonic-gate * latency timer register setting for every child
1247c478bd9Sstevel@tonic-gate * device during child initialization.
1257c478bd9Sstevel@tonic-gate * db_set_cache_line_size_register :
1267c478bd9Sstevel@tonic-gate * when 1, the driver overwrites the OBP assigned
1277c478bd9Sstevel@tonic-gate * cache line register setting for every child
1287c478bd9Sstevel@tonic-gate * device during child initialization.
1297c478bd9Sstevel@tonic-gate * db_use_config_own_bit:
1307c478bd9Sstevel@tonic-gate * when 1, the driver will use the "config own bit"
1317c478bd9Sstevel@tonic-gate * for accessing the configuration address and data
1327c478bd9Sstevel@tonic-gate * registers.
1337c478bd9Sstevel@tonic-gate */
1347c478bd9Sstevel@tonic-gate static uint32_t db_pci_own_wait = DB_PCI_WAIT_MS;
1357c478bd9Sstevel@tonic-gate static uint32_t db_pci_release_wait = DB_PCI_WAIT_MS;
1367c478bd9Sstevel@tonic-gate static uint32_t db_pci_max_wait = DB_PCI_TIMEOUT;
1377c478bd9Sstevel@tonic-gate static uint32_t db_conf_map_mode = DB_CONF_MAP_INDIRECT_CONF;
1387c478bd9Sstevel@tonic-gate static uint32_t db_io_map_mode = DB_IO_MAP_DIRECT;
1397c478bd9Sstevel@tonic-gate static uint32_t db_set_latency_timer_register = 1;
1407c478bd9Sstevel@tonic-gate static uint32_t db_set_cache_line_size_register = 1;
1417c478bd9Sstevel@tonic-gate static uint32_t db_use_config_own_bit = 0;
1427c478bd9Sstevel@tonic-gate
1437c478bd9Sstevel@tonic-gate /*
1447c478bd9Sstevel@tonic-gate * Properties that can be set via .conf files.
1457c478bd9Sstevel@tonic-gate */
1467c478bd9Sstevel@tonic-gate
1477c478bd9Sstevel@tonic-gate /*
1487c478bd9Sstevel@tonic-gate * By default, we forward SERR# from secondary to primary. This behavior
1497c478bd9Sstevel@tonic-gate * can be controlled via a property "serr-fwd-enable", type integer.
1507c478bd9Sstevel@tonic-gate * Values are 0 or 1.
1517c478bd9Sstevel@tonic-gate * 0 means 'do not forward SERR#'.
1527c478bd9Sstevel@tonic-gate * 1 means forwards SERR# to the host. Should be the default.
1537c478bd9Sstevel@tonic-gate */
1547c478bd9Sstevel@tonic-gate static uint32_t db_serr_fwd_enable = 1;
1557c478bd9Sstevel@tonic-gate
1567c478bd9Sstevel@tonic-gate /*
1577c478bd9Sstevel@tonic-gate * The next set of parameters are performance tuning parameters.
1587c478bd9Sstevel@tonic-gate * These are in the form of properties settable through a .conf file.
1597c478bd9Sstevel@tonic-gate * In case if the properties are absent the following defaults are assumed.
1607c478bd9Sstevel@tonic-gate * These initial default values can be overwritten via /etc/system also.
1617c478bd9Sstevel@tonic-gate *
1627c478bd9Sstevel@tonic-gate * -1 means no setting is done ie. we either get OBP assigned value
1637c478bd9Sstevel@tonic-gate * or reset values (at hotplug time for example).
1647c478bd9Sstevel@tonic-gate */
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate /* primary latency timer: property "p-latency-timer" : type integer */
1677c478bd9Sstevel@tonic-gate static int8_t p_latency_timer = DEF_INVALID_REG_VAL;
1687c478bd9Sstevel@tonic-gate
1697c478bd9Sstevel@tonic-gate /* secondary latency timer: property "s-latency-timer": type integer */
1707c478bd9Sstevel@tonic-gate /*
1717c478bd9Sstevel@tonic-gate * Currently on the secondary side the latency timer is not
1727c478bd9Sstevel@tonic-gate * set by the serial PROM which causes performance degradation.
1737c478bd9Sstevel@tonic-gate * Set the secondary latency timer register.
1747c478bd9Sstevel@tonic-gate */
1757c478bd9Sstevel@tonic-gate static int8_t s_latency_timer = DB_SEC_LATENCY_TIMER_VAL;
1767c478bd9Sstevel@tonic-gate
1777c478bd9Sstevel@tonic-gate /* primary cache line size: property "p-cache-line-size" : type integer */
1787c478bd9Sstevel@tonic-gate static int8_t p_cache_line_size = DEF_INVALID_REG_VAL;
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate /* secondary cache line size: property "s-cache-line-size" : type integer */
1817c478bd9Sstevel@tonic-gate /*
1827c478bd9Sstevel@tonic-gate * Currently on the secondary side the cache line size is not
1837c478bd9Sstevel@tonic-gate * set by the serial PROM which causes performance degradation.
1847c478bd9Sstevel@tonic-gate * Set the secondary cache line size register.
1857c478bd9Sstevel@tonic-gate */
1867c478bd9Sstevel@tonic-gate static int8_t s_cache_line_size = DB_SEC_CACHELN_SIZE_VAL;
1877c478bd9Sstevel@tonic-gate
1887c478bd9Sstevel@tonic-gate /*
1897c478bd9Sstevel@tonic-gate * control primary posted write queue threshold limit:
1907c478bd9Sstevel@tonic-gate * property "p-pwrite-threshold" : type integer : values are 0 or 1.
1917c478bd9Sstevel@tonic-gate * 1 enables control. 0 does not, and is the default reset value.
1927c478bd9Sstevel@tonic-gate */
1937c478bd9Sstevel@tonic-gate static int8_t p_pwrite_threshold = DEF_INVALID_REG_VAL;
1947c478bd9Sstevel@tonic-gate
1957c478bd9Sstevel@tonic-gate /*
1967c478bd9Sstevel@tonic-gate * control secondary posted write queue threshold limit:
1977c478bd9Sstevel@tonic-gate * property "s-pwrite-threshold" : type integer : values are 0 or 1.
1987c478bd9Sstevel@tonic-gate * 1 enables control. 0 does not, and is the default reset value.
1997c478bd9Sstevel@tonic-gate */
2007c478bd9Sstevel@tonic-gate static int8_t s_pwrite_threshold = DEF_INVALID_REG_VAL;
2017c478bd9Sstevel@tonic-gate
2027c478bd9Sstevel@tonic-gate /*
2037c478bd9Sstevel@tonic-gate * control read queue threshold for initiating delayed read transaction
2047c478bd9Sstevel@tonic-gate * on primary bus.
2057c478bd9Sstevel@tonic-gate * property "p-dread-threshold" : type integer: values are
2067c478bd9Sstevel@tonic-gate *
2077c478bd9Sstevel@tonic-gate * 0 : reset value, default behavior: at least 8DWords free for all MR
2087c478bd9Sstevel@tonic-gate * 1 : reserved
2097c478bd9Sstevel@tonic-gate * 2 : at least one cache line free for MRL and MRM, 8 DWords free for MR
2107c478bd9Sstevel@tonic-gate * 3 : at least one cache line free for all MR
2117c478bd9Sstevel@tonic-gate */
2127c478bd9Sstevel@tonic-gate static int8_t p_dread_threshold = DEF_INVALID_REG_VAL;
2137c478bd9Sstevel@tonic-gate
2147c478bd9Sstevel@tonic-gate /*
2157c478bd9Sstevel@tonic-gate * control read queue threshold for initiating delayed read transaction
2167c478bd9Sstevel@tonic-gate * on secondary bus.
2177c478bd9Sstevel@tonic-gate * property "s-dread-threshold" : type integer: values are
2187c478bd9Sstevel@tonic-gate *
2197c478bd9Sstevel@tonic-gate * 0 : reset value, default behavior: at least 8DWords free for all MR
2207c478bd9Sstevel@tonic-gate * 1 : reserved
2217c478bd9Sstevel@tonic-gate * 2 : at least one cache line free for MRL and MRM, 8 DWords free for MR
2227c478bd9Sstevel@tonic-gate * 3 : at least one cache line free for all MR
2237c478bd9Sstevel@tonic-gate */
2247c478bd9Sstevel@tonic-gate static int8_t s_dread_threshold = DEF_INVALID_REG_VAL;
2257c478bd9Sstevel@tonic-gate
2267c478bd9Sstevel@tonic-gate /*
2277c478bd9Sstevel@tonic-gate * control how 21554 issues delayed transactions on the target bus.
2287c478bd9Sstevel@tonic-gate * property "delayed-trans-order" : type integer: values are 0 or 1.
2297c478bd9Sstevel@tonic-gate * 1 means repeat transaction on same target on target retries.
2307c478bd9Sstevel@tonic-gate * 0 is the reset/default value, and means enable round robin based
2317c478bd9Sstevel@tonic-gate * reads on other targets in read queue on any target retries.
2327c478bd9Sstevel@tonic-gate */
2337c478bd9Sstevel@tonic-gate static int8_t delayed_trans_order = DEF_INVALID_REG_VAL;
2347c478bd9Sstevel@tonic-gate
2357c478bd9Sstevel@tonic-gate /*
2367c478bd9Sstevel@tonic-gate * In case if the system DVMA information is not available, as it is
2377c478bd9Sstevel@tonic-gate * prior to s28q1, the system dvma range can be set via these parameters.
2387c478bd9Sstevel@tonic-gate */
2397c478bd9Sstevel@tonic-gate static uint32_t db_dvma_start = DB_DVMA_START;
2407c478bd9Sstevel@tonic-gate static uint32_t db_dvma_len = DB_DVMA_LEN;
2417c478bd9Sstevel@tonic-gate
2427c478bd9Sstevel@tonic-gate /*
2437c478bd9Sstevel@tonic-gate * Default command register settings for all PCI nodes this nexus initializes.
2447c478bd9Sstevel@tonic-gate */
2457c478bd9Sstevel@tonic-gate static uint16_t db_command_default =
2467c478bd9Sstevel@tonic-gate PCI_COMM_SERR_ENABLE |
2477c478bd9Sstevel@tonic-gate PCI_COMM_PARITY_DETECT |
2487c478bd9Sstevel@tonic-gate PCI_COMM_ME |
2497c478bd9Sstevel@tonic-gate PCI_COMM_MAE |
2507c478bd9Sstevel@tonic-gate PCI_COMM_IO |
2517c478bd9Sstevel@tonic-gate PCI_COMM_BACK2BACK_ENAB |
2527c478bd9Sstevel@tonic-gate PCI_COMM_MEMWR_INVAL;
2537c478bd9Sstevel@tonic-gate
2547c478bd9Sstevel@tonic-gate static int db_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
2557c478bd9Sstevel@tonic-gate static int db_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
2567c478bd9Sstevel@tonic-gate static void db_get_perf_parameters(db_ctrl_t *dbp);
2577c478bd9Sstevel@tonic-gate static void db_set_perf_parameters(db_ctrl_t *dbp);
2587c478bd9Sstevel@tonic-gate static void db_enable_io(db_ctrl_t *dbp);
2597c478bd9Sstevel@tonic-gate static void db_orientation(db_ctrl_t *dbp);
2607c478bd9Sstevel@tonic-gate static void db_set_dvma_range(db_ctrl_t *dbp);
2617c478bd9Sstevel@tonic-gate static int db_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
2627c478bd9Sstevel@tonic-gate void **result);
2637c478bd9Sstevel@tonic-gate static int db_pci_map(dev_info_t *, dev_info_t *, ddi_map_req_t *,
2647c478bd9Sstevel@tonic-gate off_t, off_t, caddr_t *);
2657c478bd9Sstevel@tonic-gate static int db_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t,
2667c478bd9Sstevel@tonic-gate void *, void *);
2677c478bd9Sstevel@tonic-gate static int db_intr_ops(dev_info_t *dip, dev_info_t *rdip,
2687c478bd9Sstevel@tonic-gate ddi_intr_op_t intr_op, ddi_intr_handle_impl_t *hdlp,
2697c478bd9Sstevel@tonic-gate void *result);
2707c478bd9Sstevel@tonic-gate static dev_info_t *db_get_my_childs_dip(dev_info_t *dip, dev_info_t *rdip);
2717c478bd9Sstevel@tonic-gate static int db_fm_init_child(dev_info_t *dip, dev_info_t *tdip, int cap,
2727c478bd9Sstevel@tonic-gate ddi_iblock_cookie_t *ibc);
2737c478bd9Sstevel@tonic-gate static void db_bus_enter(dev_info_t *dip, ddi_acc_handle_t handle);
2747c478bd9Sstevel@tonic-gate static void db_bus_exit(dev_info_t *dip, ddi_acc_handle_t handle);
2757c478bd9Sstevel@tonic-gate
2767c478bd9Sstevel@tonic-gate struct bus_ops db_bus_ops = {
2777c478bd9Sstevel@tonic-gate BUSO_REV,
2787c478bd9Sstevel@tonic-gate db_pci_map,
2797c478bd9Sstevel@tonic-gate 0,
2807c478bd9Sstevel@tonic-gate 0,
2817c478bd9Sstevel@tonic-gate 0,
2827c478bd9Sstevel@tonic-gate i_ddi_map_fault,
283cd21e7c5SGarrett D'Amore 0,
2847c478bd9Sstevel@tonic-gate ddi_dma_allochdl,
2857c478bd9Sstevel@tonic-gate ddi_dma_freehdl,
2867c478bd9Sstevel@tonic-gate ddi_dma_bindhdl,
2877c478bd9Sstevel@tonic-gate ddi_dma_unbindhdl,
2887c478bd9Sstevel@tonic-gate ddi_dma_flush,
2897c478bd9Sstevel@tonic-gate ddi_dma_win,
2907c478bd9Sstevel@tonic-gate ddi_dma_mctl,
2917c478bd9Sstevel@tonic-gate db_ctlops,
2927c478bd9Sstevel@tonic-gate ddi_bus_prop_op,
2937c478bd9Sstevel@tonic-gate ndi_busop_get_eventcookie,
2947c478bd9Sstevel@tonic-gate ndi_busop_add_eventcall,
2957c478bd9Sstevel@tonic-gate ndi_busop_remove_eventcall,
2967c478bd9Sstevel@tonic-gate ndi_post_event,
2977c478bd9Sstevel@tonic-gate 0,
2987c478bd9Sstevel@tonic-gate 0,
2997c478bd9Sstevel@tonic-gate 0,
3007c478bd9Sstevel@tonic-gate db_fm_init_child,
3017c478bd9Sstevel@tonic-gate NULL,
3027c478bd9Sstevel@tonic-gate db_bus_enter,
3037c478bd9Sstevel@tonic-gate db_bus_exit,
3047c478bd9Sstevel@tonic-gate 0,
3057c478bd9Sstevel@tonic-gate db_intr_ops
3067c478bd9Sstevel@tonic-gate };
3077c478bd9Sstevel@tonic-gate
3087c478bd9Sstevel@tonic-gate static int db_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p);
3097c478bd9Sstevel@tonic-gate static int db_close(dev_t dev, int flag, int otyp, cred_t *cred_p);
3107c478bd9Sstevel@tonic-gate static int db_ioctl(dev_t dev, int cmd, intptr_t arg, int flag,
3117c478bd9Sstevel@tonic-gate cred_t *cred_p, int *rval_p);
3127c478bd9Sstevel@tonic-gate #ifdef DB_DEBUG
3137c478bd9Sstevel@tonic-gate static dev_info_t *db_lookup_child_name(db_ctrl_t *dbp, char *name,
3147c478bd9Sstevel@tonic-gate int instance);
3157c478bd9Sstevel@tonic-gate static void db_pci_get_header(ddi_acc_handle_t config_handle,
3167c478bd9Sstevel@tonic-gate db_pci_header_t *ph, off_t hdr_off);
3177c478bd9Sstevel@tonic-gate static void db_pci_get_conf_regs(ddi_acc_handle_t config_handle,
3187c478bd9Sstevel@tonic-gate db_conf_regs_t *cr);
3197c478bd9Sstevel@tonic-gate #endif /* DB_DEBUG */
3207c478bd9Sstevel@tonic-gate
3217c478bd9Sstevel@tonic-gate #ifdef DEBUG
3227c478bd9Sstevel@tonic-gate static void
3237c478bd9Sstevel@tonic-gate db_debug(uint64_t func_id, dev_info_t *dip, char *fmt,
3247c478bd9Sstevel@tonic-gate uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5);
3257c478bd9Sstevel@tonic-gate #endif
3267c478bd9Sstevel@tonic-gate
3277c478bd9Sstevel@tonic-gate static int db_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
3287c478bd9Sstevel@tonic-gate int flags, char *name, caddr_t valuep, int *lengthp);
3297c478bd9Sstevel@tonic-gate
3307c478bd9Sstevel@tonic-gate static struct cb_ops db_cb_ops = {
3317c478bd9Sstevel@tonic-gate db_open, /* open */
3327c478bd9Sstevel@tonic-gate db_close, /* close */
3337c478bd9Sstevel@tonic-gate nulldev, /* strategy */
3347c478bd9Sstevel@tonic-gate nulldev, /* print */
3357c478bd9Sstevel@tonic-gate nulldev, /* dump */
3367c478bd9Sstevel@tonic-gate nulldev, /* read */
3377c478bd9Sstevel@tonic-gate nulldev, /* write */
3387c478bd9Sstevel@tonic-gate db_ioctl, /* ioctl */
3397c478bd9Sstevel@tonic-gate nodev, /* devmap */
3407c478bd9Sstevel@tonic-gate nodev, /* mmap */
3417c478bd9Sstevel@tonic-gate nodev, /* segmap */
3427c478bd9Sstevel@tonic-gate nochpoll, /* poll */
3437c478bd9Sstevel@tonic-gate db_prop_op, /* cb_prop_op */
3447c478bd9Sstevel@tonic-gate NULL, /* streamtab */
3457c478bd9Sstevel@tonic-gate D_NEW | D_MP | D_HOTPLUG, /* Driver compatibility flag */
3467c478bd9Sstevel@tonic-gate CB_REV, /* rev */
3477c478bd9Sstevel@tonic-gate nodev, /* int (*cb_aread)() */
3487c478bd9Sstevel@tonic-gate nodev /* int (*cb_awrite)() */
3497c478bd9Sstevel@tonic-gate };
3507c478bd9Sstevel@tonic-gate
3517c478bd9Sstevel@tonic-gate static uint8_t db_ddi_get8(ddi_acc_impl_t *handle, uint8_t *addr);
3527c478bd9Sstevel@tonic-gate static uint16_t db_ddi_get16(ddi_acc_impl_t *handle, uint16_t *addr);
3537c478bd9Sstevel@tonic-gate static uint32_t db_ddi_get32(ddi_acc_impl_t *handle, uint32_t *addr);
3547c478bd9Sstevel@tonic-gate static uint64_t db_ddi_get64(ddi_acc_impl_t *handle, uint64_t *addr);
3557c478bd9Sstevel@tonic-gate static void db_ddi_put8(ddi_acc_impl_t *handle, uint8_t *addr,
3567c478bd9Sstevel@tonic-gate uint8_t data);
3577c478bd9Sstevel@tonic-gate static void db_ddi_put16(ddi_acc_impl_t *handle, uint16_t *addr,
3587c478bd9Sstevel@tonic-gate uint16_t data);
3597c478bd9Sstevel@tonic-gate static void db_ddi_put32(ddi_acc_impl_t *handle, uint32_t *addr,
3607c478bd9Sstevel@tonic-gate uint32_t data);
3617c478bd9Sstevel@tonic-gate static void db_ddi_put64(ddi_acc_impl_t *handle, uint64_t *addr,
3627c478bd9Sstevel@tonic-gate uint64_t data);
3637c478bd9Sstevel@tonic-gate static void db_ddi_rep_get8(ddi_acc_impl_t *handle, uint8_t *host_addr,
3647c478bd9Sstevel@tonic-gate uint8_t *dev_addr, size_t repcount, uint_t flags);
3657c478bd9Sstevel@tonic-gate static void db_ddi_rep_get16(ddi_acc_impl_t *handle, uint16_t *host_addr,
3667c478bd9Sstevel@tonic-gate uint16_t *dev_addr, size_t repcount, uint_t flags);
3677c478bd9Sstevel@tonic-gate static void db_ddi_rep_get32(ddi_acc_impl_t *handle, uint32_t *host_addr,
3687c478bd9Sstevel@tonic-gate uint32_t *dev_addr, size_t repcount, uint_t flags);
3697c478bd9Sstevel@tonic-gate static void db_ddi_rep_get64(ddi_acc_impl_t *handle, uint64_t *host_addr,
3707c478bd9Sstevel@tonic-gate uint64_t *dev_addr, size_t repcount, uint_t flags);
3717c478bd9Sstevel@tonic-gate static void db_ddi_rep_put8(ddi_acc_impl_t *handle, uint8_t *host_addr,
3727c478bd9Sstevel@tonic-gate uint8_t *dev_addr, size_t repcount, uint_t flags);
3737c478bd9Sstevel@tonic-gate static void db_ddi_rep_put16(ddi_acc_impl_t *handle, uint16_t *host_addr,
3747c478bd9Sstevel@tonic-gate uint16_t *dev_addr, size_t repcount, uint_t flags);
3757c478bd9Sstevel@tonic-gate static void db_ddi_rep_put32(ddi_acc_impl_t *handle, uint32_t *host_addr,
3767c478bd9Sstevel@tonic-gate uint32_t *dev_addr, size_t repcount, uint_t flags);
3777c478bd9Sstevel@tonic-gate static void db_ddi_rep_put64(ddi_acc_impl_t *handle, uint64_t *host_addr,
3787c478bd9Sstevel@tonic-gate uint64_t *dev_addr, size_t repcount, uint_t flags);
3797c478bd9Sstevel@tonic-gate
3807c478bd9Sstevel@tonic-gate static struct dev_ops db_dev_ops = {
3817c478bd9Sstevel@tonic-gate DEVO_REV, /* devo_rev */
3827c478bd9Sstevel@tonic-gate 0, /* refcnt */
3837c478bd9Sstevel@tonic-gate db_getinfo, /* info */
3847c478bd9Sstevel@tonic-gate nulldev, /* identify */
3857c478bd9Sstevel@tonic-gate nulldev, /* probe */
3867c478bd9Sstevel@tonic-gate db_attach, /* attach */
3877c478bd9Sstevel@tonic-gate db_detach, /* detach */
3887c478bd9Sstevel@tonic-gate nulldev, /* reset */
3897c478bd9Sstevel@tonic-gate &db_cb_ops, /* driver operations */
3907c478bd9Sstevel@tonic-gate &db_bus_ops, /* bus operations */
39119397407SSherry Moore ddi_power,
39219397407SSherry Moore ddi_quiesce_not_supported, /* devo_quiesce */
3937c478bd9Sstevel@tonic-gate };
3947c478bd9Sstevel@tonic-gate
3957c478bd9Sstevel@tonic-gate
3967c478bd9Sstevel@tonic-gate /*
3977c478bd9Sstevel@tonic-gate * Module linkage information for the kernel.
3987c478bd9Sstevel@tonic-gate */
3997c478bd9Sstevel@tonic-gate
4007c478bd9Sstevel@tonic-gate static struct modldrv modldrv = {
4017c478bd9Sstevel@tonic-gate &mod_driverops, /* Type of module */
4027c478bd9Sstevel@tonic-gate DB_MODINFO_DESCRIPTION,
4037c478bd9Sstevel@tonic-gate &db_dev_ops /* driver ops */
4047c478bd9Sstevel@tonic-gate };
4057c478bd9Sstevel@tonic-gate
4067c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
4077c478bd9Sstevel@tonic-gate MODREV_1,
4087c478bd9Sstevel@tonic-gate (void *)&modldrv,
4097c478bd9Sstevel@tonic-gate NULL
4107c478bd9Sstevel@tonic-gate };
4117c478bd9Sstevel@tonic-gate
4127c478bd9Sstevel@tonic-gate /* soft state pointer and structure template. */
4137c478bd9Sstevel@tonic-gate static void *db_state;
4147c478bd9Sstevel@tonic-gate
4157c478bd9Sstevel@tonic-gate /*
4167c478bd9Sstevel@tonic-gate * forward function declarations:
4177c478bd9Sstevel@tonic-gate */
4187c478bd9Sstevel@tonic-gate static void db_uninitchild(dev_info_t *);
4197c478bd9Sstevel@tonic-gate static int db_initchild(dev_info_t *child);
4207c478bd9Sstevel@tonic-gate static int db_create_pci_prop(dev_info_t *child);
4217c478bd9Sstevel@tonic-gate static int db_save_config_regs(db_ctrl_t *dbp);
4227c478bd9Sstevel@tonic-gate static int db_restore_config_regs(db_ctrl_t *dbp);
4237c478bd9Sstevel@tonic-gate
4247c478bd9Sstevel@tonic-gate /*
4257c478bd9Sstevel@tonic-gate * FMA error callback
4267c478bd9Sstevel@tonic-gate * Register error handling callback with our parent. We will just call
4277c478bd9Sstevel@tonic-gate * our children's error callbacks and return their status.
4287c478bd9Sstevel@tonic-gate */
4297c478bd9Sstevel@tonic-gate static int db_err_callback(dev_info_t *dip, ddi_fm_error_t *derr,
4307c478bd9Sstevel@tonic-gate const void *impl_data);
4317c478bd9Sstevel@tonic-gate
4327c478bd9Sstevel@tonic-gate /*
4337c478bd9Sstevel@tonic-gate * init/fini routines to alloc/dealloc fm structures and
4347c478bd9Sstevel@tonic-gate * register/unregister our callback.
4357c478bd9Sstevel@tonic-gate */
4367c478bd9Sstevel@tonic-gate static void db_fm_init(db_ctrl_t *db_p);
4377c478bd9Sstevel@tonic-gate static void db_fm_fini(db_ctrl_t *db_p);
4387c478bd9Sstevel@tonic-gate
4397c478bd9Sstevel@tonic-gate int
_init(void)4407c478bd9Sstevel@tonic-gate _init(void)
4417c478bd9Sstevel@tonic-gate {
4427c478bd9Sstevel@tonic-gate int rc;
4437c478bd9Sstevel@tonic-gate
4447c478bd9Sstevel@tonic-gate DB_DEBUG0(DB_INIT|DB_DONT_DISPLAY_DIP, NULL, "enter\n");
4457c478bd9Sstevel@tonic-gate if (((rc = ddi_soft_state_init(&db_state,
4467c478bd9Sstevel@tonic-gate sizeof (db_ctrl_t), 1)) == 0) &&
4477c478bd9Sstevel@tonic-gate ((rc = mod_install(&modlinkage)) != 0))
4487c478bd9Sstevel@tonic-gate ddi_soft_state_fini(&db_state);
4497c478bd9Sstevel@tonic-gate DB_DEBUG1(DB_INIT|DB_DONT_DISPLAY_DIP, NULL, "exit rc=%d\n", rc);
4507c478bd9Sstevel@tonic-gate return (rc);
4517c478bd9Sstevel@tonic-gate }
4527c478bd9Sstevel@tonic-gate
4537c478bd9Sstevel@tonic-gate
4547c478bd9Sstevel@tonic-gate int
_fini(void)4557c478bd9Sstevel@tonic-gate _fini(void)
4567c478bd9Sstevel@tonic-gate {
4577c478bd9Sstevel@tonic-gate int rc;
4587c478bd9Sstevel@tonic-gate
4597c478bd9Sstevel@tonic-gate DB_DEBUG0(DB_FINI|DB_DONT_DISPLAY_DIP, NULL, "enter\n");
4607c478bd9Sstevel@tonic-gate if ((rc = mod_remove(&modlinkage)) == 0)
4617c478bd9Sstevel@tonic-gate ddi_soft_state_fini(&db_state);
4627c478bd9Sstevel@tonic-gate DB_DEBUG1(DB_FINI|DB_DONT_DISPLAY_DIP, NULL, "exit rc=%d\n", rc);
4637c478bd9Sstevel@tonic-gate return (rc);
4647c478bd9Sstevel@tonic-gate }
4657c478bd9Sstevel@tonic-gate
4667c478bd9Sstevel@tonic-gate int
_info(struct modinfo * modinfop)4677c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
4687c478bd9Sstevel@tonic-gate {
4697c478bd9Sstevel@tonic-gate int rc;
4707c478bd9Sstevel@tonic-gate rc = mod_info(&modlinkage, modinfop);
4717c478bd9Sstevel@tonic-gate DB_DEBUG1(DB_INFO|DB_DONT_DISPLAY_DIP, NULL, "exit rc=%d\n", rc);
4727c478bd9Sstevel@tonic-gate return (rc);
4737c478bd9Sstevel@tonic-gate }
4747c478bd9Sstevel@tonic-gate
4757c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4767c478bd9Sstevel@tonic-gate static int
db_getinfo(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)4777c478bd9Sstevel@tonic-gate db_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
4787c478bd9Sstevel@tonic-gate {
4797c478bd9Sstevel@tonic-gate db_ctrl_t *dbp;
4807c478bd9Sstevel@tonic-gate int rc = DDI_FAILURE;
4817c478bd9Sstevel@tonic-gate minor_t minor = getminor((dev_t)arg);
4827c478bd9Sstevel@tonic-gate int instance = PCIHP_AP_MINOR_NUM_TO_INSTANCE(minor);
4837c478bd9Sstevel@tonic-gate
4847c478bd9Sstevel@tonic-gate DB_DEBUG1(DB_GETINFO|DB_DONT_DISPLAY_DIP, dip, "enter:cmd=%d\n",
4857c478bd9Sstevel@tonic-gate infocmd);
4867c478bd9Sstevel@tonic-gate
4877c478bd9Sstevel@tonic-gate switch (infocmd) {
4887c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO:
4897c478bd9Sstevel@tonic-gate
4907c478bd9Sstevel@tonic-gate if ((dbp = ddi_get_soft_state(db_state,
4917c478bd9Sstevel@tonic-gate instance)) != NULL) {
4927c478bd9Sstevel@tonic-gate *result = dbp->dip;
4937c478bd9Sstevel@tonic-gate rc = DDI_SUCCESS;
4947c478bd9Sstevel@tonic-gate } else
4957c478bd9Sstevel@tonic-gate *result = NULL;
4967c478bd9Sstevel@tonic-gate break;
4977c478bd9Sstevel@tonic-gate
4987c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE:
499f47a9c50Smathue *result = (void *)(uintptr_t)instance;
5007c478bd9Sstevel@tonic-gate rc = DDI_SUCCESS;
5017c478bd9Sstevel@tonic-gate break;
5027c478bd9Sstevel@tonic-gate
5037c478bd9Sstevel@tonic-gate default:
5047c478bd9Sstevel@tonic-gate break;
5057c478bd9Sstevel@tonic-gate }
5067c478bd9Sstevel@tonic-gate DB_DEBUG2(DB_GETINFO|DB_DONT_DISPLAY_DIP, dip,
5077c478bd9Sstevel@tonic-gate "exit: result=%x, rc=%d\n", *result, rc);
5087c478bd9Sstevel@tonic-gate
5097c478bd9Sstevel@tonic-gate return (rc);
5107c478bd9Sstevel@tonic-gate }
5117c478bd9Sstevel@tonic-gate
5127c478bd9Sstevel@tonic-gate static int
db_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)5137c478bd9Sstevel@tonic-gate db_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
5147c478bd9Sstevel@tonic-gate {
5157c478bd9Sstevel@tonic-gate int instance = ddi_get_instance(dip);
5167c478bd9Sstevel@tonic-gate db_ctrl_t *dbp;
5177c478bd9Sstevel@tonic-gate int rc = DDI_SUCCESS;
5187c478bd9Sstevel@tonic-gate ddi_device_acc_attr_t db_csr_attr = { /* CSR map attributes */
5197c478bd9Sstevel@tonic-gate DDI_DEVICE_ATTR_V0,
5207c478bd9Sstevel@tonic-gate DDI_STRUCTURE_LE_ACC,
5217c478bd9Sstevel@tonic-gate DDI_STRICTORDER_ACC
5227c478bd9Sstevel@tonic-gate };
5237c478bd9Sstevel@tonic-gate off_t bar_size;
5247c478bd9Sstevel@tonic-gate int range_size;
5257c478bd9Sstevel@tonic-gate char name[32];
5267c478bd9Sstevel@tonic-gate
5277c478bd9Sstevel@tonic-gate DB_DEBUG1(DB_ATTACH, dip, "enter: cmd=%d\n", cmd);
5287c478bd9Sstevel@tonic-gate switch (cmd) {
5297c478bd9Sstevel@tonic-gate
5307c478bd9Sstevel@tonic-gate case DDI_ATTACH:
5317c478bd9Sstevel@tonic-gate if (ddi_soft_state_zalloc(db_state, instance) != DDI_SUCCESS) {
5327c478bd9Sstevel@tonic-gate rc = DDI_FAILURE;
5337c478bd9Sstevel@tonic-gate break;
5347c478bd9Sstevel@tonic-gate }
5357c478bd9Sstevel@tonic-gate
5367c478bd9Sstevel@tonic-gate dbp = (db_ctrl_t *)ddi_get_soft_state(db_state, instance);
5377c478bd9Sstevel@tonic-gate
5387c478bd9Sstevel@tonic-gate dbp->dip = dip;
5397c478bd9Sstevel@tonic-gate mutex_init(&dbp->db_mutex, NULL, MUTEX_DRIVER, NULL);
5407c478bd9Sstevel@tonic-gate dbp->db_soft_state = DB_SOFT_STATE_CLOSED;
5417c478bd9Sstevel@tonic-gate
5427c478bd9Sstevel@tonic-gate /*
5437c478bd9Sstevel@tonic-gate * Cannot use pci_config_setup here as we'd need
5447c478bd9Sstevel@tonic-gate * to get a pointer to the address map to be able
5457c478bd9Sstevel@tonic-gate * to set the bus private handle during child map
5467c478bd9Sstevel@tonic-gate * operation.
5477c478bd9Sstevel@tonic-gate */
5487c478bd9Sstevel@tonic-gate if ((rc = ddi_regs_map_setup(dip, DB_PCI_CONF_RNUMBER,
5497c478bd9Sstevel@tonic-gate (caddr_t *)&dbp->conf_io, DB_PCI_CONF_OFFSET,
5507c478bd9Sstevel@tonic-gate PCI_CONF_HDR_SIZE, &db_csr_attr, &dbp->conf_handle))
5517c478bd9Sstevel@tonic-gate != DDI_SUCCESS) {
5527c478bd9Sstevel@tonic-gate
5537c478bd9Sstevel@tonic-gate cmn_err(CE_WARN,
5547c478bd9Sstevel@tonic-gate "%s#%d: cannot map configuration space",
5557c478bd9Sstevel@tonic-gate ddi_driver_name(dip), ddi_get_instance(dip));
5567c478bd9Sstevel@tonic-gate mutex_destroy(&dbp->db_mutex);
5577c478bd9Sstevel@tonic-gate ddi_soft_state_free(db_state, instance);
5587c478bd9Sstevel@tonic-gate rc = DDI_FAILURE;
5597c478bd9Sstevel@tonic-gate break;
5607c478bd9Sstevel@tonic-gate }
5617c478bd9Sstevel@tonic-gate
5627c478bd9Sstevel@tonic-gate db_get_perf_parameters(dbp);
5637c478bd9Sstevel@tonic-gate
5647c478bd9Sstevel@tonic-gate if (ddi_dev_regsize(dip, DB_CSR_MEMBAR_RNUMBER, &bar_size)
5657c478bd9Sstevel@tonic-gate != DDI_SUCCESS) {
5667c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s#%d: cannot get memory CSR size",
5677c478bd9Sstevel@tonic-gate ddi_driver_name(dbp->dip),
5687c478bd9Sstevel@tonic-gate ddi_get_instance(dbp->dip));
5697c478bd9Sstevel@tonic-gate ddi_regs_map_free(&dbp->conf_handle);
5707c478bd9Sstevel@tonic-gate mutex_destroy(&dbp->db_mutex);
5717c478bd9Sstevel@tonic-gate ddi_soft_state_free(db_state, instance);
5727c478bd9Sstevel@tonic-gate rc = DDI_FAILURE;
5737c478bd9Sstevel@tonic-gate break;
5747c478bd9Sstevel@tonic-gate }
5757c478bd9Sstevel@tonic-gate
5767c478bd9Sstevel@tonic-gate /* map memory CSR space */
5777c478bd9Sstevel@tonic-gate if (ddi_regs_map_setup(dip, DB_CSR_MEMBAR_RNUMBER,
5787c478bd9Sstevel@tonic-gate (caddr_t *)&dbp->csr_mem, DB_CSR_MEM_OFFSET, bar_size,
5797c478bd9Sstevel@tonic-gate &db_csr_attr, &dbp->csr_mem_handle) != DDI_SUCCESS) {
5807c478bd9Sstevel@tonic-gate
5817c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s#%d: cannot map memory CSR space",
5827c478bd9Sstevel@tonic-gate ddi_driver_name(dbp->dip),
5837c478bd9Sstevel@tonic-gate ddi_get_instance(dbp->dip));
5847c478bd9Sstevel@tonic-gate ddi_regs_map_free(&dbp->conf_handle);
5857c478bd9Sstevel@tonic-gate mutex_destroy(&dbp->db_mutex);
5867c478bd9Sstevel@tonic-gate ddi_soft_state_free(db_state, instance);
5877c478bd9Sstevel@tonic-gate rc = DDI_FAILURE;
5887c478bd9Sstevel@tonic-gate break;
5897c478bd9Sstevel@tonic-gate }
5907c478bd9Sstevel@tonic-gate
5917c478bd9Sstevel@tonic-gate if (ddi_dev_regsize(dip, DB_CSR_IOBAR_RNUMBER, &bar_size)
5927c478bd9Sstevel@tonic-gate != DDI_SUCCESS) {
5937c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s#%d: cannot get IO CSR size",
5947c478bd9Sstevel@tonic-gate ddi_driver_name(dbp->dip),
5957c478bd9Sstevel@tonic-gate ddi_get_instance(dbp->dip));
5967c478bd9Sstevel@tonic-gate ddi_regs_map_free(&dbp->csr_mem_handle);
5977c478bd9Sstevel@tonic-gate ddi_regs_map_free(&dbp->conf_handle);
5987c478bd9Sstevel@tonic-gate mutex_destroy(&dbp->db_mutex);
5997c478bd9Sstevel@tonic-gate ddi_soft_state_free(db_state, instance);
6007c478bd9Sstevel@tonic-gate rc = DDI_FAILURE;
6017c478bd9Sstevel@tonic-gate break;
6027c478bd9Sstevel@tonic-gate }
6037c478bd9Sstevel@tonic-gate
6047c478bd9Sstevel@tonic-gate /*
6057c478bd9Sstevel@tonic-gate * map IO CSR space. We need this map to initiate
6067c478bd9Sstevel@tonic-gate * indirect configuration transactions as this is a better
6077c478bd9Sstevel@tonic-gate * option than doing through configuration space map.
6087c478bd9Sstevel@tonic-gate */
6097c478bd9Sstevel@tonic-gate if (ddi_regs_map_setup(dip, DB_CSR_IOBAR_RNUMBER,
6107c478bd9Sstevel@tonic-gate (caddr_t *)&dbp->csr_io, DB_CSR_IO_OFFSET, bar_size,
6117c478bd9Sstevel@tonic-gate &db_csr_attr, &dbp->csr_io_handle) != DDI_SUCCESS) {
6127c478bd9Sstevel@tonic-gate
6137c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s#%d: cannot map IO CSR space",
6147c478bd9Sstevel@tonic-gate ddi_driver_name(dbp->dip),
6157c478bd9Sstevel@tonic-gate ddi_get_instance(dbp->dip));
6167c478bd9Sstevel@tonic-gate ddi_regs_map_free(&dbp->csr_mem_handle);
6177c478bd9Sstevel@tonic-gate ddi_regs_map_free(&dbp->conf_handle);
6187c478bd9Sstevel@tonic-gate mutex_destroy(&dbp->db_mutex);
6197c478bd9Sstevel@tonic-gate ddi_soft_state_free(db_state, instance);
6207c478bd9Sstevel@tonic-gate rc = DDI_FAILURE;
6217c478bd9Sstevel@tonic-gate break;
6227c478bd9Sstevel@tonic-gate }
6237c478bd9Sstevel@tonic-gate
6247c478bd9Sstevel@tonic-gate db_orientation(dbp);
6257c478bd9Sstevel@tonic-gate
6267c478bd9Sstevel@tonic-gate if (dbp->dev_state & DB_SECONDARY_NEXUS) {
6277c478bd9Sstevel@tonic-gate if (pcihp_init(dip) != DDI_SUCCESS)
6287c478bd9Sstevel@tonic-gate cmn_err(CE_WARN,
6297c478bd9Sstevel@tonic-gate "%s#%d: could not register with hotplug",
6307c478bd9Sstevel@tonic-gate ddi_driver_name(dbp->dip),
6317c478bd9Sstevel@tonic-gate ddi_get_instance(dbp->dip));
6327c478bd9Sstevel@tonic-gate } else {
6337c478bd9Sstevel@tonic-gate /*
6347c478bd9Sstevel@tonic-gate * create minor node for devctl interfaces
6357c478bd9Sstevel@tonic-gate */
6367c478bd9Sstevel@tonic-gate if (ddi_create_minor_node(dip, "devctl", S_IFCHR,
6377c478bd9Sstevel@tonic-gate PCIHP_AP_MINOR_NUM(instance, PCIHP_DEVCTL_MINOR),
6387c478bd9Sstevel@tonic-gate DDI_NT_NEXUS, 0) != DDI_SUCCESS) {
6397c478bd9Sstevel@tonic-gate ddi_regs_map_free(&dbp->csr_io_handle);
6407c478bd9Sstevel@tonic-gate ddi_regs_map_free(&dbp->csr_mem_handle);
6417c478bd9Sstevel@tonic-gate ddi_regs_map_free(&dbp->conf_handle);
6427c478bd9Sstevel@tonic-gate mutex_destroy(&dbp->db_mutex);
6437c478bd9Sstevel@tonic-gate ddi_soft_state_free(db_state, instance);
6447c478bd9Sstevel@tonic-gate rc = DDI_FAILURE;
6457c478bd9Sstevel@tonic-gate break;
6467c478bd9Sstevel@tonic-gate }
6477c478bd9Sstevel@tonic-gate }
6487c478bd9Sstevel@tonic-gate
6497c478bd9Sstevel@tonic-gate db_enable_io(dbp);
6507c478bd9Sstevel@tonic-gate
6517c478bd9Sstevel@tonic-gate range_size = sizeof (dbp->range);
652a3282898Scth if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip,
6537c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, "bus-range", (caddr_t)&dbp->range,
6547c478bd9Sstevel@tonic-gate &range_size) != DDI_SUCCESS) {
6557c478bd9Sstevel@tonic-gate
6567c478bd9Sstevel@tonic-gate cmn_err(CE_WARN,
6577c478bd9Sstevel@tonic-gate "%s#%d: cannot get bus-range property",
6587c478bd9Sstevel@tonic-gate ddi_driver_name(dip), ddi_get_instance(dip));
6597c478bd9Sstevel@tonic-gate
6607c478bd9Sstevel@tonic-gate if (dbp->dev_state & DB_SECONDARY_NEXUS)
6617c478bd9Sstevel@tonic-gate (void) pcihp_uninit(dip);
6627c478bd9Sstevel@tonic-gate else
6637c478bd9Sstevel@tonic-gate ddi_remove_minor_node(dip, "devctl");
6647c478bd9Sstevel@tonic-gate
6657c478bd9Sstevel@tonic-gate ddi_regs_map_free(&dbp->csr_mem_handle);
6667c478bd9Sstevel@tonic-gate ddi_regs_map_free(&dbp->csr_io_handle);
6677c478bd9Sstevel@tonic-gate ddi_regs_map_free(&dbp->conf_handle);
6687c478bd9Sstevel@tonic-gate mutex_destroy(&dbp->db_mutex);
6697c478bd9Sstevel@tonic-gate ddi_soft_state_free(db_state, instance);
6707c478bd9Sstevel@tonic-gate rc = DDI_FAILURE;
6717c478bd9Sstevel@tonic-gate break;
6727c478bd9Sstevel@tonic-gate }
6737c478bd9Sstevel@tonic-gate
6747c478bd9Sstevel@tonic-gate (void) sprintf(name, "%d", instance);
6757c478bd9Sstevel@tonic-gate
6767c478bd9Sstevel@tonic-gate if (ddi_create_minor_node(dip, name, S_IFCHR,
6777c478bd9Sstevel@tonic-gate PCIHP_AP_MINOR_NUM(instance, PCIHP_DEBUG_MINOR),
678*8adb60c2SToomas Soome NULL, 0) == DDI_FAILURE) {
6797c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "%s#%d: node creation failure",
6807c478bd9Sstevel@tonic-gate ddi_driver_name(dbp->dip), instance);
6817c478bd9Sstevel@tonic-gate }
6827c478bd9Sstevel@tonic-gate
6837c478bd9Sstevel@tonic-gate mutex_init(&dbp->db_busown, NULL, MUTEX_DRIVER, NULL);
6847c478bd9Sstevel@tonic-gate
6857c478bd9Sstevel@tonic-gate db_fm_init(dbp);
6867c478bd9Sstevel@tonic-gate ddi_report_dev(dip);
6877c478bd9Sstevel@tonic-gate dbp->dev_state |= DB_ATTACHED;
6887c478bd9Sstevel@tonic-gate
6897c478bd9Sstevel@tonic-gate break;
6907c478bd9Sstevel@tonic-gate
6917c478bd9Sstevel@tonic-gate case DDI_RESUME:
6927c478bd9Sstevel@tonic-gate
6937c478bd9Sstevel@tonic-gate /*
6947c478bd9Sstevel@tonic-gate * Get the soft state structure for the bridge.
6957c478bd9Sstevel@tonic-gate */
6967c478bd9Sstevel@tonic-gate dbp = (db_ctrl_t *)ddi_get_soft_state(db_state, instance);
6977c478bd9Sstevel@tonic-gate db_enable_io(dbp);
6987c478bd9Sstevel@tonic-gate (void) db_restore_config_regs(dbp);
6997c478bd9Sstevel@tonic-gate dbp->dev_state &= ~DB_SUSPENDED;
7007c478bd9Sstevel@tonic-gate break;
7017c478bd9Sstevel@tonic-gate
7027c478bd9Sstevel@tonic-gate default:
7037c478bd9Sstevel@tonic-gate rc = DDI_FAILURE; /* not supported yet */
7047c478bd9Sstevel@tonic-gate break;
7057c478bd9Sstevel@tonic-gate }
7067c478bd9Sstevel@tonic-gate
7077c478bd9Sstevel@tonic-gate DB_DEBUG1(DB_ATTACH, dip, "exit: rc=%d\n", rc);
7087c478bd9Sstevel@tonic-gate return (rc);
7097c478bd9Sstevel@tonic-gate }
7107c478bd9Sstevel@tonic-gate
7117c478bd9Sstevel@tonic-gate static int
db_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)7127c478bd9Sstevel@tonic-gate db_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
7137c478bd9Sstevel@tonic-gate {
7147c478bd9Sstevel@tonic-gate int instance = ddi_get_instance(dip);
7157c478bd9Sstevel@tonic-gate db_ctrl_t *dbp;
7167c478bd9Sstevel@tonic-gate int rc = DDI_SUCCESS;
7177c478bd9Sstevel@tonic-gate char name[32];
7187c478bd9Sstevel@tonic-gate
7197c478bd9Sstevel@tonic-gate dbp = (db_ctrl_t *)ddi_get_soft_state(db_state, instance);
7207c478bd9Sstevel@tonic-gate
7217c478bd9Sstevel@tonic-gate DB_DEBUG1(DB_DETACH, dip, "enter: cmd=%d\n", cmd);
7227c478bd9Sstevel@tonic-gate
7237c478bd9Sstevel@tonic-gate switch (cmd) {
7247c478bd9Sstevel@tonic-gate
7257c478bd9Sstevel@tonic-gate case DDI_DETACH :
7267c478bd9Sstevel@tonic-gate db_fm_fini(dbp);
7277c478bd9Sstevel@tonic-gate if (dbp->dev_state & DB_SECONDARY_NEXUS)
7287c478bd9Sstevel@tonic-gate if (pcihp_uninit(dip) == DDI_FAILURE)
7297c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
7307c478bd9Sstevel@tonic-gate else
7317c478bd9Sstevel@tonic-gate ddi_remove_minor_node(dip, "devctl");
7327c478bd9Sstevel@tonic-gate
7337c478bd9Sstevel@tonic-gate mutex_destroy(&dbp->db_busown);
7347c478bd9Sstevel@tonic-gate ddi_regs_map_free(&dbp->csr_mem_handle);
7357c478bd9Sstevel@tonic-gate ddi_regs_map_free(&dbp->csr_io_handle);
7367c478bd9Sstevel@tonic-gate
7377c478bd9Sstevel@tonic-gate ddi_regs_map_free(&dbp->conf_handle);
7387c478bd9Sstevel@tonic-gate dbp->dev_state &= ~DB_ATTACHED;
7397c478bd9Sstevel@tonic-gate (void) sprintf(name, "%d", instance);
7407c478bd9Sstevel@tonic-gate ddi_remove_minor_node(dip, name);
7417c478bd9Sstevel@tonic-gate mutex_destroy(&dbp->db_mutex);
7427c478bd9Sstevel@tonic-gate ddi_soft_state_free(db_state, instance);
7437c478bd9Sstevel@tonic-gate break;
7447c478bd9Sstevel@tonic-gate
7457c478bd9Sstevel@tonic-gate case DDI_SUSPEND :
7467c478bd9Sstevel@tonic-gate if (db_save_config_regs(dbp) != DDI_SUCCESS) {
7477c478bd9Sstevel@tonic-gate cmn_err(CE_WARN,
7487c478bd9Sstevel@tonic-gate "%s#%d: Ignoring Child state Suspend Error",
7497c478bd9Sstevel@tonic-gate ddi_driver_name(dbp->dip),
7507c478bd9Sstevel@tonic-gate ddi_get_instance(dbp->dip));
7517c478bd9Sstevel@tonic-gate }
7527c478bd9Sstevel@tonic-gate dbp->dev_state |= DB_SUSPENDED;
7537c478bd9Sstevel@tonic-gate break;
7547c478bd9Sstevel@tonic-gate
7557c478bd9Sstevel@tonic-gate default :
7567c478bd9Sstevel@tonic-gate rc = DDI_FAILURE;
7577c478bd9Sstevel@tonic-gate break;
7587c478bd9Sstevel@tonic-gate }
7597c478bd9Sstevel@tonic-gate
7607c478bd9Sstevel@tonic-gate DB_DEBUG1(DB_DETACH, dip, "exit: rc=%d\n", rc);
7617c478bd9Sstevel@tonic-gate return (rc);
7627c478bd9Sstevel@tonic-gate }
7637c478bd9Sstevel@tonic-gate
7647c478bd9Sstevel@tonic-gate static void
db_get_perf_parameters(db_ctrl_t * dbp)7657c478bd9Sstevel@tonic-gate db_get_perf_parameters(db_ctrl_t *dbp)
7667c478bd9Sstevel@tonic-gate {
7677c478bd9Sstevel@tonic-gate dbp->p_latency_timer = (int8_t)ddi_prop_get_int(DDI_DEV_T_ANY,
7687c478bd9Sstevel@tonic-gate dbp->dip, 0, "p-latency-timer", p_latency_timer);
7697c478bd9Sstevel@tonic-gate dbp->s_latency_timer = (int8_t)ddi_prop_get_int(DDI_DEV_T_ANY,
7707c478bd9Sstevel@tonic-gate dbp->dip, 0, "s-latency-timer", s_latency_timer);
7717c478bd9Sstevel@tonic-gate dbp->p_cache_line_size = (int8_t)ddi_prop_get_int(DDI_DEV_T_ANY,
7727c478bd9Sstevel@tonic-gate dbp->dip, 0, "p-cache-line-size", p_cache_line_size);
7737c478bd9Sstevel@tonic-gate dbp->s_cache_line_size = (int8_t)ddi_prop_get_int(DDI_DEV_T_ANY,
7747c478bd9Sstevel@tonic-gate dbp->dip, 0, "s-cache-line-size", s_cache_line_size);
7757c478bd9Sstevel@tonic-gate dbp->p_pwrite_threshold = (int8_t)ddi_prop_get_int(DDI_DEV_T_ANY,
7767c478bd9Sstevel@tonic-gate dbp->dip, 0, "p-pwrite-threshold", p_pwrite_threshold);
7777c478bd9Sstevel@tonic-gate dbp->s_pwrite_threshold = (int8_t)ddi_prop_get_int(DDI_DEV_T_ANY,
7787c478bd9Sstevel@tonic-gate dbp->dip, 0, "s-pwrite-threshold", s_pwrite_threshold);
7797c478bd9Sstevel@tonic-gate dbp->p_dread_threshold = (int8_t)ddi_prop_get_int(DDI_DEV_T_ANY,
7807c478bd9Sstevel@tonic-gate dbp->dip, 0, "p-dread-threshold", p_dread_threshold);
7817c478bd9Sstevel@tonic-gate dbp->s_dread_threshold = (int8_t)ddi_prop_get_int(DDI_DEV_T_ANY,
7827c478bd9Sstevel@tonic-gate dbp->dip, 0, "s-dread-threshold", s_dread_threshold);
7837c478bd9Sstevel@tonic-gate dbp->delayed_trans_order = (int8_t)ddi_prop_get_int(DDI_DEV_T_ANY,
7847c478bd9Sstevel@tonic-gate dbp->dip, 0, "delayed-trans-order", delayed_trans_order);
7857c478bd9Sstevel@tonic-gate }
7867c478bd9Sstevel@tonic-gate
7877c478bd9Sstevel@tonic-gate static void
db_set_perf_parameters(db_ctrl_t * dbp)7887c478bd9Sstevel@tonic-gate db_set_perf_parameters(db_ctrl_t *dbp)
7897c478bd9Sstevel@tonic-gate {
7907c478bd9Sstevel@tonic-gate uint_t poffset = 0, soffset = 0;
7917c478bd9Sstevel@tonic-gate
7927c478bd9Sstevel@tonic-gate if (dbp->dev_state & DB_SECONDARY_NEXUS)
7937c478bd9Sstevel@tonic-gate poffset = DB_SCONF_PRI_HDR_OFF;
7947c478bd9Sstevel@tonic-gate else
7957c478bd9Sstevel@tonic-gate soffset = DB_PCONF_SEC_HDR_OFF;
7967c478bd9Sstevel@tonic-gate
7977c478bd9Sstevel@tonic-gate if ((dbp->p_latency_timer != (int8_t)DEF_INVALID_REG_VAL) &&
7987c478bd9Sstevel@tonic-gate (dbp->p_latency_timer != -1))
7997c478bd9Sstevel@tonic-gate ddi_put8(dbp->conf_handle,
8007c478bd9Sstevel@tonic-gate (uint8_t *)dbp->conf_io+poffset+PCI_CONF_LATENCY_TIMER,
8017c478bd9Sstevel@tonic-gate dbp->p_latency_timer);
8027c478bd9Sstevel@tonic-gate if ((dbp->s_latency_timer != (int8_t)DEF_INVALID_REG_VAL) &&
8037c478bd9Sstevel@tonic-gate (dbp->s_latency_timer != -1))
8047c478bd9Sstevel@tonic-gate ddi_put8(dbp->conf_handle,
8057c478bd9Sstevel@tonic-gate (uint8_t *)dbp->conf_io+soffset+PCI_CONF_LATENCY_TIMER,
8067c478bd9Sstevel@tonic-gate dbp->s_latency_timer);
8077c478bd9Sstevel@tonic-gate if ((dbp->p_cache_line_size != (int8_t)DEF_INVALID_REG_VAL) &&
8087c478bd9Sstevel@tonic-gate (dbp->p_cache_line_size != -1))
8097c478bd9Sstevel@tonic-gate ddi_put8(dbp->conf_handle,
8107c478bd9Sstevel@tonic-gate (uint8_t *)dbp->conf_io+poffset+PCI_CONF_CACHE_LINESZ,
8117c478bd9Sstevel@tonic-gate dbp->p_cache_line_size);
8127c478bd9Sstevel@tonic-gate if ((dbp->s_cache_line_size != (int8_t)DEF_INVALID_REG_VAL) &&
8137c478bd9Sstevel@tonic-gate (dbp->s_cache_line_size != -1))
8147c478bd9Sstevel@tonic-gate ddi_put8(dbp->conf_handle,
8157c478bd9Sstevel@tonic-gate (uint8_t *)dbp->conf_io+soffset+PCI_CONF_CACHE_LINESZ,
8167c478bd9Sstevel@tonic-gate dbp->s_cache_line_size);
8177c478bd9Sstevel@tonic-gate if ((dbp->p_pwrite_threshold != (int8_t)DEF_INVALID_REG_VAL) &&
8187c478bd9Sstevel@tonic-gate (dbp->p_pwrite_threshold != -1))
8197c478bd9Sstevel@tonic-gate ddi_put16(dbp->conf_handle, (uint16_t *)
8207c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->conf_io+DB_CONF_CHIP_CTRL1),
8217c478bd9Sstevel@tonic-gate (ddi_get16(dbp->conf_handle, (uint16_t *)
8227c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->conf_io+DB_CONF_CHIP_CTRL1)) &
8237c478bd9Sstevel@tonic-gate ~P_PW_THRESHOLD) |
8247c478bd9Sstevel@tonic-gate (dbp->p_pwrite_threshold?P_PW_THRESHOLD:0));
8257c478bd9Sstevel@tonic-gate if ((dbp->s_pwrite_threshold != (int8_t)DEF_INVALID_REG_VAL) &&
8267c478bd9Sstevel@tonic-gate (dbp->s_pwrite_threshold != -1))
8277c478bd9Sstevel@tonic-gate ddi_put16(dbp->conf_handle, (uint16_t *)
8287c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->conf_io+DB_CONF_CHIP_CTRL1),
8297c478bd9Sstevel@tonic-gate (ddi_get16(dbp->conf_handle, (uint16_t *)
8307c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->conf_io+DB_CONF_CHIP_CTRL1)) &
8317c478bd9Sstevel@tonic-gate ~S_PW_THRESHOLD) |
8327c478bd9Sstevel@tonic-gate (dbp->s_pwrite_threshold?S_PW_THRESHOLD:0));
8337c478bd9Sstevel@tonic-gate /* primary delayed read threshold. 0x01 is reserved ?. */
8347c478bd9Sstevel@tonic-gate if ((dbp->p_dread_threshold != (int8_t)DEF_INVALID_REG_VAL) &&
8357c478bd9Sstevel@tonic-gate (dbp->p_dread_threshold != -1))
8367c478bd9Sstevel@tonic-gate ddi_put16(dbp->conf_handle, (uint16_t *)
8377c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->conf_io+DB_CONF_CHIP_CTRL1),
8387c478bd9Sstevel@tonic-gate ((ddi_get16(dbp->conf_handle, (uint16_t *)
8397c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->conf_io+DB_CONF_CHIP_CTRL1)) &
8407c478bd9Sstevel@tonic-gate ~P_DREAD_THRESHOLD_MASK) |
8417c478bd9Sstevel@tonic-gate ((dbp->p_dread_threshold &
8427c478bd9Sstevel@tonic-gate DREAD_THRESHOLD_VALBITS)<<2)));
8437c478bd9Sstevel@tonic-gate /* secondary delayed read threshold. 0x01 is reserved ?. */
8447c478bd9Sstevel@tonic-gate if ((dbp->s_dread_threshold != (int8_t)DEF_INVALID_REG_VAL) &&
8457c478bd9Sstevel@tonic-gate (dbp->s_dread_threshold != -1))
8467c478bd9Sstevel@tonic-gate ddi_put16(dbp->conf_handle, (uint16_t *)
8477c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->conf_io+DB_CONF_CHIP_CTRL1),
8487c478bd9Sstevel@tonic-gate ((ddi_get16(dbp->conf_handle, (uint16_t *)
8497c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->conf_io+DB_CONF_CHIP_CTRL1)) &
8507c478bd9Sstevel@tonic-gate ~S_DREAD_THRESHOLD_MASK) |
8517c478bd9Sstevel@tonic-gate ((dbp->s_dread_threshold &
8527c478bd9Sstevel@tonic-gate DREAD_THRESHOLD_VALBITS)<<4)));
8537c478bd9Sstevel@tonic-gate if ((dbp->delayed_trans_order != (int8_t)DEF_INVALID_REG_VAL) &&
8547c478bd9Sstevel@tonic-gate (dbp->delayed_trans_order != -1))
8557c478bd9Sstevel@tonic-gate ddi_put16(dbp->conf_handle, (uint16_t *)
8567c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->conf_io+DB_CONF_CHIP_CTRL0),
8577c478bd9Sstevel@tonic-gate (ddi_get16(dbp->conf_handle, (uint16_t *)
8587c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->conf_io+DB_CONF_CHIP_CTRL0)) &
8597c478bd9Sstevel@tonic-gate ~DELAYED_TRANS_ORDER) |
8607c478bd9Sstevel@tonic-gate (dbp->delayed_trans_order?DELAYED_TRANS_ORDER:0));
8617c478bd9Sstevel@tonic-gate }
8627c478bd9Sstevel@tonic-gate
8637c478bd9Sstevel@tonic-gate static void
db_orientation(db_ctrl_t * dbp)8647c478bd9Sstevel@tonic-gate db_orientation(db_ctrl_t *dbp)
8657c478bd9Sstevel@tonic-gate {
8667c478bd9Sstevel@tonic-gate dev_info_t *dip = dbp->dip;
8677c478bd9Sstevel@tonic-gate uint8_t pif;
8687c478bd9Sstevel@tonic-gate uint32_t mem1;
8697c478bd9Sstevel@tonic-gate uint32_t newval;
8707c478bd9Sstevel@tonic-gate
8717c478bd9Sstevel@tonic-gate /*
8727c478bd9Sstevel@tonic-gate * determine orientation of drawbridge and enable
8737c478bd9Sstevel@tonic-gate * Upstream or Downstream path.
8747c478bd9Sstevel@tonic-gate */
8757c478bd9Sstevel@tonic-gate
8767c478bd9Sstevel@tonic-gate /*
8777c478bd9Sstevel@tonic-gate * if PIF is set correctly, use it to determine orientation
8787c478bd9Sstevel@tonic-gate */
8797c478bd9Sstevel@tonic-gate pif = ddi_get8(dbp->conf_handle, (uchar_t *)dbp->conf_io +
8807c478bd9Sstevel@tonic-gate PCI_CONF_PROGCLASS);
8817c478bd9Sstevel@tonic-gate if (pif & 0xff) {
8827c478bd9Sstevel@tonic-gate if (pif & DB_PIF_SECONDARY_TO_HOST) {
8837c478bd9Sstevel@tonic-gate dbp->dev_state = DB_SECONDARY_NEXUS;
8847c478bd9Sstevel@tonic-gate DB_DEBUG0(DB_ATTACH, dip,
8857c478bd9Sstevel@tonic-gate "db_orientation: pif secondary\n");
8867c478bd9Sstevel@tonic-gate return;
8877c478bd9Sstevel@tonic-gate }
8887c478bd9Sstevel@tonic-gate if (pif & DB_PIF_PRIMARY_TO_HOST) {
8897c478bd9Sstevel@tonic-gate dbp->dev_state = DB_PRIMARY_NEXUS;
8907c478bd9Sstevel@tonic-gate DB_DEBUG0(DB_ATTACH, dip,
8917c478bd9Sstevel@tonic-gate "db_orientation: pif primary\n");
8927c478bd9Sstevel@tonic-gate return;
8937c478bd9Sstevel@tonic-gate }
8947c478bd9Sstevel@tonic-gate /* otherwise, fall through */
8957c478bd9Sstevel@tonic-gate }
8967c478bd9Sstevel@tonic-gate
8977c478bd9Sstevel@tonic-gate /*
8987c478bd9Sstevel@tonic-gate * otherwise, test the chip directly by trying to write
8997c478bd9Sstevel@tonic-gate * downstream mem1 setup register, only writeable from
9007c478bd9Sstevel@tonic-gate * secondary.
9017c478bd9Sstevel@tonic-gate */
9027c478bd9Sstevel@tonic-gate mem1 = ddi_get32(dbp->conf_handle,
9037c478bd9Sstevel@tonic-gate (uint32_t *)((uchar_t *)dbp->conf_io +
9047c478bd9Sstevel@tonic-gate DB_CONF_DS_IO_MEM1_SETUP));
9057c478bd9Sstevel@tonic-gate
9067c478bd9Sstevel@tonic-gate ddi_put32(dbp->conf_handle,
9077c478bd9Sstevel@tonic-gate (uint32_t *)((uchar_t *)(dbp->conf_io +
9087c478bd9Sstevel@tonic-gate DB_CONF_DS_IO_MEM1_SETUP)), ~mem1);
9097c478bd9Sstevel@tonic-gate
9107c478bd9Sstevel@tonic-gate newval = ddi_get32(dbp->conf_handle,
9117c478bd9Sstevel@tonic-gate (uint32_t *)((uchar_t *)dbp->conf_io +
9127c478bd9Sstevel@tonic-gate DB_CONF_DS_IO_MEM1_SETUP));
9137c478bd9Sstevel@tonic-gate
9147c478bd9Sstevel@tonic-gate if (newval == mem1)
9157c478bd9Sstevel@tonic-gate /* we couldn't write it, orientation is primary */
9167c478bd9Sstevel@tonic-gate dbp->dev_state = DB_PRIMARY_NEXUS;
9177c478bd9Sstevel@tonic-gate else {
9187c478bd9Sstevel@tonic-gate /*
9197c478bd9Sstevel@tonic-gate * we could write it, therefore orientation secondary.
9207c478bd9Sstevel@tonic-gate * restore mem1 value.
9217c478bd9Sstevel@tonic-gate */
9227c478bd9Sstevel@tonic-gate dbp->dev_state = DB_SECONDARY_NEXUS;
9237c478bd9Sstevel@tonic-gate ddi_put32(dbp->conf_handle,
9247c478bd9Sstevel@tonic-gate (uint32_t *)((uchar_t *)(dbp->conf_io +
9257c478bd9Sstevel@tonic-gate DB_CONF_DS_IO_MEM1_SETUP)), mem1);
9267c478bd9Sstevel@tonic-gate }
9277c478bd9Sstevel@tonic-gate
9287c478bd9Sstevel@tonic-gate
9297c478bd9Sstevel@tonic-gate if (dbp->dev_state & DB_PRIMARY_NEXUS) {
9307c478bd9Sstevel@tonic-gate DB_DEBUG0(DB_ATTACH, dip, "db_orientation: chip primary\n");
9317c478bd9Sstevel@tonic-gate } else {
9327c478bd9Sstevel@tonic-gate DB_DEBUG0(DB_ATTACH, dip, "db_orientation: chip secondary\n");
9337c478bd9Sstevel@tonic-gate }
9347c478bd9Sstevel@tonic-gate }
9357c478bd9Sstevel@tonic-gate
9367c478bd9Sstevel@tonic-gate static void
db_enable_io(db_ctrl_t * dbp)9377c478bd9Sstevel@tonic-gate db_enable_io(db_ctrl_t *dbp)
9387c478bd9Sstevel@tonic-gate {
9397c478bd9Sstevel@tonic-gate dev_info_t *dip = dbp->dip;
9407c478bd9Sstevel@tonic-gate pci_regspec_t *reg;
9417c478bd9Sstevel@tonic-gate int rcount, length, i;
9427c478bd9Sstevel@tonic-gate uint32_t offset;
9437c478bd9Sstevel@tonic-gate uint32_t p_offset, s_offset;
9447c478bd9Sstevel@tonic-gate uint16_t regval;
9457c478bd9Sstevel@tonic-gate uint16_t enable;
9467c478bd9Sstevel@tonic-gate
9477c478bd9Sstevel@tonic-gate /*
9487c478bd9Sstevel@tonic-gate * Step 0:
9497c478bd9Sstevel@tonic-gate * setup the primary and secondary offset and enable
9507c478bd9Sstevel@tonic-gate * values based on the orientation of 21554.
9517c478bd9Sstevel@tonic-gate */
9527c478bd9Sstevel@tonic-gate if (dbp->dev_state & DB_PRIMARY_NEXUS) {
9537c478bd9Sstevel@tonic-gate DB_DEBUG0(DB_ATTACH, dip, "db_enable_io: primary\n");
9547c478bd9Sstevel@tonic-gate p_offset = 0;
9557c478bd9Sstevel@tonic-gate s_offset = DB_SCONF_HDR_OFF;
9567c478bd9Sstevel@tonic-gate enable = DS_ENABLE;
9577c478bd9Sstevel@tonic-gate } else {
9587c478bd9Sstevel@tonic-gate DB_DEBUG0(DB_ATTACH, dip, "db_enable_io: secondary\n");
9597c478bd9Sstevel@tonic-gate p_offset = DB_SCONF_HDR_OFF;
9607c478bd9Sstevel@tonic-gate s_offset = 0;
9617c478bd9Sstevel@tonic-gate enable = US_ENABLE;
9627c478bd9Sstevel@tonic-gate }
9637c478bd9Sstevel@tonic-gate
9647c478bd9Sstevel@tonic-gate db_set_perf_parameters(dbp);
9657c478bd9Sstevel@tonic-gate db_set_dvma_range(dbp);
9667c478bd9Sstevel@tonic-gate
9677c478bd9Sstevel@tonic-gate /*
9687c478bd9Sstevel@tonic-gate * Step 1:
9697c478bd9Sstevel@tonic-gate * setup latency timer and cache line size parameters
9707c478bd9Sstevel@tonic-gate * which are used for child initialization.
9717c478bd9Sstevel@tonic-gate */
9727c478bd9Sstevel@tonic-gate dbp->latency_timer = ddi_get8(dbp->conf_handle, (uint8_t *)
9737c478bd9Sstevel@tonic-gate ((caddr_t)dbp->conf_io+PCI_CONF_LATENCY_TIMER));
9747c478bd9Sstevel@tonic-gate
9757c478bd9Sstevel@tonic-gate dbp->cache_line_size = ddi_get8(dbp->conf_handle, (uint8_t *)
9767c478bd9Sstevel@tonic-gate ((caddr_t)dbp->conf_io+PCI_CONF_CACHE_LINESZ));
9777c478bd9Sstevel@tonic-gate
9787c478bd9Sstevel@tonic-gate DB_DEBUG2(DB_ATTACH, dip,
9797c478bd9Sstevel@tonic-gate "db_enable_io: latency %d, cache line size %d\n",
9807c478bd9Sstevel@tonic-gate dbp->latency_timer, dbp->cache_line_size);
9817c478bd9Sstevel@tonic-gate
9827c478bd9Sstevel@tonic-gate /*
9837c478bd9Sstevel@tonic-gate * Step 2: program command reg on both primary and secondary
9847c478bd9Sstevel@tonic-gate * interfaces.
9857c478bd9Sstevel@tonic-gate */
9867c478bd9Sstevel@tonic-gate ddi_put16(dbp->conf_handle, (uint16_t *)((caddr_t)dbp->conf_io +
9877c478bd9Sstevel@tonic-gate (off_t)(p_offset + PCI_CONF_COMM)), db_command_default);
9887c478bd9Sstevel@tonic-gate
9897c478bd9Sstevel@tonic-gate ddi_put16(dbp->conf_handle, (uint16_t *)((caddr_t)dbp->conf_io +
9907c478bd9Sstevel@tonic-gate (off_t)(s_offset + PCI_CONF_COMM)), db_command_default);
9917c478bd9Sstevel@tonic-gate
9927c478bd9Sstevel@tonic-gate /*
9937c478bd9Sstevel@tonic-gate * Step 3:
9947c478bd9Sstevel@tonic-gate * set up translated base registers, using the primary/
9957c478bd9Sstevel@tonic-gate * secondary interface pci configuration Base Address
9967c478bd9Sstevel@tonic-gate * Registers (BAR's).
9977c478bd9Sstevel@tonic-gate */
9987c478bd9Sstevel@tonic-gate
9997c478bd9Sstevel@tonic-gate /* mem0 translated base is setup for primary orientation only. */
10007c478bd9Sstevel@tonic-gate if (dbp->dev_state & DB_PRIMARY_NEXUS) {
10017c478bd9Sstevel@tonic-gate /*
10027c478bd9Sstevel@tonic-gate * And only if the 21554 device node property indicates
10037c478bd9Sstevel@tonic-gate * the size of base0 register to be larger than csr map
10047c478bd9Sstevel@tonic-gate * space, DB_CSR_SIZE=4K.
10057c478bd9Sstevel@tonic-gate *
10067c478bd9Sstevel@tonic-gate * Note : Setting up 1:1 translations only (for now:), i.e.
10077c478bd9Sstevel@tonic-gate * no look up table.
10087c478bd9Sstevel@tonic-gate */
10097c478bd9Sstevel@tonic-gate if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
10107c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, "reg", (caddr_t)®,
10117c478bd9Sstevel@tonic-gate &length) != DDI_PROP_SUCCESS) {
10127c478bd9Sstevel@tonic-gate DB_DEBUG0(DB_ATTACH, dip,
10137c478bd9Sstevel@tonic-gate "Failed to read reg property\n");
10147c478bd9Sstevel@tonic-gate return;
10157c478bd9Sstevel@tonic-gate }
10167c478bd9Sstevel@tonic-gate
10177c478bd9Sstevel@tonic-gate /* Find device node's base0 reg property and check its size */
10187c478bd9Sstevel@tonic-gate rcount = length / sizeof (pci_regspec_t);
10197c478bd9Sstevel@tonic-gate for (i = 0; i < rcount; i++) {
10207c478bd9Sstevel@tonic-gate offset = PCI_REG_REG_G(reg[i].pci_phys_hi);
10217c478bd9Sstevel@tonic-gate if ((offset == PCI_CONF_BASE0) &&
10227c478bd9Sstevel@tonic-gate (reg[i].pci_size_low > DB_CSR_SIZE))
10237c478bd9Sstevel@tonic-gate break;
10247c478bd9Sstevel@tonic-gate }
10257c478bd9Sstevel@tonic-gate
10267c478bd9Sstevel@tonic-gate /*
10277c478bd9Sstevel@tonic-gate * set up mem0 translated base, if base0 register was
10287c478bd9Sstevel@tonic-gate * found and its size was larger than csr map space.
10297c478bd9Sstevel@tonic-gate */
10307c478bd9Sstevel@tonic-gate if (i != rcount) {
10317c478bd9Sstevel@tonic-gate DB_DEBUG0(DB_ATTACH, dip,
10327c478bd9Sstevel@tonic-gate "db_enable_io: setting up MEM0_TR_BASE\n");
10337c478bd9Sstevel@tonic-gate DB_DEBUG1(DB_ATTACH, dip, "BASE0 register = %x\n",
10347c478bd9Sstevel@tonic-gate pci_config_get32(dbp->conf_handle,
10357c478bd9Sstevel@tonic-gate (off_t)(p_offset + PCI_CONF_BASE0)));
10367c478bd9Sstevel@tonic-gate
10377c478bd9Sstevel@tonic-gate pci_config_put32(dbp->conf_handle,
10387c478bd9Sstevel@tonic-gate (off_t)DB_CONF_DS_MEM0_TR_BASE,
10397c478bd9Sstevel@tonic-gate pci_config_get32(dbp->conf_handle,
10407c478bd9Sstevel@tonic-gate (off_t)(p_offset + PCI_CONF_BASE0)));
10417c478bd9Sstevel@tonic-gate
10427c478bd9Sstevel@tonic-gate DB_DEBUG1(DB_ATTACH, dip,
10437c478bd9Sstevel@tonic-gate "db_enable_io: MEM0_TR_BASE set value = %x\n",
10447c478bd9Sstevel@tonic-gate pci_config_get32(dbp->conf_handle,
10457c478bd9Sstevel@tonic-gate (off_t)DB_CONF_DS_MEM0_TR_BASE));
10467c478bd9Sstevel@tonic-gate }
10477c478bd9Sstevel@tonic-gate kmem_free(reg, length);
10487c478bd9Sstevel@tonic-gate }
10497c478bd9Sstevel@tonic-gate
10507c478bd9Sstevel@tonic-gate pci_config_put32(dbp->conf_handle, (off_t)DB_CONF_DS_IO_MEM1_TR_BASE,
10517c478bd9Sstevel@tonic-gate ((pci_config_get32(dbp->conf_handle,
10527c478bd9Sstevel@tonic-gate (off_t)(p_offset + PCI_CONF_BASE2))) & ~DB_IO_BIT));
10537c478bd9Sstevel@tonic-gate
10547c478bd9Sstevel@tonic-gate pci_config_put32(dbp->conf_handle, (off_t)DB_CONF_DS_MEM2_TR_BASE,
10557c478bd9Sstevel@tonic-gate ((pci_config_get32(dbp->conf_handle,
10567c478bd9Sstevel@tonic-gate (off_t)(p_offset + PCI_CONF_BASE3))) & ~DB_IO_BIT));
10577c478bd9Sstevel@tonic-gate
10587c478bd9Sstevel@tonic-gate pci_config_put32(dbp->conf_handle, (off_t)DB_CONF_DS_MEM3_TR_BASE,
10597c478bd9Sstevel@tonic-gate ((pci_config_get32(dbp->conf_handle,
10607c478bd9Sstevel@tonic-gate (off_t)(p_offset + PCI_CONF_BASE4))) & ~DB_IO_BIT));
10617c478bd9Sstevel@tonic-gate
10627c478bd9Sstevel@tonic-gate pci_config_put32(dbp->conf_handle, (off_t)DB_CONF_US_IO_MEM0_TR_BASE,
10637c478bd9Sstevel@tonic-gate ((pci_config_get32(dbp->conf_handle,
10647c478bd9Sstevel@tonic-gate (off_t)(s_offset + PCI_CONF_BASE2))) & ~DB_IO_BIT));
10657c478bd9Sstevel@tonic-gate
10667c478bd9Sstevel@tonic-gate pci_config_put32(dbp->conf_handle, (off_t)DB_CONF_US_MEM1_TR_BASE,
10677c478bd9Sstevel@tonic-gate ((pci_config_get32(dbp->conf_handle,
10687c478bd9Sstevel@tonic-gate (off_t)(s_offset + PCI_CONF_BASE3))) & ~DB_IO_BIT));
10697c478bd9Sstevel@tonic-gate
10707c478bd9Sstevel@tonic-gate /*
10717c478bd9Sstevel@tonic-gate * Step 4: enable downstream (for primary orientation) or upstream
10727c478bd9Sstevel@tonic-gate * (for secondary orientation) bits in Configuration Control
10737c478bd9Sstevel@tonic-gate * and Status register, if not already enabled.
10747c478bd9Sstevel@tonic-gate */
10757c478bd9Sstevel@tonic-gate regval = pci_config_get16(dbp->conf_handle, (off_t)DB_CONF_CONF_CSR);
10767c478bd9Sstevel@tonic-gate
10777c478bd9Sstevel@tonic-gate DB_DEBUG1(DB_ATTACH, dip, "db_enable_io: CSR value before: %x\n",
10787c478bd9Sstevel@tonic-gate regval);
10797c478bd9Sstevel@tonic-gate
10807c478bd9Sstevel@tonic-gate if (!(regval & enable)) {
10817c478bd9Sstevel@tonic-gate /* enable down/upstream configuration transactions */
10827c478bd9Sstevel@tonic-gate regval |= enable;
10837c478bd9Sstevel@tonic-gate pci_config_put16(dbp->conf_handle, (off_t)DB_CONF_CONF_CSR,
10847c478bd9Sstevel@tonic-gate regval);
10857c478bd9Sstevel@tonic-gate regval = pci_config_get16(dbp->conf_handle,
10867c478bd9Sstevel@tonic-gate (off_t)DB_CONF_CONF_CSR);
10877c478bd9Sstevel@tonic-gate }
10887c478bd9Sstevel@tonic-gate DB_DEBUG1(DB_ATTACH, dip, "db_enable_io: CSR value after: %x\n",
10897c478bd9Sstevel@tonic-gate regval);
10907c478bd9Sstevel@tonic-gate
10917c478bd9Sstevel@tonic-gate /*
10927c478bd9Sstevel@tonic-gate * Step 5: enable downstream/upstream I/O (through CSR space)
10937c478bd9Sstevel@tonic-gate */
10947c478bd9Sstevel@tonic-gate regval = ddi_get16(dbp->csr_mem_handle,
10957c478bd9Sstevel@tonic-gate (uint16_t *)((uchar_t *)dbp->csr_mem + DB_CSR_IO_CSR));
10967c478bd9Sstevel@tonic-gate
10977c478bd9Sstevel@tonic-gate DB_DEBUG1(DB_ATTACH, dip, "db_enable_io: IO_CSR value before: %x\n",
10987c478bd9Sstevel@tonic-gate regval);
10997c478bd9Sstevel@tonic-gate if (!(regval & enable)) {
11007c478bd9Sstevel@tonic-gate regval |= enable;
11017c478bd9Sstevel@tonic-gate ddi_put16(dbp->csr_mem_handle,
11027c478bd9Sstevel@tonic-gate (uint16_t *)((uchar_t *)dbp->csr_mem +
11037c478bd9Sstevel@tonic-gate DB_CSR_IO_CSR), regval);
11047c478bd9Sstevel@tonic-gate
11057c478bd9Sstevel@tonic-gate regval = ddi_get16(dbp->csr_mem_handle,
11067c478bd9Sstevel@tonic-gate (uint16_t *)((uchar_t *)dbp->csr_mem + DB_CSR_IO_CSR));
11077c478bd9Sstevel@tonic-gate }
11087c478bd9Sstevel@tonic-gate DB_DEBUG1(DB_ATTACH, dip, "db_enable_io: IO_CSR value after: %x\n",
11097c478bd9Sstevel@tonic-gate regval);
11107c478bd9Sstevel@tonic-gate
11117c478bd9Sstevel@tonic-gate /*
11127c478bd9Sstevel@tonic-gate * Step 6: if 21554 orientation is primary to host,
11137c478bd9Sstevel@tonic-gate * forward SERR# to host.
11147c478bd9Sstevel@tonic-gate */
11157c478bd9Sstevel@tonic-gate if (dbp->dev_state & DB_PRIMARY_NEXUS) {
11167c478bd9Sstevel@tonic-gate dbp->serr_fwd_enable = ddi_prop_get_int(DDI_DEV_T_ANY,
11177c478bd9Sstevel@tonic-gate dbp->dip, 0, "serr-fwd-enable", db_serr_fwd_enable);
11187c478bd9Sstevel@tonic-gate
11197c478bd9Sstevel@tonic-gate regval = ddi_get16(dbp->conf_handle,
11207c478bd9Sstevel@tonic-gate (uint16_t *)((uchar_t *)dbp->conf_io +
11217c478bd9Sstevel@tonic-gate DB_CONF_CHIP_CTRL0));
11227c478bd9Sstevel@tonic-gate
11237c478bd9Sstevel@tonic-gate DB_DEBUG1(DB_ATTACH, dip,
11247c478bd9Sstevel@tonic-gate "db_enable_io: CHIP_CTRL0 value before: %x\n", regval);
11257c478bd9Sstevel@tonic-gate
11267c478bd9Sstevel@tonic-gate ddi_put16(dbp->conf_handle,
11277c478bd9Sstevel@tonic-gate (uint16_t *)((uchar_t *)dbp->conf_io +
11287c478bd9Sstevel@tonic-gate DB_CONF_CHIP_CTRL0),
11297c478bd9Sstevel@tonic-gate (regval & ~SERR_FWD) |
11307c478bd9Sstevel@tonic-gate (dbp->serr_fwd_enable?SERR_FWD:0));
11317c478bd9Sstevel@tonic-gate
11327c478bd9Sstevel@tonic-gate regval = ddi_get16(dbp->conf_handle,
11337c478bd9Sstevel@tonic-gate (uint16_t *)((uchar_t *)dbp->conf_io +
11347c478bd9Sstevel@tonic-gate DB_CONF_CHIP_CTRL0));
11357c478bd9Sstevel@tonic-gate
11367c478bd9Sstevel@tonic-gate DB_DEBUG1(DB_ATTACH, dip,
11377c478bd9Sstevel@tonic-gate "db_enable_io: CHIP_CTRL0 value after: %x\n", regval);
11387c478bd9Sstevel@tonic-gate }
11397c478bd9Sstevel@tonic-gate
11407c478bd9Sstevel@tonic-gate /*
11417c478bd9Sstevel@tonic-gate * Step 7: if orientation is secondary, make sure primary lockout
11427c478bd9Sstevel@tonic-gate * disable is reset.
11437c478bd9Sstevel@tonic-gate */
11447c478bd9Sstevel@tonic-gate
11457c478bd9Sstevel@tonic-gate if (dbp->dev_state & DB_SECONDARY_NEXUS) {
11467c478bd9Sstevel@tonic-gate regval = pci_config_get16(dbp->conf_handle,
11477c478bd9Sstevel@tonic-gate (off_t)DB_CONF_CHIP_CTRL0);
11487c478bd9Sstevel@tonic-gate DB_DEBUG1(DB_ATTACH, dip,
11497c478bd9Sstevel@tonic-gate "db_enable_io: chip ctrl (0x%x) before\n", regval);
11507c478bd9Sstevel@tonic-gate if (regval & PLOCKOUT)
11517c478bd9Sstevel@tonic-gate pci_config_put16(dbp->conf_handle,
11527c478bd9Sstevel@tonic-gate (off_t)DB_CONF_CHIP_CTRL0,
11537c478bd9Sstevel@tonic-gate (regval & ~PLOCKOUT));
11547c478bd9Sstevel@tonic-gate regval = pci_config_get16(dbp->conf_handle,
11557c478bd9Sstevel@tonic-gate (off_t)DB_CONF_CHIP_CTRL0);
11567c478bd9Sstevel@tonic-gate DB_DEBUG1(DB_ATTACH, dip,
11577c478bd9Sstevel@tonic-gate "db_enable_io: chip ctrl (0x%x) after\n", regval);
11587c478bd9Sstevel@tonic-gate }
11597c478bd9Sstevel@tonic-gate }
11607c478bd9Sstevel@tonic-gate
11617c478bd9Sstevel@tonic-gate /*
11627c478bd9Sstevel@tonic-gate * Set DVMA Address Range.
11637c478bd9Sstevel@tonic-gate * This code is common to both orientations of the nexus driver.
11647c478bd9Sstevel@tonic-gate */
11657c478bd9Sstevel@tonic-gate static void
db_set_dvma_range(db_ctrl_t * dbp)11667c478bd9Sstevel@tonic-gate db_set_dvma_range(db_ctrl_t *dbp)
11677c478bd9Sstevel@tonic-gate {
11687c478bd9Sstevel@tonic-gate uint32_t dvma_start = 0;
11697c478bd9Sstevel@tonic-gate uint32_t dvma_len = 0;
11707c478bd9Sstevel@tonic-gate uint64_t db_allocd = 0;
11717c478bd9Sstevel@tonic-gate uint32_t *dvma_prop;
11727c478bd9Sstevel@tonic-gate uint32_t dvma_size[2]; /* dvma size may span over 2 BARs */
11737c478bd9Sstevel@tonic-gate uint32_t dvma_bar[2]; /* dvma range may span over 2 BARs */
11747c478bd9Sstevel@tonic-gate int dvma_prop_len;
11757c478bd9Sstevel@tonic-gate uint64_t new_dvma_start, new_dvma_len, new_dvma_end;
11767c478bd9Sstevel@tonic-gate
11777c478bd9Sstevel@tonic-gate /*
11787c478bd9Sstevel@tonic-gate * Need to traverse up the tree looking for a
11797c478bd9Sstevel@tonic-gate * "virtual-dma" property that specifies the
11807c478bd9Sstevel@tonic-gate * HPB DVMA range.
11817c478bd9Sstevel@tonic-gate */
11827c478bd9Sstevel@tonic-gate if (ddi_getlongprop(DDI_DEV_T_ANY, ddi_get_parent(dbp->dip), 0,
11837c478bd9Sstevel@tonic-gate "virtual-dma", (caddr_t)&dvma_prop, &dvma_prop_len)
11847c478bd9Sstevel@tonic-gate == DDI_SUCCESS) {
11857c478bd9Sstevel@tonic-gate dvma_start = dvma_prop[0];
11867c478bd9Sstevel@tonic-gate dvma_len = dvma_prop[1];
11877c478bd9Sstevel@tonic-gate kmem_free((caddr_t)dvma_prop, dvma_prop_len);
11887c478bd9Sstevel@tonic-gate } else {
11897c478bd9Sstevel@tonic-gate /*
11907c478bd9Sstevel@tonic-gate * For initial implementation, lets avoid a warning since this
11917c478bd9Sstevel@tonic-gate * change has not been implemented in the host-pci nexus
11927c478bd9Sstevel@tonic-gate * driver.
11937c478bd9Sstevel@tonic-gate */
11947c478bd9Sstevel@tonic-gate cmn_err(CE_WARN,
11957c478bd9Sstevel@tonic-gate "%s#%d: Could not get \"virtual-dma\" property",
11967c478bd9Sstevel@tonic-gate ddi_driver_name(dbp->dip),
11977c478bd9Sstevel@tonic-gate ddi_get_instance(dbp->dip));
11987c478bd9Sstevel@tonic-gate dvma_start = db_dvma_start;
11997c478bd9Sstevel@tonic-gate dvma_len = db_dvma_len;
12007c478bd9Sstevel@tonic-gate }
12017c478bd9Sstevel@tonic-gate
12027c478bd9Sstevel@tonic-gate DB_DEBUG2(DB_DVMA, dbp->dip,
12037c478bd9Sstevel@tonic-gate "DVMA Range is %lx,%lx\n", dvma_start, dvma_len);
12047c478bd9Sstevel@tonic-gate
12057c478bd9Sstevel@tonic-gate dvma_size[0] = dvma_size[1] = 0;
12067c478bd9Sstevel@tonic-gate /* Validate DVMA size programming and system requirements. */
12077c478bd9Sstevel@tonic-gate if (dbp->dev_state & DB_SECONDARY_NEXUS) {
12087c478bd9Sstevel@tonic-gate dvma_size[0] = pci_config_get32(dbp->conf_handle,
12097c478bd9Sstevel@tonic-gate DB_CONF_DS_IO_MEM1_SETUP);
12107c478bd9Sstevel@tonic-gate if (!(dvma_size[0] & 1)) /* make sure it is not a IO BAR */
12117c478bd9Sstevel@tonic-gate dvma_size[0] = ((~dvma_size[0]) + 1) & 0xfffff000;
12127c478bd9Sstevel@tonic-gate else
12137c478bd9Sstevel@tonic-gate dvma_size[0] = 0;
12147c478bd9Sstevel@tonic-gate dvma_size[1] = db_dvma_len;
12157c478bd9Sstevel@tonic-gate } else {
12167c478bd9Sstevel@tonic-gate dvma_size[0] = pci_config_get32(dbp->conf_handle,
12177c478bd9Sstevel@tonic-gate DB_CONF_US_IO_MEM0_SETUP);
12187c478bd9Sstevel@tonic-gate if (!(dvma_size[0] & 1)) /* make sure it is not a IO BAR */
12197c478bd9Sstevel@tonic-gate dvma_size[0] = ((~dvma_size[0]) + 1) & 0xfffff000;
12207c478bd9Sstevel@tonic-gate else
12217c478bd9Sstevel@tonic-gate dvma_size[0] = 0;
12227c478bd9Sstevel@tonic-gate dvma_size[1] = ((~(pci_config_get32(dbp->conf_handle,
12237c478bd9Sstevel@tonic-gate DB_CONF_US_MEM1_SETUP))) + 1) & 0xfffff000;
12247c478bd9Sstevel@tonic-gate }
12257c478bd9Sstevel@tonic-gate DB_DEBUG2(DB_DVMA, dbp->dip, "DVMA size register pair %lx, %lx\n",
12267c478bd9Sstevel@tonic-gate dvma_size[0], dvma_size[1]);
12277c478bd9Sstevel@tonic-gate
12287c478bd9Sstevel@tonic-gate #ifdef DEBUG
12297c478bd9Sstevel@tonic-gate if ((dvma_size[0] + dvma_size[1]) < dvma_len)
12307c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s#%d: DVMA window (%u) does not coincide"
12317c478bd9Sstevel@tonic-gate " with system requirements",
12327c478bd9Sstevel@tonic-gate ddi_driver_name(dbp->dip), ddi_get_instance(dbp->dip),
12337c478bd9Sstevel@tonic-gate (dvma_size[0] + dvma_size[1]));
12347c478bd9Sstevel@tonic-gate #endif
12357c478bd9Sstevel@tonic-gate dvma_bar[0] = dvma_bar[1] = 0xFFFFFFFF;
12367c478bd9Sstevel@tonic-gate db_allocd = 0;
12377c478bd9Sstevel@tonic-gate new_dvma_start = dvma_start;
12387c478bd9Sstevel@tonic-gate new_dvma_len = dvma_len;
12397c478bd9Sstevel@tonic-gate
12407c478bd9Sstevel@tonic-gate /* now, program the correct DVMA range over the 2 BARs. Max 4GB */
12417c478bd9Sstevel@tonic-gate if (dvma_size[0]) {
12427c478bd9Sstevel@tonic-gate dvma_bar[0] = (uint32_t)(dvma_start & (~(dvma_size[0] - 1)));
12437c478bd9Sstevel@tonic-gate new_dvma_end = (uint64_t)((uint64_t)dvma_bar[0] +
12447c478bd9Sstevel@tonic-gate (uint64_t)dvma_size[0]);
12457c478bd9Sstevel@tonic-gate if (new_dvma_end > (new_dvma_start + new_dvma_len))
12467c478bd9Sstevel@tonic-gate new_dvma_end = new_dvma_start + new_dvma_len;
12477c478bd9Sstevel@tonic-gate db_allocd += (new_dvma_end - new_dvma_start);
12487c478bd9Sstevel@tonic-gate new_dvma_start = new_dvma_end;
12497c478bd9Sstevel@tonic-gate new_dvma_len = dvma_len - db_allocd;
12507c478bd9Sstevel@tonic-gate }
12517c478bd9Sstevel@tonic-gate /*
12527c478bd9Sstevel@tonic-gate * It does not serve any purpose to set the other DVMA register
12537c478bd9Sstevel@tonic-gate * when we have already met the memory requirements so leave it
12547c478bd9Sstevel@tonic-gate * disabled.
12557c478bd9Sstevel@tonic-gate */
12567c478bd9Sstevel@tonic-gate if ((db_allocd != dvma_len) && dvma_size[1]) {
12577c478bd9Sstevel@tonic-gate dvma_bar[1] = (uint32_t)((dvma_start + db_allocd) &
12587c478bd9Sstevel@tonic-gate (~(dvma_size[1] - 1)));
12597c478bd9Sstevel@tonic-gate new_dvma_end = (uint64_t)((uint64_t)dvma_bar[1] +
12607c478bd9Sstevel@tonic-gate (uint64_t)dvma_size[1]);
12617c478bd9Sstevel@tonic-gate if (new_dvma_end > (new_dvma_start + new_dvma_len))
12627c478bd9Sstevel@tonic-gate new_dvma_end = new_dvma_start + new_dvma_len;
12637c478bd9Sstevel@tonic-gate db_allocd += (new_dvma_end - new_dvma_start);
12647c478bd9Sstevel@tonic-gate }
12657c478bd9Sstevel@tonic-gate
12667c478bd9Sstevel@tonic-gate /* In case of secondary orientation, DVMA BAR0 is 0. */
12677c478bd9Sstevel@tonic-gate if (dbp->dev_state & DB_SECONDARY_NEXUS)
12687c478bd9Sstevel@tonic-gate dvma_bar[0] = 0;
12697c478bd9Sstevel@tonic-gate
12707c478bd9Sstevel@tonic-gate if (db_allocd != dvma_len) {
12717c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s#%d: dvma range error!",
12727c478bd9Sstevel@tonic-gate ddi_driver_name(dbp->dip), ddi_get_instance(dbp->dip));
12737c478bd9Sstevel@tonic-gate }
12747c478bd9Sstevel@tonic-gate
12757c478bd9Sstevel@tonic-gate DB_DEBUG2(DB_DVMA, dbp->dip, "DVMA BARs set as %x, %x\n",
12767c478bd9Sstevel@tonic-gate dvma_bar[0], dvma_bar[1]);
12777c478bd9Sstevel@tonic-gate
12787c478bd9Sstevel@tonic-gate /* configure the setup register and DVMA BARs. */
12797c478bd9Sstevel@tonic-gate if (dbp->dev_state & DB_SECONDARY_NEXUS) {
12807c478bd9Sstevel@tonic-gate if (dvma_bar[0] != 0xFFFFFFFF) {
12817c478bd9Sstevel@tonic-gate #ifdef DB_SEC_SETUP_WRITE
12827c478bd9Sstevel@tonic-gate /*
12837c478bd9Sstevel@tonic-gate * No need to program the setup register
12847c478bd9Sstevel@tonic-gate * as the PROM would have done it.
12857c478bd9Sstevel@tonic-gate */
12867c478bd9Sstevel@tonic-gate pci_config_put32(dbp->conf_handle,
12877c478bd9Sstevel@tonic-gate DB_CONF_DS_MEM1_SETUP,
12887c478bd9Sstevel@tonic-gate (uint32_t)(((~(dvma_size[0] - 1)) |
12897c478bd9Sstevel@tonic-gate (pci_config_get32(dbp->conf_handle,
12907c478bd9Sstevel@tonic-gate DB_CONF_DS_MEM1_SETUP) & 0xF)) | 0x80000000));
12917c478bd9Sstevel@tonic-gate #endif
12927c478bd9Sstevel@tonic-gate /*
12937c478bd9Sstevel@tonic-gate * when translations are to be provided, this will
12947c478bd9Sstevel@tonic-gate * change.
12957c478bd9Sstevel@tonic-gate */
12967c478bd9Sstevel@tonic-gate pci_config_put32(dbp->conf_handle,
12977c478bd9Sstevel@tonic-gate DB_CONF_DS_IO_MEM1_TR_BASE,
12987c478bd9Sstevel@tonic-gate (uint32_t)dvma_bar[0]);
12997c478bd9Sstevel@tonic-gate pci_config_put32(dbp->conf_handle,
13007c478bd9Sstevel@tonic-gate DB_SCONF_DS_IO_MEM1, dvma_bar[0]);
13017c478bd9Sstevel@tonic-gate }
13027c478bd9Sstevel@tonic-gate if (dvma_bar[1] != 0xFFFFFFFF) {
13037c478bd9Sstevel@tonic-gate #ifdef DB_SEC_SETUP_WRITE
13047c478bd9Sstevel@tonic-gate /*
13057c478bd9Sstevel@tonic-gate * No need to program the setup register
13067c478bd9Sstevel@tonic-gate * as the PROM would have done it.
13077c478bd9Sstevel@tonic-gate */
13087c478bd9Sstevel@tonic-gate pci_config_put32(dbp->conf_handle,
13097c478bd9Sstevel@tonic-gate DB_CONF_DS_MEM2_SETUP,
13107c478bd9Sstevel@tonic-gate (uint32_t)(((~(dvma_size[1] - 1)) |
13117c478bd9Sstevel@tonic-gate (pci_config_get32(dbp->conf_handle,
13127c478bd9Sstevel@tonic-gate DB_CONF_DS_MEM2_SETUP) & 0xF)) | 0x80000000));
13137c478bd9Sstevel@tonic-gate #endif
13147c478bd9Sstevel@tonic-gate /*
13157c478bd9Sstevel@tonic-gate * when translations are to be provided, this will
13167c478bd9Sstevel@tonic-gate * change.
13177c478bd9Sstevel@tonic-gate */
13187c478bd9Sstevel@tonic-gate pci_config_put32(dbp->conf_handle,
13197c478bd9Sstevel@tonic-gate DB_CONF_DS_MEM2_TR_BASE, (uint32_t)dvma_bar[1]);
13207c478bd9Sstevel@tonic-gate pci_config_put32(dbp->conf_handle,
13217c478bd9Sstevel@tonic-gate DB_SCONF_DS_MEM2, dvma_bar[1]);
13227c478bd9Sstevel@tonic-gate }
13237c478bd9Sstevel@tonic-gate
13247c478bd9Sstevel@tonic-gate } else {
13257c478bd9Sstevel@tonic-gate if (dvma_bar[0] != 0xFFFFFFFF) {
13267c478bd9Sstevel@tonic-gate #ifdef DB_CONF_P2S_WRITE_ENABLED /* primary to secondary write enabled */
13277c478bd9Sstevel@tonic-gate /*
13287c478bd9Sstevel@tonic-gate * We have a problem with this setup, because the
13297c478bd9Sstevel@tonic-gate * US_MEM1 setup register cannot be written from the
13307c478bd9Sstevel@tonic-gate * primary interface...!!! Hence in this configuration,
13317c478bd9Sstevel@tonic-gate * we cannot dynamically program the DVMA range!
13327c478bd9Sstevel@tonic-gate */
13337c478bd9Sstevel@tonic-gate pci_config_put32(dbp->conf_handle,
13347c478bd9Sstevel@tonic-gate DB_CONF_US_IO_MEM0_SETUP,
13357c478bd9Sstevel@tonic-gate (uint32_t)(((~(dvma_size[0] - 1)) |
13367c478bd9Sstevel@tonic-gate (pci_config_get32(dbp->conf_handle,
13377c478bd9Sstevel@tonic-gate DB_CONF_US_IO_MEM0_SETUP) & 0xF)) |
13387c478bd9Sstevel@tonic-gate 0x80000000));
13397c478bd9Sstevel@tonic-gate #endif
13407c478bd9Sstevel@tonic-gate /*
13417c478bd9Sstevel@tonic-gate * when translations are to be provided, this will
13427c478bd9Sstevel@tonic-gate * change.
13437c478bd9Sstevel@tonic-gate */
13447c478bd9Sstevel@tonic-gate pci_config_put32(dbp->conf_handle,
13457c478bd9Sstevel@tonic-gate DB_CONF_US_IO_MEM0_TR_BASE,
13467c478bd9Sstevel@tonic-gate (uint32_t)dvma_bar[0]);
13477c478bd9Sstevel@tonic-gate pci_config_put32(dbp->conf_handle,
13487c478bd9Sstevel@tonic-gate DB_PCONF_US_IO_MEM0, dvma_bar[0]);
13497c478bd9Sstevel@tonic-gate }
13507c478bd9Sstevel@tonic-gate if (dvma_bar[1] != 0xFFFFFFFF) {
13517c478bd9Sstevel@tonic-gate #ifdef DB_CONF_P2S_WRITE_ENABLED /* primary to secondary write enabled */
13527c478bd9Sstevel@tonic-gate /*
13537c478bd9Sstevel@tonic-gate * We have a problem with this setup, because the
13547c478bd9Sstevel@tonic-gate * US_MEM1 setup register cannot be written from the
13557c478bd9Sstevel@tonic-gate * primary interface...!!! Hence in this configuration,
13567c478bd9Sstevel@tonic-gate * we cannot dynamically program the DVMA range!
13577c478bd9Sstevel@tonic-gate */
13587c478bd9Sstevel@tonic-gate pci_config_put32(dbp->conf_handle,
13597c478bd9Sstevel@tonic-gate DB_CONF_US_MEM1_SETUP,
13607c478bd9Sstevel@tonic-gate (uint32_t)(((~(dvma_size[1] - 1)) |
13617c478bd9Sstevel@tonic-gate (pci_config_get32(dbp->conf_handle,
13627c478bd9Sstevel@tonic-gate DB_CONF_US_MEM1_SETUP) & 0xF)) | 0x80000000));
13637c478bd9Sstevel@tonic-gate #endif
13647c478bd9Sstevel@tonic-gate /*
13657c478bd9Sstevel@tonic-gate * when translations are to be provided, this will
13667c478bd9Sstevel@tonic-gate * change.
13677c478bd9Sstevel@tonic-gate */
13687c478bd9Sstevel@tonic-gate pci_config_put32(dbp->conf_handle,
13697c478bd9Sstevel@tonic-gate DB_CONF_US_MEM1_TR_BASE, (uint32_t)dvma_bar[1]);
13707c478bd9Sstevel@tonic-gate pci_config_put32(dbp->conf_handle,
13717c478bd9Sstevel@tonic-gate DB_PCONF_US_MEM1, dvma_bar[1]);
13727c478bd9Sstevel@tonic-gate }
13737c478bd9Sstevel@tonic-gate }
13747c478bd9Sstevel@tonic-gate }
13757c478bd9Sstevel@tonic-gate
13767c478bd9Sstevel@tonic-gate /*ARGSUSED*/
13777c478bd9Sstevel@tonic-gate static int
db_open(dev_t * dev_p,int flag,int otyp,cred_t * cred_p)13787c478bd9Sstevel@tonic-gate db_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
13797c478bd9Sstevel@tonic-gate {
13807c478bd9Sstevel@tonic-gate minor_t minor = getminor(*dev_p);
13817c478bd9Sstevel@tonic-gate int instance = PCIHP_AP_MINOR_NUM_TO_INSTANCE(minor);
13827c478bd9Sstevel@tonic-gate db_ctrl_t *dbp = (db_ctrl_t *)ddi_get_soft_state(db_state, instance);
13837c478bd9Sstevel@tonic-gate
13847c478bd9Sstevel@tonic-gate if (dbp == (db_ctrl_t *)NULL)
13857c478bd9Sstevel@tonic-gate return (ENXIO);
13867c478bd9Sstevel@tonic-gate
13877c478bd9Sstevel@tonic-gate /*
13887c478bd9Sstevel@tonic-gate * check for debug node
13897c478bd9Sstevel@tonic-gate */
13907c478bd9Sstevel@tonic-gate if ((minor & 0xff) == 0xfe)
13917c478bd9Sstevel@tonic-gate return (0);
13927c478bd9Sstevel@tonic-gate
13937c478bd9Sstevel@tonic-gate if (dbp->dev_state & DB_SECONDARY_NEXUS)
13947c478bd9Sstevel@tonic-gate return ((pcihp_get_cb_ops())->cb_open(dev_p, flag,
13957c478bd9Sstevel@tonic-gate otyp, cred_p));
13967c478bd9Sstevel@tonic-gate /*
13977c478bd9Sstevel@tonic-gate * Handle the open by tracking the device state.
13987c478bd9Sstevel@tonic-gate */
13997c478bd9Sstevel@tonic-gate mutex_enter(&dbp->db_mutex);
14007c478bd9Sstevel@tonic-gate if (flag & FEXCL) {
14017c478bd9Sstevel@tonic-gate if (dbp->db_soft_state != DB_SOFT_STATE_CLOSED) {
14027c478bd9Sstevel@tonic-gate mutex_exit(&dbp->db_mutex);
14037c478bd9Sstevel@tonic-gate return (EBUSY);
14047c478bd9Sstevel@tonic-gate }
14057c478bd9Sstevel@tonic-gate dbp->db_soft_state = DB_SOFT_STATE_OPEN_EXCL;
14067c478bd9Sstevel@tonic-gate } else {
14077c478bd9Sstevel@tonic-gate if (dbp->db_soft_state == DB_SOFT_STATE_OPEN_EXCL) {
14087c478bd9Sstevel@tonic-gate mutex_exit(&dbp->db_mutex);
14097c478bd9Sstevel@tonic-gate return (EBUSY);
14107c478bd9Sstevel@tonic-gate }
14117c478bd9Sstevel@tonic-gate dbp->db_soft_state = DB_SOFT_STATE_OPEN;
14127c478bd9Sstevel@tonic-gate }
14137c478bd9Sstevel@tonic-gate mutex_exit(&dbp->db_mutex);
14147c478bd9Sstevel@tonic-gate return (0);
14157c478bd9Sstevel@tonic-gate }
14167c478bd9Sstevel@tonic-gate
14177c478bd9Sstevel@tonic-gate /*ARGSUSED*/
14187c478bd9Sstevel@tonic-gate static int
db_close(dev_t dev,int flag,int otyp,cred_t * cred_p)14197c478bd9Sstevel@tonic-gate db_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
14207c478bd9Sstevel@tonic-gate {
14217c478bd9Sstevel@tonic-gate minor_t minor = getminor(dev);
14227c478bd9Sstevel@tonic-gate int instance = PCIHP_AP_MINOR_NUM_TO_INSTANCE(minor);
14237c478bd9Sstevel@tonic-gate db_ctrl_t *dbp = (db_ctrl_t *)ddi_get_soft_state(db_state, instance);
14247c478bd9Sstevel@tonic-gate
14257c478bd9Sstevel@tonic-gate if (dbp == (db_ctrl_t *)NULL)
14267c478bd9Sstevel@tonic-gate return (ENXIO);
14277c478bd9Sstevel@tonic-gate
14287c478bd9Sstevel@tonic-gate /*
14297c478bd9Sstevel@tonic-gate * check for debug node
14307c478bd9Sstevel@tonic-gate */
14317c478bd9Sstevel@tonic-gate if ((minor & 0xff) == 0xfe)
14327c478bd9Sstevel@tonic-gate return (0);
14337c478bd9Sstevel@tonic-gate
14347c478bd9Sstevel@tonic-gate if (dbp->dev_state & DB_SECONDARY_NEXUS)
14357c478bd9Sstevel@tonic-gate return ((pcihp_get_cb_ops())->cb_close(dev, flag,
14367c478bd9Sstevel@tonic-gate otyp, cred_p));
14377c478bd9Sstevel@tonic-gate mutex_enter(&dbp->db_mutex);
14387c478bd9Sstevel@tonic-gate dbp->db_soft_state = DB_SOFT_STATE_CLOSED;
14397c478bd9Sstevel@tonic-gate mutex_exit(&dbp->db_mutex);
14407c478bd9Sstevel@tonic-gate return (0);
14417c478bd9Sstevel@tonic-gate }
14427c478bd9Sstevel@tonic-gate
14437c478bd9Sstevel@tonic-gate /*ARGSUSED*/
14447c478bd9Sstevel@tonic-gate static int
db_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * cred_p,int * rval_p)14457c478bd9Sstevel@tonic-gate db_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred_p,
14467c478bd9Sstevel@tonic-gate int *rval_p)
14477c478bd9Sstevel@tonic-gate {
14487c478bd9Sstevel@tonic-gate int rc = DDI_SUCCESS;
14497c478bd9Sstevel@tonic-gate #ifdef DB_DEBUG
14507c478bd9Sstevel@tonic-gate ddi_acc_handle_t config_handle;
14517c478bd9Sstevel@tonic-gate db_pci_data_t pci_data;
14527c478bd9Sstevel@tonic-gate dev_info_t *child_dip;
14537c478bd9Sstevel@tonic-gate #endif
14547c478bd9Sstevel@tonic-gate dev_info_t *self;
14557c478bd9Sstevel@tonic-gate minor_t minor = getminor(dev);
14567c478bd9Sstevel@tonic-gate int instance = PCIHP_AP_MINOR_NUM_TO_INSTANCE(minor);
14577c478bd9Sstevel@tonic-gate struct devctl_iocdata *dcp;
14587c478bd9Sstevel@tonic-gate uint_t bus_state;
14597c478bd9Sstevel@tonic-gate db_ctrl_t *dbp = (db_ctrl_t *)ddi_get_soft_state(db_state, instance);
14607c478bd9Sstevel@tonic-gate
14617c478bd9Sstevel@tonic-gate #ifdef DB_DEBUG
14627c478bd9Sstevel@tonic-gate /*
14637c478bd9Sstevel@tonic-gate * try this first whether were SECONDARY_NEXUS or not
14647c478bd9Sstevel@tonic-gate */
14657c478bd9Sstevel@tonic-gate if (cmd == DB_PCI_READ_CONF_HEADER) {
14667c478bd9Sstevel@tonic-gate if (ddi_copyin((caddr_t)arg, (caddr_t)&pci_data,
14677c478bd9Sstevel@tonic-gate sizeof (db_pci_data_t), mode)) {
14687c478bd9Sstevel@tonic-gate rc = EFAULT;
14697c478bd9Sstevel@tonic-gate return (rc);
14707c478bd9Sstevel@tonic-gate }
14717c478bd9Sstevel@tonic-gate
14727c478bd9Sstevel@tonic-gate if (strcmp(pci_data.name, "") == 0) {
14737c478bd9Sstevel@tonic-gate child_dip = dbp->dip;
14747c478bd9Sstevel@tonic-gate (void) strcpy(pci_data.name,
14757c478bd9Sstevel@tonic-gate ddi_get_name(dbp->dip));
14767c478bd9Sstevel@tonic-gate } else {
14777c478bd9Sstevel@tonic-gate
14787c478bd9Sstevel@tonic-gate if ((child_dip = db_lookup_child_name(dbp,
14797c478bd9Sstevel@tonic-gate pci_data.name, pci_data.instance))
14807c478bd9Sstevel@tonic-gate == (dev_info_t *)NULL) {
14817c478bd9Sstevel@tonic-gate rc = ENXIO;
14827c478bd9Sstevel@tonic-gate return (rc);
14837c478bd9Sstevel@tonic-gate } else {
14847c478bd9Sstevel@tonic-gate if (ddi_getprop(DDI_DEV_T_ANY,
14857c478bd9Sstevel@tonic-gate child_dip, DDI_PROP_DONTPASS,
14867c478bd9Sstevel@tonic-gate "vendor-id", DB_INVAL_VEND)
14877c478bd9Sstevel@tonic-gate == DB_INVAL_VEND) {
14887c478bd9Sstevel@tonic-gate /* non PCI device */
14897c478bd9Sstevel@tonic-gate rc = EINVAL;
14907c478bd9Sstevel@tonic-gate return (rc);
14917c478bd9Sstevel@tonic-gate }
14927c478bd9Sstevel@tonic-gate }
14937c478bd9Sstevel@tonic-gate }
14947c478bd9Sstevel@tonic-gate pci_data.instance = ddi_get_instance(child_dip);
14957c478bd9Sstevel@tonic-gate (void) pci_config_setup(child_dip, &config_handle);
14967c478bd9Sstevel@tonic-gate db_pci_get_header(config_handle, &pci_data.pri_hdr, 0);
14977c478bd9Sstevel@tonic-gate
14987c478bd9Sstevel@tonic-gate /* if it is the drawbridge itself, read sec header */
14997c478bd9Sstevel@tonic-gate if (child_dip == dbp->dip) {
15007c478bd9Sstevel@tonic-gate db_pci_get_header(config_handle,
15017c478bd9Sstevel@tonic-gate &pci_data.sec_hdr, DB_PCONF_SEC_HDR_OFF);
15027c478bd9Sstevel@tonic-gate db_pci_get_conf_regs(config_handle,
15037c478bd9Sstevel@tonic-gate &pci_data.conf_regs);
15047c478bd9Sstevel@tonic-gate }
15057c478bd9Sstevel@tonic-gate pci_config_teardown(&config_handle);
15067c478bd9Sstevel@tonic-gate
15077c478bd9Sstevel@tonic-gate if (ddi_copyout((caddr_t)&pci_data, (caddr_t)arg,
15087c478bd9Sstevel@tonic-gate sizeof (db_pci_data_t), mode)) {
15097c478bd9Sstevel@tonic-gate rc = EFAULT;
15107c478bd9Sstevel@tonic-gate return (rc);
15117c478bd9Sstevel@tonic-gate }
15127c478bd9Sstevel@tonic-gate
15137c478bd9Sstevel@tonic-gate return (rc);
15147c478bd9Sstevel@tonic-gate }
15157c478bd9Sstevel@tonic-gate #endif /* DB_DEBUG */
15167c478bd9Sstevel@tonic-gate
15177c478bd9Sstevel@tonic-gate /*
15187c478bd9Sstevel@tonic-gate * if secondary nexus (hotplug), then use pcihp_ioctl to do everything
15197c478bd9Sstevel@tonic-gate */
15207c478bd9Sstevel@tonic-gate if (dbp->dev_state & DB_SECONDARY_NEXUS)
15217c478bd9Sstevel@tonic-gate return ((pcihp_get_cb_ops())->cb_ioctl(dev, cmd,
15227c478bd9Sstevel@tonic-gate arg, mode, cred_p, rval_p));
15237c478bd9Sstevel@tonic-gate
15247c478bd9Sstevel@tonic-gate /*
15257c478bd9Sstevel@tonic-gate * if not secondary nexus, we do DEVCTL_DEVICE and DEVCTL_BUS ourselves
15267c478bd9Sstevel@tonic-gate */
15277c478bd9Sstevel@tonic-gate self = dbp->dip;
15287c478bd9Sstevel@tonic-gate
15297c478bd9Sstevel@tonic-gate /*
15307c478bd9Sstevel@tonic-gate * We can use the generic implementation for these ioctls
15317c478bd9Sstevel@tonic-gate */
15327c478bd9Sstevel@tonic-gate switch (cmd) {
15337c478bd9Sstevel@tonic-gate case DEVCTL_DEVICE_GETSTATE:
15347c478bd9Sstevel@tonic-gate case DEVCTL_DEVICE_ONLINE:
15357c478bd9Sstevel@tonic-gate case DEVCTL_DEVICE_OFFLINE:
15367c478bd9Sstevel@tonic-gate case DEVCTL_BUS_GETSTATE:
15377c478bd9Sstevel@tonic-gate return (ndi_devctl_ioctl(self, cmd, arg, mode, 0));
15387c478bd9Sstevel@tonic-gate }
15397c478bd9Sstevel@tonic-gate
15407c478bd9Sstevel@tonic-gate /*
15417c478bd9Sstevel@tonic-gate * read devctl ioctl data
15427c478bd9Sstevel@tonic-gate */
15437c478bd9Sstevel@tonic-gate if (ndi_dc_allochdl((void *)arg, &dcp) != NDI_SUCCESS)
15447c478bd9Sstevel@tonic-gate return (EFAULT);
15457c478bd9Sstevel@tonic-gate
15467c478bd9Sstevel@tonic-gate switch (cmd) {
15477c478bd9Sstevel@tonic-gate
15487c478bd9Sstevel@tonic-gate case DEVCTL_DEVICE_RESET:
15497c478bd9Sstevel@tonic-gate rc = ENOTSUP;
15507c478bd9Sstevel@tonic-gate break;
15517c478bd9Sstevel@tonic-gate
15527c478bd9Sstevel@tonic-gate
15537c478bd9Sstevel@tonic-gate case DEVCTL_BUS_QUIESCE:
15547c478bd9Sstevel@tonic-gate if (ndi_get_bus_state(self, &bus_state) == NDI_SUCCESS)
15557c478bd9Sstevel@tonic-gate if (bus_state == BUS_QUIESCED)
15567c478bd9Sstevel@tonic-gate break;
15577c478bd9Sstevel@tonic-gate (void) ndi_set_bus_state(self, BUS_QUIESCED);
15587c478bd9Sstevel@tonic-gate break;
15597c478bd9Sstevel@tonic-gate
15607c478bd9Sstevel@tonic-gate case DEVCTL_BUS_UNQUIESCE:
15617c478bd9Sstevel@tonic-gate if (ndi_get_bus_state(self, &bus_state) == NDI_SUCCESS)
15627c478bd9Sstevel@tonic-gate if (bus_state == BUS_ACTIVE)
15637c478bd9Sstevel@tonic-gate break;
15647c478bd9Sstevel@tonic-gate (void) ndi_set_bus_state(self, BUS_ACTIVE);
15657c478bd9Sstevel@tonic-gate break;
15667c478bd9Sstevel@tonic-gate
15677c478bd9Sstevel@tonic-gate case DEVCTL_BUS_RESET:
15687c478bd9Sstevel@tonic-gate rc = ENOTSUP;
15697c478bd9Sstevel@tonic-gate break;
15707c478bd9Sstevel@tonic-gate
15717c478bd9Sstevel@tonic-gate case DEVCTL_BUS_RESETALL:
15727c478bd9Sstevel@tonic-gate rc = ENOTSUP;
15737c478bd9Sstevel@tonic-gate break;
15747c478bd9Sstevel@tonic-gate
15757c478bd9Sstevel@tonic-gate default:
15767c478bd9Sstevel@tonic-gate rc = ENOTTY;
15777c478bd9Sstevel@tonic-gate }
15787c478bd9Sstevel@tonic-gate
15797c478bd9Sstevel@tonic-gate ndi_dc_freehdl(dcp);
15807c478bd9Sstevel@tonic-gate return (rc);
15817c478bd9Sstevel@tonic-gate }
15827c478bd9Sstevel@tonic-gate
15837c478bd9Sstevel@tonic-gate #ifdef DB_DEBUG
15847c478bd9Sstevel@tonic-gate static dev_info_t *
db_lookup_child_name(db_ctrl_t * dbp,char * name,int instance)15857c478bd9Sstevel@tonic-gate db_lookup_child_name(db_ctrl_t *dbp, char *name, int instance)
15867c478bd9Sstevel@tonic-gate {
15877c478bd9Sstevel@tonic-gate dev_info_t *cdip, *pdip = dbp->dip;
15887c478bd9Sstevel@tonic-gate
15897c478bd9Sstevel@tonic-gate for (cdip = ddi_get_child(pdip); cdip;
15907c478bd9Sstevel@tonic-gate cdip = ddi_get_next_sibling(pdip)) {
15917c478bd9Sstevel@tonic-gate
15927c478bd9Sstevel@tonic-gate do {
15937c478bd9Sstevel@tonic-gate if (strcmp(ddi_node_name(cdip), name) == 0) {
15947c478bd9Sstevel@tonic-gate if (instance != -1) {
15957c478bd9Sstevel@tonic-gate if (ddi_get_instance(cdip) == instance)
15967c478bd9Sstevel@tonic-gate return (cdip);
15977c478bd9Sstevel@tonic-gate } else
15987c478bd9Sstevel@tonic-gate return (cdip);
15997c478bd9Sstevel@tonic-gate }
16007c478bd9Sstevel@tonic-gate pdip = cdip;
16017c478bd9Sstevel@tonic-gate } while ((cdip = ddi_get_child(pdip)));
16027c478bd9Sstevel@tonic-gate cdip = ddi_get_next_sibling(pdip);
16037c478bd9Sstevel@tonic-gate if (cdip == NULL) {
16047c478bd9Sstevel@tonic-gate pdip = ddi_get_parent(pdip);
16057c478bd9Sstevel@tonic-gate if (pdip == dbp->dip)
16067c478bd9Sstevel@tonic-gate break;
16077c478bd9Sstevel@tonic-gate }
16087c478bd9Sstevel@tonic-gate }
16097c478bd9Sstevel@tonic-gate return (NULL);
16107c478bd9Sstevel@tonic-gate }
16117c478bd9Sstevel@tonic-gate
16127c478bd9Sstevel@tonic-gate static void
db_pci_get_header(ddi_acc_handle_t config_handle,db_pci_header_t * ph,off_t hdr_off)16137c478bd9Sstevel@tonic-gate db_pci_get_header(ddi_acc_handle_t config_handle, db_pci_header_t *ph,
16147c478bd9Sstevel@tonic-gate off_t hdr_off)
16157c478bd9Sstevel@tonic-gate {
16167c478bd9Sstevel@tonic-gate ph->venid = pci_config_get16(config_handle, hdr_off + PCI_CONF_VENID);
16177c478bd9Sstevel@tonic-gate ph->devid = pci_config_get16(config_handle, hdr_off + PCI_CONF_DEVID);
16187c478bd9Sstevel@tonic-gate ph->command = pci_config_get16(config_handle, hdr_off + PCI_CONF_COMM);
16197c478bd9Sstevel@tonic-gate ph->status = pci_config_get16(config_handle, hdr_off + PCI_CONF_STAT);
16207c478bd9Sstevel@tonic-gate ph->revid = pci_config_get8(config_handle, hdr_off + PCI_CONF_REVID);
16217c478bd9Sstevel@tonic-gate ph->pif = pci_config_get8(config_handle, hdr_off + PCI_CONF_PROGCLASS);
16227c478bd9Sstevel@tonic-gate ph->subclass = pci_config_get8(config_handle,
16237c478bd9Sstevel@tonic-gate hdr_off + PCI_CONF_SUBCLASS);
16247c478bd9Sstevel@tonic-gate ph->class = pci_config_get8(config_handle,
16257c478bd9Sstevel@tonic-gate hdr_off + PCI_CONF_BASCLASS);
16267c478bd9Sstevel@tonic-gate ph->cacheline = pci_config_get8(config_handle,
16277c478bd9Sstevel@tonic-gate hdr_off + PCI_CONF_CACHE_LINESZ);
16287c478bd9Sstevel@tonic-gate ph->lat = pci_config_get8(config_handle,
16297c478bd9Sstevel@tonic-gate hdr_off + PCI_CONF_LATENCY_TIMER);
16307c478bd9Sstevel@tonic-gate ph->hdr_type = pci_config_get8(config_handle,
16317c478bd9Sstevel@tonic-gate hdr_off + PCI_CONF_HEADER);
16327c478bd9Sstevel@tonic-gate ph->bist = pci_config_get8(config_handle, hdr_off + PCI_CONF_BIST);
16337c478bd9Sstevel@tonic-gate ph->bar0 = pci_config_get32(config_handle, hdr_off + PCI_CONF_BASE0);
16347c478bd9Sstevel@tonic-gate ph->bar1 = pci_config_get32(config_handle, hdr_off + PCI_CONF_BASE1);
16357c478bd9Sstevel@tonic-gate ph->bar2 = pci_config_get32(config_handle, hdr_off + PCI_CONF_BASE2);
16367c478bd9Sstevel@tonic-gate ph->bar3 = pci_config_get32(config_handle, hdr_off + PCI_CONF_BASE3);
16377c478bd9Sstevel@tonic-gate ph->bar4 = pci_config_get32(config_handle, hdr_off + PCI_CONF_BASE4);
16387c478bd9Sstevel@tonic-gate ph->bar5 = pci_config_get32(config_handle, hdr_off + PCI_CONF_BASE5);
16397c478bd9Sstevel@tonic-gate ph->cardbus_cisp = pci_config_get32(config_handle,
16407c478bd9Sstevel@tonic-gate hdr_off + PCI_CONF_CIS);
16417c478bd9Sstevel@tonic-gate ph->sub_venid = pci_config_get16(config_handle,
16427c478bd9Sstevel@tonic-gate hdr_off + PCI_CONF_SUBVENID);
16437c478bd9Sstevel@tonic-gate ph->sub_devid = pci_config_get16(config_handle,
16447c478bd9Sstevel@tonic-gate hdr_off + PCI_CONF_SUBSYSID);
16457c478bd9Sstevel@tonic-gate ph->exprom_bar = pci_config_get32(config_handle,
16467c478bd9Sstevel@tonic-gate hdr_off + PCI_CONF_ROM);
16477c478bd9Sstevel@tonic-gate ph->int_line = pci_config_get8(config_handle, hdr_off + PCI_CONF_ILINE);
16487c478bd9Sstevel@tonic-gate ph->int_pin = pci_config_get8(config_handle, hdr_off + PCI_CONF_IPIN);
16497c478bd9Sstevel@tonic-gate ph->min_gnt = pci_config_get8(config_handle, hdr_off + PCI_CONF_MIN_G);
16507c478bd9Sstevel@tonic-gate ph->max_lat = pci_config_get8(config_handle, hdr_off + PCI_CONF_MAX_L);
16517c478bd9Sstevel@tonic-gate }
16527c478bd9Sstevel@tonic-gate
16537c478bd9Sstevel@tonic-gate static void
db_pci_get_conf_regs(ddi_acc_handle_t config_handle,db_conf_regs_t * cr)16547c478bd9Sstevel@tonic-gate db_pci_get_conf_regs(ddi_acc_handle_t config_handle, db_conf_regs_t *cr)
16557c478bd9Sstevel@tonic-gate {
16567c478bd9Sstevel@tonic-gate cr->ds_mem0_tr_base = pci_config_get32(config_handle,
16577c478bd9Sstevel@tonic-gate DB_CONF_DS_MEM0_TR_BASE);
16587c478bd9Sstevel@tonic-gate cr->ds_io_mem1_tr_base = pci_config_get32(config_handle,
16597c478bd9Sstevel@tonic-gate DB_CONF_DS_IO_MEM1_TR_BASE);
16607c478bd9Sstevel@tonic-gate cr->ds_mem2_tr_base = pci_config_get32(config_handle,
16617c478bd9Sstevel@tonic-gate DB_CONF_DS_MEM2_TR_BASE);
16627c478bd9Sstevel@tonic-gate cr->ds_mem3_tr_base = pci_config_get32(config_handle,
16637c478bd9Sstevel@tonic-gate DB_CONF_DS_MEM3_TR_BASE);
16647c478bd9Sstevel@tonic-gate cr->us_io_mem0_tr_base = pci_config_get32(config_handle,
16657c478bd9Sstevel@tonic-gate DB_CONF_US_IO_MEM0_TR_BASE);
16667c478bd9Sstevel@tonic-gate cr->us_mem1_tr_base = pci_config_get32(config_handle,
16677c478bd9Sstevel@tonic-gate DB_CONF_US_MEM1_TR_BASE);
16687c478bd9Sstevel@tonic-gate cr->ds_mem0_setup_reg = pci_config_get32(config_handle,
16697c478bd9Sstevel@tonic-gate DB_CONF_DS_MEM0_SETUP);
16707c478bd9Sstevel@tonic-gate cr->ds_io_mem1_setup_reg = pci_config_get32(config_handle,
16717c478bd9Sstevel@tonic-gate DB_CONF_DS_IO_MEM1_SETUP);
16727c478bd9Sstevel@tonic-gate cr->ds_mem2_setup_reg = pci_config_get32(config_handle,
16737c478bd9Sstevel@tonic-gate DB_CONF_DS_MEM2_SETUP);
16747c478bd9Sstevel@tonic-gate cr->ds_mem3_setup_reg = pci_config_get64(config_handle,
16757c478bd9Sstevel@tonic-gate DB_CONF_DS_MEM3_SETUP);
16767c478bd9Sstevel@tonic-gate cr->p_exp_rom_setup = pci_config_get32(config_handle,
16777c478bd9Sstevel@tonic-gate DB_CONF_PRIM_EXP_ROM_SETUP);
16787c478bd9Sstevel@tonic-gate cr->us_io_mem0_setup_reg = pci_config_get32(config_handle,
16797c478bd9Sstevel@tonic-gate DB_CONF_US_IO_MEM0_SETUP);
16807c478bd9Sstevel@tonic-gate cr->us_mem1_setup_reg = pci_config_get32(config_handle,
16817c478bd9Sstevel@tonic-gate DB_CONF_US_MEM1_SETUP);
16827c478bd9Sstevel@tonic-gate cr->chip_control0 = pci_config_get16(config_handle, DB_CONF_CHIP_CTRL0);
16837c478bd9Sstevel@tonic-gate cr->chip_control1 = pci_config_get16(config_handle, DB_CONF_CHIP_CTRL1);
16847c478bd9Sstevel@tonic-gate cr->chip_status = pci_config_get16(config_handle, DB_CONF_STATUS);
16857c478bd9Sstevel@tonic-gate cr->arb_control = pci_config_get16(config_handle, DB_CONF_ARBITER_CTRL);
16867c478bd9Sstevel@tonic-gate cr->p_serr_disables = pci_config_get8(config_handle,
16877c478bd9Sstevel@tonic-gate DB_CONF_PRIM_SERR_DISABLES);
16887c478bd9Sstevel@tonic-gate cr->s_serr_disables = pci_config_get8(config_handle,
16897c478bd9Sstevel@tonic-gate DB_CONF_PRIM_SERR_DISABLES);
16907c478bd9Sstevel@tonic-gate cr->config_csr = pci_config_get16(config_handle, DB_CONF_CONF_CSR);
16917c478bd9Sstevel@tonic-gate cr->reset_control = pci_config_get32(config_handle, DB_CONF_RESET_CTRL);
16927c478bd9Sstevel@tonic-gate cr->pm_cap = pci_config_get16(config_handle, DB_CONF_PM_CAP);
16937c478bd9Sstevel@tonic-gate cr->pm_csr = pci_config_get16(config_handle, DB_CONF_PM_CSR);
16947c478bd9Sstevel@tonic-gate cr->hs_csr = pci_config_get8(config_handle, DB_CONF_HS_CSR);
16957c478bd9Sstevel@tonic-gate }
16967c478bd9Sstevel@tonic-gate #endif /* DB_DEBUG */
16977c478bd9Sstevel@tonic-gate
16987c478bd9Sstevel@tonic-gate /*
16997c478bd9Sstevel@tonic-gate * Function: db_pci_map
17007c478bd9Sstevel@tonic-gate *
17017c478bd9Sstevel@tonic-gate * Note: Only memory accesses are direct. IO could be direct
17027c478bd9Sstevel@tonic-gate * or indirect. Config accesses are always indirect.
17037c478bd9Sstevel@tonic-gate * The question here is, does the "assigned-addresses"
17047c478bd9Sstevel@tonic-gate * property entry represents the addresses in the
17057c478bd9Sstevel@tonic-gate * local domain or the host domain itself.
17067c478bd9Sstevel@tonic-gate * Strictly speaking, the assumption should be that
17077c478bd9Sstevel@tonic-gate * it is in the local domain, as the transactions
17087c478bd9Sstevel@tonic-gate * upstream or downstream are automatically
17097c478bd9Sstevel@tonic-gate * translated by the bridge chip anyway.
17107c478bd9Sstevel@tonic-gate *
17117c478bd9Sstevel@tonic-gate * Return values:
17127c478bd9Sstevel@tonic-gate * DDI_SUCCESS: map call by child device success
17137c478bd9Sstevel@tonic-gate * DDI_FAILURE: map operation failed.
17147c478bd9Sstevel@tonic-gate */
17157c478bd9Sstevel@tonic-gate
17167c478bd9Sstevel@tonic-gate static int
db_pci_map(dev_info_t * dip,dev_info_t * rdip,ddi_map_req_t * mp,off_t offset,off_t len,caddr_t * addrp)17177c478bd9Sstevel@tonic-gate db_pci_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
17187c478bd9Sstevel@tonic-gate off_t offset, off_t len, caddr_t *addrp)
17197c478bd9Sstevel@tonic-gate {
17207c478bd9Sstevel@tonic-gate register dev_info_t *pdip;
17217c478bd9Sstevel@tonic-gate int reg_proplen, num_regs, rnumber;
17227c478bd9Sstevel@tonic-gate uint_t addr_space_type;
17237c478bd9Sstevel@tonic-gate pci_regspec_t *pci_regsetp, pci_reg;
17247c478bd9Sstevel@tonic-gate db_ctrl_t *dbp;
17257c478bd9Sstevel@tonic-gate db_acc_pvt_t *db_pvt;
17267c478bd9Sstevel@tonic-gate ddi_acc_impl_t *ap;
17277c478bd9Sstevel@tonic-gate ddi_acc_hdl_t *hp;
17287c478bd9Sstevel@tonic-gate db_acc_cfg_addr_t *pci_addr;
17297c478bd9Sstevel@tonic-gate int instance = ddi_get_instance(dip);
17307c478bd9Sstevel@tonic-gate
17317c478bd9Sstevel@tonic-gate DB_DEBUG0(DB_PCI_MAP, dip, "enter\n");
17327c478bd9Sstevel@tonic-gate
17337c478bd9Sstevel@tonic-gate /* get map type. check for config space */
17347c478bd9Sstevel@tonic-gate switch (mp->map_type) {
17357c478bd9Sstevel@tonic-gate
17367c478bd9Sstevel@tonic-gate case DDI_MT_RNUMBER :
17377c478bd9Sstevel@tonic-gate /* get the reg number */
17387c478bd9Sstevel@tonic-gate rnumber = mp->map_obj.rnumber;
17397c478bd9Sstevel@tonic-gate
17407c478bd9Sstevel@tonic-gate if (ddi_getlongprop(DDI_DEV_T_ANY, rdip,
17417c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, "reg",
17427c478bd9Sstevel@tonic-gate (caddr_t)&pci_regsetp, ®_proplen)
17437c478bd9Sstevel@tonic-gate != DDI_SUCCESS)
17447c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
17457c478bd9Sstevel@tonic-gate
17467c478bd9Sstevel@tonic-gate num_regs = reg_proplen / (int)sizeof (pci_regspec_t);
17477c478bd9Sstevel@tonic-gate if (rnumber >= num_regs) {
17487c478bd9Sstevel@tonic-gate /* this is a DDI_ME_RNUMBER_RANGE error */
17497c478bd9Sstevel@tonic-gate kmem_free(pci_regsetp, reg_proplen);
17507c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
17517c478bd9Sstevel@tonic-gate }
17527c478bd9Sstevel@tonic-gate
17537c478bd9Sstevel@tonic-gate pci_reg = pci_regsetp[rnumber];
17547c478bd9Sstevel@tonic-gate kmem_free(pci_regsetp, reg_proplen);
17557c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
17567c478bd9Sstevel@tonic-gate case DDI_MT_REGSPEC :
17577c478bd9Sstevel@tonic-gate if (mp->map_type == DDI_MT_REGSPEC)
17587c478bd9Sstevel@tonic-gate pci_reg = *(pci_regspec_t *)mp->map_obj.rp;
17597c478bd9Sstevel@tonic-gate
17607c478bd9Sstevel@tonic-gate /*
17617c478bd9Sstevel@tonic-gate * Intercept config space accesses only. All other
17627c478bd9Sstevel@tonic-gate * requests go to the parent.
17637c478bd9Sstevel@tonic-gate */
17647c478bd9Sstevel@tonic-gate addr_space_type = pci_reg.pci_phys_hi & PCI_ADDR_MASK;
17657c478bd9Sstevel@tonic-gate
17667c478bd9Sstevel@tonic-gate DB_DEBUG3(DB_PCI_MAP, dip, "rdip=%lx, rnum=%d(%d)\n",
17677c478bd9Sstevel@tonic-gate rdip, rnumber, num_regs);
17687c478bd9Sstevel@tonic-gate
17697c478bd9Sstevel@tonic-gate /* if we do direct map IO, then lets break here */
17707c478bd9Sstevel@tonic-gate if ((db_io_map_mode & DB_IO_MAP_DIRECT) &&
17717c478bd9Sstevel@tonic-gate (addr_space_type == PCI_ADDR_IO))
17727c478bd9Sstevel@tonic-gate break;
17737c478bd9Sstevel@tonic-gate
17747c478bd9Sstevel@tonic-gate if ((addr_space_type != PCI_ADDR_CONFIG) &&
17757c478bd9Sstevel@tonic-gate (addr_space_type != PCI_ADDR_IO))
17767c478bd9Sstevel@tonic-gate break;
17777c478bd9Sstevel@tonic-gate
17787c478bd9Sstevel@tonic-gate /*
17797c478bd9Sstevel@tonic-gate * User mapping requests not legal for indirect
17807c478bd9Sstevel@tonic-gate * IO/Config Space
17817c478bd9Sstevel@tonic-gate */
17827c478bd9Sstevel@tonic-gate if (mp->map_op == DDI_MO_MAP_HANDLE)
17837c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
17847c478bd9Sstevel@tonic-gate
17857c478bd9Sstevel@tonic-gate dbp = (db_ctrl_t *)ddi_get_soft_state(db_state,
17867c478bd9Sstevel@tonic-gate instance);
17877c478bd9Sstevel@tonic-gate /* get our common access handle */
17887c478bd9Sstevel@tonic-gate hp = (ddi_acc_hdl_t *)mp->map_handlep;
17897c478bd9Sstevel@tonic-gate
17907c478bd9Sstevel@tonic-gate /* Check for unmap operation */
17917c478bd9Sstevel@tonic-gate if ((mp->map_op == DDI_MO_UNMAP) ||
17927c478bd9Sstevel@tonic-gate (mp->map_op == DDI_MO_UNLOCK)) {
17937c478bd9Sstevel@tonic-gate /*
17947c478bd9Sstevel@tonic-gate * free up memory allocated for our
17957c478bd9Sstevel@tonic-gate * private access handle.
17967c478bd9Sstevel@tonic-gate */
17977c478bd9Sstevel@tonic-gate db_pvt = (db_acc_pvt_t *)
17987c478bd9Sstevel@tonic-gate hp->ah_bus_private;
17997c478bd9Sstevel@tonic-gate DB_DEBUG1(DB_PCI_MAP, dip,
18007c478bd9Sstevel@tonic-gate "unmap rdip=%lx\n", rdip);
18017c478bd9Sstevel@tonic-gate kmem_free((void *)db_pvt,
18027c478bd9Sstevel@tonic-gate sizeof (db_acc_pvt_t));
18037c478bd9Sstevel@tonic-gate
18047c478bd9Sstevel@tonic-gate /*
18057c478bd9Sstevel@tonic-gate * unmap operation of PCI IO/config
18067c478bd9Sstevel@tonic-gate * space.
18077c478bd9Sstevel@tonic-gate */
18087c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
18097c478bd9Sstevel@tonic-gate }
18107c478bd9Sstevel@tonic-gate
18117c478bd9Sstevel@tonic-gate if (addr_space_type == PCI_ADDR_CONFIG) {
18127c478bd9Sstevel@tonic-gate /* Config space access range check */
18137c478bd9Sstevel@tonic-gate if ((offset >= PCI_CONF_HDR_SIZE) ||
18147c478bd9Sstevel@tonic-gate (len > PCI_CONF_HDR_SIZE) ||
18157c478bd9Sstevel@tonic-gate (offset + len > PCI_CONF_HDR_SIZE)) {
18167c478bd9Sstevel@tonic-gate
18177c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
18187c478bd9Sstevel@tonic-gate }
18197c478bd9Sstevel@tonic-gate }
18207c478bd9Sstevel@tonic-gate
18217c478bd9Sstevel@tonic-gate /* define the complete access handle */
18227c478bd9Sstevel@tonic-gate hp = (ddi_acc_hdl_t *)mp->map_handlep;
18237c478bd9Sstevel@tonic-gate
18247c478bd9Sstevel@tonic-gate ap = (ddi_acc_impl_t *)hp->ah_platform_private;
18257c478bd9Sstevel@tonic-gate
18267c478bd9Sstevel@tonic-gate ap->ahi_get8 = db_ddi_get8;
18277c478bd9Sstevel@tonic-gate ap->ahi_get16 = db_ddi_get16;
18287c478bd9Sstevel@tonic-gate ap->ahi_get32 = db_ddi_get32;
18297c478bd9Sstevel@tonic-gate ap->ahi_get64 = db_ddi_get64;
18307c478bd9Sstevel@tonic-gate ap->ahi_put8 = db_ddi_put8;
18317c478bd9Sstevel@tonic-gate ap->ahi_put16 = db_ddi_put16;
18327c478bd9Sstevel@tonic-gate ap->ahi_put32 = db_ddi_put32;
18337c478bd9Sstevel@tonic-gate ap->ahi_put64 = db_ddi_put64;
18347c478bd9Sstevel@tonic-gate ap->ahi_rep_get8 = db_ddi_rep_get8;
18357c478bd9Sstevel@tonic-gate ap->ahi_rep_get16 = db_ddi_rep_get16;
18367c478bd9Sstevel@tonic-gate ap->ahi_rep_get32 = db_ddi_rep_get32;
18377c478bd9Sstevel@tonic-gate ap->ahi_rep_get64 = db_ddi_rep_get64;
18387c478bd9Sstevel@tonic-gate ap->ahi_rep_put8 = db_ddi_rep_put8;
18397c478bd9Sstevel@tonic-gate ap->ahi_rep_put16 = db_ddi_rep_put16;
18407c478bd9Sstevel@tonic-gate ap->ahi_rep_put32 = db_ddi_rep_put32;
18417c478bd9Sstevel@tonic-gate ap->ahi_rep_put64 = db_ddi_rep_put64;
18427c478bd9Sstevel@tonic-gate
18437c478bd9Sstevel@tonic-gate /* Initialize to default check/notify functions */
18447c478bd9Sstevel@tonic-gate ap->ahi_fault = 0;
18457c478bd9Sstevel@tonic-gate ap->ahi_fault_check = i_ddi_acc_fault_check;
18467c478bd9Sstevel@tonic-gate ap->ahi_fault_notify = i_ddi_acc_fault_notify;
18477c478bd9Sstevel@tonic-gate
18487c478bd9Sstevel@tonic-gate /* allocate memory for our private handle */
18497c478bd9Sstevel@tonic-gate db_pvt = kmem_zalloc(sizeof (db_acc_pvt_t), KM_SLEEP);
18507c478bd9Sstevel@tonic-gate hp->ah_bus_private = (void *)db_pvt;
18517c478bd9Sstevel@tonic-gate db_pvt->dbp = dbp;
18527c478bd9Sstevel@tonic-gate
18537c478bd9Sstevel@tonic-gate /* record the device address for future use */
18547c478bd9Sstevel@tonic-gate pci_addr = &db_pvt->dev_addr;
18557c478bd9Sstevel@tonic-gate pci_addr->c_busnum =
18567c478bd9Sstevel@tonic-gate PCI_REG_BUS_G(pci_reg.pci_phys_hi);
18577c478bd9Sstevel@tonic-gate pci_addr->c_devnum =
18587c478bd9Sstevel@tonic-gate PCI_REG_DEV_G(pci_reg.pci_phys_hi);
18597c478bd9Sstevel@tonic-gate pci_addr->c_funcnum =
18607c478bd9Sstevel@tonic-gate PCI_REG_FUNC_G(pci_reg.pci_phys_hi);
18617c478bd9Sstevel@tonic-gate /*
18627c478bd9Sstevel@tonic-gate * We should keep the upstream or
18637c478bd9Sstevel@tonic-gate * downstream info in our own ah_bus_private
18647c478bd9Sstevel@tonic-gate * structure, so that we do not waste our
18657c478bd9Sstevel@tonic-gate * time in the actual IO routines, figuring out
18667c478bd9Sstevel@tonic-gate * if we should use upstream or downstream
18677c478bd9Sstevel@tonic-gate * configuration addr/data register.
18687c478bd9Sstevel@tonic-gate * So, check orientation and setup registers
18697c478bd9Sstevel@tonic-gate * right now.
18707c478bd9Sstevel@tonic-gate */
18717c478bd9Sstevel@tonic-gate switch (addr_space_type) {
18727c478bd9Sstevel@tonic-gate
18737c478bd9Sstevel@tonic-gate case PCI_ADDR_CONFIG :
18747c478bd9Sstevel@tonic-gate if (dbp->dev_state & DB_PRIMARY_NEXUS) {
18757c478bd9Sstevel@tonic-gate DB_DEBUG0(DB_PCI_MAP, dip, "primary\n");
18767c478bd9Sstevel@tonic-gate db_pvt->mask = DS8_CONF_OWN;
18777c478bd9Sstevel@tonic-gate if (db_conf_map_mode &
18787c478bd9Sstevel@tonic-gate DB_CONF_MAP_INDIRECT_IO) {
18797c478bd9Sstevel@tonic-gate DB_DEBUG0(DB_PCI_MAP, dip,
18807c478bd9Sstevel@tonic-gate "INDIRECT_CONF\n");
18817c478bd9Sstevel@tonic-gate
18827c478bd9Sstevel@tonic-gate db_pvt->handle =
18837c478bd9Sstevel@tonic-gate dbp->csr_io_handle;
18847c478bd9Sstevel@tonic-gate db_pvt->addr =
18857c478bd9Sstevel@tonic-gate (uint32_t *)
18867c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->csr_io
18877c478bd9Sstevel@tonic-gate + DB_CSR_DS_CONF_ADDR);
18887c478bd9Sstevel@tonic-gate db_pvt->data =
18897c478bd9Sstevel@tonic-gate (uint32_t *)
18907c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->csr_io
18917c478bd9Sstevel@tonic-gate + DB_CSR_DS_CONF_DATA);
18927c478bd9Sstevel@tonic-gate db_pvt->bus_own =
18937c478bd9Sstevel@tonic-gate (uint8_t *)
18947c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->csr_io
18957c478bd9Sstevel@tonic-gate + DB_CSR8_DS_CONF_OWN);
18967c478bd9Sstevel@tonic-gate db_pvt->bus_release =
18977c478bd9Sstevel@tonic-gate (uint8_t *)
18987c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->csr_io
18997c478bd9Sstevel@tonic-gate + DB_CSR8_DS_CONF_CSR);
19007c478bd9Sstevel@tonic-gate } else {
19017c478bd9Sstevel@tonic-gate DB_DEBUG0(DB_PCI_MAP, dip,
19027c478bd9Sstevel@tonic-gate "DIRECT_CONF\n");
19037c478bd9Sstevel@tonic-gate
19047c478bd9Sstevel@tonic-gate db_pvt->handle =
19057c478bd9Sstevel@tonic-gate dbp->conf_handle;
19067c478bd9Sstevel@tonic-gate db_pvt->addr =
19077c478bd9Sstevel@tonic-gate (uint32_t *)
19087c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->conf_io
19097c478bd9Sstevel@tonic-gate + DB_CONF_DS_CONF_ADDR);
19107c478bd9Sstevel@tonic-gate db_pvt->data = (uint32_t *)
19117c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->conf_io
19127c478bd9Sstevel@tonic-gate + DB_CONF_DS_CONF_DATA);
19137c478bd9Sstevel@tonic-gate db_pvt->bus_own =
19147c478bd9Sstevel@tonic-gate (uint8_t *)
19157c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->conf_io
19167c478bd9Sstevel@tonic-gate + DB_CONF8_DS_CONF_OWN);
19177c478bd9Sstevel@tonic-gate db_pvt->bus_release =
19187c478bd9Sstevel@tonic-gate (uint8_t *)
19197c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->conf_io
19207c478bd9Sstevel@tonic-gate + DB_CONF8_DS_CONF_CSR);
19217c478bd9Sstevel@tonic-gate }
19227c478bd9Sstevel@tonic-gate } else {
19237c478bd9Sstevel@tonic-gate DB_DEBUG0(DB_PCI_MAP, dip,
19247c478bd9Sstevel@tonic-gate "secondary\n");
19257c478bd9Sstevel@tonic-gate db_pvt->mask = US8_CONF_OWN;
19267c478bd9Sstevel@tonic-gate if (db_conf_map_mode &
19277c478bd9Sstevel@tonic-gate DB_CONF_MAP_INDIRECT_IO) {
19287c478bd9Sstevel@tonic-gate DB_DEBUG0(DB_PCI_MAP, dip,
19297c478bd9Sstevel@tonic-gate "INDIRECT_CONF\n");
19307c478bd9Sstevel@tonic-gate
19317c478bd9Sstevel@tonic-gate db_pvt->handle =
19327c478bd9Sstevel@tonic-gate dbp->csr_io_handle;
19337c478bd9Sstevel@tonic-gate db_pvt->addr =
19347c478bd9Sstevel@tonic-gate (uint32_t *)
19357c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->csr_io
19367c478bd9Sstevel@tonic-gate + DB_CSR_US_CONF_ADDR);
19377c478bd9Sstevel@tonic-gate db_pvt->data =
19387c478bd9Sstevel@tonic-gate (uint32_t *)
19397c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->csr_io
19407c478bd9Sstevel@tonic-gate + DB_CSR_US_CONF_DATA);
19417c478bd9Sstevel@tonic-gate db_pvt->bus_own =
19427c478bd9Sstevel@tonic-gate (uint8_t *)
19437c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->csr_io
19447c478bd9Sstevel@tonic-gate + DB_CSR8_US_CONF_OWN);
19457c478bd9Sstevel@tonic-gate db_pvt->bus_release =
19467c478bd9Sstevel@tonic-gate (uint8_t *)
19477c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->csr_io
19487c478bd9Sstevel@tonic-gate + DB_CSR8_US_CONF_CSR);
19497c478bd9Sstevel@tonic-gate } else {
19507c478bd9Sstevel@tonic-gate DB_DEBUG0(DB_PCI_MAP, dip,
19517c478bd9Sstevel@tonic-gate "DIRECT_CONF\n");
19527c478bd9Sstevel@tonic-gate
19537c478bd9Sstevel@tonic-gate db_pvt->handle =
19547c478bd9Sstevel@tonic-gate dbp->conf_handle;
19557c478bd9Sstevel@tonic-gate db_pvt->addr =
19567c478bd9Sstevel@tonic-gate (uint32_t *)
19577c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->conf_io
19587c478bd9Sstevel@tonic-gate + DB_CONF_US_CONF_ADDR);
19597c478bd9Sstevel@tonic-gate db_pvt->data =
19607c478bd9Sstevel@tonic-gate (uint32_t *)
19617c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->conf_io
19627c478bd9Sstevel@tonic-gate + DB_CONF_US_CONF_DATA);
19637c478bd9Sstevel@tonic-gate db_pvt->bus_own =
19647c478bd9Sstevel@tonic-gate (uint8_t *)
19657c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->conf_io
19667c478bd9Sstevel@tonic-gate + DB_CONF8_US_CONF_OWN);
19677c478bd9Sstevel@tonic-gate db_pvt->bus_release =
19687c478bd9Sstevel@tonic-gate (uint8_t *)
19697c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->conf_io
19707c478bd9Sstevel@tonic-gate + DB_CONF8_US_CONF_CSR);
19717c478bd9Sstevel@tonic-gate }
19727c478bd9Sstevel@tonic-gate }
19737c478bd9Sstevel@tonic-gate break;
19747c478bd9Sstevel@tonic-gate
19757c478bd9Sstevel@tonic-gate case PCI_ADDR_IO :
19767c478bd9Sstevel@tonic-gate DB_DEBUG0(DB_PCI_MAP, dip, "PCI_ADDR_IO\n");
19777c478bd9Sstevel@tonic-gate
19787c478bd9Sstevel@tonic-gate /* ap->ahi_acc_attr |= DDI_ACCATTR_IO_SPACE; */
19797c478bd9Sstevel@tonic-gate db_pvt->handle = dbp->csr_io_handle;
19807c478bd9Sstevel@tonic-gate if (dbp->dev_state & DB_PRIMARY_NEXUS) {
19817c478bd9Sstevel@tonic-gate DB_DEBUG0(DB_PCI_MAP, dip, "primary\n");
19827c478bd9Sstevel@tonic-gate db_pvt->addr = (uint32_t *)
19837c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->csr_io
19847c478bd9Sstevel@tonic-gate + DB_CSR_DS_IO_ADDR);
19857c478bd9Sstevel@tonic-gate db_pvt->data = (uint32_t *)
19867c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->csr_io
19877c478bd9Sstevel@tonic-gate + DB_CSR_DS_IO_DATA);
19887c478bd9Sstevel@tonic-gate db_pvt->bus_own = (uint8_t *)
19897c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->csr_io
19907c478bd9Sstevel@tonic-gate + DB_CSR8_DS_IO_OWN);
19917c478bd9Sstevel@tonic-gate db_pvt->bus_release = (uint8_t *)
19927c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->csr_io
19937c478bd9Sstevel@tonic-gate + DB_CSR8_DS_IO_CSR);
19947c478bd9Sstevel@tonic-gate db_pvt->mask = DS8_IO_OWN;
19957c478bd9Sstevel@tonic-gate } else {
19967c478bd9Sstevel@tonic-gate DB_DEBUG0(DB_PCI_MAP, dip,
19977c478bd9Sstevel@tonic-gate "secondary\n");
19987c478bd9Sstevel@tonic-gate db_pvt->addr = (uint32_t *)
19997c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->csr_io
20007c478bd9Sstevel@tonic-gate + DB_CSR_US_IO_ADDR);
20017c478bd9Sstevel@tonic-gate db_pvt->data = (uint32_t *)
20027c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->csr_io
20037c478bd9Sstevel@tonic-gate + DB_CSR_US_IO_DATA);
20047c478bd9Sstevel@tonic-gate db_pvt->bus_own = (uint8_t *)
20057c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->csr_io
20067c478bd9Sstevel@tonic-gate + DB_CSR8_US_IO_OWN);
20077c478bd9Sstevel@tonic-gate db_pvt->bus_release = (uint8_t *)
20087c478bd9Sstevel@tonic-gate ((uchar_t *)dbp->csr_io
20097c478bd9Sstevel@tonic-gate + DB_CSR8_US_IO_CSR);
20107c478bd9Sstevel@tonic-gate db_pvt->mask = US8_IO_OWN;
20117c478bd9Sstevel@tonic-gate }
20127c478bd9Sstevel@tonic-gate break;
20137c478bd9Sstevel@tonic-gate
20147c478bd9Sstevel@tonic-gate default :
20157c478bd9Sstevel@tonic-gate DB_DEBUG0(DB_PCI_MAP, dip,
20167c478bd9Sstevel@tonic-gate "PCI_ADDR unknown\n");
20177c478bd9Sstevel@tonic-gate break;
20187c478bd9Sstevel@tonic-gate }
20197c478bd9Sstevel@tonic-gate
20207c478bd9Sstevel@tonic-gate /* make and store a type 0/1 address in the *addrp */
20217c478bd9Sstevel@tonic-gate if (pci_addr->c_busnum == dbp->range.lo) {
20227c478bd9Sstevel@tonic-gate *addrp = (caddr_t)DB_PCI_REG_ADDR_TYPE0(
20237c478bd9Sstevel@tonic-gate pci_addr->c_busnum,
20247c478bd9Sstevel@tonic-gate pci_addr->c_devnum,
20257c478bd9Sstevel@tonic-gate pci_addr->c_funcnum,
20267c478bd9Sstevel@tonic-gate offset);
20277c478bd9Sstevel@tonic-gate db_pvt->access_mode |= DB_PCI_CONF_CYCLE_TYPE0;
20287c478bd9Sstevel@tonic-gate DB_DEBUG0(DB_PCI_MAP, dip,
20297c478bd9Sstevel@tonic-gate "access mode type 0\n");
20307c478bd9Sstevel@tonic-gate } else {
20317c478bd9Sstevel@tonic-gate *addrp = (caddr_t)DB_PCI_REG_ADDR_TYPE1(
20327c478bd9Sstevel@tonic-gate pci_addr->c_busnum,
20337c478bd9Sstevel@tonic-gate pci_addr->c_devnum,
20347c478bd9Sstevel@tonic-gate pci_addr->c_funcnum,
20357c478bd9Sstevel@tonic-gate offset);
20367c478bd9Sstevel@tonic-gate db_pvt->access_mode |= DB_PCI_CONF_CYCLE_TYPE1;
20377c478bd9Sstevel@tonic-gate DB_DEBUG0(DB_PCI_MAP, dip,
20387c478bd9Sstevel@tonic-gate "access mode type 1\n");
20397c478bd9Sstevel@tonic-gate }
20407c478bd9Sstevel@tonic-gate DB_DEBUG4(DB_PCI_MAP, dip, "addrp<%x,%x,%x> = %lx\n",
20417c478bd9Sstevel@tonic-gate pci_addr->c_busnum, pci_addr->c_devnum,
20427c478bd9Sstevel@tonic-gate pci_addr->c_funcnum, *addrp);
20437c478bd9Sstevel@tonic-gate
20447c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
20457c478bd9Sstevel@tonic-gate
20467c478bd9Sstevel@tonic-gate default :
20477c478bd9Sstevel@tonic-gate DB_DEBUG1(DB_PCI_MAP, dip, "DDI other %x\n",
20487c478bd9Sstevel@tonic-gate mp->map_type);
20497c478bd9Sstevel@tonic-gate break;
20507c478bd9Sstevel@tonic-gate }
20517c478bd9Sstevel@tonic-gate DB_DEBUG0(DB_PCI_MAP, dip, "exit\n");
20527c478bd9Sstevel@tonic-gate
20537c478bd9Sstevel@tonic-gate pdip = (dev_info_t *)DEVI(dip)->devi_parent;
20547c478bd9Sstevel@tonic-gate return ((DEVI(pdip)->devi_ops->devo_bus_ops->bus_map)
20557c478bd9Sstevel@tonic-gate (pdip, rdip, mp, offset, len, addrp));
20567c478bd9Sstevel@tonic-gate }
20577c478bd9Sstevel@tonic-gate
20587c478bd9Sstevel@tonic-gate #ifdef DB_DEBUG
20597c478bd9Sstevel@tonic-gate char *db_ctlop_name[] = {
20607c478bd9Sstevel@tonic-gate "DDI_CTLOPS_DMAPMAPC",
20617c478bd9Sstevel@tonic-gate "DDI_CTLOPS_INITCHILD",
20627c478bd9Sstevel@tonic-gate "DDI_CTLOPS_UNINITCHILD",
20637c478bd9Sstevel@tonic-gate "DDI_CTLOPS_REPORTDEV",
20647c478bd9Sstevel@tonic-gate "DDI_CTLOPS_REPORTINT",
20657c478bd9Sstevel@tonic-gate "DDI_CTLOPS_REGSIZE",
20667c478bd9Sstevel@tonic-gate "DDI_CTLOPS_NREGS",
2067a195726fSgovinda "DDI_CTLOPS_RESERVED0",
20687c478bd9Sstevel@tonic-gate "DDI_CTLOPS_SIDDEV",
20697c478bd9Sstevel@tonic-gate "DDI_CTLOPS_SLAVEONLY",
20707c478bd9Sstevel@tonic-gate "DDI_CTLOPS_AFFINITY",
20717c478bd9Sstevel@tonic-gate "DDI_CTLOPS_IOMIN",
20727c478bd9Sstevel@tonic-gate "DDI_CTLOPS_PTOB",
20737c478bd9Sstevel@tonic-gate "DDI_CTLOPS_BTOP",
20747c478bd9Sstevel@tonic-gate "DDI_CTLOPS_BTOPR",
20757c478bd9Sstevel@tonic-gate "DDI_CTLOPS_RESERVED1",
20767c478bd9Sstevel@tonic-gate "DDI_CTLOPS_RESERVED2",
20777c478bd9Sstevel@tonic-gate "DDI_CTLOPS_RESERVED3",
2078a195726fSgovinda "DDI_CTLOPS_RESERVED4",
2079a195726fSgovinda "DDI_CTLOPS_RESERVED5",
20807c478bd9Sstevel@tonic-gate "DDI_CTLOPS_DVMAPAGESIZE",
20817c478bd9Sstevel@tonic-gate "DDI_CTLOPS_POWER",
20827c478bd9Sstevel@tonic-gate "DDI_CTLOPS_ATTACH",
20837c478bd9Sstevel@tonic-gate "DDI_CTLOPS_DETACH",
20847c478bd9Sstevel@tonic-gate "DDI_CTLOPS_POKE",
20857c478bd9Sstevel@tonic-gate "DDI_CTLOPS_PEEK"
20867c478bd9Sstevel@tonic-gate };
20877c478bd9Sstevel@tonic-gate #endif
20887c478bd9Sstevel@tonic-gate
20897c478bd9Sstevel@tonic-gate static int
db_ctlops(dev_info_t * dip,dev_info_t * rdip,ddi_ctl_enum_t ctlop,void * arg,void * result)20907c478bd9Sstevel@tonic-gate db_ctlops(dev_info_t *dip, dev_info_t *rdip,
20917c478bd9Sstevel@tonic-gate ddi_ctl_enum_t ctlop, void *arg, void *result)
20927c478bd9Sstevel@tonic-gate {
20937c478bd9Sstevel@tonic-gate
20947c478bd9Sstevel@tonic-gate if ((ctlop >= DDI_CTLOPS_DMAPMAPC) &&
20957c478bd9Sstevel@tonic-gate (ctlop <= DDI_CTLOPS_DETACH)) {
20967c478bd9Sstevel@tonic-gate DB_DEBUG1(DB_CTLOPS, dip, "ctlop=%s\n", db_ctlop_name[ctlop]);
20977c478bd9Sstevel@tonic-gate } else {
20987c478bd9Sstevel@tonic-gate DB_DEBUG1(DB_CTLOPS, dip, "ctlop=%d\n", ctlop);
20997c478bd9Sstevel@tonic-gate }
21007c478bd9Sstevel@tonic-gate
21017c478bd9Sstevel@tonic-gate switch (ctlop) {
21027c478bd9Sstevel@tonic-gate case DDI_CTLOPS_REPORTDEV :
21037c478bd9Sstevel@tonic-gate if (rdip == (dev_info_t *)0)
21047c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
21057c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?PCI-device: %s@%s, %s#%d\n",
21067c478bd9Sstevel@tonic-gate ddi_node_name(rdip), ddi_get_name_addr(rdip),
21077c478bd9Sstevel@tonic-gate ddi_driver_name(rdip),
21087c478bd9Sstevel@tonic-gate ddi_get_instance(rdip));
21097c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
21107c478bd9Sstevel@tonic-gate
21117c478bd9Sstevel@tonic-gate case DDI_CTLOPS_INITCHILD :
21127c478bd9Sstevel@tonic-gate return (db_initchild((dev_info_t *)arg));
21137c478bd9Sstevel@tonic-gate
21147c478bd9Sstevel@tonic-gate case DDI_CTLOPS_UNINITCHILD :
21157c478bd9Sstevel@tonic-gate db_uninitchild((dev_info_t *)arg);
21167c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
21177c478bd9Sstevel@tonic-gate
21187c478bd9Sstevel@tonic-gate case DDI_CTLOPS_SIDDEV :
21197c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
21207c478bd9Sstevel@tonic-gate
21217c478bd9Sstevel@tonic-gate case DDI_CTLOPS_REGSIZE :
21227c478bd9Sstevel@tonic-gate case DDI_CTLOPS_NREGS :
21237c478bd9Sstevel@tonic-gate if (rdip == (dev_info_t *)0)
21247c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
21257c478bd9Sstevel@tonic-gate /* fall through */
21267c478bd9Sstevel@tonic-gate
21277c478bd9Sstevel@tonic-gate default :
21287c478bd9Sstevel@tonic-gate return (ddi_ctlops(dip, rdip, ctlop, arg, result));
21297c478bd9Sstevel@tonic-gate }
21307c478bd9Sstevel@tonic-gate
21317c478bd9Sstevel@tonic-gate }
21327c478bd9Sstevel@tonic-gate
21337c478bd9Sstevel@tonic-gate static dev_info_t *
db_get_my_childs_dip(dev_info_t * dip,dev_info_t * rdip)21347c478bd9Sstevel@tonic-gate db_get_my_childs_dip(dev_info_t *dip, dev_info_t *rdip)
21357c478bd9Sstevel@tonic-gate {
21367c478bd9Sstevel@tonic-gate dev_info_t *cdip = rdip;
21377c478bd9Sstevel@tonic-gate
21387c478bd9Sstevel@tonic-gate for (; ddi_get_parent(cdip) != dip; cdip = ddi_get_parent(cdip))
21397c478bd9Sstevel@tonic-gate ;
21407c478bd9Sstevel@tonic-gate
21417c478bd9Sstevel@tonic-gate return (cdip);
21427c478bd9Sstevel@tonic-gate }
21437c478bd9Sstevel@tonic-gate
21447c478bd9Sstevel@tonic-gate static int
db_intr_ops(dev_info_t * dip,dev_info_t * rdip,ddi_intr_op_t intr_op,ddi_intr_handle_impl_t * hdlp,void * result)21457c478bd9Sstevel@tonic-gate db_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
21467c478bd9Sstevel@tonic-gate ddi_intr_handle_impl_t *hdlp, void *result)
21477c478bd9Sstevel@tonic-gate {
21487c478bd9Sstevel@tonic-gate dev_info_t *cdip = rdip;
21497c478bd9Sstevel@tonic-gate pci_regspec_t *pci_rp;
21507c478bd9Sstevel@tonic-gate int reglen, len;
21517c478bd9Sstevel@tonic-gate uint32_t d, intr;
21527c478bd9Sstevel@tonic-gate
21537c478bd9Sstevel@tonic-gate DB_DEBUG1(DB_INTR_OPS, dip, "intr_op=%d\n", intr_op);
21547c478bd9Sstevel@tonic-gate
21551f4643f9Sgovinda if ((intr_op == DDI_INTROP_SUPPORTED_TYPES) ||
21561f4643f9Sgovinda (hdlp->ih_type != DDI_INTR_TYPE_FIXED))
21577c478bd9Sstevel@tonic-gate goto done;
21587c478bd9Sstevel@tonic-gate
21597c478bd9Sstevel@tonic-gate /*
21607c478bd9Sstevel@tonic-gate * If the interrupt-map property is defined at this
21617c478bd9Sstevel@tonic-gate * node, it will have performed the interrupt
21627c478bd9Sstevel@tonic-gate * translation as part of the property, so no
21637c478bd9Sstevel@tonic-gate * rotation needs to be done.
21647c478bd9Sstevel@tonic-gate */
21657c478bd9Sstevel@tonic-gate
21667c478bd9Sstevel@tonic-gate if (ddi_getproplen(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
21677c478bd9Sstevel@tonic-gate "interrupt-map", &len) == DDI_PROP_SUCCESS)
21687c478bd9Sstevel@tonic-gate goto done;
21697c478bd9Sstevel@tonic-gate
21707c478bd9Sstevel@tonic-gate cdip = db_get_my_childs_dip(dip, rdip);
21717c478bd9Sstevel@tonic-gate
21727c478bd9Sstevel@tonic-gate /*
21737c478bd9Sstevel@tonic-gate * Use the devices reg property to determine it's
21747c478bd9Sstevel@tonic-gate * PCI bus number and device number.
21757c478bd9Sstevel@tonic-gate */
2176a3282898Scth if (ddi_getlongprop(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS,
21777c478bd9Sstevel@tonic-gate "reg", (caddr_t)&pci_rp, ®len) != DDI_SUCCESS)
21787c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
21797c478bd9Sstevel@tonic-gate
2180a195726fSgovinda intr = hdlp->ih_vector;
21817c478bd9Sstevel@tonic-gate
21827c478bd9Sstevel@tonic-gate /* Spin the interrupt */
21837c478bd9Sstevel@tonic-gate d = PCI_REG_DEV_G(pci_rp[0].pci_phys_hi);
21847c478bd9Sstevel@tonic-gate
21857c478bd9Sstevel@tonic-gate if ((intr >= PCI_INTA) && (intr <= PCI_INTD))
2186a195726fSgovinda hdlp->ih_vector = ((intr - 1 + (d % 4)) % 4 + 1);
21877c478bd9Sstevel@tonic-gate else
21887c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s#%d: %s: PCI intr=%x out of range",
21897c478bd9Sstevel@tonic-gate ddi_driver_name(rdip), ddi_get_instance(rdip),
21907c478bd9Sstevel@tonic-gate ddi_driver_name(dip), intr);
21917c478bd9Sstevel@tonic-gate
21927c478bd9Sstevel@tonic-gate DB_DEBUG3(DB_INTR_OPS, dip, "intr=%d, d=%d, is_intr=%d\n",
2193a195726fSgovinda intr, d, hdlp->ih_vector);
21947c478bd9Sstevel@tonic-gate
21957c478bd9Sstevel@tonic-gate kmem_free(pci_rp, reglen);
21967c478bd9Sstevel@tonic-gate
21977c478bd9Sstevel@tonic-gate done:
21987c478bd9Sstevel@tonic-gate /* Pass up the request to our parent. */
21997c478bd9Sstevel@tonic-gate return (i_ddi_intr_ops(dip, rdip, intr_op, hdlp, result));
22007c478bd9Sstevel@tonic-gate }
22017c478bd9Sstevel@tonic-gate
22027c478bd9Sstevel@tonic-gate static int
db_name_child(dev_info_t * child,char * name,int namelen)22037c478bd9Sstevel@tonic-gate db_name_child(dev_info_t *child, char *name, int namelen)
22047c478bd9Sstevel@tonic-gate {
22057c478bd9Sstevel@tonic-gate uint_t n, slot, func;
22067c478bd9Sstevel@tonic-gate pci_regspec_t *pci_rp;
22077c478bd9Sstevel@tonic-gate
22087c478bd9Sstevel@tonic-gate if (ndi_dev_is_persistent_node(child) == 0) {
22097c478bd9Sstevel@tonic-gate char **unit_addr;
22107c478bd9Sstevel@tonic-gate
22117c478bd9Sstevel@tonic-gate /* name .conf nodes by "unit-address" property" */
22127c478bd9Sstevel@tonic-gate if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, child,
22137c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, "unit-address", &unit_addr, &n) !=
22147c478bd9Sstevel@tonic-gate DDI_PROP_SUCCESS) {
22157c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "cannot name node from %s.conf",
22167c478bd9Sstevel@tonic-gate ddi_driver_name(child));
22177c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
22187c478bd9Sstevel@tonic-gate }
22197c478bd9Sstevel@tonic-gate if (n != 1 || *unit_addr == NULL || **unit_addr == 0) {
22207c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "unit-address property in %s.conf"
22217c478bd9Sstevel@tonic-gate " not well-formed", ddi_driver_name(child));
22227c478bd9Sstevel@tonic-gate ddi_prop_free(unit_addr);
22237c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
22247c478bd9Sstevel@tonic-gate }
22257c478bd9Sstevel@tonic-gate
22267c478bd9Sstevel@tonic-gate (void) snprintf(name, namelen, "%s", *unit_addr);
22277c478bd9Sstevel@tonic-gate ddi_prop_free(unit_addr);
22287c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
22297c478bd9Sstevel@tonic-gate }
22307c478bd9Sstevel@tonic-gate
22317c478bd9Sstevel@tonic-gate /* name hardware nodes by "reg" property */
22327c478bd9Sstevel@tonic-gate if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child, 0, "reg",
22337c478bd9Sstevel@tonic-gate (int **)&pci_rp, &n) != DDI_SUCCESS)
22347c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
22357c478bd9Sstevel@tonic-gate
22367c478bd9Sstevel@tonic-gate /* get the device identifications */
22377c478bd9Sstevel@tonic-gate slot = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
22387c478bd9Sstevel@tonic-gate func = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
22397c478bd9Sstevel@tonic-gate
22407c478bd9Sstevel@tonic-gate if (func != 0)
22417c478bd9Sstevel@tonic-gate (void) snprintf(name, namelen, "%x,%x", slot, func);
22427c478bd9Sstevel@tonic-gate else
22437c478bd9Sstevel@tonic-gate (void) snprintf(name, namelen, "%x", slot);
22447c478bd9Sstevel@tonic-gate
22457c478bd9Sstevel@tonic-gate ddi_prop_free(pci_rp);
22467c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
22477c478bd9Sstevel@tonic-gate }
22487c478bd9Sstevel@tonic-gate
22497c478bd9Sstevel@tonic-gate static int
db_initchild(dev_info_t * child)22507c478bd9Sstevel@tonic-gate db_initchild(dev_info_t *child)
22517c478bd9Sstevel@tonic-gate {
22527c478bd9Sstevel@tonic-gate char name[MAXNAMELEN];
22537c478bd9Sstevel@tonic-gate ddi_acc_handle_t config_handle;
22547c478bd9Sstevel@tonic-gate ushort_t command_preserve, command;
22557c478bd9Sstevel@tonic-gate uint_t n;
22567c478bd9Sstevel@tonic-gate ushort_t bcr;
22577c478bd9Sstevel@tonic-gate uchar_t header_type, min_gnt, latency_timer;
22587c478bd9Sstevel@tonic-gate db_ctrl_t *dbp;
22597c478bd9Sstevel@tonic-gate
22607c478bd9Sstevel@tonic-gate if (db_name_child(child, name, MAXNAMELEN) != DDI_SUCCESS)
22617c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
22627c478bd9Sstevel@tonic-gate
22637c478bd9Sstevel@tonic-gate ddi_set_name_addr(child, name);
22647c478bd9Sstevel@tonic-gate ddi_set_parent_data(child, NULL);
22657c478bd9Sstevel@tonic-gate
22667c478bd9Sstevel@tonic-gate /*
22677c478bd9Sstevel@tonic-gate * Pseudo nodes indicate a prototype node with per-instance
22687c478bd9Sstevel@tonic-gate * properties to be merged into the real h/w device node.
22697c478bd9Sstevel@tonic-gate * The interpretation of the unit-address is DD[,F]
22707c478bd9Sstevel@tonic-gate * where DD is the device id and F is the function.
22717c478bd9Sstevel@tonic-gate */
22727c478bd9Sstevel@tonic-gate if (ndi_dev_is_persistent_node(child) == 0) {
22737c478bd9Sstevel@tonic-gate extern int pci_allow_pseudo_children;
22747c478bd9Sstevel@tonic-gate
22757c478bd9Sstevel@tonic-gate /*
22767c478bd9Sstevel@tonic-gate * Try to merge the properties from this prototype
22777c478bd9Sstevel@tonic-gate * node into real h/w nodes.
22787c478bd9Sstevel@tonic-gate */
22797c478bd9Sstevel@tonic-gate if (ndi_merge_node(child, db_name_child) == DDI_SUCCESS) {
22807c478bd9Sstevel@tonic-gate /*
22817c478bd9Sstevel@tonic-gate * Merged ok - return failure to remove the node.
22827c478bd9Sstevel@tonic-gate */
22837c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
22847c478bd9Sstevel@tonic-gate }
22857c478bd9Sstevel@tonic-gate
22867c478bd9Sstevel@tonic-gate /* workaround for ddivs to run under PCI */
22877c478bd9Sstevel@tonic-gate if (pci_allow_pseudo_children) {
22887c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
22897c478bd9Sstevel@tonic-gate }
22907c478bd9Sstevel@tonic-gate
22917c478bd9Sstevel@tonic-gate /*
22927c478bd9Sstevel@tonic-gate * The child was not merged into a h/w node,
22937c478bd9Sstevel@tonic-gate * but there's not much we can do with it other
22947c478bd9Sstevel@tonic-gate * than return failure to cause the node to be removed.
22957c478bd9Sstevel@tonic-gate */
22967c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged",
22977c478bd9Sstevel@tonic-gate ddi_driver_name(child), ddi_get_name_addr(child),
22987c478bd9Sstevel@tonic-gate ddi_driver_name(child));
22997c478bd9Sstevel@tonic-gate return (DDI_NOT_WELL_FORMED);
23007c478bd9Sstevel@tonic-gate }
23017c478bd9Sstevel@tonic-gate
23027c478bd9Sstevel@tonic-gate
23037c478bd9Sstevel@tonic-gate if ((db_create_pci_prop(child) != DDI_SUCCESS) ||
23047c478bd9Sstevel@tonic-gate (pci_config_setup(child, &config_handle) != DDI_SUCCESS)) {
23057c478bd9Sstevel@tonic-gate db_uninitchild(child);
23067c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
23077c478bd9Sstevel@tonic-gate }
23087c478bd9Sstevel@tonic-gate
23097c478bd9Sstevel@tonic-gate /*
23107c478bd9Sstevel@tonic-gate * Determine the configuration header type.
23117c478bd9Sstevel@tonic-gate */
23127c478bd9Sstevel@tonic-gate header_type = pci_config_get8(config_handle, PCI_CONF_HEADER);
23137c478bd9Sstevel@tonic-gate
23147c478bd9Sstevel@tonic-gate /*
23157c478bd9Sstevel@tonic-gate * Support for the "command-preserve" property.
23167c478bd9Sstevel@tonic-gate */
23177c478bd9Sstevel@tonic-gate command_preserve = ddi_prop_get_int(DDI_DEV_T_ANY, child,
23187c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, "command-preserve", 0);
23197c478bd9Sstevel@tonic-gate command = pci_config_get16(config_handle, PCI_CONF_COMM);
23207c478bd9Sstevel@tonic-gate command &= (command_preserve | PCI_COMM_BACK2BACK_ENAB);
23217c478bd9Sstevel@tonic-gate command |= (db_command_default & ~command_preserve);
23227c478bd9Sstevel@tonic-gate pci_config_put16(config_handle, PCI_CONF_COMM, command);
23237c478bd9Sstevel@tonic-gate
23247c478bd9Sstevel@tonic-gate DB_DEBUG2(DB_INITCHILD, ddi_get_parent(child),
23257c478bd9Sstevel@tonic-gate "initializing device vend=%x, devid=%x\n",
23267c478bd9Sstevel@tonic-gate pci_config_get16(config_handle, PCI_CONF_VENID),
23277c478bd9Sstevel@tonic-gate pci_config_get16(config_handle, PCI_CONF_DEVID));
23287c478bd9Sstevel@tonic-gate /*
23297c478bd9Sstevel@tonic-gate * If the device has a bus control register then program it
23307c478bd9Sstevel@tonic-gate * based on the settings in the command register.
23317c478bd9Sstevel@tonic-gate */
23327c478bd9Sstevel@tonic-gate if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) {
23337c478bd9Sstevel@tonic-gate bcr = pci_config_get8(config_handle, PCI_BCNF_BCNTRL);
23347c478bd9Sstevel@tonic-gate if (db_command_default & PCI_COMM_PARITY_DETECT)
23357c478bd9Sstevel@tonic-gate bcr |= PCI_BCNF_BCNTRL_PARITY_ENABLE;
23367c478bd9Sstevel@tonic-gate if (db_command_default & PCI_COMM_SERR_ENABLE)
23377c478bd9Sstevel@tonic-gate bcr |= PCI_BCNF_BCNTRL_SERR_ENABLE;
23387c478bd9Sstevel@tonic-gate bcr |= PCI_BCNF_BCNTRL_MAST_AB_MODE;
23397c478bd9Sstevel@tonic-gate pci_config_put8(config_handle, PCI_BCNF_BCNTRL, bcr);
23407c478bd9Sstevel@tonic-gate }
23417c478bd9Sstevel@tonic-gate
23427c478bd9Sstevel@tonic-gate dbp = (db_ctrl_t *)ddi_get_soft_state(db_state,
23437c478bd9Sstevel@tonic-gate ddi_get_instance(ddi_get_parent(child)));
23447c478bd9Sstevel@tonic-gate
23457c478bd9Sstevel@tonic-gate /*
23467c478bd9Sstevel@tonic-gate * Initialize cache-line-size configuration register if needed.
23477c478bd9Sstevel@tonic-gate */
23487c478bd9Sstevel@tonic-gate if (db_set_cache_line_size_register &&
23497c478bd9Sstevel@tonic-gate ddi_getprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
23507c478bd9Sstevel@tonic-gate "cache-line-size", 0) == 0) {
23517c478bd9Sstevel@tonic-gate pci_config_put8(config_handle, PCI_CONF_CACHE_LINESZ,
23527c478bd9Sstevel@tonic-gate dbp->cache_line_size);
23537c478bd9Sstevel@tonic-gate n = pci_config_get8(config_handle, PCI_CONF_CACHE_LINESZ);
23547c478bd9Sstevel@tonic-gate if (n != 0) {
23557c478bd9Sstevel@tonic-gate (void) ndi_prop_update_int(DDI_DEV_T_NONE, child,
23567c478bd9Sstevel@tonic-gate "cache-line-size", n);
23577c478bd9Sstevel@tonic-gate }
23587c478bd9Sstevel@tonic-gate DB_DEBUG1(DB_INITCHILD, ddi_get_parent(child),
23597c478bd9Sstevel@tonic-gate "\nChild Device Cache Size %x\n", dbp->cache_line_size);
23607c478bd9Sstevel@tonic-gate }
23617c478bd9Sstevel@tonic-gate
23627c478bd9Sstevel@tonic-gate /*
23637c478bd9Sstevel@tonic-gate * Initialize latency timer configuration registers if needed.
23647c478bd9Sstevel@tonic-gate */
23657c478bd9Sstevel@tonic-gate if (db_set_latency_timer_register &&
23667c478bd9Sstevel@tonic-gate ddi_getprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
23677c478bd9Sstevel@tonic-gate "latency-timer", 0) == 0) {
23687c478bd9Sstevel@tonic-gate
23697c478bd9Sstevel@tonic-gate if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) {
23707c478bd9Sstevel@tonic-gate latency_timer = dbp->p_latency_timer;
23717c478bd9Sstevel@tonic-gate pci_config_put8(config_handle, PCI_BCNF_LATENCY_TIMER,
23727c478bd9Sstevel@tonic-gate dbp->latency_timer);
23737c478bd9Sstevel@tonic-gate } else {
23747c478bd9Sstevel@tonic-gate min_gnt = pci_config_get8(config_handle,
23757c478bd9Sstevel@tonic-gate PCI_CONF_MIN_G);
23767c478bd9Sstevel@tonic-gate latency_timer = min_gnt * 8;
23777c478bd9Sstevel@tonic-gate }
23787c478bd9Sstevel@tonic-gate pci_config_put8(config_handle, PCI_CONF_LATENCY_TIMER,
23797c478bd9Sstevel@tonic-gate latency_timer);
23807c478bd9Sstevel@tonic-gate n = pci_config_get8(config_handle, PCI_CONF_LATENCY_TIMER);
23817c478bd9Sstevel@tonic-gate if (n != 0) {
23827c478bd9Sstevel@tonic-gate (void) ndi_prop_update_int(DDI_DEV_T_NONE, child,
23837c478bd9Sstevel@tonic-gate "latency-timer", n);
23847c478bd9Sstevel@tonic-gate }
23857c478bd9Sstevel@tonic-gate DB_DEBUG1(DB_INITCHILD, ddi_get_parent(child),
23867c478bd9Sstevel@tonic-gate "\nChild Device latency %x\n", latency_timer);
23877c478bd9Sstevel@tonic-gate }
23887c478bd9Sstevel@tonic-gate
23897c478bd9Sstevel@tonic-gate pci_config_teardown(&config_handle);
23907c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
23917c478bd9Sstevel@tonic-gate }
23927c478bd9Sstevel@tonic-gate
23937c478bd9Sstevel@tonic-gate static void
db_uninitchild(dev_info_t * dip)23947c478bd9Sstevel@tonic-gate db_uninitchild(dev_info_t *dip)
23957c478bd9Sstevel@tonic-gate {
23967c478bd9Sstevel@tonic-gate ddi_set_name_addr(dip, NULL);
23977c478bd9Sstevel@tonic-gate
23987c478bd9Sstevel@tonic-gate /*
23997c478bd9Sstevel@tonic-gate * Strip the node to properly convert it back to prototype form
24007c478bd9Sstevel@tonic-gate */
24017c478bd9Sstevel@tonic-gate impl_rem_dev_props(dip);
24027c478bd9Sstevel@tonic-gate }
24037c478bd9Sstevel@tonic-gate
24047c478bd9Sstevel@tonic-gate static int
db_create_pci_prop(dev_info_t * child)24057c478bd9Sstevel@tonic-gate db_create_pci_prop(dev_info_t *child)
24067c478bd9Sstevel@tonic-gate {
24077c478bd9Sstevel@tonic-gate pci_regspec_t *pci_rp;
24087c478bd9Sstevel@tonic-gate int length;
24097c478bd9Sstevel@tonic-gate int value;
24107c478bd9Sstevel@tonic-gate
24117c478bd9Sstevel@tonic-gate /* get child "reg" property */
2412a3282898Scth value = ddi_getlongprop(DDI_DEV_T_ANY, child, DDI_PROP_CANSLEEP,
24137c478bd9Sstevel@tonic-gate "reg", (caddr_t)&pci_rp, &length);
24147c478bd9Sstevel@tonic-gate if (value != DDI_SUCCESS)
24157c478bd9Sstevel@tonic-gate return (value);
24167c478bd9Sstevel@tonic-gate
24177c478bd9Sstevel@tonic-gate (void) ndi_prop_update_byte_array(DDI_DEV_T_NONE, child, "reg",
24187c478bd9Sstevel@tonic-gate (uchar_t *)pci_rp, length);
24197c478bd9Sstevel@tonic-gate
24207c478bd9Sstevel@tonic-gate /*
24217c478bd9Sstevel@tonic-gate * free the memory allocated by ddi_getlongprop ().
24227c478bd9Sstevel@tonic-gate */
24237c478bd9Sstevel@tonic-gate kmem_free(pci_rp, length);
24247c478bd9Sstevel@tonic-gate
24257c478bd9Sstevel@tonic-gate /*
24267c478bd9Sstevel@tonic-gate * No need to create any 1275 properties here, because either
24277c478bd9Sstevel@tonic-gate * the OBP creates them or the hotplug framework creates it
24287c478bd9Sstevel@tonic-gate * during a hotplug operation. So lets return here.
24297c478bd9Sstevel@tonic-gate */
24307c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
24317c478bd9Sstevel@tonic-gate }
24327c478bd9Sstevel@tonic-gate
24337c478bd9Sstevel@tonic-gate /*
24347c478bd9Sstevel@tonic-gate * db_save_config_regs
24357c478bd9Sstevel@tonic-gate *
24367c478bd9Sstevel@tonic-gate * This routine saves the state of the configuration registers of all
24377c478bd9Sstevel@tonic-gate * immediate child nodes.
24387c478bd9Sstevel@tonic-gate *
24397c478bd9Sstevel@tonic-gate * used by: db_detach() on suspends
24407c478bd9Sstevel@tonic-gate *
24417c478bd9Sstevel@tonic-gate * return value: DDI_SUCCESS: ALl children state saved.
24427c478bd9Sstevel@tonic-gate * DDI_FAILURE: Child device state could not be saved.
24437c478bd9Sstevel@tonic-gate */
24447c478bd9Sstevel@tonic-gate static int
db_save_config_regs(db_ctrl_t * dbp)24457c478bd9Sstevel@tonic-gate db_save_config_regs(db_ctrl_t *dbp)
24467c478bd9Sstevel@tonic-gate {
24477c478bd9Sstevel@tonic-gate int i;
24487c478bd9Sstevel@tonic-gate dev_info_t *dip;
24497c478bd9Sstevel@tonic-gate ddi_acc_handle_t config_handle;
24507c478bd9Sstevel@tonic-gate db_cfg_state_t *statep;
24517c478bd9Sstevel@tonic-gate
24527c478bd9Sstevel@tonic-gate for (i = 0, dip = ddi_get_child(dbp->dip); dip != NULL;
24537c478bd9Sstevel@tonic-gate dip = ddi_get_next_sibling(dip)) {
2454737d277aScth if (i_ddi_devi_attached(dip))
24557c478bd9Sstevel@tonic-gate i++;
24567c478bd9Sstevel@tonic-gate }
24577c478bd9Sstevel@tonic-gate dbp->config_state_index = i;
24587c478bd9Sstevel@tonic-gate
24597c478bd9Sstevel@tonic-gate if (!i) {
24607c478bd9Sstevel@tonic-gate /* no children */
24617c478bd9Sstevel@tonic-gate dbp->db_config_state_p = NULL;
24627c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
24637c478bd9Sstevel@tonic-gate }
24647c478bd9Sstevel@tonic-gate
24657c478bd9Sstevel@tonic-gate /* i now equals the total number of child devices */
24667c478bd9Sstevel@tonic-gate dbp->db_config_state_p =
24677c478bd9Sstevel@tonic-gate kmem_zalloc(i * sizeof (db_cfg_state_t), KM_NOSLEEP);
24687c478bd9Sstevel@tonic-gate if (!dbp->db_config_state_p) {
24697c478bd9Sstevel@tonic-gate cmn_err(CE_WARN,
24707c478bd9Sstevel@tonic-gate "%s#%d: No memory to save state for child %s#%d\n",
24717c478bd9Sstevel@tonic-gate ddi_driver_name(dbp->dip),
24727c478bd9Sstevel@tonic-gate ddi_get_instance(dbp->dip),
24737c478bd9Sstevel@tonic-gate ddi_get_name(dip), ddi_get_instance(dip));
24747c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
24757c478bd9Sstevel@tonic-gate }
24767c478bd9Sstevel@tonic-gate
24777c478bd9Sstevel@tonic-gate for (statep = dbp->db_config_state_p,
24787c478bd9Sstevel@tonic-gate dip = ddi_get_child(dbp->dip);
24797c478bd9Sstevel@tonic-gate dip != NULL;
24807c478bd9Sstevel@tonic-gate dip = ddi_get_next_sibling(dip)) {
24817c478bd9Sstevel@tonic-gate
2482737d277aScth if (!i_ddi_devi_attached(dip))
24837c478bd9Sstevel@tonic-gate continue;
24847c478bd9Sstevel@tonic-gate
24857c478bd9Sstevel@tonic-gate if (pci_config_setup(dip, &config_handle) != DDI_SUCCESS) {
24867c478bd9Sstevel@tonic-gate cmn_err(CE_WARN,
24877c478bd9Sstevel@tonic-gate "%s#%d: can't config space for %s#%d",
24887c478bd9Sstevel@tonic-gate ddi_driver_name(dbp->dip),
24897c478bd9Sstevel@tonic-gate ddi_get_instance(dbp->dip),
24907c478bd9Sstevel@tonic-gate ddi_driver_name(dip),
24917c478bd9Sstevel@tonic-gate ddi_get_instance(dip));
24927c478bd9Sstevel@tonic-gate continue;
24937c478bd9Sstevel@tonic-gate }
24947c478bd9Sstevel@tonic-gate
24957c478bd9Sstevel@tonic-gate statep->dip = dip;
24967c478bd9Sstevel@tonic-gate statep->command =
24977c478bd9Sstevel@tonic-gate pci_config_get16(config_handle, PCI_CONF_COMM);
24987c478bd9Sstevel@tonic-gate statep->header_type =
24997c478bd9Sstevel@tonic-gate pci_config_get8(config_handle, PCI_CONF_HEADER);
25007c478bd9Sstevel@tonic-gate if ((statep->header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE)
25017c478bd9Sstevel@tonic-gate statep->bridge_control =
25027c478bd9Sstevel@tonic-gate pci_config_get16(config_handle, PCI_BCNF_BCNTRL);
25037c478bd9Sstevel@tonic-gate statep->cache_line_size =
25047c478bd9Sstevel@tonic-gate pci_config_get8(config_handle, PCI_CONF_CACHE_LINESZ);
25057c478bd9Sstevel@tonic-gate statep->latency_timer =
25067c478bd9Sstevel@tonic-gate pci_config_get8(config_handle, PCI_CONF_LATENCY_TIMER);
25077c478bd9Sstevel@tonic-gate if ((statep->header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE)
25087c478bd9Sstevel@tonic-gate statep->sec_latency_timer =
25097c478bd9Sstevel@tonic-gate pci_config_get8(config_handle,
25107c478bd9Sstevel@tonic-gate PCI_BCNF_LATENCY_TIMER);
25117c478bd9Sstevel@tonic-gate pci_config_teardown(&config_handle);
25127c478bd9Sstevel@tonic-gate statep++;
25137c478bd9Sstevel@tonic-gate }
25147c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
25157c478bd9Sstevel@tonic-gate }
25167c478bd9Sstevel@tonic-gate
25177c478bd9Sstevel@tonic-gate
25187c478bd9Sstevel@tonic-gate /*
25197c478bd9Sstevel@tonic-gate * db_restore_config_regs
25207c478bd9Sstevel@tonic-gate *
25217c478bd9Sstevel@tonic-gate * This routine restores the state of the configuration registers of
25227c478bd9Sstevel@tonic-gate * all immediate child nodes.
25237c478bd9Sstevel@tonic-gate *
25247c478bd9Sstevel@tonic-gate * used by: db_attach() on resume
25257c478bd9Sstevel@tonic-gate *
25267c478bd9Sstevel@tonic-gate * return value: none
25277c478bd9Sstevel@tonic-gate */
25287c478bd9Sstevel@tonic-gate static int
db_restore_config_regs(db_ctrl_t * dbp)25297c478bd9Sstevel@tonic-gate db_restore_config_regs(db_ctrl_t *dbp)
25307c478bd9Sstevel@tonic-gate {
25317c478bd9Sstevel@tonic-gate int i;
25327c478bd9Sstevel@tonic-gate dev_info_t *dip;
25337c478bd9Sstevel@tonic-gate ddi_acc_handle_t config_handle;
25347c478bd9Sstevel@tonic-gate db_cfg_state_t *statep = dbp->db_config_state_p;
25357c478bd9Sstevel@tonic-gate
25367c478bd9Sstevel@tonic-gate for (i = 0; i < dbp->config_state_index; i++, statep++) {
25377c478bd9Sstevel@tonic-gate dip = statep->dip;
25387c478bd9Sstevel@tonic-gate if (!dip) {
25397c478bd9Sstevel@tonic-gate cmn_err(CE_WARN,
25407c478bd9Sstevel@tonic-gate "%s#%d: skipping bad dev info (index %d)",
25417c478bd9Sstevel@tonic-gate ddi_driver_name(dbp->dip),
25427c478bd9Sstevel@tonic-gate ddi_get_instance(dbp->dip), i);
25437c478bd9Sstevel@tonic-gate continue;
25447c478bd9Sstevel@tonic-gate }
25457c478bd9Sstevel@tonic-gate if (pci_config_setup(dip, &config_handle) != DDI_SUCCESS) {
25467c478bd9Sstevel@tonic-gate cmn_err(CE_WARN,
25477c478bd9Sstevel@tonic-gate "%s#%d: can't config space for %s#%d",
25487c478bd9Sstevel@tonic-gate ddi_driver_name(dbp->dip),
25497c478bd9Sstevel@tonic-gate ddi_get_instance(dbp->dip),
25507c478bd9Sstevel@tonic-gate ddi_driver_name(dip),
25517c478bd9Sstevel@tonic-gate ddi_get_instance(dip));
25527c478bd9Sstevel@tonic-gate continue;
25537c478bd9Sstevel@tonic-gate }
25547c478bd9Sstevel@tonic-gate pci_config_put16(config_handle, PCI_CONF_COMM, statep->command);
25557c478bd9Sstevel@tonic-gate if ((statep->header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE)
25567c478bd9Sstevel@tonic-gate pci_config_put16(config_handle, PCI_BCNF_BCNTRL,
25577c478bd9Sstevel@tonic-gate statep->bridge_control);
25587c478bd9Sstevel@tonic-gate pci_config_put8(config_handle, PCI_CONF_CACHE_LINESZ,
25597c478bd9Sstevel@tonic-gate statep->cache_line_size);
25607c478bd9Sstevel@tonic-gate pci_config_put8(config_handle, PCI_CONF_LATENCY_TIMER,
25617c478bd9Sstevel@tonic-gate statep->latency_timer);
25627c478bd9Sstevel@tonic-gate if ((statep->header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE)
25637c478bd9Sstevel@tonic-gate pci_config_put8(config_handle, PCI_BCNF_LATENCY_TIMER,
25647c478bd9Sstevel@tonic-gate statep->sec_latency_timer);
25657c478bd9Sstevel@tonic-gate pci_config_teardown(&config_handle);
25667c478bd9Sstevel@tonic-gate }
25677c478bd9Sstevel@tonic-gate
25687c478bd9Sstevel@tonic-gate kmem_free(dbp->db_config_state_p,
25697c478bd9Sstevel@tonic-gate dbp->config_state_index * sizeof (db_cfg_state_t));
25707c478bd9Sstevel@tonic-gate dbp->db_config_state_p = NULL;
25717c478bd9Sstevel@tonic-gate dbp->config_state_index = 0;
25727c478bd9Sstevel@tonic-gate
25737c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
25747c478bd9Sstevel@tonic-gate }
25757c478bd9Sstevel@tonic-gate
25767c478bd9Sstevel@tonic-gate /* put a type 0/1 address on the bus */
25777c478bd9Sstevel@tonic-gate static void
db_put_reg_conf_addr(db_acc_pvt_t * db_pvt,uint32_t conf_addr)25787c478bd9Sstevel@tonic-gate db_put_reg_conf_addr(db_acc_pvt_t *db_pvt, uint32_t conf_addr)
25797c478bd9Sstevel@tonic-gate {
25807c478bd9Sstevel@tonic-gate if (db_pvt->access_mode & DB_PCI_CONF_CYCLE_TYPE0)\
25817c478bd9Sstevel@tonic-gate ddi_put32(db_pvt->handle, db_pvt->addr, (uint32_t)\
25827c478bd9Sstevel@tonic-gate DB_PCI_CONF_CYCLE_TYPE0_ADDR((conf_addr)));\
25837c478bd9Sstevel@tonic-gate else /* type 1 cycle */\
25847c478bd9Sstevel@tonic-gate ddi_put32(db_pvt->handle, db_pvt->addr, (uint32_t)\
25857c478bd9Sstevel@tonic-gate DB_PCI_CONF_CYCLE_TYPE1_ADDR((conf_addr)));
25867c478bd9Sstevel@tonic-gate }
25877c478bd9Sstevel@tonic-gate
25887c478bd9Sstevel@tonic-gate /* Get 8bits data off the 32bit data */
25897c478bd9Sstevel@tonic-gate static uint8_t
db_get_data8(uint32_t addr,uint32_t data)25907c478bd9Sstevel@tonic-gate db_get_data8(uint32_t addr, uint32_t data)
25917c478bd9Sstevel@tonic-gate {
25927c478bd9Sstevel@tonic-gate return (((data) >> (((addr) & 3) * 8)) & 0xff);
25937c478bd9Sstevel@tonic-gate }
25947c478bd9Sstevel@tonic-gate
25957c478bd9Sstevel@tonic-gate /* Get 16bits data off the 32bit data */
25967c478bd9Sstevel@tonic-gate static uint16_t
db_get_data16(uint32_t addr,uint32_t data)25977c478bd9Sstevel@tonic-gate db_get_data16(uint32_t addr, uint32_t data)
25987c478bd9Sstevel@tonic-gate {
25997c478bd9Sstevel@tonic-gate return (((data) >> (((addr) & 3) * 8)) & 0xffff);
26007c478bd9Sstevel@tonic-gate }
26017c478bd9Sstevel@tonic-gate
26027c478bd9Sstevel@tonic-gate /* merge 8bit data into the 32bit data */
26037c478bd9Sstevel@tonic-gate static uint32_t
db_put_data8(uint32_t addr,uint32_t rdata,uint8_t wdata)26047c478bd9Sstevel@tonic-gate db_put_data8(uint32_t addr, uint32_t rdata, uint8_t wdata)
26057c478bd9Sstevel@tonic-gate {
26067c478bd9Sstevel@tonic-gate return ((rdata & (~((0xff << ((((addr) & 3) * 8))) & 0xffffffff))) |
26077c478bd9Sstevel@tonic-gate (((wdata) & 0xff)<<((((addr) & 3))*8)));
26087c478bd9Sstevel@tonic-gate }
26097c478bd9Sstevel@tonic-gate
26107c478bd9Sstevel@tonic-gate /* merge 16bit data into the 32bit data */
26117c478bd9Sstevel@tonic-gate static uint32_t
db_put_data16(uint32_t addr,uint32_t rdata,uint16_t wdata)26127c478bd9Sstevel@tonic-gate db_put_data16(uint32_t addr, uint32_t rdata, uint16_t wdata)
26137c478bd9Sstevel@tonic-gate {
26147c478bd9Sstevel@tonic-gate return ((rdata & (~((0xffff << ((((addr) & 3) * 8))) & 0xffffffff))) |
26157c478bd9Sstevel@tonic-gate (((wdata) & 0xffff) << ((((addr) & 3))*8)));
26167c478bd9Sstevel@tonic-gate }
26177c478bd9Sstevel@tonic-gate
26187c478bd9Sstevel@tonic-gate
26197c478bd9Sstevel@tonic-gate /*
26207c478bd9Sstevel@tonic-gate * For the next set of PCI configuration IO calls, we need
26217c478bd9Sstevel@tonic-gate * to make sure we own the bus before generating the config cycles,
26227c478bd9Sstevel@tonic-gate * using the drawbridge's semaphore method.
26237c478bd9Sstevel@tonic-gate */
26247c478bd9Sstevel@tonic-gate
26257c478bd9Sstevel@tonic-gate /*
26267c478bd9Sstevel@tonic-gate * Function to read 8 bit data off the PCI configuration space behind
26277c478bd9Sstevel@tonic-gate * the 21554's host interface.
26287c478bd9Sstevel@tonic-gate */
26297c478bd9Sstevel@tonic-gate static uint8_t
db_ddi_get8(ddi_acc_impl_t * handle,uint8_t * addr)26307c478bd9Sstevel@tonic-gate db_ddi_get8(ddi_acc_impl_t *handle, uint8_t *addr)
26317c478bd9Sstevel@tonic-gate {
26327c478bd9Sstevel@tonic-gate uint32_t data;
26337c478bd9Sstevel@tonic-gate
26347c478bd9Sstevel@tonic-gate data = db_ddi_get32(handle, (uint32_t *)addr);
2635f47a9c50Smathue return (db_get_data8((uint32_t)(uintptr_t)addr, data));
26367c478bd9Sstevel@tonic-gate }
26377c478bd9Sstevel@tonic-gate
26387c478bd9Sstevel@tonic-gate /*
26397c478bd9Sstevel@tonic-gate * Function to read 16 bit data off the PCI configuration space behind
26407c478bd9Sstevel@tonic-gate * the 21554's host interface.
26417c478bd9Sstevel@tonic-gate */
26427c478bd9Sstevel@tonic-gate static uint16_t
db_ddi_get16(ddi_acc_impl_t * handle,uint16_t * addr)26437c478bd9Sstevel@tonic-gate db_ddi_get16(ddi_acc_impl_t *handle, uint16_t *addr)
26447c478bd9Sstevel@tonic-gate {
26457c478bd9Sstevel@tonic-gate uint32_t data;
26467c478bd9Sstevel@tonic-gate
26477c478bd9Sstevel@tonic-gate data = db_ddi_get32(handle, (uint32_t *)addr);
2648f47a9c50Smathue return (db_get_data16((uint32_t)(uintptr_t)addr, data));
26497c478bd9Sstevel@tonic-gate }
26507c478bd9Sstevel@tonic-gate
26517c478bd9Sstevel@tonic-gate /*
26527c478bd9Sstevel@tonic-gate * Function to read 32 bit data off the PCI configuration space behind
26537c478bd9Sstevel@tonic-gate * the 21554's host interface.
26547c478bd9Sstevel@tonic-gate */
26557c478bd9Sstevel@tonic-gate static uint32_t
db_ddi_get32(ddi_acc_impl_t * handle,uint32_t * addr)26567c478bd9Sstevel@tonic-gate db_ddi_get32(ddi_acc_impl_t *handle, uint32_t *addr)
26577c478bd9Sstevel@tonic-gate {
26587c478bd9Sstevel@tonic-gate db_acc_pvt_t *db_pvt = (db_acc_pvt_t *)
26597c478bd9Sstevel@tonic-gate handle->ahi_common.ah_bus_private;
26607c478bd9Sstevel@tonic-gate uint32_t wait_count = 0;
26617c478bd9Sstevel@tonic-gate uint32_t data;
26627c478bd9Sstevel@tonic-gate db_ctrl_t *dbp;
26637c478bd9Sstevel@tonic-gate
26647c478bd9Sstevel@tonic-gate dbp = db_pvt->dbp;
26657c478bd9Sstevel@tonic-gate
26667c478bd9Sstevel@tonic-gate mutex_enter(&dbp->db_busown);
26677c478bd9Sstevel@tonic-gate
26687c478bd9Sstevel@tonic-gate if (db_use_config_own_bit) {
26697c478bd9Sstevel@tonic-gate /*
26707c478bd9Sstevel@tonic-gate * check if (upstream/downstream)configuration address own
26717c478bd9Sstevel@tonic-gate * bit set. With this set, we cannot proceed.
26727c478bd9Sstevel@tonic-gate */
26737c478bd9Sstevel@tonic-gate while (((ddi_get8(db_pvt->handle, db_pvt->bus_own)) &
26747c478bd9Sstevel@tonic-gate db_pvt->mask) == db_pvt->mask) {
26757c478bd9Sstevel@tonic-gate #ifdef DEBUG
26767c478bd9Sstevel@tonic-gate if (dbp->db_pci_max_wait_count < wait_count)
26777c478bd9Sstevel@tonic-gate dbp->db_pci_max_wait_count = wait_count;
26787c478bd9Sstevel@tonic-gate #endif
26797c478bd9Sstevel@tonic-gate drv_usecwait(db_pci_own_wait);
26807c478bd9Sstevel@tonic-gate if (++wait_count == db_pci_max_wait) {
26817c478bd9Sstevel@tonic-gate /*
26827c478bd9Sstevel@tonic-gate * the man page for pci_config_* routines do
26837c478bd9Sstevel@tonic-gate * Not specify any error condition values.
26847c478bd9Sstevel@tonic-gate */
26857c478bd9Sstevel@tonic-gate cmn_err(CE_WARN,
26867c478bd9Sstevel@tonic-gate "%s#%d: pci config bus own error",
26877c478bd9Sstevel@tonic-gate ddi_driver_name(dbp->dip),
26887c478bd9Sstevel@tonic-gate ddi_get_instance(dbp->dip));
26897c478bd9Sstevel@tonic-gate dbp->db_pci_err_count++;
26907c478bd9Sstevel@tonic-gate mutex_exit(&dbp->db_busown);
26917c478bd9Sstevel@tonic-gate return ((uint32_t)DB_CONF_FAILURE);
26927c478bd9Sstevel@tonic-gate }
26937c478bd9Sstevel@tonic-gate }
26947c478bd9Sstevel@tonic-gate wait_count = 0;
26957c478bd9Sstevel@tonic-gate }
26967c478bd9Sstevel@tonic-gate
2697f47a9c50Smathue db_put_reg_conf_addr(db_pvt, (uint32_t)(uintptr_t)addr);
26987c478bd9Sstevel@tonic-gate data = ddi_get32(db_pvt->handle, (uint32_t *)db_pvt->data);
26997c478bd9Sstevel@tonic-gate
27007c478bd9Sstevel@tonic-gate if (db_use_config_own_bit) {
27017c478bd9Sstevel@tonic-gate while (((ddi_get8(db_pvt->handle, db_pvt->bus_release)) &
27027c478bd9Sstevel@tonic-gate db_pvt->mask) == db_pvt->mask) {
27037c478bd9Sstevel@tonic-gate #ifdef DEBUG
27047c478bd9Sstevel@tonic-gate if (dbp->db_pci_max_wait_count < wait_count)
27057c478bd9Sstevel@tonic-gate dbp->db_pci_max_wait_count = wait_count;
27067c478bd9Sstevel@tonic-gate #endif
27077c478bd9Sstevel@tonic-gate drv_usecwait(db_pci_release_wait);
27087c478bd9Sstevel@tonic-gate if (++wait_count == db_pci_max_wait) {
27097c478bd9Sstevel@tonic-gate /*
27107c478bd9Sstevel@tonic-gate * the man page for pci_config_* routines do
27117c478bd9Sstevel@tonic-gate * not specify any error condition values.
27127c478bd9Sstevel@tonic-gate */
27137c478bd9Sstevel@tonic-gate cmn_err(CE_WARN,
27147c478bd9Sstevel@tonic-gate "%s#%d: pci config bus release error",
27157c478bd9Sstevel@tonic-gate ddi_driver_name(dbp->dip),
27167c478bd9Sstevel@tonic-gate ddi_get_instance(dbp->dip));
27177c478bd9Sstevel@tonic-gate dbp->db_pci_err_count++;
27187c478bd9Sstevel@tonic-gate mutex_exit(&dbp->db_busown);
27197c478bd9Sstevel@tonic-gate return ((uint32_t)DB_CONF_FAILURE);
27207c478bd9Sstevel@tonic-gate }
27217c478bd9Sstevel@tonic-gate data = ddi_get32(db_pvt->handle,
27227c478bd9Sstevel@tonic-gate (uint32_t *)db_pvt->data);
27237c478bd9Sstevel@tonic-gate }
27247c478bd9Sstevel@tonic-gate }
27257c478bd9Sstevel@tonic-gate
27267c478bd9Sstevel@tonic-gate mutex_exit(&dbp->db_busown);
27277c478bd9Sstevel@tonic-gate
27287c478bd9Sstevel@tonic-gate return (data);
27297c478bd9Sstevel@tonic-gate }
27307c478bd9Sstevel@tonic-gate
27317c478bd9Sstevel@tonic-gate /*
27327c478bd9Sstevel@tonic-gate * Function to read 64 bit data off the PCI configuration space behind
27337c478bd9Sstevel@tonic-gate * the 21554's host interface.
27347c478bd9Sstevel@tonic-gate */
27357c478bd9Sstevel@tonic-gate static uint64_t
db_ddi_get64(ddi_acc_impl_t * handle,uint64_t * addr)27367c478bd9Sstevel@tonic-gate db_ddi_get64(ddi_acc_impl_t *handle, uint64_t *addr)
27377c478bd9Sstevel@tonic-gate {
27387c478bd9Sstevel@tonic-gate uint64_t udata, ldata;
27397c478bd9Sstevel@tonic-gate
27407c478bd9Sstevel@tonic-gate ldata = (uint32_t)db_ddi_get32(handle, (uint32_t *)addr);
27417c478bd9Sstevel@tonic-gate udata = (uint32_t)db_ddi_get32(handle, (uint32_t *)addr + 1);
27427c478bd9Sstevel@tonic-gate return (ldata | (udata << 32));
27437c478bd9Sstevel@tonic-gate }
27447c478bd9Sstevel@tonic-gate
27457c478bd9Sstevel@tonic-gate /*
27467c478bd9Sstevel@tonic-gate * Function to write 8 bit data into the PCI configuration space behind
27477c478bd9Sstevel@tonic-gate * the 21554's host interface.
27487c478bd9Sstevel@tonic-gate */
27497c478bd9Sstevel@tonic-gate static void
db_ddi_put8(ddi_acc_impl_t * handle,uint8_t * addr,uint8_t data)27507c478bd9Sstevel@tonic-gate db_ddi_put8(ddi_acc_impl_t *handle, uint8_t *addr, uint8_t data)
27517c478bd9Sstevel@tonic-gate {
27527c478bd9Sstevel@tonic-gate uint32_t rdata;
27537c478bd9Sstevel@tonic-gate
27547c478bd9Sstevel@tonic-gate rdata = db_ddi_get32(handle, (uint32_t *)addr);
27557c478bd9Sstevel@tonic-gate db_ddi_put32(handle, (uint32_t *)addr,
2756f47a9c50Smathue db_put_data8((uint32_t)(uintptr_t)addr, rdata, data));
27577c478bd9Sstevel@tonic-gate }
27587c478bd9Sstevel@tonic-gate
27597c478bd9Sstevel@tonic-gate /*
27607c478bd9Sstevel@tonic-gate * Function to write 16 bit data into the PCI configuration space behind
27617c478bd9Sstevel@tonic-gate * the 21554's host interface.
27627c478bd9Sstevel@tonic-gate */
27637c478bd9Sstevel@tonic-gate static void
db_ddi_put16(ddi_acc_impl_t * handle,uint16_t * addr,uint16_t data)27647c478bd9Sstevel@tonic-gate db_ddi_put16(ddi_acc_impl_t *handle, uint16_t *addr, uint16_t data)
27657c478bd9Sstevel@tonic-gate {
27667c478bd9Sstevel@tonic-gate uint32_t rdata;
27677c478bd9Sstevel@tonic-gate
27687c478bd9Sstevel@tonic-gate rdata = db_ddi_get32(handle, (uint32_t *)addr);
27697c478bd9Sstevel@tonic-gate db_ddi_put32(handle, (uint32_t *)addr,
2770f47a9c50Smathue db_put_data16((uint32_t)(uintptr_t)addr, rdata, data));
27717c478bd9Sstevel@tonic-gate }
27727c478bd9Sstevel@tonic-gate
27737c478bd9Sstevel@tonic-gate /*
27747c478bd9Sstevel@tonic-gate * Function to write 32 bit data into the PCI configuration space behind
27757c478bd9Sstevel@tonic-gate * the 21554's host interface.
27767c478bd9Sstevel@tonic-gate */
27777c478bd9Sstevel@tonic-gate static void
db_ddi_put32(ddi_acc_impl_t * handle,uint32_t * addr,uint32_t data)27787c478bd9Sstevel@tonic-gate db_ddi_put32(ddi_acc_impl_t *handle, uint32_t *addr, uint32_t data)
27797c478bd9Sstevel@tonic-gate {
27807c478bd9Sstevel@tonic-gate db_acc_pvt_t *db_pvt = (db_acc_pvt_t *)
27817c478bd9Sstevel@tonic-gate handle->ahi_common.ah_bus_private;
27827c478bd9Sstevel@tonic-gate db_ctrl_t *dbp;
27837c478bd9Sstevel@tonic-gate uint32_t wait_count = 0;
27847c478bd9Sstevel@tonic-gate
27857c478bd9Sstevel@tonic-gate dbp = db_pvt->dbp;
27867c478bd9Sstevel@tonic-gate
27877c478bd9Sstevel@tonic-gate mutex_enter(&dbp->db_busown);
27887c478bd9Sstevel@tonic-gate
27897c478bd9Sstevel@tonic-gate if (db_use_config_own_bit) {
27907c478bd9Sstevel@tonic-gate /*
27917c478bd9Sstevel@tonic-gate * check if (upstream/downstream)configuration address own
27927c478bd9Sstevel@tonic-gate * bit set. with this set, we cannot proceed.
27937c478bd9Sstevel@tonic-gate */
27947c478bd9Sstevel@tonic-gate while (((ddi_get8(db_pvt->handle, db_pvt->bus_own)) &
27957c478bd9Sstevel@tonic-gate db_pvt->mask) == db_pvt->mask) {
27967c478bd9Sstevel@tonic-gate #ifdef DEBUG
27977c478bd9Sstevel@tonic-gate if (dbp->db_pci_max_wait_count < wait_count)
27987c478bd9Sstevel@tonic-gate dbp->db_pci_max_wait_count = wait_count;
27997c478bd9Sstevel@tonic-gate #endif
28007c478bd9Sstevel@tonic-gate drv_usecwait(db_pci_own_wait);
28017c478bd9Sstevel@tonic-gate if (++wait_count == db_pci_max_wait) {
28027c478bd9Sstevel@tonic-gate /*
28037c478bd9Sstevel@tonic-gate * Since the return value is void here,
28047c478bd9Sstevel@tonic-gate * we may need to print a message, as this
28057c478bd9Sstevel@tonic-gate * could be a serious situation.
28067c478bd9Sstevel@tonic-gate */
28077c478bd9Sstevel@tonic-gate cmn_err(CE_WARN,
28087c478bd9Sstevel@tonic-gate "%s#%d: pci config bus own error",
28097c478bd9Sstevel@tonic-gate ddi_driver_name(dbp->dip),
28107c478bd9Sstevel@tonic-gate ddi_get_instance(dbp->dip));
28117c478bd9Sstevel@tonic-gate dbp->db_pci_err_count++;
28127c478bd9Sstevel@tonic-gate mutex_exit(&dbp->db_busown);
28137c478bd9Sstevel@tonic-gate return;
28147c478bd9Sstevel@tonic-gate }
28157c478bd9Sstevel@tonic-gate }
28167c478bd9Sstevel@tonic-gate wait_count = 0;
28177c478bd9Sstevel@tonic-gate }
28187c478bd9Sstevel@tonic-gate
2819f47a9c50Smathue db_put_reg_conf_addr(db_pvt, (uint32_t)(uintptr_t)addr);
28207c478bd9Sstevel@tonic-gate ddi_put32(db_pvt->handle, (uint32_t *)db_pvt->data, data);
28217c478bd9Sstevel@tonic-gate
28227c478bd9Sstevel@tonic-gate if (db_use_config_own_bit) {
28237c478bd9Sstevel@tonic-gate while (((ddi_get8(db_pvt->handle, db_pvt->bus_release)) &
28247c478bd9Sstevel@tonic-gate db_pvt->mask) == db_pvt->mask) {
28257c478bd9Sstevel@tonic-gate #ifdef DEBUG
28267c478bd9Sstevel@tonic-gate if (dbp->db_pci_max_wait_count < wait_count)
28277c478bd9Sstevel@tonic-gate dbp->db_pci_max_wait_count = wait_count;
28287c478bd9Sstevel@tonic-gate #endif
28297c478bd9Sstevel@tonic-gate drv_usecwait(db_pci_release_wait);
28307c478bd9Sstevel@tonic-gate if (++wait_count == db_pci_max_wait) {
28317c478bd9Sstevel@tonic-gate /*
28327c478bd9Sstevel@tonic-gate * the man page for pci_config_* routines do
28337c478bd9Sstevel@tonic-gate * Not specify any error condition values.
28347c478bd9Sstevel@tonic-gate */
28357c478bd9Sstevel@tonic-gate cmn_err(CE_WARN,
28367c478bd9Sstevel@tonic-gate "%s#%d: pci config bus release error",
28377c478bd9Sstevel@tonic-gate ddi_driver_name(dbp->dip),
28387c478bd9Sstevel@tonic-gate ddi_get_instance(dbp->dip));
28397c478bd9Sstevel@tonic-gate dbp->db_pci_err_count++;
28407c478bd9Sstevel@tonic-gate mutex_exit(&dbp->db_busown);
28417c478bd9Sstevel@tonic-gate return;
28427c478bd9Sstevel@tonic-gate }
28437c478bd9Sstevel@tonic-gate ddi_put32(db_pvt->handle, (uint32_t *)db_pvt->data,
28447c478bd9Sstevel@tonic-gate data);
28457c478bd9Sstevel@tonic-gate }
28467c478bd9Sstevel@tonic-gate }
28477c478bd9Sstevel@tonic-gate
28487c478bd9Sstevel@tonic-gate mutex_exit(&dbp->db_busown);
28497c478bd9Sstevel@tonic-gate }
28507c478bd9Sstevel@tonic-gate
28517c478bd9Sstevel@tonic-gate /*
28527c478bd9Sstevel@tonic-gate * Function to write 64 bit data into the PCI configuration space behind
28537c478bd9Sstevel@tonic-gate * the 21554's host interface.
28547c478bd9Sstevel@tonic-gate */
28557c478bd9Sstevel@tonic-gate static void
db_ddi_put64(ddi_acc_impl_t * handle,uint64_t * addr,uint64_t data)28567c478bd9Sstevel@tonic-gate db_ddi_put64(ddi_acc_impl_t *handle, uint64_t *addr, uint64_t data)
28577c478bd9Sstevel@tonic-gate {
28587c478bd9Sstevel@tonic-gate db_ddi_put32(handle, (uint32_t *)addr, (uint32_t)(data & 0xffffffff));
28597c478bd9Sstevel@tonic-gate db_ddi_put32(handle, (uint32_t *)addr + 1, (uint32_t)(data >> 32));
28607c478bd9Sstevel@tonic-gate }
28617c478bd9Sstevel@tonic-gate
28627c478bd9Sstevel@tonic-gate /*
28637c478bd9Sstevel@tonic-gate * Function to rep read 8 bit data off the PCI configuration space behind
28647c478bd9Sstevel@tonic-gate * the 21554's host interface.
28657c478bd9Sstevel@tonic-gate */
28667c478bd9Sstevel@tonic-gate static void
db_ddi_rep_get8(ddi_acc_impl_t * handle,uint8_t * host_addr,uint8_t * dev_addr,size_t repcount,uint_t flags)28677c478bd9Sstevel@tonic-gate db_ddi_rep_get8(ddi_acc_impl_t *handle, uint8_t *host_addr,
28687c478bd9Sstevel@tonic-gate uint8_t *dev_addr, size_t repcount, uint_t flags)
28697c478bd9Sstevel@tonic-gate {
28707c478bd9Sstevel@tonic-gate if (flags == DDI_DEV_AUTOINCR)
28717c478bd9Sstevel@tonic-gate for (; repcount; repcount--)
28727c478bd9Sstevel@tonic-gate *host_addr++ = db_ddi_get8(handle, dev_addr++);
28737c478bd9Sstevel@tonic-gate else
28747c478bd9Sstevel@tonic-gate for (; repcount; repcount--)
28757c478bd9Sstevel@tonic-gate *host_addr++ = db_ddi_get8(handle, dev_addr);
28767c478bd9Sstevel@tonic-gate }
28777c478bd9Sstevel@tonic-gate
28787c478bd9Sstevel@tonic-gate /*
28797c478bd9Sstevel@tonic-gate * Function to rep read 16 bit data off the PCI configuration space behind
28807c478bd9Sstevel@tonic-gate * the 21554's host interface.
28817c478bd9Sstevel@tonic-gate */
28827c478bd9Sstevel@tonic-gate static void
db_ddi_rep_get16(ddi_acc_impl_t * handle,uint16_t * host_addr,uint16_t * dev_addr,size_t repcount,uint_t flags)28837c478bd9Sstevel@tonic-gate db_ddi_rep_get16(ddi_acc_impl_t *handle, uint16_t *host_addr,
28847c478bd9Sstevel@tonic-gate uint16_t *dev_addr, size_t repcount, uint_t flags)
28857c478bd9Sstevel@tonic-gate {
28867c478bd9Sstevel@tonic-gate if (flags == DDI_DEV_AUTOINCR)
28877c478bd9Sstevel@tonic-gate for (; repcount; repcount--)
28887c478bd9Sstevel@tonic-gate *host_addr++ = db_ddi_get16(handle, dev_addr++);
28897c478bd9Sstevel@tonic-gate else
28907c478bd9Sstevel@tonic-gate for (; repcount; repcount--)
28917c478bd9Sstevel@tonic-gate *host_addr++ = db_ddi_get16(handle, dev_addr);
28927c478bd9Sstevel@tonic-gate }
28937c478bd9Sstevel@tonic-gate
28947c478bd9Sstevel@tonic-gate /*
28957c478bd9Sstevel@tonic-gate * Function to rep read 32 bit data off the PCI configuration space behind
28967c478bd9Sstevel@tonic-gate * the 21554's host interface.
28977c478bd9Sstevel@tonic-gate */
28987c478bd9Sstevel@tonic-gate static void
db_ddi_rep_get32(ddi_acc_impl_t * handle,uint32_t * host_addr,uint32_t * dev_addr,size_t repcount,uint_t flags)28997c478bd9Sstevel@tonic-gate db_ddi_rep_get32(ddi_acc_impl_t *handle, uint32_t *host_addr,
29007c478bd9Sstevel@tonic-gate uint32_t *dev_addr, size_t repcount, uint_t flags)
29017c478bd9Sstevel@tonic-gate {
29027c478bd9Sstevel@tonic-gate if (flags == DDI_DEV_AUTOINCR)
29037c478bd9Sstevel@tonic-gate for (; repcount; repcount--)
29047c478bd9Sstevel@tonic-gate *host_addr++ = db_ddi_get32(handle, dev_addr++);
29057c478bd9Sstevel@tonic-gate else
29067c478bd9Sstevel@tonic-gate for (; repcount; repcount--)
29077c478bd9Sstevel@tonic-gate *host_addr++ = db_ddi_get32(handle, dev_addr);
29087c478bd9Sstevel@tonic-gate }
29097c478bd9Sstevel@tonic-gate
29107c478bd9Sstevel@tonic-gate /*
29117c478bd9Sstevel@tonic-gate * Function to rep read 64 bit data off the PCI configuration space behind
29127c478bd9Sstevel@tonic-gate * the 21554's host interface.
29137c478bd9Sstevel@tonic-gate */
29147c478bd9Sstevel@tonic-gate static void
db_ddi_rep_get64(ddi_acc_impl_t * handle,uint64_t * host_addr,uint64_t * dev_addr,size_t repcount,uint_t flags)29157c478bd9Sstevel@tonic-gate db_ddi_rep_get64(ddi_acc_impl_t *handle, uint64_t *host_addr,
29167c478bd9Sstevel@tonic-gate uint64_t *dev_addr, size_t repcount, uint_t flags)
29177c478bd9Sstevel@tonic-gate {
29187c478bd9Sstevel@tonic-gate if (flags == DDI_DEV_AUTOINCR)
29197c478bd9Sstevel@tonic-gate for (; repcount; repcount--)
29207c478bd9Sstevel@tonic-gate *host_addr++ = db_ddi_get64(handle, dev_addr++);
29217c478bd9Sstevel@tonic-gate else
29227c478bd9Sstevel@tonic-gate for (; repcount; repcount--)
29237c478bd9Sstevel@tonic-gate *host_addr++ = db_ddi_get64(handle, dev_addr);
29247c478bd9Sstevel@tonic-gate }
29257c478bd9Sstevel@tonic-gate
29267c478bd9Sstevel@tonic-gate /*
29277c478bd9Sstevel@tonic-gate * Function to rep write 8 bit data into the PCI configuration space behind
29287c478bd9Sstevel@tonic-gate * the 21554's host interface.
29297c478bd9Sstevel@tonic-gate */
29307c478bd9Sstevel@tonic-gate static void
db_ddi_rep_put8(ddi_acc_impl_t * handle,uint8_t * host_addr,uint8_t * dev_addr,size_t repcount,uint_t flags)29317c478bd9Sstevel@tonic-gate db_ddi_rep_put8(ddi_acc_impl_t *handle, uint8_t *host_addr,
29327c478bd9Sstevel@tonic-gate uint8_t *dev_addr, size_t repcount, uint_t flags)
29337c478bd9Sstevel@tonic-gate {
29347c478bd9Sstevel@tonic-gate if (flags == DDI_DEV_AUTOINCR)
29357c478bd9Sstevel@tonic-gate for (; repcount; repcount--)
29367c478bd9Sstevel@tonic-gate db_ddi_put8(handle, dev_addr++, *host_addr++);
29377c478bd9Sstevel@tonic-gate else
29387c478bd9Sstevel@tonic-gate for (; repcount; repcount--)
29397c478bd9Sstevel@tonic-gate db_ddi_put8(handle, dev_addr, *host_addr++);
29407c478bd9Sstevel@tonic-gate }
29417c478bd9Sstevel@tonic-gate
29427c478bd9Sstevel@tonic-gate /*
29437c478bd9Sstevel@tonic-gate * Function to rep write 16 bit data into the PCI configuration space behind
29447c478bd9Sstevel@tonic-gate * the 21554's host interface.
29457c478bd9Sstevel@tonic-gate */
29467c478bd9Sstevel@tonic-gate static void
db_ddi_rep_put16(ddi_acc_impl_t * handle,uint16_t * host_addr,uint16_t * dev_addr,size_t repcount,uint_t flags)29477c478bd9Sstevel@tonic-gate db_ddi_rep_put16(ddi_acc_impl_t *handle, uint16_t *host_addr,
29487c478bd9Sstevel@tonic-gate uint16_t *dev_addr, size_t repcount, uint_t flags)
29497c478bd9Sstevel@tonic-gate {
29507c478bd9Sstevel@tonic-gate if (flags == DDI_DEV_AUTOINCR)
29517c478bd9Sstevel@tonic-gate for (; repcount; repcount--)
29527c478bd9Sstevel@tonic-gate db_ddi_put16(handle, dev_addr++, *host_addr++);
29537c478bd9Sstevel@tonic-gate else
29547c478bd9Sstevel@tonic-gate for (; repcount; repcount--)
29557c478bd9Sstevel@tonic-gate db_ddi_put16(handle, dev_addr, *host_addr++);
29567c478bd9Sstevel@tonic-gate }
29577c478bd9Sstevel@tonic-gate
29587c478bd9Sstevel@tonic-gate /*
29597c478bd9Sstevel@tonic-gate * Function to rep write 32 bit data into the PCI configuration space behind
29607c478bd9Sstevel@tonic-gate * the 21554's host interface.
29617c478bd9Sstevel@tonic-gate */
29627c478bd9Sstevel@tonic-gate static void
db_ddi_rep_put32(ddi_acc_impl_t * handle,uint32_t * host_addr,uint32_t * dev_addr,size_t repcount,uint_t flags)29637c478bd9Sstevel@tonic-gate db_ddi_rep_put32(ddi_acc_impl_t *handle, uint32_t *host_addr,
29647c478bd9Sstevel@tonic-gate uint32_t *dev_addr, size_t repcount, uint_t flags)
29657c478bd9Sstevel@tonic-gate {
29667c478bd9Sstevel@tonic-gate if (flags == DDI_DEV_AUTOINCR)
29677c478bd9Sstevel@tonic-gate for (; repcount; repcount--)
29687c478bd9Sstevel@tonic-gate db_ddi_put32(handle, dev_addr++, *host_addr++);
29697c478bd9Sstevel@tonic-gate else
29707c478bd9Sstevel@tonic-gate for (; repcount; repcount--)
29717c478bd9Sstevel@tonic-gate db_ddi_put32(handle, dev_addr, *host_addr++);
29727c478bd9Sstevel@tonic-gate }
29737c478bd9Sstevel@tonic-gate
29747c478bd9Sstevel@tonic-gate /*
29757c478bd9Sstevel@tonic-gate * Function to rep write 64 bit data into the PCI configuration space behind
29767c478bd9Sstevel@tonic-gate * the 21554's host interface.
29777c478bd9Sstevel@tonic-gate */
29787c478bd9Sstevel@tonic-gate static void
db_ddi_rep_put64(ddi_acc_impl_t * handle,uint64_t * host_addr,uint64_t * dev_addr,size_t repcount,uint_t flags)29797c478bd9Sstevel@tonic-gate db_ddi_rep_put64(ddi_acc_impl_t *handle, uint64_t *host_addr,
29807c478bd9Sstevel@tonic-gate uint64_t *dev_addr, size_t repcount, uint_t flags)
29817c478bd9Sstevel@tonic-gate {
29827c478bd9Sstevel@tonic-gate if (flags == DDI_DEV_AUTOINCR)
29837c478bd9Sstevel@tonic-gate for (; repcount; repcount--)
29847c478bd9Sstevel@tonic-gate db_ddi_put64(handle, dev_addr++, *host_addr++);
29857c478bd9Sstevel@tonic-gate else
29867c478bd9Sstevel@tonic-gate for (; repcount; repcount--)
29877c478bd9Sstevel@tonic-gate db_ddi_put64(handle, dev_addr, *host_addr++);
29887c478bd9Sstevel@tonic-gate }
29897c478bd9Sstevel@tonic-gate
29907c478bd9Sstevel@tonic-gate #ifdef DEBUG
29917c478bd9Sstevel@tonic-gate
29927c478bd9Sstevel@tonic-gate static void
db_debug(uint64_t func_id,dev_info_t * dip,char * fmt,uintptr_t a1,uintptr_t a2,uintptr_t a3,uintptr_t a4,uintptr_t a5)29937c478bd9Sstevel@tonic-gate db_debug(uint64_t func_id, dev_info_t *dip, char *fmt,
29947c478bd9Sstevel@tonic-gate uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5)
29957c478bd9Sstevel@tonic-gate {
29967c478bd9Sstevel@tonic-gate char *s = NULL;
29977c478bd9Sstevel@tonic-gate uint_t dip_no_disp = 0;
29987c478bd9Sstevel@tonic-gate
29997c478bd9Sstevel@tonic-gate if (func_id & DB_DONT_DISPLAY_DIP) {
30007c478bd9Sstevel@tonic-gate dip_no_disp = 1;
30017c478bd9Sstevel@tonic-gate }
30027c478bd9Sstevel@tonic-gate if (db_debug_funcs & func_id) {
30037c478bd9Sstevel@tonic-gate switch (func_id) {
30047c478bd9Sstevel@tonic-gate case DB_INIT: s = "_init"; break;
30057c478bd9Sstevel@tonic-gate case DB_FINI: s = "_fini"; break;
30067c478bd9Sstevel@tonic-gate case DB_INFO: s = "_info"; break;
30077c478bd9Sstevel@tonic-gate case DB_GETINFO: s = "getinfo"; break;
30087c478bd9Sstevel@tonic-gate case DB_ATTACH: s = "attach"; break;
30097c478bd9Sstevel@tonic-gate case DB_DETACH: s = "detach"; break;
30107c478bd9Sstevel@tonic-gate case DB_CTLOPS: s = "ctlops"; break;
30117c478bd9Sstevel@tonic-gate case DB_INITCHILD: s = "initchild"; break;
30127c478bd9Sstevel@tonic-gate case DB_REMOVECHILD: s = "removechild"; break;
30137c478bd9Sstevel@tonic-gate case DB_INTR_OPS: s = "intr_ops"; break;
30147c478bd9Sstevel@tonic-gate case DB_PCI_MAP: s = "map"; break;
30157c478bd9Sstevel@tonic-gate case DB_SAVE_CONF_REGS: s = "save_conf_regs"; break;
30167c478bd9Sstevel@tonic-gate case DB_REST_CONF_REGS: s = "restore_conf_regs"; break;
30177c478bd9Sstevel@tonic-gate case DB_INTR: s = "intr"; break;
30187c478bd9Sstevel@tonic-gate case DB_OPEN: s = "open"; break;
30197c478bd9Sstevel@tonic-gate case DB_CLOSE: s = "close"; break;
30207c478bd9Sstevel@tonic-gate case DB_IOCTL: s = "ioctl"; break;
30217c478bd9Sstevel@tonic-gate case DB_DVMA: s = "set_dvma_range"; break;
30227c478bd9Sstevel@tonic-gate
30237c478bd9Sstevel@tonic-gate default: s = "PCI debug unknown"; break;
30247c478bd9Sstevel@tonic-gate }
30257c478bd9Sstevel@tonic-gate
30267c478bd9Sstevel@tonic-gate if (s && !dip_no_disp) {
30277c478bd9Sstevel@tonic-gate prom_printf("%s(%d): %s: ", ddi_driver_name(dip),
30287c478bd9Sstevel@tonic-gate ddi_get_instance(dip), s);
30297c478bd9Sstevel@tonic-gate }
30307c478bd9Sstevel@tonic-gate prom_printf(fmt, a1, a2, a3, a4, a5);
30317c478bd9Sstevel@tonic-gate }
30327c478bd9Sstevel@tonic-gate }
30337c478bd9Sstevel@tonic-gate #endif
30347c478bd9Sstevel@tonic-gate
db_prop_op(dev_t dev,dev_info_t * dip,ddi_prop_op_t prop_op,int flags,char * name,caddr_t valuep,int * lengthp)30357c478bd9Sstevel@tonic-gate static int db_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
30367c478bd9Sstevel@tonic-gate int flags, char *name, caddr_t valuep, int *lengthp)
30377c478bd9Sstevel@tonic-gate {
30387c478bd9Sstevel@tonic-gate minor_t minor = getminor(dev);
30397c478bd9Sstevel@tonic-gate int instance = PCIHP_AP_MINOR_NUM_TO_INSTANCE(minor);
30407c478bd9Sstevel@tonic-gate
30417c478bd9Sstevel@tonic-gate db_ctrl_t *dbp = (db_ctrl_t *)ddi_get_soft_state(db_state, instance);
30427c478bd9Sstevel@tonic-gate
30437c478bd9Sstevel@tonic-gate
30447c478bd9Sstevel@tonic-gate if (dbp == NULL)
30457c478bd9Sstevel@tonic-gate return (ENXIO);
30467c478bd9Sstevel@tonic-gate
30477c478bd9Sstevel@tonic-gate if (dbp->dev_state & DB_SECONDARY_NEXUS)
30487c478bd9Sstevel@tonic-gate return ((pcihp_get_cb_ops())->cb_prop_op(dev, dip,
30497c478bd9Sstevel@tonic-gate prop_op, flags, name, valuep, lengthp));
30507c478bd9Sstevel@tonic-gate
30517c478bd9Sstevel@tonic-gate return (ddi_prop_op(dev, dip, prop_op, flags, name, valuep, lengthp));
30527c478bd9Sstevel@tonic-gate }
30537c478bd9Sstevel@tonic-gate
30547c478bd9Sstevel@tonic-gate /*
30557c478bd9Sstevel@tonic-gate * Initialize our FMA resources
30567c478bd9Sstevel@tonic-gate */
30577c478bd9Sstevel@tonic-gate static void
db_fm_init(db_ctrl_t * db_p)30587c478bd9Sstevel@tonic-gate db_fm_init(db_ctrl_t *db_p)
30597c478bd9Sstevel@tonic-gate {
30607c478bd9Sstevel@tonic-gate db_p->fm_cap = DDI_FM_EREPORT_CAPABLE | DDI_FM_ERRCB_CAPABLE |
30617c478bd9Sstevel@tonic-gate DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE;
30627c478bd9Sstevel@tonic-gate
30637c478bd9Sstevel@tonic-gate /*
30647c478bd9Sstevel@tonic-gate * Request our capability level and get our parents capability
30657c478bd9Sstevel@tonic-gate * and ibc.
30667c478bd9Sstevel@tonic-gate */
30677c478bd9Sstevel@tonic-gate ddi_fm_init(db_p->dip, &db_p->fm_cap, &db_p->fm_ibc);
30687c478bd9Sstevel@tonic-gate ASSERT((db_p->fm_cap & DDI_FM_EREPORT_CAPABLE) &&
30697c478bd9Sstevel@tonic-gate (db_p->fm_cap & DDI_FM_ERRCB_CAPABLE));
30707c478bd9Sstevel@tonic-gate
30717c478bd9Sstevel@tonic-gate pci_ereport_setup(db_p->dip);
30727c478bd9Sstevel@tonic-gate
30737c478bd9Sstevel@tonic-gate /*
30747c478bd9Sstevel@tonic-gate * Register error callback with our parent.
30757c478bd9Sstevel@tonic-gate */
30767c478bd9Sstevel@tonic-gate ddi_fm_handler_register(db_p->dip, db_err_callback, NULL);
30777c478bd9Sstevel@tonic-gate }
30787c478bd9Sstevel@tonic-gate
30797c478bd9Sstevel@tonic-gate /*
30807c478bd9Sstevel@tonic-gate * Breakdown our FMA resources
30817c478bd9Sstevel@tonic-gate */
30827c478bd9Sstevel@tonic-gate static void
db_fm_fini(db_ctrl_t * db_p)30837c478bd9Sstevel@tonic-gate db_fm_fini(db_ctrl_t *db_p)
30847c478bd9Sstevel@tonic-gate {
30857c478bd9Sstevel@tonic-gate /*
30867c478bd9Sstevel@tonic-gate * Clean up allocated fm structures
30877c478bd9Sstevel@tonic-gate */
30887c478bd9Sstevel@tonic-gate ddi_fm_handler_unregister(db_p->dip);
30897c478bd9Sstevel@tonic-gate pci_ereport_teardown(db_p->dip);
30907c478bd9Sstevel@tonic-gate ddi_fm_fini(db_p->dip);
30917c478bd9Sstevel@tonic-gate }
30927c478bd9Sstevel@tonic-gate
30937c478bd9Sstevel@tonic-gate /*
30947c478bd9Sstevel@tonic-gate * Initialize FMA resources for children devices. Called when
30957c478bd9Sstevel@tonic-gate * child calls ddi_fm_init().
30967c478bd9Sstevel@tonic-gate */
30977c478bd9Sstevel@tonic-gate /*ARGSUSED*/
30987c478bd9Sstevel@tonic-gate static int
db_fm_init_child(dev_info_t * dip,dev_info_t * tdip,int cap,ddi_iblock_cookie_t * ibc)30997c478bd9Sstevel@tonic-gate db_fm_init_child(dev_info_t *dip, dev_info_t *tdip, int cap,
31007c478bd9Sstevel@tonic-gate ddi_iblock_cookie_t *ibc)
31017c478bd9Sstevel@tonic-gate {
31027c478bd9Sstevel@tonic-gate db_ctrl_t *db_p = (db_ctrl_t *)ddi_get_soft_state(db_state,
31037c478bd9Sstevel@tonic-gate ddi_get_instance(dip));
31047c478bd9Sstevel@tonic-gate *ibc = db_p->fm_ibc;
31057c478bd9Sstevel@tonic-gate return (db_p->fm_cap);
31067c478bd9Sstevel@tonic-gate }
31077c478bd9Sstevel@tonic-gate
31087c478bd9Sstevel@tonic-gate /*
31097c478bd9Sstevel@tonic-gate * FMA registered error callback
31107c478bd9Sstevel@tonic-gate */
31117c478bd9Sstevel@tonic-gate static int
db_err_callback(dev_info_t * dip,ddi_fm_error_t * derr,const void * impl_data)31127c478bd9Sstevel@tonic-gate db_err_callback(dev_info_t *dip, ddi_fm_error_t *derr, const void *impl_data)
31137c478bd9Sstevel@tonic-gate {
31147c478bd9Sstevel@tonic-gate ASSERT(impl_data == NULL);
311500d0963fSdilpreet pci_ereport_post(dip, derr, NULL);
311600d0963fSdilpreet return (derr->fme_status);
31177c478bd9Sstevel@tonic-gate }
31187c478bd9Sstevel@tonic-gate
31197c478bd9Sstevel@tonic-gate static void
db_bus_enter(dev_info_t * dip,ddi_acc_handle_t handle)31207c478bd9Sstevel@tonic-gate db_bus_enter(dev_info_t *dip, ddi_acc_handle_t handle)
31217c478bd9Sstevel@tonic-gate {
31227c478bd9Sstevel@tonic-gate i_ndi_busop_access_enter(dip, handle);
31237c478bd9Sstevel@tonic-gate }
31247c478bd9Sstevel@tonic-gate
31257c478bd9Sstevel@tonic-gate /* ARGSUSED */
31267c478bd9Sstevel@tonic-gate static void
db_bus_exit(dev_info_t * dip,ddi_acc_handle_t handle)31277c478bd9Sstevel@tonic-gate db_bus_exit(dev_info_t *dip, ddi_acc_handle_t handle)
31287c478bd9Sstevel@tonic-gate {
31297c478bd9Sstevel@tonic-gate i_ndi_busop_access_exit(dip, handle);
31307c478bd9Sstevel@tonic-gate }
3131