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