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