xref: /titanic_51/usr/src/uts/common/io/cardbus/cardbus_cfg.c (revision 11c2b4c0e543fe2e1e5910cde1f4422cc3218160)
13db86aabSstevel /*
23db86aabSstevel  * CDDL HEADER START
33db86aabSstevel  *
43db86aabSstevel  * The contents of this file are subject to the terms of the
53db86aabSstevel  * Common Development and Distribution License (the "License").
63db86aabSstevel  * You may not use this file except in compliance with the License.
73db86aabSstevel  *
83db86aabSstevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93db86aabSstevel  * or http://www.opensolaris.org/os/licensing.
103db86aabSstevel  * See the License for the specific language governing permissions
113db86aabSstevel  * and limitations under the License.
123db86aabSstevel  *
133db86aabSstevel  * When distributing Covered Code, include this CDDL HEADER in each
143db86aabSstevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153db86aabSstevel  * If applicable, add the following below this CDDL HEADER, with the
163db86aabSstevel  * fields enclosed by brackets "[]" replaced with your own identifying
173db86aabSstevel  * information: Portions Copyright [yyyy] [name of copyright owner]
183db86aabSstevel  *
193db86aabSstevel  * CDDL HEADER END
203db86aabSstevel  */
213db86aabSstevel /*
22*11c2b4c0Srw148561  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
233db86aabSstevel  * Use is subject to license terms.
243db86aabSstevel  */
253db86aabSstevel /*
263db86aabSstevel  * Copyright (c)  * Copyright (c) 2001 Tadpole Technology plc
273db86aabSstevel  * All rights reserved.
283db86aabSstevel  * From "@(#)pcicfg.c   1.31    99/06/18 SMI"
293db86aabSstevel  */
303db86aabSstevel 
313db86aabSstevel #pragma ident	"%Z%%M%	%I%	%E% SMI"
323db86aabSstevel 
333db86aabSstevel /*
343db86aabSstevel  * Cardbus configurator
353db86aabSstevel  */
363db86aabSstevel 
373db86aabSstevel #include <sys/ddi.h>
383db86aabSstevel #include <sys/sunndi.h>
393db86aabSstevel #include <sys/ndi_impldefs.h>
403db86aabSstevel 
413db86aabSstevel #include <sys/pci.h>
423db86aabSstevel #include <sys/ebus.h>
433db86aabSstevel #include <sys/hotplug/hpctrl.h>
443db86aabSstevel #include <sys/hotplug/pci/pcicfg.h>
453db86aabSstevel 
463db86aabSstevel #include <sys/pctypes.h>
473db86aabSstevel #include <sys/pcmcia.h>
488134ee03Srw148561 #include <sys/sservice.h>
493db86aabSstevel 
503db86aabSstevel #include <sys/isa_defs.h>
513db86aabSstevel 
523db86aabSstevel #include <sys/note.h>
533db86aabSstevel 
543db86aabSstevel #include <sys/ethernet.h>
553db86aabSstevel 
563db86aabSstevel #include "cardbus.h"
573db86aabSstevel #include "cardbus_parse.h"
583db86aabSstevel #include "cardbus_cfg.h"
593db86aabSstevel 
603db86aabSstevel /*
613db86aabSstevel  * ************************************************************************
623db86aabSstevel  * *** Implementation specific local data structures/definitions.       ***
633db86aabSstevel  * ************************************************************************
643db86aabSstevel  */
653db86aabSstevel 
663db86aabSstevel #define	PCICFG_MAX_DEVICE 32
673db86aabSstevel #define	PCICFG_MAX_FUNCTION 8
683db86aabSstevel 
693db86aabSstevel static uint32_t pcicfg_max_device = PCICFG_MAX_DEVICE;
703db86aabSstevel static uint32_t pcicfg_max_function = PCICFG_MAX_FUNCTION;
713db86aabSstevel 
723db86aabSstevel #define	PCICFG_NODEVICE 42
733db86aabSstevel #define	PCICFG_NOMEMORY 43
743db86aabSstevel #define	PCICFG_NOMULTI  44
753db86aabSstevel 
763db86aabSstevel #define	PCICFG_HIADDR(n) ((uint32_t)(((uint64_t)(n) & 0xFFFFFFFF00000000)>> 32))
773db86aabSstevel #define	PCICFG_LOADDR(n) ((uint32_t)((uint64_t)(n) & 0x00000000FFFFFFFF))
783db86aabSstevel #define	PCICFG_LADDR(lo, hi)    (((uint64_t)(hi) << 32) | (uint32_t)(lo))
793db86aabSstevel 
803db86aabSstevel #define	PCICFG_HIWORD(n) ((uint16_t)(((uint32_t)(n) & 0xFFFF0000)>> 16))
813db86aabSstevel #define	PCICFG_LOWORD(n) ((uint16_t)((uint32_t)(n) & 0x0000FFFF))
823db86aabSstevel #define	PCICFG_HIBYTE(n) ((uint8_t)(((uint16_t)(n) & 0xFF00)>> 8))
833db86aabSstevel #define	PCICFG_LOBYTE(n) ((uint8_t)((uint16_t)(n) & 0x00FF))
843db86aabSstevel 
853db86aabSstevel #define	PCICFG_ROUND_UP(addr, gran) ((uintptr_t)((gran+addr-1)&(~(gran-1))))
863db86aabSstevel #define	PCICFG_ROUND_DOWN(addr, gran) ((uintptr_t)((addr) & ~(gran-1)))
873db86aabSstevel 
883db86aabSstevel #define	PCICFG_MEMGRAN 0x100000
893db86aabSstevel #define	PCICFG_IOGRAN 0x1000
903db86aabSstevel #define	PCICFG_4GIG_LIMIT 0xFFFFFFFFUL
913db86aabSstevel #define	CBCFG_MEMGRAN 0x1000
923db86aabSstevel #define	CBCFG_IOGRAN 0x4
933db86aabSstevel 
943db86aabSstevel #define	PCICFG_MEM_MULT 4
953db86aabSstevel #define	PCICFG_IO_MULT 4
963db86aabSstevel #define	PCICFG_RANGE_LEN 2 /* Number of range entries */
973db86aabSstevel 
983db86aabSstevel /*
993db86aabSstevel  * ISA node declaration structure.
1003db86aabSstevel  */
1013db86aabSstevel struct isa_node {
1023db86aabSstevel 	char	*name;
1033db86aabSstevel 	char	*compatible[5];
1043db86aabSstevel 	char	*type;
1053db86aabSstevel 	char	*model;
1063db86aabSstevel 	uint16_t	reg;
1073db86aabSstevel 	uint16_t	span;
1083db86aabSstevel };
1093db86aabSstevel 
1103db86aabSstevel struct cardbus_name_entry {
1113db86aabSstevel 	uint32_t class_code;
1123db86aabSstevel 	char  *name;
1133db86aabSstevel 	int pil;
1143db86aabSstevel };
1153db86aabSstevel 
1163db86aabSstevel struct cardbus_find_ctrl {
1173db86aabSstevel 	uint_t		bus;
1183db86aabSstevel 	uint_t		device;
1193db86aabSstevel 	uint_t		function;
1203db86aabSstevel 	dev_info_t	*dip;
1213db86aabSstevel };
1223db86aabSstevel 
1233db86aabSstevel #define	PCICFG_MAKE_REG_HIGH(busnum, devnum, funcnum, register)\
1243db86aabSstevel 	(\
1253db86aabSstevel 	((ulong_t)(busnum & 0xff) << 16)    |\
1263db86aabSstevel 	((ulong_t)(devnum & 0x1f) << 11)    |\
1273db86aabSstevel 	((ulong_t)(funcnum & 0x7) <<  8)    |\
1283db86aabSstevel 	((ulong_t)(register & 0x3f)))
1293db86aabSstevel 
1303db86aabSstevel typedef struct cardbus_phdl cardbus_phdl_t;
1313db86aabSstevel 
1323db86aabSstevel struct cardbus_phdl {
1333db86aabSstevel 
1343db86aabSstevel 	dev_info_t	*dip;	/* Associated with the attach point */
1358134ee03Srw148561 	dev_info_t	*res_dip; /* dip from which io/mem is allocated */
1363db86aabSstevel 	cardbus_phdl_t  *next;
1373db86aabSstevel 
1383db86aabSstevel 	uint64_t	memory_base;    /* Memory base for this attach point */
1393db86aabSstevel 	uint64_t	memory_last;
1403db86aabSstevel 	uint64_t	memory_len;
1413db86aabSstevel 	uint32_t	memory_gran;
1423db86aabSstevel 	uint32_t	io_base;	/* I/O base for this attach point */
1433db86aabSstevel 	uint32_t	io_last;
1443db86aabSstevel 	uint32_t	io_len;
1453db86aabSstevel 	uint32_t	io_gran;
1463db86aabSstevel 
1473db86aabSstevel 	int	error;
1483db86aabSstevel 	uint_t	highest_bus;    /* Highest bus seen on the probe */
1493db86aabSstevel 	ndi_ra_request_t mem_req;	/* allocator request for memory */
1503db86aabSstevel 	ndi_ra_request_t io_req;	/* allocator request for I/O */
1513db86aabSstevel };
1523db86aabSstevel 
1533db86aabSstevel typedef struct {
1543db86aabSstevel 	dev_info_t  *dip;	/* Associated with the attach point */
1553db86aabSstevel 	ddi_acc_handle_t handle;    /* open handle on parent PCI config space */
1563db86aabSstevel 	uint32_t    io_base;	/* I/O base for this attach point */
1573db86aabSstevel 	int	io_decode_reg;
1583db86aabSstevel } isa_phdl_t;
1593db86aabSstevel 
1603db86aabSstevel 
1613db86aabSstevel /*
1623db86aabSstevel  * forward declarations for routines defined in this module (called here)
1633db86aabSstevel  */
1643db86aabSstevel static cardbus_phdl_t *cardbus_find_phdl(dev_info_t *dip);
1653db86aabSstevel static cardbus_phdl_t *cardbus_create_phdl(dev_info_t *dip);
1663db86aabSstevel static int cardbus_destroy_phdl(dev_info_t *dip);
1673db86aabSstevel static int cardbus_program_ap(dev_info_t *);
1683db86aabSstevel static void cardbus_topbridge_assign(dev_info_t *, cardbus_phdl_t *);
1693db86aabSstevel static int cardbus_bridge_ranges(dev_info_t *, cardbus_phdl_t *,
1703db86aabSstevel 			ddi_acc_handle_t);
1713db86aabSstevel static int cardbus_bridge_assign(dev_info_t *, void *);
1723db86aabSstevel static int cardbus_isa_bridge_ranges(dev_info_t *dip, cardbus_phdl_t *entry,
1733db86aabSstevel 			ddi_acc_handle_t handle);
1743db86aabSstevel static int cardbus_add_isa_reg(dev_info_t *, void *);
1753db86aabSstevel static int cardbus_allocate_chunk(dev_info_t *, uint8_t, uint8_t);
1763db86aabSstevel static int cardbus_free_chunk(dev_info_t *);
1773db86aabSstevel static void cardbus_setup_bridge(dev_info_t *, cardbus_phdl_t *,
1783db86aabSstevel 			ddi_acc_handle_t);
1793db86aabSstevel static void cardbus_update_bridge(dev_info_t *, cardbus_phdl_t *,
1803db86aabSstevel 			ddi_acc_handle_t);
1813db86aabSstevel static void cardbus_get_mem(dev_info_t *, cardbus_phdl_t *, uint32_t,
1823db86aabSstevel 			uint64_t *);
1833db86aabSstevel static void cardbus_get_io(dev_info_t *, cardbus_phdl_t *, uint32_t,
1843db86aabSstevel 			uint32_t *);
1853db86aabSstevel static int cardbus_sum_resources(dev_info_t *, void *);
1863db86aabSstevel static int cardbus_free_bridge_resources(dev_info_t *);
1873db86aabSstevel static int cardbus_free_device_resources(dev_info_t *);
1883db86aabSstevel static int cardbus_free_resources(dev_info_t *);
1893db86aabSstevel static int cardbus_probe_bridge(cbus_t *, dev_info_t *, uint_t,
1903db86aabSstevel 			uint_t, uint_t);
1913db86aabSstevel static int cardbus_probe_children(cbus_t *, dev_info_t *, uint_t, uint_t,
1923db86aabSstevel 			uint_t, uint8_t *);
1933db86aabSstevel static int cardbus_add_config_reg(dev_info_t *, uint_t, uint_t, uint_t);
1943db86aabSstevel static int cardbus_add_isa_node(cbus_t *, dev_info_t *, struct isa_node *);
1953db86aabSstevel static int cardbus_config_setup(dev_info_t *, ddi_acc_handle_t *);
1963db86aabSstevel static void cardbus_config_teardown(ddi_acc_handle_t *);
1973db86aabSstevel static void cardbus_reparent_children(dev_info_t *, dev_info_t *);
1983db86aabSstevel static int cardbus_update_assigned_prop(dev_info_t *, pci_regspec_t *);
1993db86aabSstevel static int cardbus_update_available_prop(dev_info_t *, uint32_t,
2003db86aabSstevel 			uint64_t, uint64_t);
2013db86aabSstevel static int cardbus_update_ranges_prop(dev_info_t *, cardbus_range_t *);
2023db86aabSstevel static int cardbus_update_reg_prop(dev_info_t *dip, uint32_t regvalue,
2033db86aabSstevel 			uint_t reg_offset);
2043db86aabSstevel static int cardbus_set_standard_props(dev_info_t *parent, dev_info_t *dip,
2053db86aabSstevel 			ddi_acc_handle_t config_handle);
2063db86aabSstevel static int cardbus_set_isa_props(dev_info_t *parent, dev_info_t *dip,
2073db86aabSstevel 			char *name, char *compat[]);
2083db86aabSstevel static int cardbus_set_busnode_props(dev_info_t *);
2093db86aabSstevel static int cardbus_set_busnode_isaprops(dev_info_t *);
2103db86aabSstevel static int cardbus_set_childnode_props(dev_info_t *dip,
2113db86aabSstevel 			ddi_acc_handle_t config_handle);
2123db86aabSstevel static void cardbus_set_bus_numbers(ddi_acc_handle_t config_handle,
2133db86aabSstevel 			uint_t primary, uint_t secondary);
2143db86aabSstevel static void enable_pci_isa_bridge(dev_info_t *dip,
2153db86aabSstevel 			ddi_acc_handle_t config_handle);
2163db86aabSstevel static void enable_pci_pci_bridge(dev_info_t *dip,
2173db86aabSstevel 			ddi_acc_handle_t config_handle);
2183db86aabSstevel static void enable_cardbus_bridge(dev_info_t *dip,
2193db86aabSstevel 			ddi_acc_handle_t config_handle);
2203db86aabSstevel static void disable_pci_pci_bridge(dev_info_t *dip,
2213db86aabSstevel 			ddi_acc_handle_t config_handle);
2223db86aabSstevel static void disable_cardbus_bridge(dev_info_t *dip,
2233db86aabSstevel 			ddi_acc_handle_t config_handle);
2243db86aabSstevel static void enable_cardbus_device(dev_info_t *, ddi_acc_handle_t);
2253db86aabSstevel static void disable_cardbus_device(ddi_acc_handle_t config_handle);
2263db86aabSstevel static void cardbus_force_boolprop(dev_info_t *dip, char *pname);
2273db86aabSstevel static void cardbus_force_intprop(dev_info_t *dip, char *pname,
2283db86aabSstevel 			int *pval, int len);
2293db86aabSstevel static void cardbus_force_stringprop(dev_info_t *dip, char *pname,
2303db86aabSstevel 			char *pval);
2313db86aabSstevel static void split_addr(char *, int *, int *);
2323db86aabSstevel #ifdef DEBUG
2333db86aabSstevel static void cardbus_dump_common_config(ddi_acc_handle_t config_handle);
2343db86aabSstevel static void cardbus_dump_device_config(ddi_acc_handle_t config_handle);
2353db86aabSstevel static void cardbus_dump_bridge_config(ddi_acc_handle_t config_handle,
2363db86aabSstevel 			uint8_t header_type);
2373db86aabSstevel static void cardbus_dump_config(ddi_acc_handle_t config_handle);
2383db86aabSstevel static void cardbus_dump_reg(dev_info_t *dip, const pci_regspec_t *regspec,
2393db86aabSstevel 			int nelems);
2403db86aabSstevel #endif
2413db86aabSstevel 
2423db86aabSstevel static cardbus_phdl_t *cardbus_phdl_list = NULL;
2433db86aabSstevel 
2443db86aabSstevel static struct cardbus_name_entry cardbus_class_lookup [] = {
2453db86aabSstevel 	{ 0x001, "display", 9 },
2463db86aabSstevel 	{ 0x100, "scsi", 4 },
2473db86aabSstevel 	{ 0x101, "ide", 4 },
2483db86aabSstevel 	{ 0x102, "fdc", 4 },
2493db86aabSstevel 	{ 0x103, "ipi", 4 },
2503db86aabSstevel 	{ 0x104, "raid", 4 },
2513db86aabSstevel 	{ 0x200, "ethernet", 6 },
2523db86aabSstevel 	{ 0x201, "token-ring", 6 },
2533db86aabSstevel 	{ 0x202, "fddi", 6 },
2543db86aabSstevel 	{ 0x203, "atm", 6 },
2553db86aabSstevel 	{ 0x300, "display", 9 },    /* VGA card */
2563db86aabSstevel 	{ 0x380, "display", 9 },    /* other - for the Raptor Card */
2573db86aabSstevel 	{ 0x400, "video", 11 },
2583db86aabSstevel 	{ 0x401, "sound", 11 },
2593db86aabSstevel 	{ 0x500, "memory", 11 },
2603db86aabSstevel 	{ 0x501, "flash", 11 },
2613db86aabSstevel 	{ 0x600, "host", 11 },
2623db86aabSstevel 	{ 0x601, "isa", 11 },
2633db86aabSstevel 	{ 0x602, "eisa", 11 },
2643db86aabSstevel 	{ 0x603, "mca", 11 },
2653db86aabSstevel 	{ 0x604, "pci", 11 },
2663db86aabSstevel 	{ 0x605, "pcmcia", 11 },
2673db86aabSstevel 	{ 0x606, "nubus", 11 },
2683db86aabSstevel 	{ 0x607, "cardbus", 11 },
2693db86aabSstevel 	{ 0x680, NULL, 8 },
2703db86aabSstevel 	{ 0x700, "serial", 11 },
2713db86aabSstevel 	{ 0x701, "parallel", 6 },
2723db86aabSstevel 	{ 0x800, "interrupt-controller", 3 },
2733db86aabSstevel 	{ 0x801, "dma-controller", 3 },
2743db86aabSstevel 	{ 0x802, "timer", 3 },
2753db86aabSstevel 	{ 0x803, "rtc", 3 },
2763db86aabSstevel 	{ 0x900, "keyboard", 8 },
2773db86aabSstevel 	{ 0x901, "pen", 8 },
2783db86aabSstevel 	{ 0x902, "mouse", 8 },
2793db86aabSstevel 	{ 0xa00, "dock", 1 },
2803db86aabSstevel 	{ 0xb00, "cpu", 1 },
2813db86aabSstevel 	{ 0xc00, "firewire", 9 },
2823db86aabSstevel 	{ 0xc01, "access-bus", 4 },
2833db86aabSstevel 	{ 0xc02, "ssa", 4 },
2843db86aabSstevel 	{ 0xc03, "usb", 9 },
2853db86aabSstevel 	{ 0xc04, "fibre-channel", 6 },
2863db86aabSstevel 	{ 0, 0 }
2873db86aabSstevel };
2883db86aabSstevel 
2893db86aabSstevel #ifndef _DONT_USE_1275_GENERIC_NAMES
2903db86aabSstevel static char *cardbus_get_class_name(uint32_t classcode);
2913db86aabSstevel #endif /* _DONT_USE_1275_GENERIC_NAMES */
2923db86aabSstevel 
2933db86aabSstevel /*
2943db86aabSstevel  * Reprogram ILINE with default value only if BIOS doesn't program it
2953db86aabSstevel  */
2963db86aabSstevel int
2973db86aabSstevel cardbus_validate_iline(dev_info_t *dip, ddi_acc_handle_t handle)
2983db86aabSstevel {
2993db86aabSstevel 	uint8_t intline = 0xff;
3003db86aabSstevel 
3013db86aabSstevel 	if (pci_config_get8(handle, PCI_CONF_IPIN)) {
3023db86aabSstevel 	intline = pci_config_get8(handle, PCI_CONF_ILINE);
3033db86aabSstevel 	if ((intline == 0) || (intline == 0xff)) {
3043db86aabSstevel 		intline = ddi_getprop(DDI_DEV_T_ANY, dip,
3053db86aabSstevel 			DDI_PROP_CANSLEEP|DDI_PROP_DONTPASS,
3063db86aabSstevel 			"interrupt-line", 0xff);
3073db86aabSstevel 		if (intline == (uint8_t)0xff) {
3083db86aabSstevel 			intline = ddi_getprop(DDI_DEV_T_ANY,
3093db86aabSstevel 				ddi_get_parent(dip),
3103db86aabSstevel 				DDI_PROP_CANSLEEP /* |DDI_PROP_DONTPASS */,
3113db86aabSstevel 				"interrupt-line", 0xb);
3123db86aabSstevel 		}
3133db86aabSstevel 
3143db86aabSstevel 		pci_config_put8(handle, PCI_CONF_ILINE, intline);
3153db86aabSstevel 	}
3163db86aabSstevel 	(void) ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3173db86aabSstevel 		"interrupt-line", intline);
3183db86aabSstevel 	}
3193db86aabSstevel 	return (intline);
3203db86aabSstevel }
3213db86aabSstevel 
3223db86aabSstevel /*
3233db86aabSstevel  * This entry point is called to configure a device (and
3243db86aabSstevel  * all its children) on the given bus. It is called when
3253db86aabSstevel  * a new device is added to the PCI domain.  This routine
3263db86aabSstevel  * will create the device tree and program the devices
3273db86aabSstevel  * registers.
3283db86aabSstevel  */
3293db86aabSstevel int
3303db86aabSstevel cardbus_configure(cbus_t *cbp)
3313db86aabSstevel {
3323db86aabSstevel 	uint_t bus;
3333db86aabSstevel 	int cardbus_dev, func;
3343db86aabSstevel 	dev_info_t *attach_point;
3353db86aabSstevel 
3363db86aabSstevel 	cardbus_err(cbp->cb_dip, 6, "cardbus_configure ()\n");
3373db86aabSstevel 
3383db86aabSstevel 	bus = cardbus_primary_busno(cbp->cb_dip);
3393db86aabSstevel 
3403db86aabSstevel 	if (ndi_devi_alloc(cbp->cb_dip, DEVI_PSEUDO_NEXNAME,
3413db86aabSstevel 	    (pnode_t)DEVI_SID_NODEID,
3423db86aabSstevel 	    &attach_point) != NDI_SUCCESS) {
3433db86aabSstevel 		cardbus_err(cbp->cb_dip, 1,
3443db86aabSstevel 		    "cardbus_configure(): Failed to alloc probe node\n");
3453db86aabSstevel 		return (PCICFG_FAILURE);
3463db86aabSstevel 	}
3473db86aabSstevel 
3483db86aabSstevel 	/*
3493db86aabSstevel 	 * Node name marks this node as the "attachment point".
3503db86aabSstevel 	 */
3513db86aabSstevel 	if (ndi_devi_set_nodename(attach_point,
3523db86aabSstevel 	    "hp_attachment", 0) != NDI_SUCCESS) {
3533db86aabSstevel 	    cardbus_err(cbp->cb_dip, 1,
3543db86aabSstevel 		    "Failed to set nodename for attachment node\n");
3553db86aabSstevel 		(void) ndi_devi_free(attach_point);
3563db86aabSstevel 		return (PCICFG_FAILURE);
3573db86aabSstevel 	}
3583db86aabSstevel 
3593db86aabSstevel 	cardbus_err(ddi_get_parent(attach_point), 8,
3603db86aabSstevel 	    "Set bus type to cardbus\n");
3613db86aabSstevel 	(void) ddi_prop_update_string(DDI_DEV_T_NONE,
3623db86aabSstevel 	    ddi_get_parent(attach_point), PCM_DEVICETYPE,
3633db86aabSstevel 	    "cardbus");
3643db86aabSstevel 
3653db86aabSstevel 	split_addr(ddi_get_name_addr(cbp->cb_dip), &cardbus_dev, &func);
3663db86aabSstevel 
3673db86aabSstevel 	cardbus_err(attach_point, 8,
3683db86aabSstevel 	    "Configuring [0x%x][0x%x][0x%x]\n", bus, cardbus_dev, func);
3693db86aabSstevel 
3703db86aabSstevel 	switch (cardbus_probe_bridge(cbp, attach_point,
3713db86aabSstevel 	    bus, cardbus_dev, func)) {
3723db86aabSstevel 	case PCICFG_FAILURE:
3733db86aabSstevel 		cardbus_err(cbp->cb_dip, 4,
3743db86aabSstevel 		    "configure failed: bus [0x%x] slot [0x%x] func [0x%x]\n",
3753db86aabSstevel 		    bus, cardbus_dev, func);
3763db86aabSstevel 		goto cleanup;
3773db86aabSstevel 	case PCICFG_NODEVICE:
3783db86aabSstevel 		cardbus_err(cbp->cb_dip, 4,
3793db86aabSstevel 		    "no device: bus [0x%x] slot [0x%x] func [0x%x]\n",
3803db86aabSstevel 		    bus, cardbus_dev, func);
3813db86aabSstevel 		goto cleanup;
3823db86aabSstevel 	default:
3833db86aabSstevel 		cardbus_err(cbp->cb_dip, 9,
3843db86aabSstevel 		    "configure: bus => [%d] slot => [%d] func => [%d]\n",
3853db86aabSstevel 		    bus, cardbus_dev, func);
3863db86aabSstevel 		break;
3873db86aabSstevel 	}
3883db86aabSstevel 
3893db86aabSstevel 	if (cardbus_program_ap(cbp->cb_dip) == PCICFG_SUCCESS) {
3903db86aabSstevel 		(void) cardbus_reparent_children(attach_point, cbp->cb_dip);
3913db86aabSstevel 		(void) ndi_devi_free(attach_point);
3923db86aabSstevel 		cbp->cb_nex_ops->enable_intr(cbp->cb_dip);
3933db86aabSstevel 		return (PCICFG_SUCCESS);
3943db86aabSstevel 	}
3953db86aabSstevel 
3963db86aabSstevel 	cardbus_err(cbp->cb_dip, 1, "Failed to program devices\n");
3973db86aabSstevel 
3983db86aabSstevel cleanup:
3993db86aabSstevel 	/*
4003db86aabSstevel 	 * Clean up a partially created "probe state" tree.
4013db86aabSstevel 	 * There are no resources allocated to the in the
4023db86aabSstevel 	 * probe state.
4033db86aabSstevel 	 */
4043db86aabSstevel 
4053db86aabSstevel 	cardbus_err(cbp->cb_dip, 6,
4063db86aabSstevel 	    "Look up device [0x%x] function [0x%x] to clean up\n",
4073db86aabSstevel 	    cardbus_dev, func);
4083db86aabSstevel 
4093db86aabSstevel 	cardbus_err(cbp->cb_dip, 6,
4103db86aabSstevel 	    "Cleaning up device [0x%x] function [0x%x]\n",
4113db86aabSstevel 	    cardbus_dev, func);
4123db86aabSstevel 
4133db86aabSstevel 	/*
4143db86aabSstevel 	 * If this was a bridge device it will have a
4153db86aabSstevel 	 * probe handle - if not, no harm in calling this.
4163db86aabSstevel 	 */
4173db86aabSstevel 	(void) cardbus_destroy_phdl(cbp->cb_dip);
4183db86aabSstevel 
4193db86aabSstevel 	if (ddi_get_child(attach_point)) {
4203db86aabSstevel 		/*
4213db86aabSstevel 		 * This will free up the node
4223db86aabSstevel 		 */
4233db86aabSstevel 		(void) ndi_devi_offline(ddi_get_child(attach_point),
4243db86aabSstevel 		    NDI_UNCONFIG|NDI_DEVI_REMOVE);
4253db86aabSstevel 	}
4263db86aabSstevel 	(void) ndi_devi_free(attach_point);
4273db86aabSstevel 
4283db86aabSstevel 	return (PCICFG_FAILURE);
4293db86aabSstevel }
4303db86aabSstevel 
4313db86aabSstevel int
4323db86aabSstevel cardbus_unconfigure(cbus_t *cbp)
4333db86aabSstevel {
4343db86aabSstevel 	ddi_acc_handle_t config_handle;
4353db86aabSstevel 	dev_info_t *dip = cbp->cb_dip;
4363db86aabSstevel 
4373db86aabSstevel 	cbp->cb_nex_ops->disable_intr(dip);
4383db86aabSstevel 	if (pci_config_setup(dip, &config_handle) == DDI_SUCCESS) {
4393db86aabSstevel 		disable_cardbus_bridge(dip, config_handle);
4403db86aabSstevel 		(void) pci_config_teardown(&config_handle);
4413db86aabSstevel 	} else {
4423db86aabSstevel 		cardbus_err(dip, 1,
4433db86aabSstevel 		    "cardbus_unconfigure(): Failed to setup config space\n");
4443db86aabSstevel 	}
4453db86aabSstevel 
4463db86aabSstevel 	(void) cardbus_free_chunk(dip);
4473db86aabSstevel 	cardbus_err(dip, 6,
4483db86aabSstevel 	    "cardbus_unconfigure: calling cardbus_free_bridge_resources\n");
4493db86aabSstevel 	(void) cardbus_free_bridge_resources(dip);
4503db86aabSstevel 
4513db86aabSstevel 	return (PCICFG_SUCCESS);
4523db86aabSstevel }
4533db86aabSstevel 
4543db86aabSstevel int
4553db86aabSstevel cardbus_teardown_device(dev_info_t *dip)
4563db86aabSstevel {
4573db86aabSstevel 	/*
4583db86aabSstevel 	 * Free up resources associated with 'dip'
4593db86aabSstevel 	 */
4603db86aabSstevel 
4613db86aabSstevel 	if (cardbus_free_resources(dip) != PCICFG_SUCCESS) {
4623db86aabSstevel 		cardbus_err(dip, 1,
4633db86aabSstevel 		    "cardbus_teardown_device: Failed to free resources\n");
4643db86aabSstevel 		return (PCICFG_FAILURE);
4653db86aabSstevel 	}
4663db86aabSstevel 
4673db86aabSstevel 	if (ndi_devi_offline(dip, NDI_DEVI_REMOVE) != NDI_SUCCESS) {
4683db86aabSstevel 		cardbus_err(dip, 1,
4693db86aabSstevel 		    "cardbus_teardown_device: "
4703db86aabSstevel 		    "Failed to offline and remove node\n");
4713db86aabSstevel 		return (PCICFG_FAILURE);
4723db86aabSstevel 	}
4733db86aabSstevel 
4743db86aabSstevel 	return (PCICFG_SUCCESS);
4753db86aabSstevel }
4763db86aabSstevel 
4773db86aabSstevel /*
4783db86aabSstevel  * Get the primary pci bus number. This should be the lowest number
4793db86aabSstevel  * in the bus-range property of our parent.
4803db86aabSstevel  */
4813db86aabSstevel int
4823db86aabSstevel cardbus_primary_busno(dev_info_t *dip)
4833db86aabSstevel {
4843db86aabSstevel 	int	len, rval;
4853db86aabSstevel 	char	bus_type[16] = "(unknown)";
4863db86aabSstevel 	dev_info_t *par = ddi_get_parent(dip);
4873db86aabSstevel 	cardbus_bus_range_t *bus_range;
4883db86aabSstevel 
4893db86aabSstevel 	ASSERT(strcmp(ddi_driver_name(dip), "pcic") == 0);
4903db86aabSstevel 	len = sizeof (bus_type);
4913db86aabSstevel 	if ((ddi_prop_op(DDI_DEV_T_ANY, par, PROP_LEN_AND_VAL_BUF,
4923db86aabSstevel 	    DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS,
4933db86aabSstevel 	    "device_type",
4943db86aabSstevel 	    (caddr_t)&bus_type, &len) == DDI_SUCCESS)) {
4953db86aabSstevel 		ASSERT((strcmp(bus_type, "pci") == 0) ||
4963db86aabSstevel 		    (strcmp(bus_type, "cardbus") == 0));
4973db86aabSstevel 		if (ddi_getlongprop(DDI_DEV_T_ANY, par, 0, "bus-range",
4983db86aabSstevel 		    (caddr_t)&bus_range, &len) == DDI_PROP_SUCCESS) {
4993db86aabSstevel 			cardbus_err(dip, 9,
5003db86aabSstevel 			    "cardbus_primary_busno: bus range is %d to %d\n",
5013db86aabSstevel 			    bus_range->lo, bus_range->hi);
5023db86aabSstevel 			rval = (int)bus_range->lo;
5033db86aabSstevel 			kmem_free((caddr_t)bus_range, len);
5043db86aabSstevel 			return (rval);
5053db86aabSstevel 		}
5063db86aabSstevel 	}
5073db86aabSstevel 
5083db86aabSstevel 	cardbus_err(dip, 2,
5093db86aabSstevel 	    "cardbus_primary_busno: Not a pci device or no bus-range\n");
5103db86aabSstevel 	return (-1);
5113db86aabSstevel }
5123db86aabSstevel 
5133db86aabSstevel static cardbus_phdl_t *
5143db86aabSstevel cardbus_find_phdl(dev_info_t *dip)
5153db86aabSstevel {
5163db86aabSstevel 	cardbus_phdl_t *entry;
5173db86aabSstevel 
5183db86aabSstevel 	mutex_enter(&cardbus_list_mutex);
5193db86aabSstevel 	for (entry = cardbus_phdl_list; entry != NULL; entry = entry->next) {
5203db86aabSstevel 		if (entry->dip == dip) {
5213db86aabSstevel 			mutex_exit(&cardbus_list_mutex);
5223db86aabSstevel 			return (entry);
5233db86aabSstevel 		}
5243db86aabSstevel 	}
5253db86aabSstevel 	mutex_exit(&cardbus_list_mutex);
5263db86aabSstevel 
5273db86aabSstevel 	/*
5283db86aabSstevel 	 * Did'nt find entry - create one
5293db86aabSstevel 	 */
5303db86aabSstevel 	return (cardbus_create_phdl(dip));
5313db86aabSstevel }
5323db86aabSstevel 
5333db86aabSstevel static cardbus_phdl_t *
5343db86aabSstevel cardbus_create_phdl(dev_info_t *dip)
5353db86aabSstevel {
5363db86aabSstevel 	cardbus_phdl_t *new;
5373db86aabSstevel 
5383db86aabSstevel 	new = (cardbus_phdl_t *)kmem_zalloc(sizeof (cardbus_phdl_t), KM_SLEEP);
5393db86aabSstevel 
5403db86aabSstevel 	new->dip = dip;
5413db86aabSstevel 	new->io_gran = CBCFG_IOGRAN;
5423db86aabSstevel 	new->memory_gran = CBCFG_MEMGRAN;
5433db86aabSstevel 	mutex_enter(&cardbus_list_mutex);
5443db86aabSstevel 	new->next = cardbus_phdl_list;
5453db86aabSstevel 	cardbus_phdl_list = new;
5463db86aabSstevel 	mutex_exit(&cardbus_list_mutex);
5473db86aabSstevel 
5483db86aabSstevel 	return (new);
5493db86aabSstevel }
5503db86aabSstevel 
5513db86aabSstevel static int
5523db86aabSstevel cardbus_destroy_phdl(dev_info_t *dip)
5533db86aabSstevel {
5543db86aabSstevel 	cardbus_phdl_t *entry;
5553db86aabSstevel 	cardbus_phdl_t *follow = NULL;
5568134ee03Srw148561 	ra_return_t	res;
5573db86aabSstevel 
5583db86aabSstevel 	mutex_enter(&cardbus_list_mutex);
5593db86aabSstevel 	for (entry = cardbus_phdl_list; entry != NULL; follow = entry,
5603db86aabSstevel 	    entry = entry->next) {
5613db86aabSstevel 		if (entry->dip == dip) {
5623db86aabSstevel 			if (entry == cardbus_phdl_list) {
5633db86aabSstevel 				cardbus_phdl_list = entry->next;
5643db86aabSstevel 			} else {
5653db86aabSstevel 				follow->next = entry->next;
5663db86aabSstevel 			}
5673db86aabSstevel 			/*
5683db86aabSstevel 			 * If this entry has any allocated memory
5693db86aabSstevel 			 * or IO space associated with it, that
5703db86aabSstevel 			 * must be freed up.
5713db86aabSstevel 			 */
5723db86aabSstevel 			if (entry->memory_len > 0) {
5738134ee03Srw148561 				res.ra_addr_lo = entry->memory_base;
5748134ee03Srw148561 				res.ra_len = entry->memory_len;
5758134ee03Srw148561 				(void) pcmcia_free_mem(entry->res_dip, &res);
5763db86aabSstevel #ifdef  _LP64
5773db86aabSstevel 				cardbus_err(dip, 8,
5783db86aabSstevel 				    "cardbus_destroy_phdl: "
5793db86aabSstevel 				    "MEMORY BASE = [0x%lx] length [0x%lx]\n",
5803db86aabSstevel 				    entry->memory_base, entry->memory_len);
5813db86aabSstevel #else
5823db86aabSstevel 				cardbus_err(dip, 8,
5833db86aabSstevel 				    "cardbus_destroy_phdl: "
5843db86aabSstevel 				    "MEMORY BASE = [0x%llx] length [0x%llx]\n",
5853db86aabSstevel 				    entry->memory_base, entry->memory_len);
5863db86aabSstevel #endif
5873db86aabSstevel 			}
5883db86aabSstevel 			if (entry->io_len > 0) {
5898134ee03Srw148561 				res.ra_addr_lo = entry->io_base;
5908134ee03Srw148561 				res.ra_len = entry->io_len;
5918134ee03Srw148561 				(void) pcmcia_free_io(entry->res_dip, &res);
5923db86aabSstevel 				cardbus_err(dip, 8,
5933db86aabSstevel 				    "cardbus_destroy_phdl: "
5943db86aabSstevel 				    "IO BASE = [0x%x] length [0x%x]\n",
5953db86aabSstevel 				    entry->io_base, entry->io_len);
5963db86aabSstevel 			}
5973db86aabSstevel 			/*
5983db86aabSstevel 			 * Destroy this entry
5993db86aabSstevel 			 */
6003db86aabSstevel 			kmem_free((caddr_t)entry, sizeof (cardbus_phdl_t));
6013db86aabSstevel 			mutex_exit(&cardbus_list_mutex);
6023db86aabSstevel 			return (PCICFG_SUCCESS);
6033db86aabSstevel 		}
6043db86aabSstevel 	}
6053db86aabSstevel 
6063db86aabSstevel 	mutex_exit(&cardbus_list_mutex);
6073db86aabSstevel 
6083db86aabSstevel 	/*
6093db86aabSstevel 	 * Didn't find the entry
6103db86aabSstevel 	 */
6113db86aabSstevel 	return (PCICFG_FAILURE);
6123db86aabSstevel }
6133db86aabSstevel 
6143db86aabSstevel static int
6153db86aabSstevel cardbus_program_ap(dev_info_t *dip)
6163db86aabSstevel {
6173db86aabSstevel 	cardbus_phdl_t *phdl;
6183db86aabSstevel 	uint8_t header_type, sec_bus;
6193db86aabSstevel 	ddi_acc_handle_t handle;
6203db86aabSstevel 
6213db86aabSstevel 	if (pci_config_setup(dip, &handle) != DDI_SUCCESS) {
6223db86aabSstevel 		cardbus_err(dip, 1,
6233db86aabSstevel 		    "cardbus_program_ap: Failed to map config space!\n");
6243db86aabSstevel 		return (PCICFG_FAILURE);
6253db86aabSstevel 	}
6263db86aabSstevel 
6273db86aabSstevel 	header_type = pci_config_get8(handle, PCI_CONF_HEADER);
6283db86aabSstevel 	sec_bus = pci_config_get8(handle, PCI_BCNF_SECBUS);
6293db86aabSstevel 
6303db86aabSstevel 	cardbus_err(dip, 6,
6313db86aabSstevel 	    "cardbus_program_ap (header_type=0x%x)\n", header_type);
6323db86aabSstevel 	(void) pci_config_teardown(&handle);
6333db86aabSstevel 
6343db86aabSstevel 	/*
6353db86aabSstevel 	 * Header type two is PCI to Cardbus bridge, see page 43 of the
6363db86aabSstevel 	 * CL-PD6832 data sheet
6373db86aabSstevel 	 */
6383db86aabSstevel 	switch (header_type & PCI_HEADER_TYPE_M) {
6393db86aabSstevel 	case PCI_HEADER_CARDBUS:
6403db86aabSstevel 		cardbus_err(dip, 8,
6413db86aabSstevel 		    "cardbus_program_ap calling cardbus_allocate_chunk\n");
6423db86aabSstevel 		if (cardbus_allocate_chunk(dip,
6433db86aabSstevel 		    header_type & PCI_HEADER_TYPE_M,
6443db86aabSstevel 		    sec_bus) != PCICFG_SUCCESS) {
6453db86aabSstevel 			cardbus_err(dip, 1,
6463db86aabSstevel 			    "cardbus_program_ap: "
6473db86aabSstevel 			    "Not enough memory to hotplug\n");
6483db86aabSstevel 			(void) cardbus_destroy_phdl(dip);
6493db86aabSstevel 			return (PCICFG_FAILURE);
6503db86aabSstevel 		}
6513db86aabSstevel 
6523db86aabSstevel 		cardbus_err(dip, 8,
6533db86aabSstevel 		    "cardbus_program_ap calling cardbus_find_phdl\n");
6543db86aabSstevel 		phdl = cardbus_find_phdl(dip);
6553db86aabSstevel 		ASSERT(phdl);
6563db86aabSstevel 
6573db86aabSstevel 		if (phdl == NULL) {
6583db86aabSstevel 			cardbus_err(dip, 1, "cardbus_find_phdl failed\n");
6593db86aabSstevel 			return (PCICFG_FAILURE);
6603db86aabSstevel 		}
6613db86aabSstevel 		phdl->error = PCICFG_SUCCESS;
6623db86aabSstevel 		cardbus_err(dip, 8,
6633db86aabSstevel 		    "cardbus_program_ap calling cardbus_topbridge_assign\n");
6643db86aabSstevel 		cardbus_topbridge_assign(dip, phdl);
6653db86aabSstevel 
6663db86aabSstevel 		if (phdl->error != PCICFG_SUCCESS) {
6673db86aabSstevel 			cardbus_err(dip, 1, "Problem assigning bridge\n");
6683db86aabSstevel 			(void) cardbus_destroy_phdl(dip);
6693db86aabSstevel 			return (phdl->error);
6703db86aabSstevel 		}
6713db86aabSstevel 		break;
6723db86aabSstevel 
6733db86aabSstevel 	default:
6743db86aabSstevel 		return (PCICFG_FAILURE);
6753db86aabSstevel 	}
6763db86aabSstevel 
6773db86aabSstevel 	return (PCICFG_SUCCESS);
6783db86aabSstevel }
6793db86aabSstevel 
6803db86aabSstevel static void
6813db86aabSstevel cardbus_topbridge_assign(dev_info_t *dip, cardbus_phdl_t *entry)
6823db86aabSstevel {
6833db86aabSstevel 	ddi_acc_handle_t handle;
6843db86aabSstevel 	uint8_t header_type;
6853db86aabSstevel 
6863db86aabSstevel 	cardbus_err(dip, 6, "cardbus_topbridge_assign\n");
6873db86aabSstevel 
6883db86aabSstevel 	if (pci_config_setup(dip, &handle) != DDI_SUCCESS) {
6893db86aabSstevel 		cardbus_err(dip, 1,
6903db86aabSstevel 		    "cardbus_topbridge_bridge_assign: "
6913db86aabSstevel 		    "Failed to map config space!\n");
6923db86aabSstevel 		return;
6933db86aabSstevel 	}
6943db86aabSstevel 
6953db86aabSstevel 	header_type = pci_config_get8(handle,
6963db86aabSstevel 	    PCI_CONF_HEADER) & PCI_HEADER_TYPE_M;
6973db86aabSstevel 
6983db86aabSstevel 	/* cardbus bridge is the same as PCI-PCI bridge */
6993db86aabSstevel 	ASSERT((header_type == PCI_HEADER_PPB) ||
7003db86aabSstevel 	    (header_type == PCI_HEADER_CARDBUS));
7013db86aabSstevel 
7023db86aabSstevel 	(void) cardbus_bridge_ranges(dip, entry, handle);
7033db86aabSstevel 
7043db86aabSstevel 	(void) pci_config_teardown(&handle);
7053db86aabSstevel }
7063db86aabSstevel 
7073db86aabSstevel static int
7083db86aabSstevel cardbus_bridge_ranges(dev_info_t *dip, cardbus_phdl_t *entry,
7093db86aabSstevel 			ddi_acc_handle_t handle)
7103db86aabSstevel {
7113db86aabSstevel 	cardbus_range_t range[PCICFG_RANGE_LEN];
7123db86aabSstevel 	int bus_range[2];
7133db86aabSstevel 	int count;
7143db86aabSstevel 	int i;
7153db86aabSstevel 
7163db86aabSstevel 	cardbus_err(dip, 8, "cardbus_bridge_ranges\n");
7173db86aabSstevel 
7183db86aabSstevel 	bzero((caddr_t)range, sizeof (cardbus_range_t) * PCICFG_RANGE_LEN);
7193db86aabSstevel 
7203db86aabSstevel 	(void) cardbus_setup_bridge(dip, entry, handle);
7213db86aabSstevel 
7223db86aabSstevel 	range[0].child_hi = range[0].parent_hi |= (PCI_REG_REL_M | PCI_ADDR_IO);
7233db86aabSstevel 	range[0].child_lo = range[0].parent_lo = entry->io_last;
7243db86aabSstevel 	range[1].child_hi = range[1].parent_hi |= (PCI_REG_REL_M |
7253db86aabSstevel 						PCI_ADDR_MEM32);
7263db86aabSstevel 	range[1].child_lo = range[1].parent_lo = entry->memory_last;
7273db86aabSstevel 
7283db86aabSstevel 	ndi_devi_enter(dip, &count);
7293db86aabSstevel 	ddi_walk_devs(ddi_get_child(dip), cardbus_bridge_assign, (void *)entry);
7303db86aabSstevel 	ndi_devi_exit(dip, count);
7313db86aabSstevel 
7323db86aabSstevel 	(void) cardbus_update_bridge(dip, entry, handle);
7333db86aabSstevel 
7343db86aabSstevel 	bus_range[0] = pci_config_get8(handle, PCI_BCNF_SECBUS);
7353db86aabSstevel 	bus_range[1] = pci_config_get8(handle, PCI_BCNF_SUBBUS);
7363db86aabSstevel 
7373db86aabSstevel 	cardbus_err(dip, 8,
7383db86aabSstevel 	    "Set up bus-range property to %u->%u\n",
7393db86aabSstevel 	    bus_range[0], bus_range[1]);
7403db86aabSstevel 
7413db86aabSstevel 	if ((i = ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
7423db86aabSstevel 	    "bus-range",
7433db86aabSstevel 	    bus_range, 2)) != DDI_SUCCESS) {
7443db86aabSstevel 
7453db86aabSstevel 		if (i == DDI_PROP_NOT_FOUND) {
7463db86aabSstevel 			cardbus_err(dip, 8,
7473db86aabSstevel 			    "Create bus-range property, %u->%u\n",
7483db86aabSstevel 			    bus_range[0], bus_range[1]);
7493db86aabSstevel 			i = ddi_prop_create(DDI_DEV_T_NONE, dip,
7503db86aabSstevel 			    DDI_PROP_CANSLEEP,
7513db86aabSstevel 			    "bus-range", (caddr_t)bus_range,
7523db86aabSstevel 			    sizeof (bus_range));
7533db86aabSstevel 		}
7543db86aabSstevel 
7553db86aabSstevel 		if (i != DDI_PROP_SUCCESS) {
7563db86aabSstevel 			cardbus_err(dip, 1,
7573db86aabSstevel 			    "Failed to set bus-range property, %u->%u (%d)\n",
7583db86aabSstevel 			    bus_range[0], bus_range[1], i);
7593db86aabSstevel 			entry->error = PCICFG_FAILURE;
7603db86aabSstevel 			return (DDI_WALK_TERMINATE);
7613db86aabSstevel 		}
7623db86aabSstevel 	}
7633db86aabSstevel 
7643db86aabSstevel 	if (entry->io_len > 0) {
7653db86aabSstevel 		range[0].size_lo = entry->io_last - entry->io_base;
7663db86aabSstevel 		if (cardbus_update_ranges_prop(dip, &range[0])) {
7673db86aabSstevel 			cardbus_err(dip, 1, "Failed to update ranges (i/o)\n");
7683db86aabSstevel 			entry->error = PCICFG_FAILURE;
7693db86aabSstevel 			return (DDI_WALK_TERMINATE);
7703db86aabSstevel 		}
7713db86aabSstevel 	}
7723db86aabSstevel 	if (entry->memory_len > 0) {
7733db86aabSstevel 		range[1].size_lo = entry->memory_last - entry->memory_base;
7743db86aabSstevel 		if (cardbus_update_ranges_prop(dip, &range[1])) {
7753db86aabSstevel 			cardbus_err(dip, 1,
7763db86aabSstevel 			    "Failed to update ranges (memory)\n");
7773db86aabSstevel 			entry->error = PCICFG_FAILURE;
7783db86aabSstevel 			return (DDI_WALK_TERMINATE);
7793db86aabSstevel 		}
7803db86aabSstevel 	}
7813db86aabSstevel 
7823db86aabSstevel 	return (DDI_WALK_PRUNECHILD);
7833db86aabSstevel }
7843db86aabSstevel static int
7853db86aabSstevel cardbus_bridge_assign(dev_info_t *dip, void *hdl)
7863db86aabSstevel {
7873db86aabSstevel 	ddi_acc_handle_t handle;
7883db86aabSstevel 	pci_regspec_t *reg;
7893db86aabSstevel 	int length;
7903db86aabSstevel 	int rcount;
7913db86aabSstevel 	int i;
7923db86aabSstevel 	int offset;
7933db86aabSstevel 	uint64_t mem_answer;
7943db86aabSstevel 	uint32_t io_answer, request;
7953db86aabSstevel 	uint8_t header_type, base_class;
7963db86aabSstevel 	cardbus_phdl_t *entry = (cardbus_phdl_t *)hdl;
7973db86aabSstevel 
7983db86aabSstevel 	/*
7993db86aabSstevel 	 * Ignore the attachment point and pcs.
8003db86aabSstevel 	 */
8013db86aabSstevel 	if (strcmp(ddi_binding_name(dip), "hp_attachment") == 0 ||
8023db86aabSstevel 	    strcmp(ddi_binding_name(dip), "pcs") == 0) {
8033db86aabSstevel 		cardbus_err(dip, 8, "cardbus_bridge_assign: Ignoring\n");
8043db86aabSstevel 		return (DDI_WALK_CONTINUE);
8053db86aabSstevel 	}
8063db86aabSstevel 
8073db86aabSstevel 
8083db86aabSstevel 	cardbus_err(dip, 6, "cardbus_bridge_assign\n");
8093db86aabSstevel 
8103db86aabSstevel 	if (entry == NULL) {
8113db86aabSstevel 		cardbus_err(dip, 1, "Failed to get entry\n");
8123db86aabSstevel 		return (DDI_WALK_TERMINATE);
8133db86aabSstevel 	}
8143db86aabSstevel 	if (cardbus_config_setup(dip, &handle) != DDI_SUCCESS) {
8153db86aabSstevel 		cardbus_err(dip, 1,
8163db86aabSstevel 		    "cardbus_bridge_assign: Failed to map config space!\n");
8173db86aabSstevel 		entry->error = PCICFG_FAILURE;
8183db86aabSstevel 		return (DDI_WALK_TERMINATE);
8193db86aabSstevel 	}
8203db86aabSstevel 
8213db86aabSstevel 	header_type = pci_config_get8(handle, PCI_CONF_HEADER) &
8223db86aabSstevel 		PCI_HEADER_TYPE_M;
8233db86aabSstevel 	base_class = pci_config_get8(handle, PCI_CONF_BASCLASS);
8243db86aabSstevel 
8253db86aabSstevel 	/*
8263db86aabSstevel 	 * This function is not called for the top bridge and we are
8273db86aabSstevel 	 * not enumerating down a further cardbus interface yet!
8283db86aabSstevel 	 */
8293db86aabSstevel 	if (base_class == PCI_CLASS_BRIDGE) {
8303db86aabSstevel 		uint8_t	sub_class;
8313db86aabSstevel 
8323db86aabSstevel 		sub_class = pci_config_get8(handle, PCI_CONF_SUBCLASS);
8333db86aabSstevel 
8343db86aabSstevel 		switch (sub_class) {
8353db86aabSstevel 		case PCI_BRIDGE_PCI:
8363db86aabSstevel 			if (header_type == PCI_HEADER_PPB) {
8373db86aabSstevel 				i = cardbus_bridge_ranges(dip, entry, handle);
8383db86aabSstevel 				(void) cardbus_config_teardown(&handle);
8393db86aabSstevel 				return (i);
8403db86aabSstevel 			}
8413db86aabSstevel 			goto bad_device;
8423db86aabSstevel 
8433db86aabSstevel 		case PCI_BRIDGE_ISA:
8443db86aabSstevel 			i = cardbus_isa_bridge_ranges(dip, entry, handle);
8453db86aabSstevel 			(void) cardbus_config_teardown(&handle);
8463db86aabSstevel 			return (i);
8473db86aabSstevel 
8483db86aabSstevel 		case PCI_BRIDGE_CARDBUS:
8493db86aabSstevel 			/*
8503db86aabSstevel 			 * Fall through, there should be at least one register
8513db86aabSstevel 			 * set for this.
8523db86aabSstevel 			 */
8533db86aabSstevel 			break;
8543db86aabSstevel 
8553db86aabSstevel 		case PCI_BRIDGE_OTHER:
8563db86aabSstevel 		default:
8573db86aabSstevel 			break;
8583db86aabSstevel 		}
8593db86aabSstevel 	}
8603db86aabSstevel 
8613db86aabSstevel #ifdef sparc
8623db86aabSstevel 	/*
8633db86aabSstevel 	 * If there is an interrupt pin set program
8643db86aabSstevel 	 * interrupt line with default values.
8653db86aabSstevel 	 */
8663db86aabSstevel 	if (pci_config_get8(handle, PCI_CONF_IPIN)) {
8673db86aabSstevel 	    pci_config_put8(handle, PCI_CONF_ILINE, 0xf);
8683db86aabSstevel 	}
8693db86aabSstevel #else
8703db86aabSstevel 	(void) cardbus_validate_iline(dip, handle);
8713db86aabSstevel #endif
8723db86aabSstevel 
8733db86aabSstevel 	/*
8743db86aabSstevel 	 * A single device (under a bridge).
8753db86aabSstevel 	 * For each "reg" property with a length, allocate memory
8763db86aabSstevel 	 * and program the base registers.
8773db86aabSstevel 	 */
8783db86aabSstevel 	if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
8793db86aabSstevel 	    DDI_PROP_DONTPASS, "reg", (caddr_t)&reg,
8803db86aabSstevel 	    &length) != DDI_PROP_SUCCESS) {
8813db86aabSstevel 		cardbus_err(dip, 1, "Failed to read reg property\n");
8823db86aabSstevel 		entry->error = PCICFG_FAILURE;
8833db86aabSstevel 		(void) cardbus_config_teardown(&handle);
8843db86aabSstevel 		return (DDI_WALK_TERMINATE);
8853db86aabSstevel 	}
8863db86aabSstevel 
8873db86aabSstevel 	rcount = length / sizeof (pci_regspec_t);
8883db86aabSstevel 	cardbus_err(dip, 9, "rcount = %d\n", rcount);
8893db86aabSstevel 
8903db86aabSstevel 	for (i = 0; i < rcount; i++) {
8913db86aabSstevel 		if ((reg[i].pci_size_low != 0) || (reg[i].pci_size_hi != 0)) {
8923db86aabSstevel 			offset = PCI_REG_REG_G(reg[i].pci_phys_hi);
8933db86aabSstevel 			switch (PCI_REG_ADDR_G(reg[i].pci_phys_hi)) {
8943db86aabSstevel 			case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
8953db86aabSstevel 
8963db86aabSstevel 				(void) cardbus_get_mem(ddi_get_parent(dip),
8973db86aabSstevel 				    entry, reg[i].pci_size_low, &mem_answer);
8983db86aabSstevel 				ASSERT(!PCICFG_HIADDR(mem_answer));
8993db86aabSstevel 				pci_config_put32(handle, offset,
9003db86aabSstevel 				    PCICFG_LOADDR(mem_answer));
9013db86aabSstevel 				pci_config_put32(handle, offset + 4,
9023db86aabSstevel 				    PCICFG_HIADDR(mem_answer));
9033db86aabSstevel 				cardbus_err(dip, 8,
9043db86aabSstevel 				    "REGISTER (64)LO [0x%x] ----> [0x%02x]\n",
9053db86aabSstevel 				    pci_config_get32(handle, offset), offset);
9063db86aabSstevel 				cardbus_err(dip, 8,
9073db86aabSstevel 				    "REGISTER (64)HI [0x%x] ----> [0x%02x]\n",
9083db86aabSstevel 				    pci_config_get32(handle, offset+4),
9093db86aabSstevel 					offset+4);
9103db86aabSstevel 				reg[i].pci_phys_low = PCICFG_HIADDR(mem_answer);
9113db86aabSstevel 				reg[i].pci_phys_mid = PCICFG_LOADDR(mem_answer);
9123db86aabSstevel 				break;
9133db86aabSstevel 
9143db86aabSstevel 			case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
9153db86aabSstevel 				/* allocate memory space from the allocator */
9163db86aabSstevel 
9173db86aabSstevel 				(void) cardbus_get_mem(ddi_get_parent(dip),
9183db86aabSstevel 				    entry, reg[i].pci_size_low, &mem_answer);
9193db86aabSstevel 				pci_config_put32(handle, offset, 0xffffffff);
9203db86aabSstevel 				request = pci_config_get32(handle, offset);
9213db86aabSstevel 
9223db86aabSstevel 				pci_config_put32(handle, offset,
9233db86aabSstevel 				    (uint32_t)mem_answer);
9243db86aabSstevel 				reg[i].pci_phys_low = (uint32_t)mem_answer;
9253db86aabSstevel 				reg[i].pci_phys_mid = 0;
9263db86aabSstevel 				if (((PCI_BASE_TYPE_M & request) ==
9273db86aabSstevel 					PCI_BASE_TYPE_ALL) &&
9283db86aabSstevel 				    ((PCI_BASE_SPACE_M & request) ==
9293db86aabSstevel 					PCI_BASE_SPACE_MEM)) {
9303db86aabSstevel 					cardbus_err(dip, 8,
9313db86aabSstevel 					    "REGISTER (64)LO [0x%x] ----> "
9323db86aabSstevel 					    "[0x%02x]\n",
9333db86aabSstevel 					    pci_config_get32(handle, offset),
9343db86aabSstevel 						offset);
9353db86aabSstevel 					    pci_config_put32(handle,
9363db86aabSstevel 						offset + 4, 0);
9373db86aabSstevel 					cardbus_err(dip, 8,
9383db86aabSstevel 					    "REGISTER (64)HI [0x%x] ----> "
9393db86aabSstevel 					    "[0x%02x]\n",
9403db86aabSstevel 					    pci_config_get32(handle, offset+4),
9413db86aabSstevel 						offset+4);
9423db86aabSstevel 				} else {
9433db86aabSstevel 					cardbus_err(dip, 8,
9443db86aabSstevel 					    "REGISTER (32)LO [0x%x] ----> "
9453db86aabSstevel 					    "[0x%02x]\n",
9463db86aabSstevel 					    pci_config_get32(handle, offset),
9473db86aabSstevel 					    offset);
9483db86aabSstevel 				}
9493db86aabSstevel 				break;
9503db86aabSstevel 
9513db86aabSstevel 			case PCI_REG_ADDR_G(PCI_ADDR_IO):
9523db86aabSstevel 				/* allocate I/O space from the allocator */
9533db86aabSstevel 
9543db86aabSstevel 				(void) cardbus_get_io(ddi_get_parent(dip),
9553db86aabSstevel 				    entry, reg[i].pci_size_low, &io_answer);
9563db86aabSstevel 				pci_config_put32(handle, offset, io_answer);
9573db86aabSstevel 				cardbus_err(dip, 8,
9583db86aabSstevel 				    "REGISTER (I/O)LO [0x%x] ----> [0x%02x]\n",
9593db86aabSstevel 				    pci_config_get32(handle, offset), offset);
9603db86aabSstevel 				reg[i].pci_phys_low = io_answer;
9613db86aabSstevel 				break;
9623db86aabSstevel 
9633db86aabSstevel 			default:
9643db86aabSstevel 				cardbus_err(dip, 1, "Unknown register type\n");
9653db86aabSstevel 				kmem_free(reg, length);
9663db86aabSstevel 				(void) cardbus_config_teardown(&handle);
9673db86aabSstevel 				entry->error = PCICFG_FAILURE;
9683db86aabSstevel 				return (DDI_WALK_TERMINATE);
9693db86aabSstevel 			} /* switch */
9703db86aabSstevel 
9713db86aabSstevel 			/*
9723db86aabSstevel 			 * Now that memory locations are assigned,
9733db86aabSstevel 			 * update the assigned address property.
9743db86aabSstevel 			 */
9753db86aabSstevel 			if (cardbus_update_assigned_prop(dip,
9763db86aabSstevel 			    &reg[i]) != PCICFG_SUCCESS) {
9773db86aabSstevel 				kmem_free(reg, length);
9783db86aabSstevel 				(void) cardbus_config_teardown(&handle);
9793db86aabSstevel 				entry->error = PCICFG_FAILURE;
9803db86aabSstevel 				return (DDI_WALK_TERMINATE);
9813db86aabSstevel 			}
9823db86aabSstevel 		}
9833db86aabSstevel 	}
9843db86aabSstevel 	kmem_free(reg, length);
9853db86aabSstevel 	enable_cardbus_device(dip, handle);
9863db86aabSstevel #ifdef CARDBUS_DEBUG
9873db86aabSstevel 	if (cardbus_debug >= 9) {
9883db86aabSstevel 		cardbus_dump_config(handle);
9893db86aabSstevel 	}
9903db86aabSstevel #endif
9913db86aabSstevel bad_device:
9923db86aabSstevel 	(void) cardbus_config_teardown(&handle);
9933db86aabSstevel 	return (DDI_WALK_CONTINUE);
9943db86aabSstevel }
9953db86aabSstevel 
9963db86aabSstevel static int
9973db86aabSstevel cardbus_isa_bridge_ranges(dev_info_t *dip, cardbus_phdl_t *entry,
9983db86aabSstevel 			ddi_acc_handle_t handle)
9993db86aabSstevel {
10003db86aabSstevel 	struct ebus_pci_rangespec range;
10013db86aabSstevel 	int count;
10023db86aabSstevel 	pci_regspec_t *reg;
10033db86aabSstevel 	int length;
10043db86aabSstevel 	int rcount;
10053db86aabSstevel 	uint32_t io_answer = 0xffffffff;
10063db86aabSstevel 	isa_phdl_t isa_phdl;
10073db86aabSstevel 	int i;
10083db86aabSstevel 
10093db86aabSstevel 	cardbus_err(dip, 8, "cardbus_isa_bridge_ranges\n");
10103db86aabSstevel 
10113db86aabSstevel 	bzero((caddr_t)&range, sizeof (range));
10123db86aabSstevel 
10133db86aabSstevel #ifdef sparc
10143db86aabSstevel 	/*
10153db86aabSstevel 	 * If there is an interrupt pin set program
10163db86aabSstevel 	 * interrupt line with default values.
10173db86aabSstevel 	 */
10183db86aabSstevel 	if (pci_config_get8(handle, PCI_CONF_IPIN)) {
10193db86aabSstevel 	    pci_config_put8(handle, PCI_CONF_ILINE, 0xf);
10203db86aabSstevel 	}
10213db86aabSstevel #else
10223db86aabSstevel 	(void) cardbus_validate_iline(dip, handle);
10233db86aabSstevel #endif
10243db86aabSstevel 
10253db86aabSstevel 	/*
10263db86aabSstevel 	 * For each "reg" property with a length, allocate memory.
10273db86aabSstevel 	 */
10283db86aabSstevel 	if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
10293db86aabSstevel 	    DDI_PROP_DONTPASS, "reg", (caddr_t)&reg,
10303db86aabSstevel 	    &length) != DDI_PROP_SUCCESS) {
10313db86aabSstevel 		cardbus_err(dip, 1, "Failed to read reg property\n");
10323db86aabSstevel 		entry->error = PCICFG_FAILURE;
10333db86aabSstevel 		return (DDI_WALK_TERMINATE);
10343db86aabSstevel 	}
10353db86aabSstevel 
10363db86aabSstevel 	rcount = length / sizeof (pci_regspec_t);
10373db86aabSstevel 
10383db86aabSstevel 	for (i = 0; i < rcount; i++) {
10393db86aabSstevel 		if ((reg[i].pci_size_low != 0) || (reg[i].pci_size_hi != 0)) {
10403db86aabSstevel 			switch (PCI_REG_ADDR_G(reg[i].pci_phys_hi)) {
10413db86aabSstevel 			case PCI_REG_ADDR_G(PCI_ADDR_IO):
10423db86aabSstevel 				/* allocate I/O space from the allocator */
10433db86aabSstevel 
10443db86aabSstevel 				(void) cardbus_get_io(ddi_get_parent(dip),
10453db86aabSstevel 				    entry, reg[i].pci_size_low, &io_answer);
10463db86aabSstevel 				cardbus_err(dip, 8,
10473db86aabSstevel 				    "ISA (I/O)LO ----> [0x%x]\n", io_answer);
10483db86aabSstevel 				reg[i].pci_phys_low = io_answer;
10493db86aabSstevel 				range.phys_hi = 0;
10503db86aabSstevel 				range.phys_low = io_answer;
10513db86aabSstevel 				range.par_phys_hi = reg[i].pci_phys_hi |
10523db86aabSstevel 						PCI_REG_REL_M;
10533db86aabSstevel 				range.par_phys_low = reg[i].pci_phys_low;
10543db86aabSstevel 				range.par_phys_mid = reg[i].pci_phys_mid;
10553db86aabSstevel 				range.rng_size = reg[i].pci_size_low;
10563db86aabSstevel 				i = rcount;
10573db86aabSstevel 				break;
10583db86aabSstevel 
10593db86aabSstevel 			default:
10603db86aabSstevel 				cardbus_err(dip, 1, "Unknown register type\n");
10613db86aabSstevel 				kmem_free(reg, length);
10623db86aabSstevel 				(void) cardbus_config_teardown(&handle);
10633db86aabSstevel 				entry->error = PCICFG_FAILURE;
10643db86aabSstevel 				return (DDI_WALK_TERMINATE);
10653db86aabSstevel 			} /* switch */
10663db86aabSstevel 		}
10673db86aabSstevel 	}
10683db86aabSstevel 	kmem_free(reg, length);
10693db86aabSstevel 
10703db86aabSstevel 	(void) ndi_prop_update_int_array(DDI_DEV_T_NONE,
10713db86aabSstevel 	    dip, "ranges", (int *)&range,
10723db86aabSstevel 	    sizeof (range)/sizeof (int));
10733db86aabSstevel 	if (io_answer != 0xffffffff) {
10743db86aabSstevel 		isa_phdl.dip = dip;
10753db86aabSstevel 		isa_phdl.handle = handle;
10763db86aabSstevel 		isa_phdl.io_base = io_answer;
10773db86aabSstevel 		isa_phdl.io_decode_reg = 0x58; /* Pos decoded IO space 0 reg */
10783db86aabSstevel 		/* i_ndi_block_device_tree_changes(&count); */
10793db86aabSstevel 		ndi_devi_enter(dip, &count);
10803db86aabSstevel 		ddi_walk_devs(ddi_get_child(dip),
10813db86aabSstevel 			cardbus_add_isa_reg, (void *)&isa_phdl);
10823db86aabSstevel 		/* i_ndi_allow_device_tree_changes(count); */
10833db86aabSstevel 		ndi_devi_exit(dip, count);
10843db86aabSstevel 	}
10853db86aabSstevel 	return (DDI_WALK_PRUNECHILD);
10863db86aabSstevel }
10873db86aabSstevel 
10883db86aabSstevel /*
10893db86aabSstevel  * This is specific to ITE8888 chip.
10903db86aabSstevel  */
10913db86aabSstevel static int
10923db86aabSstevel cardbus_add_isa_reg(dev_info_t *dip, void *arg)
10933db86aabSstevel {
10943db86aabSstevel 	uint32_t	io_reg = 0;
10953db86aabSstevel 	int		length;
10963db86aabSstevel 	uint32_t	reg[3], *breg;
10973db86aabSstevel 	isa_phdl_t	*phdl;
10983db86aabSstevel 	uint8_t		sz;
10993db86aabSstevel 
11003db86aabSstevel 	phdl = (isa_phdl_t *)arg;
11013db86aabSstevel 	cardbus_err(dip, 6,
11023db86aabSstevel 	    "cardbus_add_isa_reg, base 0x%x\n", phdl->io_base);
11033db86aabSstevel 
11043db86aabSstevel 	if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
11053db86aabSstevel 	    DDI_PROP_DONTPASS, "basereg", (caddr_t)&breg,
11063db86aabSstevel 	    &length) != DDI_PROP_SUCCESS) {
11073db86aabSstevel 		return (DDI_WALK_CONTINUE);
11083db86aabSstevel 	}
11093db86aabSstevel 
11103db86aabSstevel 	if ((length / sizeof (reg)) < 1) {
11113db86aabSstevel 		kmem_free(breg, length);
11123db86aabSstevel 		return (DDI_WALK_CONTINUE);
11133db86aabSstevel 	}
11143db86aabSstevel 
11153db86aabSstevel 	/*
11163db86aabSstevel 	 * Add the "reg" property.
11173db86aabSstevel 	 */
11183db86aabSstevel 	reg[0] = 0;
11193db86aabSstevel 	reg[1] = breg[1] + phdl->io_base;
11203db86aabSstevel 	reg[2] = breg[2];
11213db86aabSstevel 
11223db86aabSstevel 	/*
11233db86aabSstevel 	 * Generate the postive IO decode register setting.
11243db86aabSstevel 	 */
11253db86aabSstevel 	for (sz = 0; sz < 8; sz++)
11263db86aabSstevel 		if ((1<<sz) >= breg[2]) {
11273db86aabSstevel 			io_reg = breg[1]
11283db86aabSstevel 			    | (1uL <<31) /* Enable */
11293db86aabSstevel 			    | (2uL <<29) /* Medium speed */
11303db86aabSstevel 			    | (1uL <<28) /* Aliase enable, */
11313db86aabSstevel 					/* Don't care A[15:10] */
11323db86aabSstevel 			    | (sz<<24); /* Size code */
11333db86aabSstevel 			break;
11343db86aabSstevel 		}
11353db86aabSstevel 
11363db86aabSstevel 	(void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
11373db86aabSstevel 	    "reg", (int *)reg, 3);
11383db86aabSstevel 	(void) ndi_prop_remove(DDI_DEV_T_NONE, dip, "basereg");
11393db86aabSstevel 
11403db86aabSstevel 	if (io_reg) {
11413db86aabSstevel 		pci_config_put32(phdl->handle, phdl->io_decode_reg, io_reg);
11423db86aabSstevel 		cardbus_err(dip, 6,
11433db86aabSstevel 		    "cardbus_add_isa_reg: I/O decode reg (0x%x) set to 0x%x\n",
11443db86aabSstevel 		    phdl->io_decode_reg,
11453db86aabSstevel 		    pci_config_get32(phdl->handle, phdl->io_decode_reg));
11463db86aabSstevel 		phdl->io_decode_reg += sizeof (io_reg);
11473db86aabSstevel 	} else
11483db86aabSstevel 		cardbus_err(dip, 1,
11493db86aabSstevel 		    "cardbus_add_isa_reg: register size (0x%x) too large\n",
11503db86aabSstevel 		    breg[2]);
11513db86aabSstevel 	kmem_free(breg, length);
11523db86aabSstevel 	return (DDI_WALK_CONTINUE);
11533db86aabSstevel }
11543db86aabSstevel 
11553db86aabSstevel /*
11563db86aabSstevel  * In case we want to ensure that some space is allocated to the
11573db86aabSstevel  * device tree below the cardbus bridge.
11583db86aabSstevel  * This is only necessary if there is a device that needs to allocate
11593db86aabSstevel  * resource below us. This can happen if there is another cardbus/PCMCIA
11603db86aabSstevel  * bridge downstream.
11613db86aabSstevel  */
11623db86aabSstevel static uint32_t cardbus_min_spare_mem = 0;
11633db86aabSstevel static uint32_t cardbus_min_spare_io = 0;
11643db86aabSstevel 
11653db86aabSstevel /*
11663db86aabSstevel  * The "dip" passed to this routine is assumed to be
11673db86aabSstevel  * the device at the attachment point. Currently it is
11683db86aabSstevel  * assumed to be a bridge.
11693db86aabSstevel  */
11703db86aabSstevel static int
11713db86aabSstevel cardbus_allocate_chunk(dev_info_t *dip, uint8_t type, uint8_t sec_bus)
11723db86aabSstevel {
11733db86aabSstevel 	cardbus_phdl_t		*phdl;
11743db86aabSstevel 	ndi_ra_request_t	*mem_request;
11753db86aabSstevel 	ndi_ra_request_t	*io_request;
11768134ee03Srw148561 	ra_return_t		res;
11773db86aabSstevel 	int			count;
11783db86aabSstevel 
11793db86aabSstevel 	/*
11803db86aabSstevel 	 * This should not find an existing entry - so
11813db86aabSstevel 	 * it will create a new one.
11823db86aabSstevel 	 */
11833db86aabSstevel 	phdl = cardbus_find_phdl(dip);
11843db86aabSstevel 	ASSERT(phdl);
11853db86aabSstevel 
11863db86aabSstevel 	mem_request = &phdl->mem_req;
11873db86aabSstevel 	io_request  = &phdl->io_req;
11883db86aabSstevel 
11893db86aabSstevel 	/*
11903db86aabSstevel 	 * Set highest_bus here.
11913db86aabSstevel 	 * Otherwise if we don't find another bridge
11923db86aabSstevel 	 * this never gets set.
11933db86aabSstevel 	 */
11943db86aabSstevel 	phdl->highest_bus = sec_bus;
11953db86aabSstevel 
11963db86aabSstevel 	/*
11973db86aabSstevel 	 * From this point in the tree - walk the devices,
11983db86aabSstevel 	 * The function passed in will read and "sum" up
11993db86aabSstevel 	 * the memory and I/O requirements and put them in
12003db86aabSstevel 	 * structure "phdl".
12013db86aabSstevel 	 */
12023db86aabSstevel 	phdl->error = PCICFG_SUCCESS;
12033db86aabSstevel 	ndi_devi_enter(dip, &count);
12043db86aabSstevel 	ddi_walk_devs(ddi_get_child(dip), cardbus_sum_resources, (void *)phdl);
12053db86aabSstevel 	ndi_devi_exit(dip, count);
12063db86aabSstevel 
12073db86aabSstevel 	if (phdl->error != PCICFG_SUCCESS) {
12080d282d13Srw148561 		cmn_err(CE_WARN, "Failure summing resources\n");
12093db86aabSstevel 		return (phdl->error);
12103db86aabSstevel 	}
12113db86aabSstevel 
12123db86aabSstevel 	/*
12133db86aabSstevel 	 * Call into the memory allocator with the request.
12143db86aabSstevel 	 * Record the addresses returned in the phdl
12153db86aabSstevel 	 */
12163db86aabSstevel #ifdef  _LP64
12173db86aabSstevel 	cardbus_err(dip, 8,
12183db86aabSstevel 	    "AP requires [0x%lx] bytes of memory space, alligned 0x%x\n",
12193db86aabSstevel 	    mem_request->ra_len, phdl->memory_gran);
12203db86aabSstevel 	cardbus_err(dip, 8,
12213db86aabSstevel 	    "AP requires [0x%lx] bytes of I/O space, alligned 0x%x\n",
12223db86aabSstevel 	    io_request->ra_len, phdl->io_gran);
12233db86aabSstevel #else
12243db86aabSstevel 	cardbus_err(dip, 8,
12253db86aabSstevel 	    "AP requires [0x%llx] bytes of memory space, alligned 0x%x\n",
12263db86aabSstevel 	    mem_request->ra_len, phdl->memory_gran);
12273db86aabSstevel 	cardbus_err(dip, 8,
12283db86aabSstevel 	    "AP requires [0x%llx] bytes of I/O space, alligned 0x%x\n",
12293db86aabSstevel 	    io_request->ra_len, phdl->io_gran);
12303db86aabSstevel #endif
12313db86aabSstevel 
12323db86aabSstevel 	ASSERT(type == PCI_HEADER_CARDBUS);
12333db86aabSstevel 
12343db86aabSstevel 	mem_request->ra_align_mask = phdl->memory_gran - 1;
12353db86aabSstevel 	io_request->ra_align_mask = phdl->io_gran - 1;
123681ea8c75Srw148561 	phdl->res_dip = (dev_info_t *)-1;
12373db86aabSstevel 
12383db86aabSstevel 	mem_request->ra_len += cardbus_min_spare_mem;
12393db86aabSstevel 	if (mem_request->ra_len) {
12403db86aabSstevel 		mem_request->ra_len = PCICFG_ROUND_UP(
12413db86aabSstevel 					mem_request->ra_len,
12423db86aabSstevel 					phdl->memory_gran);
12433db86aabSstevel #ifdef _LP64
12443db86aabSstevel 		cardbus_err(dip, 8,
12453db86aabSstevel 		    "cardbus_allocate_chunk: ndi_ra_alloc 0x%lx bytes\n",
12463db86aabSstevel 		    mem_request->ra_len);
12473db86aabSstevel #else
12483db86aabSstevel 		cardbus_err(dip, 8,
12493db86aabSstevel 		    "cardbus_allocate_chunk: ndi_ra_alloc 0x%llx bytes\n",
12503db86aabSstevel 		    mem_request->ra_len);
12513db86aabSstevel #endif
12523db86aabSstevel 
12538134ee03Srw148561 		if (pcmcia_alloc_mem(dip, mem_request, &res,
12548134ee03Srw148561 		    &phdl->res_dip) != NDI_SUCCESS) {
12550d282d13Srw148561 			cmn_err(CE_WARN, "Failed to allocate memory for %s\n",
12560d282d13Srw148561 				ddi_driver_name(dip));
12573db86aabSstevel 			return (PCICFG_FAILURE);
12583db86aabSstevel 		}
12593db86aabSstevel 
12608134ee03Srw148561 		phdl->memory_base = phdl->memory_last = res.ra_addr_lo;
12618134ee03Srw148561 		phdl->memory_len = res.ra_len;
12623db86aabSstevel 	}
12633db86aabSstevel 
12643db86aabSstevel 	io_request->ra_len += cardbus_min_spare_io;
12653db86aabSstevel 	if (io_request->ra_len) {
12663db86aabSstevel 
12670d282d13Srw148561 #if defined(__x86) || defined(__amd64)
12680d282d13Srw148561 		io_request->ra_boundbase = 0x1000;
12690d282d13Srw148561 		io_request->ra_boundlen = 0xefff;
12700d282d13Srw148561 #else
12713db86aabSstevel 		io_request->ra_boundbase = 0;
12723db86aabSstevel 		io_request->ra_boundlen = PCICFG_4GIG_LIMIT;
12730d282d13Srw148561 #endif
12743db86aabSstevel 		io_request->ra_flags |= NDI_RA_ALLOC_BOUNDED;
12753db86aabSstevel 		io_request->ra_len = PCICFG_ROUND_UP(io_request->ra_len,
12763db86aabSstevel 				phdl->io_gran);
12778134ee03Srw148561 		io_request->ra_align_mask = max(PCICFG_IOGRAN,
12788134ee03Srw148561 				phdl->io_gran) - 1;
12793db86aabSstevel 
12808134ee03Srw148561 		if (pcmcia_alloc_io(dip, io_request, &res,
12818134ee03Srw148561 		    &phdl->res_dip) != NDI_SUCCESS) {
12820d282d13Srw148561 			cmn_err(CE_WARN, "Failed to allocate I/O space "
12830d282d13Srw148561 				"for %s\n", ddi_driver_name(dip));
12843db86aabSstevel 			if (mem_request->ra_len) {
12858134ee03Srw148561 				res.ra_addr_lo = phdl->memory_base;
12868134ee03Srw148561 				res.ra_len = phdl->memory_len;
12878134ee03Srw148561 				(void) pcmcia_free_mem(phdl->res_dip, &res);
12883db86aabSstevel 				phdl->memory_len = phdl->io_len = 0;
12893db86aabSstevel 			}
12903db86aabSstevel 			return (PCICFG_FAILURE);
12913db86aabSstevel 		}
12923db86aabSstevel 
12938134ee03Srw148561 		phdl->io_base = phdl->io_last = (uint32_t)res.ra_addr_lo;
12948134ee03Srw148561 		phdl->io_len  = (uint32_t)res.ra_len;
12953db86aabSstevel 	}
12963db86aabSstevel 
12973db86aabSstevel #ifdef  _LP64
12983db86aabSstevel 	cardbus_err(dip, 6,
12993db86aabSstevel 	    "MEMORY BASE = [0x%lx] length [0x%lx]\n",
13003db86aabSstevel 	    phdl->memory_base, phdl->memory_len);
13013db86aabSstevel #else
13023db86aabSstevel 	cardbus_err(dip, 6,
13033db86aabSstevel 	    "MEMORY BASE = [0x%llx] length [0x%llx]\n",
13043db86aabSstevel 	    phdl->memory_base, phdl->memory_len);
13053db86aabSstevel #endif
13063db86aabSstevel 	cardbus_err(dip, 6,
13073db86aabSstevel 	    "IO BASE = [0x%x] length [0x%x]\n",
13083db86aabSstevel 	    phdl->io_base, phdl->io_len);
13093db86aabSstevel 
13103db86aabSstevel 	return (PCICFG_SUCCESS);
13113db86aabSstevel }
13123db86aabSstevel 
13133db86aabSstevel static int
13143db86aabSstevel cardbus_free_chunk(dev_info_t *dip)
13153db86aabSstevel {
13163db86aabSstevel 	uint_t	*bus;
13173db86aabSstevel 	int	k;
13183db86aabSstevel 
13193db86aabSstevel 	cardbus_err(dip, 6, "cardbus_free_chunk\n");
13203db86aabSstevel 
13213db86aabSstevel 	(void) cardbus_destroy_phdl(dip);
13223db86aabSstevel 
13233db86aabSstevel 	if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
13243db86aabSstevel 	    DDI_PROP_DONTPASS, "bus-range", (caddr_t)&bus,
13253db86aabSstevel 	    &k) != DDI_PROP_SUCCESS) {
13263db86aabSstevel 		cardbus_err(dip, 1,
13273db86aabSstevel 		    "cardbus_free_chunk: Failed to read bus-range property\n");
13283db86aabSstevel 		return (PCICFG_FAILURE);
13293db86aabSstevel 	}
13303db86aabSstevel 
13313db86aabSstevel 	cardbus_err(dip, 6,
13323db86aabSstevel 	    "cardbus_free_chunk: Freeing bus [%d] range [%d]\n",
13333db86aabSstevel 	    bus[0], bus[1] - bus[0] + 1);
13343db86aabSstevel 
13353db86aabSstevel 	if (ndi_ra_free(dip,
13363db86aabSstevel 	    (uint64_t)bus[0], (uint64_t)(bus[1] - bus[0] + 1),
13373db86aabSstevel 	    NDI_RA_TYPE_PCI_BUSNUM, NDI_RA_PASS) != NDI_SUCCESS) {
13383db86aabSstevel 		cardbus_err(dip, 1,
13393db86aabSstevel 		    "cardbus_free_chunk: Failed to free bus numbers\n");
13403db86aabSstevel 
13413db86aabSstevel 		kmem_free(bus, k);
13423db86aabSstevel 		return (PCICFG_FAILURE);
13433db86aabSstevel 	}
13443db86aabSstevel 
13453db86aabSstevel 	kmem_free(bus, k);
13463db86aabSstevel 	return (PCICFG_SUCCESS);
13473db86aabSstevel }
13483db86aabSstevel 
13493db86aabSstevel /*
13503db86aabSstevel  * Put bridge registers into initial state
13513db86aabSstevel  */
13523db86aabSstevel static void
13533db86aabSstevel cardbus_setup_bridge(dev_info_t *dip, cardbus_phdl_t *entry,
13543db86aabSstevel 		ddi_acc_handle_t handle)
13553db86aabSstevel {
13563db86aabSstevel 	uint8_t header_type = pci_config_get8(handle, PCI_CONF_HEADER);
13573db86aabSstevel 
13583db86aabSstevel #ifdef _LP64
13593db86aabSstevel 	cardbus_err(NULL, 6,
13603db86aabSstevel 	    "cardbus_setup_bridge: "
13613db86aabSstevel 	    "highest bus %d, mem_last 0x%lx, io_last 0x%x\n",
13623db86aabSstevel 	    entry->highest_bus, entry->memory_last, entry->io_last);
13633db86aabSstevel #else
13643db86aabSstevel 	cardbus_err(NULL, 6,
13653db86aabSstevel 	    "cardbus_setup_bridge: "
13663db86aabSstevel 	    "highest bus %d, mem_last 0x%llx, io_last 0x%x\n",
13673db86aabSstevel 	    entry->highest_bus, entry->memory_last, entry->io_last);
13683db86aabSstevel #endif
13693db86aabSstevel 
13703db86aabSstevel 	if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
13713db86aabSstevel 		uint32_t uval;
13723db86aabSstevel 
13733db86aabSstevel 		/*
13743db86aabSstevel 		 * The highest bus seen during probing is
13753db86aabSstevel 		 * the max-subordinate bus
13763db86aabSstevel 		 */
13773db86aabSstevel 		pci_config_put8(handle, PCI_BCNF_SUBBUS, entry->highest_bus);
13783db86aabSstevel 
13793db86aabSstevel 		uval = PCICFG_ROUND_UP(entry->memory_last, PCICFG_MEMGRAN);
13803db86aabSstevel 		if (uval != entry->memory_last) {
13813db86aabSstevel #ifdef _LP64
13823db86aabSstevel 			cardbus_err(dip, 8,
13833db86aabSstevel 			    "Adding [0x%lx] before bridge (mem)\n",
13843db86aabSstevel 			    uval - entry->memory_last);
13853db86aabSstevel #else
13863db86aabSstevel 			cardbus_err(dip, 8,
13873db86aabSstevel 			    "Adding [0x%llx] before bridge (mem)\n",
13883db86aabSstevel 			    uval - entry->memory_last);
13893db86aabSstevel #endif
13903db86aabSstevel 			(void) cardbus_get_mem(ddi_get_parent(dip), entry,
13913db86aabSstevel 			    uval - entry->memory_last, NULL);
13923db86aabSstevel 		}
13933db86aabSstevel 
13943db86aabSstevel 		/*
13953db86aabSstevel 		 * Program the memory base register with the
13963db86aabSstevel 		 * start of the memory range
13973db86aabSstevel 		 */
13983db86aabSstevel #ifdef _LP64
13993db86aabSstevel 		cardbus_err(NULL, 8,
14003db86aabSstevel 		    "store 0x%x(0x%lx) in pci bridge memory base register\n",
14013db86aabSstevel 		    PCICFG_HIWORD(PCICFG_LOADDR(uval)),
14023db86aabSstevel 		    entry->memory_last);
14033db86aabSstevel #else
14043db86aabSstevel 		cardbus_err(NULL, 8,
14053db86aabSstevel 		    "store 0x%x(0x%llx) in pci bridge memory base register\n",
14063db86aabSstevel 		    PCICFG_HIWORD(PCICFG_LOADDR(uval)),
14073db86aabSstevel 		    entry->memory_last);
14083db86aabSstevel #endif
14093db86aabSstevel 		pci_config_put16(handle, PCI_BCNF_MEM_BASE,
14103db86aabSstevel 		    PCICFG_HIWORD(PCICFG_LOADDR(uval)));
14113db86aabSstevel 
14123db86aabSstevel 		uval = PCICFG_ROUND_UP(entry->io_last, PCICFG_IOGRAN);
14133db86aabSstevel 		if (uval != entry->io_last) {
14143db86aabSstevel 			cardbus_err(dip, 8,
14153db86aabSstevel 			    "Adding [0x%x] before bridge (I/O)\n",
14163db86aabSstevel 			    uval - entry->io_last);
14173db86aabSstevel 			(void) cardbus_get_io(ddi_get_parent(dip), entry,
14183db86aabSstevel 			    uval - entry->io_last, NULL);
14193db86aabSstevel 		}
14203db86aabSstevel 		cardbus_err(NULL, 8,
14213db86aabSstevel 		    "store 0x%02x/0x%04x(0x%x) in "
14223db86aabSstevel 		    "pci bridge I/O hi/low base register\n",
14233db86aabSstevel 		    PCICFG_HIWORD(PCICFG_LOADDR(uval)),
14243db86aabSstevel 		    PCICFG_HIBYTE(PCICFG_LOWORD(PCICFG_LOADDR(uval))),
14253db86aabSstevel 		    entry->io_last);
14263db86aabSstevel 		/*
14273db86aabSstevel 		 * Program the I/O base register with the start of the I/O range
14283db86aabSstevel 		 */
14293db86aabSstevel 		pci_config_put8(handle, PCI_BCNF_IO_BASE_LOW,
14303db86aabSstevel 		    PCICFG_HIBYTE(PCICFG_LOWORD(PCICFG_LOADDR(uval))));
14313db86aabSstevel 
14323db86aabSstevel 		pci_config_put16(handle, PCI_BCNF_IO_BASE_HI,
14333db86aabSstevel 		    PCICFG_HIWORD(PCICFG_LOADDR(uval)));
14343db86aabSstevel 
14353db86aabSstevel 		/*
14363db86aabSstevel 		 * Clear status bits
14373db86aabSstevel 		 */
14383db86aabSstevel 		pci_config_put16(handle, PCI_BCNF_SEC_STATUS, 0xffff);
14393db86aabSstevel 
14403db86aabSstevel 		/*
14413db86aabSstevel 		 * Turn off prefetchable range
14423db86aabSstevel 		 */
14433db86aabSstevel 		pci_config_put32(handle, PCI_BCNF_PF_BASE_LOW, 0x0000ffff);
14443db86aabSstevel 		pci_config_put32(handle, PCI_BCNF_PF_BASE_HIGH, 0xffffffff);
14453db86aabSstevel 
14463db86aabSstevel 		pci_config_put32(handle, PCI_BCNF_PF_LIMIT_HIGH, 0x0);
14473db86aabSstevel 
14483db86aabSstevel #ifdef sparc
14493db86aabSstevel 		/*
14503db86aabSstevel 		 * If there is an interrupt pin set program
14513db86aabSstevel 		 * interrupt line with default values.
14523db86aabSstevel 		 */
14533db86aabSstevel 		if (pci_config_get8(handle, PCI_CONF_IPIN)) {
14543db86aabSstevel 		    pci_config_put8(handle, PCI_CONF_ILINE, 0xf);
14553db86aabSstevel 		}
14563db86aabSstevel #else
14573db86aabSstevel 		(void) cardbus_validate_iline(dip, handle);
14583db86aabSstevel #endif
14593db86aabSstevel 
14603db86aabSstevel 
14613db86aabSstevel 	} else if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_CARDBUS) {
14623db86aabSstevel 
14633db86aabSstevel 		/*
14643db86aabSstevel 		 * The highest bus seen during probing is
14653db86aabSstevel 		 * the max-subordinate bus
14663db86aabSstevel 		 */
14673db86aabSstevel 		pci_config_put8(handle, PCI_CBUS_SUB_BUS_NO,
14683db86aabSstevel 		    entry->highest_bus);
14693db86aabSstevel 
14703db86aabSstevel 		/*
14713db86aabSstevel 		 * Program the memory base register with the
14723db86aabSstevel 		 * start of the memory range
14733db86aabSstevel 		 */
14743db86aabSstevel #ifdef _LP64
14753db86aabSstevel 		cardbus_err(NULL, 8,
14763db86aabSstevel 		    "store 0x%x(0x%lx) in "
14773db86aabSstevel 		    "cardbus memory base register 0, len 0x%lx\n",
14783db86aabSstevel 		    PCICFG_LOADDR(entry->memory_last), entry->memory_last,
14793db86aabSstevel 		    entry->memory_len);
14803db86aabSstevel #else
14813db86aabSstevel 		cardbus_err(NULL, 8,
14823db86aabSstevel 		    "store 0x%x(0x%llx) in "
14833db86aabSstevel 		    "cardbus memory base register 0, len 0x%llx\n",
14843db86aabSstevel 		    PCICFG_LOADDR(entry->memory_last), entry->memory_last,
14853db86aabSstevel 		    entry->memory_len);
14863db86aabSstevel #endif
14873db86aabSstevel 
14883db86aabSstevel 		pci_config_put32(handle, PCI_CBUS_MEM_BASE0,
14893db86aabSstevel 		    PCICFG_LOADDR(entry->memory_last));
14903db86aabSstevel 
14913db86aabSstevel 		/*
14923db86aabSstevel 		 * Program the I/O base register with the start of the I/O range
14933db86aabSstevel 		 */
14943db86aabSstevel 		cardbus_err(NULL, 8,
14953db86aabSstevel 		    "store 0x%x in cb IO base register 0 len 0x%x\n",
14963db86aabSstevel 		    PCICFG_LOADDR(entry->io_last),
14973db86aabSstevel 		    entry->io_len);
14983db86aabSstevel 
14993db86aabSstevel 		pci_config_put32(handle, PCI_CBUS_IO_BASE0,
15003db86aabSstevel 		    PCICFG_LOADDR(entry->io_last));
15013db86aabSstevel 
15023db86aabSstevel 		/*
15033db86aabSstevel 		 * Clear status bits
15043db86aabSstevel 		 */
15053db86aabSstevel 		pci_config_put16(handle, PCI_CBUS_SEC_STATUS, 0xffff);
15063db86aabSstevel 
15073db86aabSstevel #ifdef sparc
15083db86aabSstevel 		/*
15093db86aabSstevel 		 * If there is an interrupt pin set program
15103db86aabSstevel 		 * interrupt line with default values.
15113db86aabSstevel 		 */
15123db86aabSstevel 		if (pci_config_get8(handle, PCI_CONF_IPIN)) {
15133db86aabSstevel 		    pci_config_put8(handle, PCI_CONF_ILINE, 0xf);
15143db86aabSstevel 		}
15153db86aabSstevel #else
15163db86aabSstevel 		(void) cardbus_validate_iline(dip, handle);
15173db86aabSstevel #endif
15183db86aabSstevel 
15193db86aabSstevel 
15203db86aabSstevel 		/*
15213db86aabSstevel 		 * LATER: use these registers
15223db86aabSstevel 		 */
15233db86aabSstevel 		pci_config_put32(handle, PCI_CBUS_MEM_BASE1, 0);
15243db86aabSstevel 		pci_config_put32(handle, PCI_CBUS_MEM_LIMIT1, 0);
15253db86aabSstevel 		pci_config_put32(handle, PCI_CBUS_IO_BASE1, 0);
15263db86aabSstevel 		pci_config_put32(handle, PCI_CBUS_IO_LIMIT1, 0);
15273db86aabSstevel 	} else {
15283db86aabSstevel 		cmn_err(CE_WARN, "header type 0x%x, probably unknown bridge\n",
15293db86aabSstevel 		    header_type & PCI_HEADER_TYPE_M);
15303db86aabSstevel 	}
15313db86aabSstevel 
15323db86aabSstevel 	cardbus_err(NULL, 7, "cardbus_setup_bridge complete\n");
15333db86aabSstevel }
15343db86aabSstevel 
15353db86aabSstevel static void
15363db86aabSstevel cardbus_update_bridge(dev_info_t *dip, cardbus_phdl_t *entry,
15373db86aabSstevel 		ddi_acc_handle_t handle)
15383db86aabSstevel {
15393db86aabSstevel 	uint_t length;
15403db86aabSstevel 	uint16_t word16 = pci_config_get16(handle, PCI_CONF_COMM);
15413db86aabSstevel 	const	uint8_t header_type = pci_config_get8(handle, PCI_CONF_HEADER)
15423db86aabSstevel 			& PCI_HEADER_TYPE_M;
15433db86aabSstevel 	uint32_t bridge_gran;
15443db86aabSstevel 	uint64_t rlval;
15453db86aabSstevel 
15463db86aabSstevel 	if (header_type == PCI_HEADER_CARDBUS)
15473db86aabSstevel 		bridge_gran = CBCFG_MEMGRAN;
15483db86aabSstevel 	else
15493db86aabSstevel 		bridge_gran = PCICFG_MEMGRAN;
15503db86aabSstevel 
15513db86aabSstevel 	/*
15523db86aabSstevel 	 * Program the memory limit register with the end of the memory range
15533db86aabSstevel 	 */
15543db86aabSstevel #ifdef _LP64
15553db86aabSstevel 	cardbus_err(dip, 6,
15563db86aabSstevel 	    "cardbus_update_bridge: Mem base 0x%lx len 0x%lx "
15573db86aabSstevel 	    "last 0x%lx gran 0x%x gran end 0x%lx\n",
15583db86aabSstevel 	    entry->memory_base, entry->memory_len,
15593db86aabSstevel 	    entry->memory_last, entry->memory_gran,
15603db86aabSstevel 	    PCICFG_ROUND_UP(entry->memory_last, entry->memory_gran));
15613db86aabSstevel #else
15623db86aabSstevel 	cardbus_err(dip, 6,
15633db86aabSstevel 	    "cardbus_update_bridge: Mem base 0x%llx len 0x%llx "
15643db86aabSstevel 	    "last 0x%llx gran 0x%x gran end 0x%lx\n",
15653db86aabSstevel 	    entry->memory_base, entry->memory_len,
15663db86aabSstevel 	    entry->memory_last, entry->memory_gran,
15673db86aabSstevel 	    PCICFG_ROUND_UP(entry->memory_last, entry->memory_gran));
15683db86aabSstevel #endif
15693db86aabSstevel 	/*
15703db86aabSstevel 	 * Since this is a bridge, the rest of this range will
15713db86aabSstevel 	 * be responded to by the bridge.  We have to round up
15723db86aabSstevel 	 * so no other device claims it.
15733db86aabSstevel 	 */
15743db86aabSstevel 	length = PCICFG_ROUND_UP(entry->memory_last + cardbus_min_spare_mem,
15753db86aabSstevel 	    bridge_gran) - entry->memory_last;
15763db86aabSstevel 
15773db86aabSstevel 	if (length > 0) {
15783db86aabSstevel 		/*
15793db86aabSstevel 		 * This is to allow space that isn't actually being used by
15803db86aabSstevel 		 * anything to be allocated by devices such as a downstream
15813db86aabSstevel 		 * PCMCIA controller.
15823db86aabSstevel 		 */
15833db86aabSstevel 		(void) cardbus_get_mem(dip, entry, length, NULL);
15843db86aabSstevel 		cardbus_err(dip, 8,
15853db86aabSstevel 		    "Added [0x%x] at the top of the bridge (mem)\n", length);
15863db86aabSstevel 	}
15873db86aabSstevel 
15883db86aabSstevel 	if (entry->memory_len) {
15893db86aabSstevel 		if (header_type == PCI_HEADER_CARDBUS) {
15903db86aabSstevel 			rlval = PCICFG_ROUND_DOWN(entry->memory_last - 1,
15913db86aabSstevel 			    CBCFG_MEMGRAN);
15923db86aabSstevel #ifdef _LP64
15933db86aabSstevel 			cardbus_err(dip, 8,
15943db86aabSstevel 			    "store 0x%x(0x%lx) in memory limit register 0\n",
15953db86aabSstevel 			    PCICFG_LOADDR(rlval), rlval);
15963db86aabSstevel #else
15973db86aabSstevel 			cardbus_err(dip, 8,
15983db86aabSstevel 			    "store 0x%x(0x%llx) in memory limit register 0\n",
15993db86aabSstevel 			    PCICFG_LOADDR(rlval), rlval);
16003db86aabSstevel #endif
16013db86aabSstevel 			pci_config_put32(handle, PCI_CBUS_MEM_LIMIT0,
16023db86aabSstevel 			    PCICFG_LOADDR(rlval));
16033db86aabSstevel 		} else {
16043db86aabSstevel 			rlval = PCICFG_ROUND_DOWN(entry->memory_last - 1,
16053db86aabSstevel 			    PCICFG_MEMGRAN);
16063db86aabSstevel #ifdef _LP64
16073db86aabSstevel 			cardbus_err(dip, 8,
16083db86aabSstevel 			    "store 0x%x(0x%lx) in memory limit register\n",
16093db86aabSstevel 			    PCICFG_HIWORD(PCICFG_LOADDR(rlval)),
16103db86aabSstevel 			    rlval);
16113db86aabSstevel #else
16123db86aabSstevel 			cardbus_err(dip, 8,
16133db86aabSstevel 			    "store 0x%x(0x%llx) in memory limit register\n",
16143db86aabSstevel 			    PCICFG_HIWORD(PCICFG_LOADDR(rlval)),
16153db86aabSstevel 			    rlval);
16163db86aabSstevel #endif
16173db86aabSstevel 			pci_config_put16(handle, PCI_BCNF_MEM_LIMIT,
16183db86aabSstevel 			    PCICFG_HIWORD(PCICFG_LOADDR(rlval)));
16193db86aabSstevel 		}
16203db86aabSstevel 		word16 |= PCI_COMM_MAE;
16213db86aabSstevel 	}
16223db86aabSstevel 
16233db86aabSstevel 	cardbus_err(dip, 6,
16243db86aabSstevel 	    "cardbus_update_bridge: I/O base 0x%x len 0x%x last 0x%x "
16253db86aabSstevel 	    "gran 0x%x gran_end 0x%lx\n",
16263db86aabSstevel 	    entry->io_base, entry->io_len, entry->io_last, entry->io_gran,
16273db86aabSstevel 	    PCICFG_ROUND_UP(entry->io_last, entry->io_gran));
16283db86aabSstevel 
16293db86aabSstevel 	if (header_type == PCI_HEADER_CARDBUS)
16303db86aabSstevel 		bridge_gran = CBCFG_IOGRAN;
16313db86aabSstevel 	else
16323db86aabSstevel 		bridge_gran = PCICFG_IOGRAN;
16333db86aabSstevel 
16343db86aabSstevel 	/*
16353db86aabSstevel 	 * Same as above for I/O space. Since this is a
16363db86aabSstevel 	 * bridge, the rest of this range will be responded
16373db86aabSstevel 	 * to by the bridge.  We have to round up so no
16383db86aabSstevel 	 * other device claims it.
16393db86aabSstevel 	 */
16403db86aabSstevel 	length = PCICFG_ROUND_UP(entry->io_last + cardbus_min_spare_io,
16413db86aabSstevel 	    bridge_gran) - entry->io_last;
16423db86aabSstevel 	if (length > 0) {
16433db86aabSstevel 		(void) cardbus_get_io(dip, entry, length, NULL);
16443db86aabSstevel 		cardbus_err(dip, 8,
16453db86aabSstevel 		    "Added [0x%x] at the top of the bridge (I/O)\n",  length);
16463db86aabSstevel 	}
16473db86aabSstevel 
16483db86aabSstevel 	/*
16493db86aabSstevel 	 * Program the I/O limit register with the end of the I/O range
16503db86aabSstevel 	 */
16513db86aabSstevel 	if (entry->io_len) {
16523db86aabSstevel 		if (header_type == PCI_HEADER_CARDBUS) {
16533db86aabSstevel 			rlval = PCICFG_ROUND_DOWN(entry->io_last - 1,
16543db86aabSstevel 			    CBCFG_IOGRAN);
16553db86aabSstevel #ifdef _LP64
16563db86aabSstevel 			cardbus_err(dip, 8,
16573db86aabSstevel 			    "store 0x%lx in IO limit register 0\n", rlval);
16583db86aabSstevel #else
16593db86aabSstevel 			cardbus_err(dip, 8,
16603db86aabSstevel 			    "store 0x%llx in IO limit register 0\n", rlval);
16613db86aabSstevel #endif
16623db86aabSstevel 			pci_config_put32(handle, PCI_CBUS_IO_LIMIT0, rlval);
16633db86aabSstevel 		} else {
16643db86aabSstevel 			rlval = PCICFG_ROUND_DOWN(entry->io_last - 1,
16653db86aabSstevel 			    PCICFG_IOGRAN);
16663db86aabSstevel #ifdef _LP64
16673db86aabSstevel 			cardbus_err(dip, 8,
16683db86aabSstevel 			    "store 0x%x/0x%x(0x%lx) in "
16693db86aabSstevel 			    "IO limit low/hi register\n",
16703db86aabSstevel 			    PCICFG_HIBYTE(PCICFG_LOWORD(PCICFG_LOADDR(rlval))),
16713db86aabSstevel 			    PCICFG_HIWORD(PCICFG_LOADDR(rlval)),
16723db86aabSstevel 			    rlval);
16733db86aabSstevel #else
16743db86aabSstevel 			cardbus_err(dip, 8,
16753db86aabSstevel 			    "store 0x%x/0x%x(0x%llx) in "
16763db86aabSstevel 			    "IO limit low/hi register\n",
16773db86aabSstevel 			    PCICFG_HIBYTE(PCICFG_LOWORD(PCICFG_LOADDR(rlval))),
16783db86aabSstevel 			    PCICFG_HIWORD(PCICFG_LOADDR(rlval)),
16793db86aabSstevel 			    rlval);
16803db86aabSstevel #endif
16813db86aabSstevel 
16823db86aabSstevel 			pci_config_put8(handle, PCI_BCNF_IO_LIMIT_LOW,
16833db86aabSstevel 			    PCICFG_HIBYTE(PCICFG_LOWORD(PCICFG_LOADDR(rlval))));
16843db86aabSstevel 			pci_config_put16(handle, PCI_BCNF_IO_LIMIT_HI,
16853db86aabSstevel 			    PCICFG_HIWORD(PCICFG_LOADDR(rlval)));
16863db86aabSstevel 		}
16873db86aabSstevel 		word16 |= PCI_COMM_IO;
16883db86aabSstevel 	}
16893db86aabSstevel 
16903db86aabSstevel 	pci_config_put16(handle, PCI_CONF_COMM, word16);
16913db86aabSstevel }
16923db86aabSstevel 
16933db86aabSstevel static void
16943db86aabSstevel cardbus_get_mem(dev_info_t *dip, cardbus_phdl_t *entry,
16953db86aabSstevel 		uint32_t length, uint64_t *ans)
16963db86aabSstevel {
16973db86aabSstevel 	uint32_t hole;
16983db86aabSstevel 
16993db86aabSstevel #ifdef  _LP64
17003db86aabSstevel 	cardbus_err(NULL, 6,
17013db86aabSstevel 	    "cardbus_get_mem: memory_last 0x%lx, length 0x%x, "
17023db86aabSstevel 	    "memory_base 0x%lx, memory_len 0x%lx ans=0x%p\n",
17033db86aabSstevel 	    entry->memory_last, length,
17043db86aabSstevel 	    entry->memory_base, entry->memory_len, (void *) ans);
17053db86aabSstevel #else
17063db86aabSstevel 	cardbus_err(NULL, 6,
17073db86aabSstevel 	    "cardbus_get_mem: memory_last 0x%llx, length 0x%x, "
17083db86aabSstevel 	    "memory_base 0x%llx, memory_len 0x%llx ans=0x%p\n",
17093db86aabSstevel 	    entry->memory_last, length,
17103db86aabSstevel 	    entry->memory_base, entry->memory_len, (void *) ans);
17113db86aabSstevel #endif
17123db86aabSstevel 
17133db86aabSstevel 	if (ans) {
17143db86aabSstevel 		/*
17153db86aabSstevel 		 * Round up the request to the "size" boundary
17163db86aabSstevel 		 */
17173db86aabSstevel 		hole = PCICFG_ROUND_UP(entry->memory_last, length)
17183db86aabSstevel 			- entry->memory_last;
17193db86aabSstevel 		if (hole != 0) {
17203db86aabSstevel 			(void) cardbus_update_available_prop(dip,
17213db86aabSstevel 			    PCI_ADDR_MEM32,
17223db86aabSstevel 			    entry->memory_last,
17233db86aabSstevel 			    (uint64_t)hole);
17243db86aabSstevel 			entry->memory_last += hole;
17253db86aabSstevel 
17263db86aabSstevel #ifdef  _LP64
17273db86aabSstevel 			cardbus_err(NULL, 6,
17283db86aabSstevel 			    "cardbus_get_mem: "
17293db86aabSstevel 			    "rounded memory_last up by 0x%x to 0x%lx, ",
17303db86aabSstevel 			    hole, entry->memory_last);
17313db86aabSstevel #else
17323db86aabSstevel 			cardbus_err(NULL, 6,
17333db86aabSstevel 			    "cardbus_get_mem: "
17343db86aabSstevel 			    "rounded memory_last up by 0x%x to 0x%llx, ",
17353db86aabSstevel 			    hole, entry->memory_last);
17363db86aabSstevel #endif
17373db86aabSstevel 		}
17383db86aabSstevel 	} else
17393db86aabSstevel 		(void) cardbus_update_available_prop(dip, PCI_ADDR_MEM32,
17403db86aabSstevel 			entry->memory_last,
17413db86aabSstevel 			(uint64_t)length);
17423db86aabSstevel 
17433db86aabSstevel 	/*
17443db86aabSstevel 	 * These routines should parcel out the memory
17453db86aabSstevel 	 * completely.  There should never be a case of
17463db86aabSstevel 	 * over running the bounds.
17473db86aabSstevel 	 */
17483db86aabSstevel 	if ((entry->memory_last + length) >
17493db86aabSstevel 	    (entry->memory_base + entry->memory_len))
17503db86aabSstevel #ifdef  _LP64
17513db86aabSstevel 		cardbus_err(NULL, 1,
17523db86aabSstevel 		    "cardbus_get_mem: assert will fail %ld <= %ld,"
17533db86aabSstevel 		    "(0x%lx + 0x%x) <= (0x%lx + 0x%lx)\n",
17543db86aabSstevel #else
17553db86aabSstevel 		cardbus_err(NULL, 1,
17563db86aabSstevel 		    "cardbus_get_mem: assert will fail %lld <= %lld, "
17573db86aabSstevel 		    "(0x%llx + 0x%x) <= (0x%llx + 0x%llx)\n",
17583db86aabSstevel #endif
17593db86aabSstevel 		    entry->memory_last + length,
17603db86aabSstevel 		    entry->memory_base + entry->memory_len,
17613db86aabSstevel 		    entry->memory_last,
17623db86aabSstevel 		    length,
17633db86aabSstevel 		    entry->memory_base,
17643db86aabSstevel 		    entry->memory_len);
17653db86aabSstevel 
17663db86aabSstevel 	ASSERT((entry->memory_last + length) <=
17673db86aabSstevel 	(entry->memory_base + entry->memory_len));
17683db86aabSstevel 	/*
17693db86aabSstevel 	 * If ans is NULL don't return anything,
17703db86aabSstevel 	 * they are just asking to reserve the memory.
17713db86aabSstevel 	 */
17723db86aabSstevel 	if (ans != NULL)
17733db86aabSstevel 		*ans = entry->memory_last;
17743db86aabSstevel 
17753db86aabSstevel 	/*
17763db86aabSstevel 	 * Increment to the next location
17773db86aabSstevel 	 */
17783db86aabSstevel 	entry->memory_last += length;
17793db86aabSstevel }
17803db86aabSstevel 
17813db86aabSstevel static void
17823db86aabSstevel cardbus_get_io(dev_info_t *dip, cardbus_phdl_t *entry,
17833db86aabSstevel 		uint32_t length, uint32_t *ans)
17843db86aabSstevel {
17853db86aabSstevel 	uint32_t	hole;
17863db86aabSstevel 
17873db86aabSstevel 	cardbus_err(NULL, 6,
17883db86aabSstevel 	    "cardbus_get_io: io_last 0x%x, length 0x%x, "
17893db86aabSstevel 	    "io_base 0x%x, io_len 0x%x ans=0x%p\n",
17903db86aabSstevel 	    entry->io_last, length,
17913db86aabSstevel 	    entry->io_base, entry->io_len, (void *) ans);
17923db86aabSstevel 
17933db86aabSstevel 	if (ans) {
17943db86aabSstevel 		/*
17953db86aabSstevel 		 * Round up the request to the "size" boundary
17963db86aabSstevel 		 */
17973db86aabSstevel 		hole = PCICFG_ROUND_UP(entry->io_last, length) - entry->io_last;
17983db86aabSstevel 		if (hole != 0) {
17993db86aabSstevel 			(void) cardbus_update_available_prop(dip, PCI_ADDR_IO,
18003db86aabSstevel 			    (uint64_t)entry->io_last,
18013db86aabSstevel 			    (uint64_t)hole);
18023db86aabSstevel 			entry->io_last += hole;
18033db86aabSstevel 
18043db86aabSstevel 			cardbus_err(NULL, 6,
18053db86aabSstevel 			    "cardbus_get_io: "
18063db86aabSstevel 			    "rounded io_last up by 0x%x to 0x%x, ",
18073db86aabSstevel 			    hole, entry->io_last);
18083db86aabSstevel 		}
18093db86aabSstevel 	} else
18103db86aabSstevel 		(void) cardbus_update_available_prop(dip, PCI_ADDR_IO,
18113db86aabSstevel 		    (uint64_t)entry->io_last,
18123db86aabSstevel 		    (uint64_t)length);
18133db86aabSstevel 	/*
18143db86aabSstevel 	 * These routines should parcel out the memory
18153db86aabSstevel 	 * completely.  There should never be a case of
18163db86aabSstevel 	 * over running the bounds.
18173db86aabSstevel 	 */
18183db86aabSstevel 	ASSERT((entry->io_last + length) <=
18193db86aabSstevel 	    (entry->io_base + entry->io_len));
18203db86aabSstevel 
18213db86aabSstevel 	/*
18223db86aabSstevel 	 * If ans is NULL don't return anything,
18233db86aabSstevel 	 * they are just asking to reserve the memory.
18243db86aabSstevel 	 */
18253db86aabSstevel 	if (ans != NULL)
18263db86aabSstevel 		*ans = entry->io_last;
18273db86aabSstevel 
18283db86aabSstevel 	/*
18293db86aabSstevel 	 * Increment to the next location
18303db86aabSstevel 	 */
18313db86aabSstevel 	entry->io_last += length;
18323db86aabSstevel }
18333db86aabSstevel 
18343db86aabSstevel static int
18353db86aabSstevel cardbus_sum_resources(dev_info_t *dip, void *hdl)
18363db86aabSstevel {
18373db86aabSstevel 	cardbus_phdl_t *entry = (cardbus_phdl_t *)hdl;
18383db86aabSstevel 	pci_regspec_t *pci_rp;
18393db86aabSstevel 	int length;
18403db86aabSstevel 	int rcount;
18413db86aabSstevel 	int i, ret;
18423db86aabSstevel 	ndi_ra_request_t *mem_request;
18433db86aabSstevel 	ndi_ra_request_t *io_request;
18443db86aabSstevel 	uint8_t header_type, base_class;
18453db86aabSstevel 	ddi_acc_handle_t handle;
18463db86aabSstevel 
18473db86aabSstevel 	/*
18483db86aabSstevel 	 * Ignore the attachment point and pcs.
18493db86aabSstevel 	 */
18503db86aabSstevel 	if (strcmp(ddi_binding_name(dip), "hp_attachment") == 0 ||
18513db86aabSstevel 	    strcmp(ddi_binding_name(dip), "pcs") == 0) {
18523db86aabSstevel 		cardbus_err(dip, 8, "cardbus_sum_resources: Ignoring\n");
18533db86aabSstevel 		return (DDI_WALK_CONTINUE);
18543db86aabSstevel 	}
18553db86aabSstevel 
18563db86aabSstevel 	mem_request = &entry->mem_req;
18573db86aabSstevel 	io_request =  &entry->io_req;
18583db86aabSstevel 
18593db86aabSstevel 	if (cardbus_config_setup(dip, &handle) != DDI_SUCCESS) {
18603db86aabSstevel 		cardbus_err(dip, 1,
18613db86aabSstevel 		    "cardbus_sum_resources: Failed to map config space!\n");
18623db86aabSstevel 		entry->error = PCICFG_FAILURE;
18633db86aabSstevel 		return (DDI_WALK_TERMINATE);
18643db86aabSstevel 	}
18653db86aabSstevel 
18663db86aabSstevel 	ret = DDI_WALK_CONTINUE;
18673db86aabSstevel 	header_type = pci_config_get8(handle, PCI_CONF_HEADER);
18683db86aabSstevel 	base_class = pci_config_get8(handle, PCI_CONF_BASCLASS);
18693db86aabSstevel 
18703db86aabSstevel 	/*
18713db86aabSstevel 	 * If its a bridge - just record the highest bus seen
18723db86aabSstevel 	 */
18733db86aabSstevel 	if (base_class == PCI_CLASS_BRIDGE) {
18743db86aabSstevel 		uint8_t	sub_class;
18753db86aabSstevel 
18763db86aabSstevel 		sub_class = pci_config_get8(handle, PCI_CONF_SUBCLASS);
18773db86aabSstevel 
18783db86aabSstevel 		switch (sub_class) {
18793db86aabSstevel 		case PCI_BRIDGE_PCI:
18803db86aabSstevel 			if ((header_type & PCI_HEADER_TYPE_M)
18813db86aabSstevel 			    == PCI_HEADER_PPB) {
18823db86aabSstevel 
18833db86aabSstevel 				if (entry->highest_bus < pci_config_get8(handle,
18843db86aabSstevel 				    PCI_BCNF_SECBUS)) {
18853db86aabSstevel 					entry->highest_bus = pci_config_get8(
18863db86aabSstevel 					    handle, PCI_BCNF_SECBUS);
18873db86aabSstevel 				}
18883db86aabSstevel 
18893db86aabSstevel 				(void) cardbus_config_teardown(&handle);
18903db86aabSstevel #if defined(CARDBUS_DEBUG)
18913db86aabSstevel 				if (mem_request->ra_len !=
18923db86aabSstevel 				    PCICFG_ROUND_UP(mem_request->ra_len,
18933db86aabSstevel 				    PCICFG_MEMGRAN)) {
18943db86aabSstevel 
18953db86aabSstevel #ifdef _LP64
18963db86aabSstevel 					cardbus_err(dip, 8,
18973db86aabSstevel 					    "Pre-align [0x%lx] to PCI bridge "
18983db86aabSstevel 					    "memory gran "
18993db86aabSstevel 					    "[0x%lx] -> [0x%lx]\n",
19003db86aabSstevel 					    PCICFG_ROUND_UP(mem_request->ra_len,
19013db86aabSstevel 						PCICFG_MEMGRAN) -
19023db86aabSstevel 						mem_request->ra_len,
19033db86aabSstevel 					    mem_request->ra_len,
19043db86aabSstevel 					    PCICFG_ROUND_UP(mem_request->ra_len,
19053db86aabSstevel 						PCICFG_MEMGRAN));
19063db86aabSstevel #else
19073db86aabSstevel 					cardbus_err(dip, 8,
19083db86aabSstevel 					    "Pre-align [0x%llx] to PCI bridge "
19093db86aabSstevel 					    "memory gran "
19103db86aabSstevel 					    "[0x%llx] -> [0x%lx]\n",
19113db86aabSstevel 					    PCICFG_ROUND_UP(mem_request->ra_len,
19123db86aabSstevel 						PCICFG_MEMGRAN) -
19133db86aabSstevel 						mem_request->ra_len,
19143db86aabSstevel 					    mem_request->ra_len,
19153db86aabSstevel 					    PCICFG_ROUND_UP(mem_request->ra_len,
19163db86aabSstevel 						PCICFG_MEMGRAN));
19173db86aabSstevel #endif
19183db86aabSstevel 				}
19193db86aabSstevel 
19203db86aabSstevel 				if (io_request->ra_len !=
19213db86aabSstevel 				    PCICFG_ROUND_UP(io_request->ra_len,
19223db86aabSstevel 				    PCICFG_IOGRAN)) {
19233db86aabSstevel 
19243db86aabSstevel #ifdef _LP64
19253db86aabSstevel 					cardbus_err(dip, 8,
19263db86aabSstevel 					    "Pre-align [0x%lx] to PCI bridge "
19273db86aabSstevel 					    "I/O gran "
19283db86aabSstevel 					    "[0x%lx] -> [0x%lx]\n",
19293db86aabSstevel 					    PCICFG_ROUND_UP(io_request->ra_len,
19303db86aabSstevel 						PCICFG_IOGRAN) -
19313db86aabSstevel 						io_request->ra_len,
19323db86aabSstevel 					    io_request->ra_len,
19333db86aabSstevel 					    PCICFG_ROUND_UP(io_request->ra_len,
19343db86aabSstevel 						PCICFG_IOGRAN));
19353db86aabSstevel #else
19363db86aabSstevel 					cardbus_err(dip, 8,
19373db86aabSstevel 					    "Pre-align [0x%llx] to PCI bridge "
19383db86aabSstevel 					    "I/O gran "
19393db86aabSstevel 					    "[0x%llx] -> [0x%lx]\n",
19403db86aabSstevel 					    PCICFG_ROUND_UP(io_request->ra_len,
19413db86aabSstevel 						PCICFG_IOGRAN) -
19423db86aabSstevel 						io_request->ra_len,
19433db86aabSstevel 					    io_request->ra_len,
19443db86aabSstevel 					    PCICFG_ROUND_UP(io_request->ra_len,
19453db86aabSstevel 						PCICFG_IOGRAN));
19463db86aabSstevel #endif
19473db86aabSstevel 				}
19483db86aabSstevel 
19493db86aabSstevel #endif
19503db86aabSstevel 				mem_request->ra_len = PCICFG_ROUND_UP(
19513db86aabSstevel 							mem_request->ra_len,
19523db86aabSstevel 							PCICFG_MEMGRAN);
19533db86aabSstevel 				io_request->ra_len = PCICFG_ROUND_UP(
19543db86aabSstevel 							io_request->ra_len,
19553db86aabSstevel 							PCICFG_IOGRAN);
19563db86aabSstevel 				if (entry->memory_gran < PCICFG_MEMGRAN)
19573db86aabSstevel 					entry->memory_gran = PCICFG_MEMGRAN;
19583db86aabSstevel 				if (entry->io_gran < PCICFG_IOGRAN)
19593db86aabSstevel 					entry->io_gran = PCICFG_IOGRAN;
19603db86aabSstevel 				ddi_walk_devs(ddi_get_child(dip),
19613db86aabSstevel 				    cardbus_sum_resources,
19623db86aabSstevel 				    (void *)entry);
19633db86aabSstevel #if defined(CARDBUS_DEBUG)
19643db86aabSstevel 				if (mem_request->ra_len !=
19653db86aabSstevel 				    PCICFG_ROUND_UP(mem_request->ra_len +
19663db86aabSstevel 				    cardbus_min_spare_mem, PCICFG_MEMGRAN)) {
19673db86aabSstevel 
19683db86aabSstevel #ifdef _LP64
19693db86aabSstevel 					cardbus_err(dip, 8,
19703db86aabSstevel 					    "Post-align [0x%lx] to PCI bridge "
19713db86aabSstevel 					    "memory gran "
19723db86aabSstevel 					    "[0x%lx] -> [0x%lx]\n",
19733db86aabSstevel 					    PCICFG_ROUND_UP(
19743db86aabSstevel 						mem_request->ra_len +
19753db86aabSstevel 						cardbus_min_spare_mem,
19763db86aabSstevel 						PCICFG_MEMGRAN) -
19773db86aabSstevel 						mem_request->ra_len,
19783db86aabSstevel 					    mem_request->ra_len,
19793db86aabSstevel 					    PCICFG_ROUND_UP(mem_request->ra_len
19803db86aabSstevel 						+ cardbus_min_spare_mem,
19813db86aabSstevel 						PCICFG_MEMGRAN));
19823db86aabSstevel #else
19833db86aabSstevel 					cardbus_err(dip, 8,
19843db86aabSstevel 					    "Post-align [0x%llx] to PCI bridge "
19853db86aabSstevel 					    "memory gran "
19863db86aabSstevel 					    "[0x%llx] -> [0x%lx]\n",
19873db86aabSstevel 					    PCICFG_ROUND_UP(
19883db86aabSstevel 						mem_request->ra_len +
19893db86aabSstevel 						cardbus_min_spare_mem,
19903db86aabSstevel 						PCICFG_MEMGRAN) -
19913db86aabSstevel 						mem_request->ra_len,
19923db86aabSstevel 					    mem_request->ra_len,
19933db86aabSstevel 					    PCICFG_ROUND_UP(mem_request->ra_len
19943db86aabSstevel 						+ cardbus_min_spare_mem,
19953db86aabSstevel 						PCICFG_MEMGRAN));
19963db86aabSstevel #endif
19973db86aabSstevel 				}
19983db86aabSstevel 
19993db86aabSstevel 				if (io_request->ra_len !=
20003db86aabSstevel 				    PCICFG_ROUND_UP(io_request->ra_len +
20013db86aabSstevel 				    cardbus_min_spare_io,
20023db86aabSstevel 				    PCICFG_IOGRAN)) {
20033db86aabSstevel 
20043db86aabSstevel #ifdef _LP64
20053db86aabSstevel 					cardbus_err(dip, 8,
20063db86aabSstevel 					    "Post-align [0x%lx] to PCI bridge "
20073db86aabSstevel 					    "I/O gran "
20083db86aabSstevel 					    "[0x%lx] -> [0x%lx]\n",
20093db86aabSstevel 					    PCICFG_ROUND_UP(io_request->ra_len +
20103db86aabSstevel 						cardbus_min_spare_io,
20113db86aabSstevel 						PCICFG_IOGRAN) -
20123db86aabSstevel 						io_request->ra_len,
20133db86aabSstevel 					    io_request->ra_len,
20143db86aabSstevel 					    PCICFG_ROUND_UP(io_request->ra_len +
20153db86aabSstevel 						cardbus_min_spare_io,
20163db86aabSstevel 						PCICFG_IOGRAN));
20173db86aabSstevel #else
20183db86aabSstevel 					cardbus_err(dip, 8,
20193db86aabSstevel 					    "Post-align [0x%llx] to PCI bridge "
20203db86aabSstevel 					    "I/O gran "
20213db86aabSstevel 					    "[0x%llx] -> [0x%lx]\n",
20223db86aabSstevel 					    PCICFG_ROUND_UP(io_request->ra_len +
20233db86aabSstevel 						cardbus_min_spare_io,
20243db86aabSstevel 						PCICFG_IOGRAN) -
20253db86aabSstevel 						io_request->ra_len,
20263db86aabSstevel 					    io_request->ra_len,
20273db86aabSstevel 					    PCICFG_ROUND_UP(io_request->ra_len +
20283db86aabSstevel 						cardbus_min_spare_io,
20293db86aabSstevel 						PCICFG_IOGRAN));
20303db86aabSstevel #endif
20313db86aabSstevel 				}
20323db86aabSstevel #endif
20333db86aabSstevel 				mem_request->ra_len = PCICFG_ROUND_UP(
20343db86aabSstevel 						mem_request->ra_len +
20353db86aabSstevel 						    cardbus_min_spare_mem,
20363db86aabSstevel 						PCICFG_MEMGRAN);
20373db86aabSstevel 				io_request->ra_len = PCICFG_ROUND_UP(
20383db86aabSstevel 						io_request->ra_len +
20393db86aabSstevel 						    cardbus_min_spare_io,
20403db86aabSstevel 						PCICFG_IOGRAN);
20413db86aabSstevel 			}
20423db86aabSstevel 			return (DDI_WALK_PRUNECHILD);
20433db86aabSstevel 
20443db86aabSstevel 		case PCI_BRIDGE_CARDBUS:
20453db86aabSstevel 			/*
20463db86aabSstevel 			 * Cardbus has I/O registers.
20473db86aabSstevel 			 */
20483db86aabSstevel 			break;
20493db86aabSstevel 
20503db86aabSstevel 		case PCI_BRIDGE_ISA:
20513db86aabSstevel 			/*
20523db86aabSstevel 			 * All the registers requirements for ISA
20533db86aabSstevel 			 * are stored in the reg structure of the bridge.
20543db86aabSstevel 			 * Children of ISA are not of type PCI
20553db86aabSstevel 			 * so must not come through here because
20563db86aabSstevel 			 * cardbus_config_setup() will fail.
20573db86aabSstevel 			 */
20583db86aabSstevel 			ret = DDI_WALK_PRUNECHILD;
20593db86aabSstevel 			break;
20603db86aabSstevel 
20613db86aabSstevel 		default:
20623db86aabSstevel 			/*
20633db86aabSstevel 			 * Treat other bridges as leaf nodes.
20643db86aabSstevel 			 */
20653db86aabSstevel 			break;
20663db86aabSstevel 		}
20673db86aabSstevel 	}
20683db86aabSstevel 
20693db86aabSstevel 	if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
20703db86aabSstevel 	    DDI_PROP_DONTPASS, "reg", (caddr_t)&pci_rp,
20713db86aabSstevel 	    &length) != DDI_PROP_SUCCESS) {
20723db86aabSstevel 		/*
20733db86aabSstevel 		 * If one node in (the subtree of nodes)
20743db86aabSstevel 		 * does'nt have a "reg" property fail the
20753db86aabSstevel 		 * allocation.
20763db86aabSstevel 		 */
20773db86aabSstevel 		entry->memory_len = 0;
20783db86aabSstevel 		entry->io_len = 0;
20793db86aabSstevel 		entry->error = PCICFG_FAILURE;
20803db86aabSstevel 		(void) cardbus_config_teardown(&handle);
20813db86aabSstevel 		return (DDI_WALK_TERMINATE);
20823db86aabSstevel 	}
20833db86aabSstevel 
20843db86aabSstevel 	/*
20853db86aabSstevel 	 * For each "reg" property with a length, add that to the
20863db86aabSstevel 	 * total memory (or I/O) to allocate.
20873db86aabSstevel 	 */
20883db86aabSstevel 	rcount = length / sizeof (pci_regspec_t);
20893db86aabSstevel 
20903db86aabSstevel 	for (i = 0; i < rcount; i++) {
20913db86aabSstevel 
20923db86aabSstevel 		switch (PCI_REG_ADDR_G(pci_rp[i].pci_phys_hi)) {
20933db86aabSstevel 
20943db86aabSstevel 		case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
20953db86aabSstevel 			mem_request->ra_len =
20963db86aabSstevel 				pci_rp[i].pci_size_low +
20973db86aabSstevel 				PCICFG_ROUND_UP(mem_request->ra_len,
20983db86aabSstevel 					pci_rp[i].pci_size_low);
20993db86aabSstevel 
21003db86aabSstevel 			cardbus_err(dip, 8,
21013db86aabSstevel 			    "ADDING 32 --->0x%x for BAR@0x%x\n",
21023db86aabSstevel 			    pci_rp[i].pci_size_low,
21033db86aabSstevel 			    PCI_REG_REG_G(pci_rp[i].pci_phys_hi));
21043db86aabSstevel 			/*
21053db86aabSstevel 			 * the granualarity needs to be the larger of
21063db86aabSstevel 			 * the maximum amount of memory that we're going to
21073db86aabSstevel 			 * ask for, and the PCI-PCI bridge granularity (1M)
21083db86aabSstevel 			 */
21093db86aabSstevel 			if (pci_rp[i].pci_size_low > entry->memory_gran)
21103db86aabSstevel 				entry->memory_gran = pci_rp[i].pci_size_low;
21113db86aabSstevel 			break;
21123db86aabSstevel 
21133db86aabSstevel 		case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
21143db86aabSstevel 			mem_request->ra_len =
21153db86aabSstevel 				pci_rp[i].pci_size_low +
21163db86aabSstevel 				PCICFG_ROUND_UP(mem_request->ra_len,
21173db86aabSstevel 					pci_rp[i].pci_size_low);
21183db86aabSstevel 			cardbus_err(dip, 8,
21193db86aabSstevel 			    "ADDING 64 --->0x%x for BAR@0x%x\n",
21203db86aabSstevel 			    pci_rp[i].pci_size_low,
21213db86aabSstevel 			    PCI_REG_REG_G(pci_rp[i].pci_phys_hi));
21223db86aabSstevel 
21233db86aabSstevel 			if (pci_rp[i].pci_size_low > entry->memory_gran)
21243db86aabSstevel 				entry->memory_gran = pci_rp[i].pci_size_low;
21253db86aabSstevel 			break;
21263db86aabSstevel 
21273db86aabSstevel 		case PCI_REG_ADDR_G(PCI_ADDR_IO):
21283db86aabSstevel 			io_request->ra_len =
21293db86aabSstevel 				pci_rp[i].pci_size_low +
21303db86aabSstevel 				PCICFG_ROUND_UP(io_request->ra_len,
21313db86aabSstevel 					pci_rp[i].pci_size_low);
21323db86aabSstevel 			cardbus_err(dip, 8,
21333db86aabSstevel 			    "ADDING I/O --->0x%x for BAR@0x%x\n",
21343db86aabSstevel 			    pci_rp[i].pci_size_low,
21353db86aabSstevel 			    PCI_REG_REG_G(pci_rp[i].pci_phys_hi));
21363db86aabSstevel 
21373db86aabSstevel 			if (pci_rp[i].pci_size_low > entry->io_gran)
21383db86aabSstevel 				entry->io_gran = pci_rp[i].pci_size_low;
21393db86aabSstevel 			break;
21403db86aabSstevel 
21413db86aabSstevel 		default:
21423db86aabSstevel 			/* Config space register - not included */
21433db86aabSstevel 			break;
21443db86aabSstevel 		}
21453db86aabSstevel 	}
21463db86aabSstevel 
21473db86aabSstevel 	/*
21483db86aabSstevel 	 * free the memory allocated by ddi_getlongprop
21493db86aabSstevel 	 */
21503db86aabSstevel 	kmem_free(pci_rp, length);
21513db86aabSstevel 
21523db86aabSstevel 	/*
21533db86aabSstevel 	 * continue the walk to the next sibling to sum memory
21543db86aabSstevel 	 */
21553db86aabSstevel 
21563db86aabSstevel 	(void) cardbus_config_teardown(&handle);
21573db86aabSstevel 
21583db86aabSstevel #ifdef  _LP64
21593db86aabSstevel 	cardbus_err(dip, 8,
21603db86aabSstevel 	    "Memory 0x%lx bytes, I/O 0x%lx bytes, "
21613db86aabSstevel 	    "Memgran 0x%x, IOgran 0x%x\n",
21623db86aabSstevel 	    mem_request->ra_len, io_request->ra_len,
21633db86aabSstevel 	    entry->memory_gran, entry->io_gran);
21643db86aabSstevel #else
21653db86aabSstevel 	cardbus_err(dip, 8,
21663db86aabSstevel 	    "Memory 0x%llx bytes, I/O 0x%llx bytes, "
21673db86aabSstevel 	    "Memgran 0x%x, IOgran 0x%x\n",
21683db86aabSstevel 	    mem_request->ra_len, io_request->ra_len,
21693db86aabSstevel 	    entry->memory_gran, entry->io_gran);
21703db86aabSstevel #endif
21713db86aabSstevel 
21723db86aabSstevel 	return (ret);
21733db86aabSstevel }
21743db86aabSstevel 
21753db86aabSstevel /*
21763db86aabSstevel  * Free resources allocated to a bridge.
21773db86aabSstevel  * Note that this routine does not call ndi_ra_free() to actually
21783db86aabSstevel  * free memory/IO/Bus. This is done as a single chunk for the entire
21793db86aabSstevel  * device tree in cardbus_free_chunk().
21803db86aabSstevel  */
21813db86aabSstevel static int
21823db86aabSstevel cardbus_free_bridge_resources(dev_info_t *dip)
21833db86aabSstevel {
21843db86aabSstevel 	cardbus_range_t	*ranges;
21853db86aabSstevel 	uint_t		*bus;
21863db86aabSstevel 	int		k;
21873db86aabSstevel 	int		length;
21883db86aabSstevel 	int		i;
21893db86aabSstevel 
21903db86aabSstevel 	cardbus_err(dip, 6, "cardbus_free_bridge_resources\n");
21913db86aabSstevel 
21923db86aabSstevel 	if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
21933db86aabSstevel 	    DDI_PROP_DONTPASS, "ranges", (caddr_t)&ranges,
21943db86aabSstevel 	    &length) == DDI_PROP_SUCCESS) {
21953db86aabSstevel 		for (i = 0; i < length / sizeof (cardbus_range_t); i++) {
21963db86aabSstevel 			if (ranges[i].size_lo != 0 || ranges[i].size_hi != 0) {
21973db86aabSstevel 				switch (ranges[i].parent_hi & PCI_REG_ADDR_M) {
21983db86aabSstevel 				case PCI_ADDR_IO:
21993db86aabSstevel 					cardbus_err(dip, 6,
22003db86aabSstevel 					    "Need to Free I/O    "
22013db86aabSstevel 					    "base/length = [0x%x]/[0x%x]\n",
22023db86aabSstevel 					    ranges[i].child_lo,
22033db86aabSstevel 					    ranges[i].size_lo);
22043db86aabSstevel 					break;
22053db86aabSstevel 
22063db86aabSstevel 				case PCI_ADDR_MEM32:
22073db86aabSstevel 				case PCI_ADDR_MEM64:
22083db86aabSstevel 					cardbus_err(dip, 6,
22093db86aabSstevel 					    "Need to Free Memory base/length = "
22103db86aabSstevel 					    "[0x%x.%x]/[0x%x]\n",
22113db86aabSstevel 					    ranges[i].child_mid,
22123db86aabSstevel 					    ranges[i].child_lo,
22133db86aabSstevel 					    ranges[i].size_lo);
22143db86aabSstevel 					break;
22153db86aabSstevel 
22163db86aabSstevel 				default:
22173db86aabSstevel 					cardbus_err(dip, 6,
22183db86aabSstevel 					    "Unknown memory space\n");
22193db86aabSstevel 					break;
22203db86aabSstevel 				}
22213db86aabSstevel 			}
22223db86aabSstevel 		}
22233db86aabSstevel 
22243db86aabSstevel 		kmem_free(ranges, length);
22253db86aabSstevel 		(void) ndi_prop_remove(DDI_DEV_T_NONE, dip, "ranges");
22263db86aabSstevel 	} else {
22273db86aabSstevel 		cardbus_err(dip, 8,
22283db86aabSstevel 		    "cardbus_free_bridge_resources: Failed"
22293db86aabSstevel 		    "to read ranges property\n");
22303db86aabSstevel 	}
22313db86aabSstevel 
22323db86aabSstevel 	if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
22333db86aabSstevel 	    DDI_PROP_DONTPASS, "bus-range", (caddr_t)&bus,
22343db86aabSstevel 	    &k) != DDI_PROP_SUCCESS) {
22353db86aabSstevel 		cardbus_err(dip, 6, "Failed to read bus-range property\n");
22363db86aabSstevel 		return (PCICFG_FAILURE);
22373db86aabSstevel 	}
22383db86aabSstevel 
22393db86aabSstevel 	cardbus_err(dip, 6,
22403db86aabSstevel 	    "Need to free bus [%d] range [%d]\n",
22413db86aabSstevel 	    bus[0], bus[1] - bus[0] + 1);
2242d577a050Syx209050 	kmem_free(bus, k);
22433db86aabSstevel 	(void) ndi_prop_remove(DDI_DEV_T_NONE, dip, "available");
22443db86aabSstevel 	(void) ndi_prop_remove(DDI_DEV_T_NONE, dip, "bus-range");
22453db86aabSstevel 
22463db86aabSstevel 	return (PCICFG_SUCCESS);
22473db86aabSstevel }
22483db86aabSstevel 
22493db86aabSstevel static int
22503db86aabSstevel cardbus_free_device_resources(dev_info_t *dip)
22513db86aabSstevel {
22523db86aabSstevel 	pci_regspec_t *assigned;
22533db86aabSstevel 
22543db86aabSstevel 	int length;
22553db86aabSstevel 	int acount;
22563db86aabSstevel 	int i;
22573db86aabSstevel 
22583db86aabSstevel 	if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
22593db86aabSstevel 	    DDI_PROP_DONTPASS, "assigned-addresses",
22603db86aabSstevel 	    (caddr_t)&assigned,
22613db86aabSstevel 	    &length) != DDI_PROP_SUCCESS) {
22623db86aabSstevel 		cardbus_err(dip, 1,
22633db86aabSstevel 		    "Failed to read assigned-addresses property\n");
22643db86aabSstevel 		return (PCICFG_FAILURE);
22653db86aabSstevel 	}
22663db86aabSstevel 
22673db86aabSstevel 	/*
22683db86aabSstevel 	 * For each "assigned-addresses" property entry with a length,
22693db86aabSstevel 	 * call the memory allocation routines to return the
22703db86aabSstevel 	 * resource.
22713db86aabSstevel 	 */
22723db86aabSstevel 	acount = length / sizeof (pci_regspec_t);
22733db86aabSstevel 	for (i = 0; i < acount; i++) {
22743db86aabSstevel 
22753db86aabSstevel 		/*
22763db86aabSstevel 		 * Free the resource if the size of it is not zero.
22773db86aabSstevel 		 */
22783db86aabSstevel 		if ((assigned[i].pci_size_low != 0)||
22793db86aabSstevel 		    (assigned[i].pci_size_hi != 0)) {
22803db86aabSstevel 			switch (PCI_REG_ADDR_G(assigned[i].pci_phys_hi)) {
22813db86aabSstevel 			case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
22823db86aabSstevel 				cardbus_err(dip, 6,
22833db86aabSstevel 				    "Need to return 0x%x of 32 bit MEM space"
22843db86aabSstevel 				    " @ 0x%x from register 0x%x\n",
22853db86aabSstevel 				    assigned[i].pci_size_low,
22863db86aabSstevel 				    assigned[i].pci_phys_low,
22873db86aabSstevel 				    PCI_REG_REG_G(assigned[i].pci_phys_hi));
22883db86aabSstevel 
22893db86aabSstevel 				break;
22903db86aabSstevel 
22913db86aabSstevel 			case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
22923db86aabSstevel 				cardbus_err(dip, 6,
22933db86aabSstevel 				    "Need to return 0x%x of 64 bit MEM space"
22943db86aabSstevel 				    " @ 0x%x.%x from register 0x%x\n",
22953db86aabSstevel 				    assigned[i].pci_size_low,
22963db86aabSstevel 				    assigned[i].pci_phys_mid,
22973db86aabSstevel 				    assigned[i].pci_phys_low,
22983db86aabSstevel 				    PCI_REG_REG_G(assigned[i].pci_phys_hi));
22993db86aabSstevel 
23003db86aabSstevel 				break;
23013db86aabSstevel 
23023db86aabSstevel 			case PCI_REG_ADDR_G(PCI_ADDR_IO):
23033db86aabSstevel 				cardbus_err(dip, 6,
23043db86aabSstevel 				    "Need to return 0x%x of IO space @ 0x%x"
23053db86aabSstevel 				    " from register 0x%x\n",
23063db86aabSstevel 				    assigned[i].pci_size_low,
23073db86aabSstevel 				    assigned[i].pci_phys_low,
23083db86aabSstevel 				    PCI_REG_REG_G(assigned[i].pci_phys_hi));
23093db86aabSstevel 				break;
23103db86aabSstevel 
23113db86aabSstevel 			default:
23123db86aabSstevel 				cardbus_err(dip, 1, "Unknown register type\n");
23133db86aabSstevel 				kmem_free(assigned, length);
23143db86aabSstevel 				return (PCICFG_FAILURE);
23153db86aabSstevel 			} /* switch */
23163db86aabSstevel 		}
23173db86aabSstevel 	}
23183db86aabSstevel 	kmem_free(assigned, length);
23193db86aabSstevel 	return (PCICFG_SUCCESS);
23203db86aabSstevel }
23213db86aabSstevel 
23223db86aabSstevel static int
23233db86aabSstevel cardbus_free_resources(dev_info_t *dip)
23243db86aabSstevel {
23253db86aabSstevel 	uint32_t classcode;
23263db86aabSstevel 
23273db86aabSstevel 	classcode = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
23283db86aabSstevel 				"class-code", -1);
23293db86aabSstevel 	/*
23303db86aabSstevel 	 * A different algorithim is used for bridges and leaf devices.
23313db86aabSstevel 	 */
23323db86aabSstevel 	if (classcode != -1) {
23333db86aabSstevel 		classcode = ((uint_t)classcode & 0xffff00) >> 8;
23343db86aabSstevel 		if (classcode == 0x604 || classcode == 0x607) {
23353db86aabSstevel 			if (cardbus_free_bridge_resources(dip)
23363db86aabSstevel 			    != PCICFG_SUCCESS) {
23373db86aabSstevel 				cardbus_err(dip, 1,
23383db86aabSstevel 				    "Failed freeing up bridge resources\n");
23393db86aabSstevel 				return (PCICFG_FAILURE);
23403db86aabSstevel 			}
23413db86aabSstevel 			return (PCICFG_SUCCESS);
23423db86aabSstevel 		}
23433db86aabSstevel 	}
23443db86aabSstevel 
23453db86aabSstevel 	if (cardbus_free_device_resources(dip) != PCICFG_SUCCESS) {
23463db86aabSstevel 		cardbus_err(dip, 1, "Failed freeing up device resources\n");
23473db86aabSstevel 		return (PCICFG_FAILURE);
23483db86aabSstevel 	}
23493db86aabSstevel 	return (PCICFG_SUCCESS);
23503db86aabSstevel }
23513db86aabSstevel 
23523db86aabSstevel static int
23533db86aabSstevel cardbus_probe_bridge(cbus_t *cbp, dev_info_t *attpt, uint_t bus,
23543db86aabSstevel 			uint_t device, uint_t func)
23553db86aabSstevel {
23563db86aabSstevel 	/* Declairations */
23573db86aabSstevel 	cardbus_bus_range_t	*bus_range;
23583db86aabSstevel 	int			i, j;
23593db86aabSstevel 	uint8_t			header_type;
23603db86aabSstevel 	ddi_acc_handle_t	config_handle;
23613db86aabSstevel 	ndi_ra_request_t	req;
23623db86aabSstevel 	uint_t			new_bus;
23633db86aabSstevel 	uint64_t		blen;
23643db86aabSstevel 	uint64_t		next_bus;
23653db86aabSstevel 	int circ;
23663db86aabSstevel 
23673db86aabSstevel 	cardbus_err(cbp->cb_dip, 6,
23683db86aabSstevel 	    "cardbus_probe_bridge bus %d device %d func %d\n",
23693db86aabSstevel 	    bus, device, func);
23703db86aabSstevel 
23713db86aabSstevel 	ndi_devi_enter(cbp->cb_dip, &circ);
23723db86aabSstevel 	if (pci_config_setup(cbp->cb_dip, &config_handle) != DDI_SUCCESS) {
23733db86aabSstevel 
23743db86aabSstevel 		cardbus_err(cbp->cb_dip, 1,
23753db86aabSstevel 		    "cardbus_probe_bridge(): Failed to setup config space\n");
23763db86aabSstevel 
23773db86aabSstevel 		ndi_devi_exit(cbp->cb_dip, circ);
23783db86aabSstevel 		return (PCICFG_FAILURE);
23793db86aabSstevel 	}
23803db86aabSstevel 
23813db86aabSstevel 	header_type = pci_config_get8(config_handle, PCI_CONF_HEADER);
23823db86aabSstevel 
23833db86aabSstevel 	/*
23843db86aabSstevel 	 * As soon as we have access to config space, check device
23853db86aabSstevel 	 * is a bridge.
23863db86aabSstevel 	 */
23873db86aabSstevel 	if ((header_type & PCI_HEADER_TYPE_M) != PCI_HEADER_CARDBUS)
23883db86aabSstevel 		goto failed;
23893db86aabSstevel 
23903db86aabSstevel 	cardbus_err(cbp->cb_dip, 8,
23913db86aabSstevel 	    "---Vendor ID = [0x%04x]\n",
23923db86aabSstevel 	    pci_config_get16(config_handle, PCI_CONF_VENID));
23933db86aabSstevel 	cardbus_err(cbp->cb_dip, 8,
23943db86aabSstevel 	    "---Device ID = [0x%04x]\n",
23953db86aabSstevel 	    pci_config_get16(config_handle, PCI_CONF_DEVID));
23963db86aabSstevel 
23973db86aabSstevel 	/* say what type of header */
23983db86aabSstevel 	cardbus_err(cbp->cb_dip, 8,
23993db86aabSstevel 	    "--%s bridge found root bus [0x%x] device [0x%x] func [0x%x]\n",
24003db86aabSstevel 	    ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) ?
24013db86aabSstevel 		"PCI-PCI" : "Cardbus",
24023db86aabSstevel 	    bus, device, func);
24033db86aabSstevel 
24043db86aabSstevel 	if (ddi_getlongprop(DDI_DEV_T_ANY, cbp->cb_dip, 0, "bus-range",
24053db86aabSstevel 	    (caddr_t)&bus_range, &i) != DDI_PROP_SUCCESS)
24063db86aabSstevel 		cardbus_err(cbp->cb_dip, 1,
24073db86aabSstevel 		    "No bus-range property seems to have been set up\n");
24083db86aabSstevel 	else {
24093db86aabSstevel 		cardbus_err(cbp->cb_dip, 8,
24103db86aabSstevel 		    "allowable bus range is %u->%u\n",
24113db86aabSstevel 		    bus_range->lo, bus_range->hi);
24123db86aabSstevel 		kmem_free((caddr_t)bus_range, i);
24133db86aabSstevel 	}
24143db86aabSstevel 
24153db86aabSstevel 	/*
24163db86aabSstevel 	 * Get next bus in sequence and program device.
24173db86aabSstevel 	 */
24183db86aabSstevel 	bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
24193db86aabSstevel 	req.ra_len = 1;
24203db86aabSstevel 
24213db86aabSstevel 	if (ndi_ra_alloc(cbp->cb_dip, &req,
24223db86aabSstevel 	    &next_bus, &blen, NDI_RA_TYPE_PCI_BUSNUM,
24233db86aabSstevel 	    NDI_RA_PASS) != NDI_SUCCESS) {
24240d282d13Srw148561 		cmn_err(CE_WARN, "Failed to get a bus number\n");
24253db86aabSstevel 		goto failed;
24263db86aabSstevel 	}
24273db86aabSstevel 
24283db86aabSstevel 	new_bus = next_bus;
24293db86aabSstevel 	cardbus_err(cbp->cb_dip, 8,
24303db86aabSstevel 	    "NEW bus found [%u]->[%u]\n", bus, new_bus);
24313db86aabSstevel 
24323db86aabSstevel 	(void) cardbus_set_bus_numbers(config_handle, bus, new_bus);
24333db86aabSstevel 
24343db86aabSstevel 	/* Enable it all */
24353db86aabSstevel 	enable_cardbus_bridge(cbp->cb_dip, config_handle);
24363db86aabSstevel 
24373db86aabSstevel 	/*
24383db86aabSstevel 	 * Probe all children devices
24393db86aabSstevel 	 */
24403db86aabSstevel 	for (i = 0; i < pcicfg_max_device; i++)
24413db86aabSstevel 		for (j = 0; j < pcicfg_max_function; j++)
24423db86aabSstevel 			switch (cardbus_probe_children(cbp, attpt, new_bus, i,
24433db86aabSstevel 			    j, &header_type)) {
24443db86aabSstevel 
24453db86aabSstevel 			case PCICFG_FAILURE:
24463db86aabSstevel 				cardbus_err(cbp->cb_dip, 1,
24473db86aabSstevel 				    "Failed to configure bus "
24483db86aabSstevel 				    "[0x%x] device [0x%x] func [0x%x]\n",
24493db86aabSstevel 				    new_bus, i, j);
24503db86aabSstevel 				disable_cardbus_bridge(cbp->cb_dip,
24513db86aabSstevel 				    config_handle);
24523db86aabSstevel 				goto failed;
24533db86aabSstevel 
24543db86aabSstevel 			case PCICFG_NODEVICE:
24553db86aabSstevel 				/*
24563db86aabSstevel 				 * if there's no function 0
24573db86aabSstevel 				 * there's no point in probing other
24583db86aabSstevel 				 * functions
24593db86aabSstevel 				 */
24603db86aabSstevel 				if (j != 0)
24613db86aabSstevel 					break;
24623db86aabSstevel 				/* FALLTHROUGH */
24633db86aabSstevel 			case PCICFG_NOMULTI:
24643db86aabSstevel 				j = pcicfg_max_function;
24653db86aabSstevel 				break;
24663db86aabSstevel 
24673db86aabSstevel 			default:
24683db86aabSstevel 				break;
24693db86aabSstevel 			}
24703db86aabSstevel 
24713db86aabSstevel 	(void) pci_config_teardown(&config_handle);
24723db86aabSstevel 	(void) i_ndi_config_node(attpt, DS_LINKED, 0);
24733db86aabSstevel 	ndi_devi_exit(cbp->cb_dip, circ);
24743db86aabSstevel 
24753db86aabSstevel 	return (PCICFG_SUCCESS);
24763db86aabSstevel 
24773db86aabSstevel failed:
24783db86aabSstevel 	(void) pci_config_teardown(&config_handle);
24793db86aabSstevel 	ndi_devi_exit(cbp->cb_dip, circ);
24803db86aabSstevel 
24813db86aabSstevel 	return (PCICFG_FAILURE);
24823db86aabSstevel }
24833db86aabSstevel 
24843db86aabSstevel static struct isa_node isa_nodes[] = {
24853db86aabSstevel 	{"dummy", {NULL, NULL, NULL, NULL, NULL}, "serial", "", 0x4e, 0x2}
24863db86aabSstevel };
24873db86aabSstevel 
24883db86aabSstevel static int
24893db86aabSstevel cardbus_probe_children(cbus_t *cbp, dev_info_t *parent, uint_t bus,
24903db86aabSstevel 			uint_t device, uint_t func, uint8_t *header_type)
24913db86aabSstevel {
24923db86aabSstevel 	dev_info_t		*new_child;
24933db86aabSstevel 	ddi_acc_handle_t	config_handle;
24943db86aabSstevel 	int			i, j;
24953db86aabSstevel 	ndi_ra_request_t	req;
24963db86aabSstevel 	uint64_t		next_bus;
24973db86aabSstevel 	uint64_t		blen;
24983db86aabSstevel 	uint32_t		request;
24993db86aabSstevel 	uint8_t			base_class;
25003db86aabSstevel 	uint_t			new_bus;
25013db86aabSstevel 	int			ret;
25023db86aabSstevel 	int			circ;
25033db86aabSstevel 
25043db86aabSstevel 	cardbus_err(parent, 6,
25053db86aabSstevel 	    "cardbus_probe_children bus %d device %d func %d\n",
25063db86aabSstevel 	    bus, device, func);
25073db86aabSstevel 
25083db86aabSstevel 	/*
25093db86aabSstevel 	 * This node will be put immediately below
25103db86aabSstevel 	 * "parent". Allocate a blank device node.  It will either
25113db86aabSstevel 	 * be filled in or freed up based on further probing.
25123db86aabSstevel 	 */
25133db86aabSstevel 
25143db86aabSstevel 	ndi_devi_enter(parent, &circ);
25153db86aabSstevel 
25163db86aabSstevel 	if (ndi_devi_alloc(parent, DEVI_PSEUDO_NEXNAME,
25173db86aabSstevel 	    (pnode_t)DEVI_SID_NODEID,
25183db86aabSstevel 	    &new_child) != NDI_SUCCESS) {
25193db86aabSstevel 		cardbus_err(parent, 1,
25203db86aabSstevel 		    "cardbus_probe_children(): Failed to alloc child node\n");
25213db86aabSstevel 		ndi_devi_exit(parent, circ);
25223db86aabSstevel 		return (PCICFG_FAILURE);
25233db86aabSstevel 	}
25243db86aabSstevel 
25253db86aabSstevel 	if (cardbus_add_config_reg(new_child, bus,
25263db86aabSstevel 	    device, func) != DDI_SUCCESS) {
25273db86aabSstevel 		cardbus_err(parent, 1,
25283db86aabSstevel 		    "cardbus_probe_children(): Failed to add candidate REG\n");
25293db86aabSstevel 		goto failedconfig;
25303db86aabSstevel 	}
25313db86aabSstevel 
25323db86aabSstevel 	if ((ret = cardbus_config_setup(new_child, &config_handle))
25333db86aabSstevel 	    != PCICFG_SUCCESS) {
25343db86aabSstevel 
25353db86aabSstevel 		if (ret == PCICFG_NODEVICE) {
25363db86aabSstevel 			(void) ndi_devi_free(new_child);
25373db86aabSstevel 			return (ret);
25383db86aabSstevel 		}
25393db86aabSstevel 		cardbus_err(parent, 1,
25403db86aabSstevel 		    "cardbus_probe_children(): Failed to setup config space\n");
25413db86aabSstevel 
25423db86aabSstevel 		goto failedconfig;
25433db86aabSstevel 	}
25443db86aabSstevel 
25453db86aabSstevel 	base_class = pci_config_get8(config_handle, PCI_CONF_BASCLASS);
25463db86aabSstevel 
25473db86aabSstevel 	if (func == 0) {
25483db86aabSstevel 		/*
25493db86aabSstevel 		 * Preserve the header type from function 0.
25503db86aabSstevel 		 * Additional functions may not preserve the PCI_HEADER_MULTI
25513db86aabSstevel 		 * bit.
25523db86aabSstevel 		 */
25533db86aabSstevel 		*header_type = pci_config_get8(config_handle, PCI_CONF_HEADER);
25543db86aabSstevel 	} else if (!(*header_type & PCI_HEADER_MULTI) ||
25553db86aabSstevel 		    ((*header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) ||
25563db86aabSstevel 		    (base_class == PCI_CLASS_BRIDGE)) {
25573db86aabSstevel 
25583db86aabSstevel 		(void) cardbus_config_teardown(&config_handle);
25593db86aabSstevel 		(void) ndi_devi_free(new_child);
25603db86aabSstevel 		return (PCICFG_NOMULTI);
25613db86aabSstevel 	}
25623db86aabSstevel 
25633db86aabSstevel 	/*
25643db86aabSstevel 	 * As soon as we have access to config space,
25653db86aabSstevel 	 * turn off device. It will get turned on
25663db86aabSstevel 	 * later (after memory is assigned).
25673db86aabSstevel 	 * not if it's a cardbus device. It may be OK to leave
25683db86aabSstevel 	 * it on - try LATER
25693db86aabSstevel 	 */
25703db86aabSstevel 	disable_cardbus_device(config_handle);
25713db86aabSstevel 
25723db86aabSstevel 	/*
25733db86aabSstevel 	 * Set 1275 properties common to all devices
25743db86aabSstevel 	 */
25753db86aabSstevel 	if (cardbus_set_standard_props(parent, new_child,
25763db86aabSstevel 	    config_handle) != PCICFG_SUCCESS) {
25773db86aabSstevel 		cardbus_err(parent, 1, "Failed to set standard properties\n");
25783db86aabSstevel 		goto failedchild;
25793db86aabSstevel 	}
25803db86aabSstevel 
25813db86aabSstevel 	/*
25823db86aabSstevel 	 * Child node properties  NOTE: Both for PCI-PCI bridge and child node
25833db86aabSstevel 	 */
25843db86aabSstevel 	if (cardbus_set_childnode_props(new_child,
25853db86aabSstevel 	    config_handle) != PCICFG_SUCCESS) {
25863db86aabSstevel 		goto failedchild;
25873db86aabSstevel 	}
25883db86aabSstevel 
25893db86aabSstevel 	cardbus_err(parent, 8,
25903db86aabSstevel 	    "---Vendor ID = [0x%04x]\n",
25913db86aabSstevel 	    pci_config_get16(config_handle, PCI_CONF_VENID));
25923db86aabSstevel 	cardbus_err(parent, 8,
25933db86aabSstevel 	    "---Device ID = [0x%04x]\n",
25943db86aabSstevel 	    pci_config_get16(config_handle, PCI_CONF_DEVID));
25953db86aabSstevel 
25963db86aabSstevel 	if (base_class == PCI_CLASS_BRIDGE) {
25973db86aabSstevel 		uint8_t	sub_class;
25983db86aabSstevel 
25993db86aabSstevel 		sub_class = pci_config_get8(config_handle, PCI_CONF_SUBCLASS);
26003db86aabSstevel 
26013db86aabSstevel 		switch (sub_class) {
26023db86aabSstevel 		case PCI_BRIDGE_PCI:
26033db86aabSstevel 			if ((*header_type & PCI_HEADER_TYPE_M)
26043db86aabSstevel 			    == PCI_HEADER_PPB) {
26053db86aabSstevel 				cardbus_bus_range_t *bus_range;
26063db86aabSstevel 				int k;
26073db86aabSstevel 
26083db86aabSstevel 				/* say what type of header */
26093db86aabSstevel 				cardbus_err(parent, 8,
26103db86aabSstevel 				    "-- Found PCI-PCI bridge @ "
26113db86aabSstevel 				    " bus [0x%x] device [0x%x] func [0x%x]\n",
26123db86aabSstevel 				    bus, device, func);
26133db86aabSstevel 
26143db86aabSstevel 				if (ddi_getlongprop(DDI_DEV_T_ANY,
26153db86aabSstevel 				    new_child, 0, "bus-range",
26163db86aabSstevel 				    (caddr_t)&bus_range,
26173db86aabSstevel 				    &k) != DDI_PROP_SUCCESS)
26183db86aabSstevel 					cardbus_err(new_child, 1,
26193db86aabSstevel 					    "No bus-range property"
26203db86aabSstevel 					    " seems to have been set up\n");
26213db86aabSstevel 				else {
26223db86aabSstevel 					cardbus_err(new_child, 8,
26233db86aabSstevel 					    "allowable bus range is %u->%u\n",
26243db86aabSstevel 					    bus_range->lo, bus_range->hi);
26253db86aabSstevel 					kmem_free((caddr_t)bus_range, k);
26263db86aabSstevel 				}
26273db86aabSstevel 
26283db86aabSstevel 				/*
26293db86aabSstevel 				 * Get next bus in sequence and program device.
26303db86aabSstevel 				 */
26313db86aabSstevel 				bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
26323db86aabSstevel 				req.ra_len = 1;
26333db86aabSstevel 
26343db86aabSstevel 				if (ndi_ra_alloc(new_child, &req,
26353db86aabSstevel 				    &next_bus, &blen,
26363db86aabSstevel 				    NDI_RA_TYPE_PCI_BUSNUM,
26373db86aabSstevel 				    NDI_RA_PASS) != NDI_SUCCESS) {
26380d282d13Srw148561 					cmn_err(CE_WARN,
26393db86aabSstevel 					    "Failed to get a bus number\n");
26403db86aabSstevel 					goto failedchild;
26413db86aabSstevel 				}
26423db86aabSstevel 
26433db86aabSstevel 				new_bus = next_bus;
26443db86aabSstevel 
26453db86aabSstevel 				cardbus_err(new_child, 8,
26463db86aabSstevel 				    "NEW bus found [%u]->[%u]\n", bus, new_bus);
26473db86aabSstevel 
26483db86aabSstevel 				/* Enable it all */
26493db86aabSstevel 				enable_pci_pci_bridge(new_child, config_handle);
26503db86aabSstevel 				(void) cardbus_set_bus_numbers(config_handle,
26513db86aabSstevel 				    bus, new_bus);
26523db86aabSstevel 
26533db86aabSstevel #if defined(CARDBUS_DEBUG)
26543db86aabSstevel 				if (cardbus_debug >= 9) {
26553db86aabSstevel 					cardbus_dump_config(config_handle);
26563db86aabSstevel 				}
26573db86aabSstevel #endif
26583db86aabSstevel 
26593db86aabSstevel 				/*
26603db86aabSstevel 				 * Set bus properties
26613db86aabSstevel 				 */
26623db86aabSstevel 				if (cardbus_set_busnode_props(new_child)
26633db86aabSstevel 				    != PCICFG_SUCCESS) {
26643db86aabSstevel 					cardbus_err(new_child, 1,
26653db86aabSstevel 					    "Failed to set busnode props\n");
26663db86aabSstevel 					disable_pci_pci_bridge(new_child,
26673db86aabSstevel 					    config_handle);
26683db86aabSstevel 					goto failedchild;
26693db86aabSstevel 				}
26703db86aabSstevel 
26713db86aabSstevel 				/*
26723db86aabSstevel 				 * Probe all children devices
26733db86aabSstevel 				 */
26743db86aabSstevel 				for (i = 0; i < pcicfg_max_device; i++)
26753db86aabSstevel 					for (j = 0; j < pcicfg_max_function;
26763db86aabSstevel 					    j++)
26773db86aabSstevel 						switch (cardbus_probe_children(
26783db86aabSstevel 						    cbp,
26793db86aabSstevel 						    new_child,
26803db86aabSstevel 						    new_bus, i,
26813db86aabSstevel 						    j, header_type)) {
26823db86aabSstevel 						case PCICFG_FAILURE:
26833db86aabSstevel 							cardbus_err(parent, 1,
26843db86aabSstevel 							    "Failed to "
26853db86aabSstevel 							    "configure "
26863db86aabSstevel 							    "bus [0x%x] "
26873db86aabSstevel 							    "device [0x%x] "
26883db86aabSstevel 							    "func [0x%x]\n",
26893db86aabSstevel 							    new_bus, i, j);
26903db86aabSstevel 							disable_pci_pci_bridge(
26913db86aabSstevel 								new_child,
26923db86aabSstevel 								config_handle);
26933db86aabSstevel 							goto failedchild;
26943db86aabSstevel 
26953db86aabSstevel 						case PCICFG_NODEVICE:
26963db86aabSstevel 							/*
26973db86aabSstevel 							 * if there's no
26983db86aabSstevel 							 * function 0
26993db86aabSstevel 							 * there's no point in
27003db86aabSstevel 							 * probing other
27013db86aabSstevel 							 * functions
27023db86aabSstevel 							 */
27033db86aabSstevel 							if (j != 0)
27043db86aabSstevel 								break;
27053db86aabSstevel 							/* FALLTHROUGH */
27063db86aabSstevel 						case PCICFG_NOMULTI:
27073db86aabSstevel 							j = pcicfg_max_function;
27083db86aabSstevel 							break;
27093db86aabSstevel 
27103db86aabSstevel 						default:
27113db86aabSstevel 							break;
27123db86aabSstevel 						}
27133db86aabSstevel 			}
27143db86aabSstevel 			break;
27153db86aabSstevel 
27163db86aabSstevel 		case PCI_BRIDGE_CARDBUS:
27173db86aabSstevel 			cardbus_err(parent, 8,
27183db86aabSstevel 			    "--Found Cardbus bridge @ "
27193db86aabSstevel 			    "bus [0x%x] device [0x%x] func [0x%x]\n",
27203db86aabSstevel 			    bus, device, func);
27213db86aabSstevel 			pci_config_put32(config_handle,
27223db86aabSstevel 			    PCI_CONF_BASE0, 0xffffffff);
27233db86aabSstevel 
27243db86aabSstevel 			request = pci_config_get32(config_handle,
27253db86aabSstevel 			    PCI_CONF_BASE0);
27263db86aabSstevel 
27273db86aabSstevel 			/*
27283db86aabSstevel 			 * If its a zero length, don't do
27293db86aabSstevel 			 * any programming.
27303db86aabSstevel 			 */
27313db86aabSstevel 			if (request != 0) {
27323db86aabSstevel 				if (request == (uint32_t)0xffffffff) {
27333db86aabSstevel 					cmn_err(CE_WARN,
27343db86aabSstevel 					    "cardbus_probe_children: "
27353db86aabSstevel 					    "can't access device");
27363db86aabSstevel 					goto failedchild;
27373db86aabSstevel 				}
27383db86aabSstevel 				/*
27393db86aabSstevel 				 * Add to the "reg" property
27403db86aabSstevel 				 */
27413db86aabSstevel 				if (cardbus_update_reg_prop(new_child,
27423db86aabSstevel 				    request,
27433db86aabSstevel 				    PCI_CONF_BASE0) != PCICFG_SUCCESS) {
27443db86aabSstevel 					goto failedchild;
27453db86aabSstevel 				}
27463db86aabSstevel 				cardbus_err(parent, 8,
27473db86aabSstevel 				    "BASE register [0x%x] asks for "
27483db86aabSstevel 				    "[0x%x]=[0x%x](32)\n",
27493db86aabSstevel 				    PCI_CONF_BASE0, request,
27503db86aabSstevel 				    (~(PCI_BASE_M_ADDR_M & request))+1);
27513db86aabSstevel 			}
27523db86aabSstevel 			break;
27533db86aabSstevel 
27543db86aabSstevel 		case PCI_BRIDGE_ISA:
27553db86aabSstevel 			cardbus_err(parent, 8,
27563db86aabSstevel 			    "--Found ISA bridge @ "
27573db86aabSstevel 			    "bus [0x%x] device [0x%x] func [0x%x]\n",
27583db86aabSstevel 			    bus, device, func);
27593db86aabSstevel 			enable_pci_isa_bridge(new_child, config_handle);
27603db86aabSstevel 
27613db86aabSstevel #if defined(CARDBUS_DEBUG)
27623db86aabSstevel 			if (cardbus_debug >= 4) {
27633db86aabSstevel 				cardbus_dump_common_config(config_handle);
27643db86aabSstevel 				cardbus_err(NULL, 1,
27653db86aabSstevel 				    " DDMA SlvCh0 = [0x%04x]        "
27663db86aabSstevel 				    "DDMA SlvCh1 = [0x%04x]\n",
27673db86aabSstevel 				    pci_config_get16(config_handle, 0x40),
27683db86aabSstevel 				    pci_config_get16(config_handle, 0x42));
27693db86aabSstevel 				cardbus_err(NULL, 1,
27703db86aabSstevel 				    " DDMA SlvCh2 = [0x%04x]        "
27713db86aabSstevel 				    "DDMA SlvCh3 = [0x%04x]\n",
27723db86aabSstevel 				    pci_config_get16(config_handle, 0x44),
27733db86aabSstevel 				    pci_config_get16(config_handle, 0x46));
27743db86aabSstevel 				cardbus_err(NULL, 1,
27753db86aabSstevel 				    " DDMA SlvCh5 = [0x%04x]        "
27763db86aabSstevel 				    "DDMA SlvCh6 = [0x%04x]\n",
27773db86aabSstevel 				    pci_config_get16(config_handle, 0x4a),
27783db86aabSstevel 				    pci_config_get16(config_handle, 0x4c));
27793db86aabSstevel 				cardbus_err(NULL, 1,
27803db86aabSstevel 				    " DDMA SlvCh7 = [0x%04x]        "
27813db86aabSstevel 				    "Misc Cntrl  = [0x%02x]\n",
27823db86aabSstevel 				    pci_config_get16(config_handle, 0x4e),
27833db86aabSstevel 				    pci_config_get8(config_handle, 0x57));
27843db86aabSstevel 				cardbus_err(NULL, 1,
27853db86aabSstevel 				    " DMA Cntl    = [0x%02x]          "
27863db86aabSstevel 				    "DMA TyF Tim = [0x%02x]\n",
27873db86aabSstevel 				    pci_config_get8(config_handle, 0x48),
27883db86aabSstevel 				    pci_config_get8(config_handle, 0x49));
27893db86aabSstevel 				cardbus_err(NULL, 1,
27903db86aabSstevel 				    " TimCntrl    = [0x%02x]          "
27913db86aabSstevel 				    "MTOP        = [0x%02x]\n",
27923db86aabSstevel 				    pci_config_get8(config_handle, 0x50),
27933db86aabSstevel 				    pci_config_get8(config_handle, 0x51));
27943db86aabSstevel 				cardbus_err(NULL, 1,
27953db86aabSstevel 				    " MDMA Access = [0x%02x]          "
27963db86aabSstevel 				    "ROMCS       = [0x%02x]\n",
27973db86aabSstevel 				    pci_config_get8(config_handle, 0x52),
27983db86aabSstevel 				    pci_config_get8(config_handle, 0x53));
27993db86aabSstevel 				cardbus_err(NULL, 1,
28003db86aabSstevel 				    " Dscrd Tmr   = [0x%02x]          "
28013db86aabSstevel 				    "Retry Tmr   = [0x%02x]\n",
28023db86aabSstevel 				    pci_config_get8(config_handle, 0x55),
28033db86aabSstevel 				    pci_config_get8(config_handle, 0x54));
28043db86aabSstevel 				cardbus_err(NULL, 1,
28053db86aabSstevel 				    " I/O Spc 0   = [0x%08x]    "
28063db86aabSstevel 				    "I/O Spc 1   = [0x%08x]\n",
28073db86aabSstevel 				    pci_config_get32(config_handle, 0x58),
28083db86aabSstevel 				    pci_config_get32(config_handle, 0x5c));
28093db86aabSstevel 				cardbus_err(NULL, 1,
28103db86aabSstevel 				    " I/O Spc 2   = [0x%08x]    "
28113db86aabSstevel 				    "I/O Spc 3   = [0x%08x]\n",
28123db86aabSstevel 				    pci_config_get32(config_handle, 0x60),
28133db86aabSstevel 				    pci_config_get32(config_handle, 0x64));
28143db86aabSstevel 				cardbus_err(NULL, 1,
28153db86aabSstevel 				    " I/O Spc 4   = [0x%08x]    "
28163db86aabSstevel 				    "I/O Spc 5   = [0x%08x]\n",
28173db86aabSstevel 				    pci_config_get32(config_handle, 0x68),
28183db86aabSstevel 				    pci_config_get32(config_handle, 0x6c));
28193db86aabSstevel 				cardbus_err(NULL, 1,
28203db86aabSstevel 				    " Mem Spc 0   = [0x%08x]    "
28213db86aabSstevel 				    "Mem Spc 1   = [0x%08x]\n",
28223db86aabSstevel 				    pci_config_get32(config_handle, 0x70),
28233db86aabSstevel 				    pci_config_get32(config_handle, 0x74));
28243db86aabSstevel 				cardbus_err(NULL, 1,
28253db86aabSstevel 				    " Mem Spc 2   = [0x%08x]    "
28263db86aabSstevel 				    "Mem Spc 3   = [0x%08x]\n",
28273db86aabSstevel 				    pci_config_get32(config_handle, 0x78),
28283db86aabSstevel 				    pci_config_get32(config_handle, 0x7c));
28293db86aabSstevel 			}
28303db86aabSstevel #endif
28313db86aabSstevel 			/*
28323db86aabSstevel 			 * Set bus properties
28333db86aabSstevel 			 */
28343db86aabSstevel 			if (cardbus_set_busnode_isaprops(new_child)
28353db86aabSstevel 			    != PCICFG_SUCCESS) {
28363db86aabSstevel 				cardbus_err(new_child, 1,
28373db86aabSstevel 				    "Failed to set busnode props\n");
28383db86aabSstevel 				disable_cardbus_device(config_handle);
28393db86aabSstevel 				goto failedchild;
28403db86aabSstevel 			}
28413db86aabSstevel 
28423db86aabSstevel 			/*
28433db86aabSstevel 			 * Add to the "reg" property.
28443db86aabSstevel 			 * Simply grab 1K of I/O space.
28453db86aabSstevel 			 */
28463db86aabSstevel 			if (cardbus_update_reg_prop(new_child,
28473db86aabSstevel 			    0xfffffc00 | PCI_BASE_SPACE_IO,
28483db86aabSstevel 			    PCI_CONF_BASE0) != PCICFG_SUCCESS) {
28493db86aabSstevel 				goto failedchild;
28503db86aabSstevel 			}
28513db86aabSstevel 
28523db86aabSstevel 			/*
28533db86aabSstevel 			 * Probe all potential children devices.
28543db86aabSstevel 			 */
28553db86aabSstevel 			for (i = 0;
28563db86aabSstevel 			    i < sizeof (isa_nodes) / sizeof (isa_nodes[0]);
28573db86aabSstevel 			    i++)
28583db86aabSstevel 				switch (cardbus_add_isa_node(cbp, new_child,
28593db86aabSstevel 				    &isa_nodes[i])) {
28603db86aabSstevel 				case PCICFG_FAILURE:
28613db86aabSstevel 					cardbus_err(parent, 1,
28623db86aabSstevel 					    "Failed to configure isa bus\n");
28633db86aabSstevel 					disable_cardbus_device(config_handle);
28643db86aabSstevel 					goto failedchild;
28653db86aabSstevel 
28663db86aabSstevel 				case PCICFG_NODEVICE:
28673db86aabSstevel 					continue;
28683db86aabSstevel 				}
28693db86aabSstevel 
28703db86aabSstevel 			break;
28713db86aabSstevel 
28723db86aabSstevel 		case PCI_BRIDGE_OTHER:
28733db86aabSstevel 		default:
28743db86aabSstevel 			cardbus_err(parent, 8,
28753db86aabSstevel 			    "--Found unknown bridge, subclass 0x%x @ "
28763db86aabSstevel 			    "bus [0x%x] device [0x%x] func [0x%x]\n",
28773db86aabSstevel 			    sub_class, bus, device, func);
28783db86aabSstevel 			goto leaf_node;
28793db86aabSstevel 		}
28803db86aabSstevel 	} else {
28813db86aabSstevel 		cardbus_err(parent, 8,
28823db86aabSstevel 		    "--Leaf device found "
28833db86aabSstevel 		    "bus [0x%x] device [0x%x] func [0x%x]\n",
28843db86aabSstevel 		    bus, device, func);
28853db86aabSstevel 		/*
28863db86aabSstevel 		 * Ethernet devices.
28873db86aabSstevel 		 */
28883db86aabSstevel 		if (strcmp(ddi_binding_name(new_child), "ethernet") == 0) {
28893db86aabSstevel 			extern int localetheraddr(struct ether_addr *,
28903db86aabSstevel 			    struct ether_addr *);
28913db86aabSstevel 			uchar_t mac[6];
28923db86aabSstevel 
28933db86aabSstevel 			cardbus_force_stringprop(new_child,
28943db86aabSstevel 			    "device_type", "network");
28953db86aabSstevel 
28963db86aabSstevel 			if (localetheraddr(NULL, (struct ether_addr *)mac)) {
28973db86aabSstevel 				(void) ddi_prop_create(DDI_DEV_T_NONE,
28983db86aabSstevel 				    new_child,
28993db86aabSstevel 				    DDI_PROP_CANSLEEP, "local-mac-address",
29003db86aabSstevel 				    (caddr_t)mac, 6);
29013db86aabSstevel 			}
29023db86aabSstevel 		}
29033db86aabSstevel leaf_node:
29043db86aabSstevel 		if (cbp->cb_dsp) {
29053db86aabSstevel 			struct cb_deviceset_props *cdsp = cbp->cb_dsp;
29063db86aabSstevel 			uint16_t venid = pci_config_get16(config_handle,
29073db86aabSstevel 						PCI_CONF_VENID);
29083db86aabSstevel 			uint16_t devid = pci_config_get16(config_handle,
29093db86aabSstevel 						PCI_CONF_DEVID);
29103db86aabSstevel 			ddi_prop_t *propp;
29113db86aabSstevel 
29123db86aabSstevel 			for (cdsp = cbp->cb_dsp; cdsp; cdsp = cdsp->next) {
29133db86aabSstevel 				if (cdsp->binding_name &&
29143db86aabSstevel 				    strcmp(ddi_binding_name(new_child),
29153db86aabSstevel 				    cdsp->binding_name))
29163db86aabSstevel 					continue;
29173db86aabSstevel 				if (cdsp->venid && (cdsp->venid != venid))
29183db86aabSstevel 					continue;
29193db86aabSstevel 				if (cdsp->devid && (cdsp->devid != devid))
29203db86aabSstevel 					continue;
29213db86aabSstevel 				if (cdsp->nodename) {
29223db86aabSstevel 					if (ndi_devi_set_nodename(new_child,
29233db86aabSstevel 					    cdsp->nodename,
29243db86aabSstevel 					    0) != NDI_SUCCESS)
29253db86aabSstevel 						cardbus_err(new_child, 1,
29263db86aabSstevel 						    "Failed to set nodename\n");
29273db86aabSstevel 				}
29283db86aabSstevel 				for (propp = cdsp->prop_list; propp;
29293db86aabSstevel 				    propp = propp->prop_next) {
29303db86aabSstevel 					switch (propp->prop_flags) {
29313db86aabSstevel 					case DDI_PROP_TYPE_INT:
29323db86aabSstevel 						cardbus_force_intprop(
29333db86aabSstevel 						    new_child,
29343db86aabSstevel 						    propp->prop_name,
29353db86aabSstevel 						    (int *)propp->prop_val,
29363db86aabSstevel 						    propp->prop_len);
29373db86aabSstevel 						break;
29383db86aabSstevel 					case DDI_PROP_TYPE_STRING:
29393db86aabSstevel 						cardbus_force_stringprop(
29403db86aabSstevel 						    new_child,
29413db86aabSstevel 						    propp->prop_name,
29423db86aabSstevel 						    (char *)propp->prop_val);
29433db86aabSstevel 						break;
29443db86aabSstevel 					case DDI_PROP_TYPE_ANY:
29453db86aabSstevel 						cardbus_force_boolprop(
29463db86aabSstevel 						    new_child,
29473db86aabSstevel 						    propp->prop_name);
29483db86aabSstevel 						break;
29493db86aabSstevel 					}
29503db86aabSstevel 				}
29513db86aabSstevel 			}
29523db86aabSstevel 		}
29533db86aabSstevel 
29543db86aabSstevel #if defined(CARDBUS_DEBUG)
29553db86aabSstevel 		if (cardbus_debug >= 9) {
29563db86aabSstevel 			cardbus_dump_config(config_handle);
29573db86aabSstevel 		}
29583db86aabSstevel #endif
29593db86aabSstevel 
29603db86aabSstevel 		i = PCI_CONF_BASE0;
29613db86aabSstevel 
29623db86aabSstevel 		while (i <= PCI_CONF_BASE5) {
29633db86aabSstevel 			pci_config_put32(config_handle, i, 0xffffffff);
29643db86aabSstevel 
29653db86aabSstevel 			request = pci_config_get32(config_handle, i);
29663db86aabSstevel 
29673db86aabSstevel 			/*
29683db86aabSstevel 			 * If its a zero length, don't do
29693db86aabSstevel 			 * any programming.
29703db86aabSstevel 			 */
29713db86aabSstevel 			if (request != 0) {
29723db86aabSstevel 				if (request == (uint32_t)0xffffffff) {
29733db86aabSstevel 					cmn_err(CE_WARN,
29743db86aabSstevel 					    "cardbus_probe_children: "
29753db86aabSstevel 					    "can't access device");
29763db86aabSstevel 					goto failedchild;
29773db86aabSstevel 				}
29783db86aabSstevel 				/*
29793db86aabSstevel 				 * Add to the "reg" property
29803db86aabSstevel 				 */
29813db86aabSstevel 				if (cardbus_update_reg_prop(new_child,
29823db86aabSstevel 				    request, i) != PCICFG_SUCCESS) {
29833db86aabSstevel 					goto failedchild;
29843db86aabSstevel 				}
29853db86aabSstevel 			} else {
29863db86aabSstevel 				cardbus_err(parent, 8, "All memory found\n");
29873db86aabSstevel 				break;
29883db86aabSstevel 			}
29893db86aabSstevel 
29903db86aabSstevel 			/*
29913db86aabSstevel 			 * Increment by eight if it is 64 bit address space
29923db86aabSstevel 			 * only if memory space
29933db86aabSstevel 			 */
29943db86aabSstevel 			if (((PCI_BASE_TYPE_M & request)
29953db86aabSstevel 				== PCI_BASE_TYPE_ALL) &&
29963db86aabSstevel 			    ((PCI_BASE_SPACE_M & request)
29973db86aabSstevel 				== PCI_BASE_SPACE_MEM)) {
29983db86aabSstevel 				cardbus_err(parent, 8,
29993db86aabSstevel 				    "BASE register [0x%x] asks for "
30003db86aabSstevel 				    "[0x%x]=[0x%x] (64)\n",
30013db86aabSstevel 				    i, request,
30023db86aabSstevel 				    (~(PCI_BASE_M_ADDR_M & request))+1);
30033db86aabSstevel 				i += 8;
30043db86aabSstevel 			} else {
30053db86aabSstevel 				cardbus_err(parent, 8,
30063db86aabSstevel 				    "BASE register [0x%x] asks for "
30073db86aabSstevel 				    "[0x%x]=[0x%x](32)\n",
30083db86aabSstevel 				    i, request,
30093db86aabSstevel 				    (~(PCI_BASE_M_ADDR_M & request))+1);
30103db86aabSstevel 				i += 4;
30113db86aabSstevel 			}
30123db86aabSstevel 		}
30133db86aabSstevel 
30143db86aabSstevel 		/*
30153db86aabSstevel 		 * Get the ROM size and create register for it
30163db86aabSstevel 		 */
30173db86aabSstevel 		pci_config_put32(config_handle, PCI_CONF_ROM, 0xffffffff);
30183db86aabSstevel 
30193db86aabSstevel 		request = pci_config_get32(config_handle, PCI_CONF_ROM);
30203db86aabSstevel 		/*
30213db86aabSstevel 		 * If its a zero length, don't do
30223db86aabSstevel 		 * any programming.
30233db86aabSstevel 		 */
30243db86aabSstevel 
30253db86aabSstevel 		if (request != 0) {
30263db86aabSstevel 			cardbus_err(parent, 9,
30273db86aabSstevel 			    "BASE register [0x%x] asks for "
30283db86aabSstevel 			    "[0x%x]=[0x%x] (ROM)\n",
30293db86aabSstevel 			    PCI_CONF_ROM, request,
30303db86aabSstevel 			    (~(PCI_BASE_ROM_ADDR_M & request))+1);
30313db86aabSstevel 			/*
30323db86aabSstevel 			 * Add to the "reg" property
30333db86aabSstevel 			 */
30343db86aabSstevel 			if (cardbus_update_reg_prop(new_child,
30353db86aabSstevel 			    request,
30363db86aabSstevel 			    PCI_CONF_ROM) != PCICFG_SUCCESS) {
30373db86aabSstevel 				goto failedchild;
30383db86aabSstevel 			}
30393db86aabSstevel 		}
30403db86aabSstevel 	}
30413db86aabSstevel 
30423db86aabSstevel 	(void) cardbus_config_teardown(&config_handle);
30433db86aabSstevel 
30443db86aabSstevel 	/*
30453db86aabSstevel 	 * Attach the child to its parent
30463db86aabSstevel 	 */
30473db86aabSstevel 	(void) i_ndi_config_node(new_child, DS_LINKED, 0);
30483db86aabSstevel 	ndi_devi_exit(parent, circ);
30493db86aabSstevel 
30503db86aabSstevel 	return (PCICFG_SUCCESS);
30513db86aabSstevel failedchild:
30523db86aabSstevel 	/*
30533db86aabSstevel 	 * check if it should be taken offline (if online)
30543db86aabSstevel 	 */
30553db86aabSstevel 	(void) cardbus_config_teardown(&config_handle);
30563db86aabSstevel 
30573db86aabSstevel failedconfig:
30583db86aabSstevel 
30593db86aabSstevel 	(void) ndi_devi_free(new_child);
30603db86aabSstevel 	ndi_devi_exit(parent, circ);
30613db86aabSstevel 
30623db86aabSstevel 	return (PCICFG_FAILURE);
30633db86aabSstevel }
30643db86aabSstevel 
30653db86aabSstevel static int
30663db86aabSstevel cardbus_add_config_reg(dev_info_t *dip,
30673db86aabSstevel 		uint_t bus, uint_t device, uint_t func)
30683db86aabSstevel {
30693db86aabSstevel 	int reg[10] = { PCI_ADDR_CONFIG, 0, 0, 0, 0};
30703db86aabSstevel 
30713db86aabSstevel 	reg[0] = PCICFG_MAKE_REG_HIGH(bus, device, func, 0);
30723db86aabSstevel 
30733db86aabSstevel 	return (ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
30743db86aabSstevel 	    "reg", reg, 5));
30753db86aabSstevel }
30763db86aabSstevel 
30773db86aabSstevel static int
30783db86aabSstevel cardbus_add_isa_node(cbus_t *cbp, dev_info_t *parent, struct isa_node *node)
30793db86aabSstevel {
30803db86aabSstevel 	dev_info_t		*new_child;
30813db86aabSstevel 	int			ret;
30823db86aabSstevel 	uint32_t		reg[3];
30833db86aabSstevel 
30843db86aabSstevel 	_NOTE(ARGUNUSED(cbp))
30853db86aabSstevel 
30863db86aabSstevel 	cardbus_err(parent, 6, "cardbus_add_isa_node\n");
30873db86aabSstevel 
30883db86aabSstevel 	/*
30893db86aabSstevel 	 * This node will be put immediately below
30903db86aabSstevel 	 * "parent". Allocate a blank device node.
30913db86aabSstevel 	 */
30923db86aabSstevel 	if (ndi_devi_alloc(parent, DEVI_PSEUDO_NEXNAME,
30933db86aabSstevel 	    (pnode_t)DEVI_SID_NODEID,
30943db86aabSstevel 	    &new_child) != NDI_SUCCESS) {
30953db86aabSstevel 		cardbus_err(parent, 1,
30963db86aabSstevel 		    "cardbus_add_isa_child(): Failed to alloc child node\n");
30973db86aabSstevel 		return (PCICFG_FAILURE);
30983db86aabSstevel 	}
30993db86aabSstevel 
31003db86aabSstevel 	/*
31013db86aabSstevel 	 * Set properties common to ISA devices
31023db86aabSstevel 	 */
31033db86aabSstevel 	if (cardbus_set_isa_props(parent, new_child, node->name,
31043db86aabSstevel 	    node->compatible) != PCICFG_SUCCESS) {
31053db86aabSstevel 		cardbus_err(parent, 1, "Failed to set ISA properties\n");
31063db86aabSstevel 		goto failed;
31073db86aabSstevel 	}
31083db86aabSstevel 
31093db86aabSstevel 	cardbus_err(new_child, 8, "--Leaf ISA device\n");
31103db86aabSstevel 
31113db86aabSstevel 	/*
31123db86aabSstevel 	 * Add the "reg" property.
31133db86aabSstevel 	 */
31143db86aabSstevel 	reg[0] = 0;
31153db86aabSstevel 	reg[1] = node->reg;
31163db86aabSstevel 	reg[2] = node->span;
31173db86aabSstevel 
31183db86aabSstevel 	ret = ndi_prop_update_int_array(DDI_DEV_T_NONE, new_child,
31193db86aabSstevel 	    "basereg", (int *)reg, 3);
31203db86aabSstevel 	if (ret != DDI_SUCCESS)
31213db86aabSstevel 		goto failed;
31223db86aabSstevel 
31233db86aabSstevel 	(void) i_ndi_config_node(new_child, DS_LINKED, 0);
31243db86aabSstevel 
31253db86aabSstevel 	return (PCICFG_SUCCESS);
31263db86aabSstevel 
31273db86aabSstevel failed:
31283db86aabSstevel 	(void) ndi_devi_free(new_child);
31293db86aabSstevel 
31303db86aabSstevel 	return (PCICFG_FAILURE);
31313db86aabSstevel }
31323db86aabSstevel 
31333db86aabSstevel static int
31343db86aabSstevel cardbus_config_setup(dev_info_t *dip, ddi_acc_handle_t *handle)
31353db86aabSstevel {
31363db86aabSstevel 	caddr_t		cfgaddr;
31373db86aabSstevel 	ddi_device_acc_attr_t	attr;
31383db86aabSstevel 	dev_info_t	*anode;
31393db86aabSstevel 	int	status;
31403db86aabSstevel 	int	rlen;
31413db86aabSstevel 	pci_regspec_t	*reg;
31423db86aabSstevel 	int		ret;
31433db86aabSstevel #ifdef sparc
31443db86aabSstevel 	int16_t		val;
31453db86aabSstevel #endif
31463db86aabSstevel 
31473db86aabSstevel 	cardbus_err(dip, 10,
31483db86aabSstevel 	    "cardbus_config_setup(dip=0x%p)\n", (void *) dip);
31493db86aabSstevel 
31503db86aabSstevel 	/*
31513db86aabSstevel 	 * Get the pci register spec from the node
31523db86aabSstevel 	 */
31533db86aabSstevel 	status = ddi_getlongprop(DDI_DEV_T_NONE,
31543db86aabSstevel 	    dip, DDI_PROP_DONTPASS, "reg",
31553db86aabSstevel 	    (caddr_t)&reg, &rlen);
31563db86aabSstevel 
31573db86aabSstevel 	cardbus_err(dip, 10,
31583db86aabSstevel 	    "cardbus_config_setup, reg = 0x%p\n", (void *) reg);
31593db86aabSstevel 
31603db86aabSstevel 	switch (status) {
31613db86aabSstevel 	case DDI_PROP_SUCCESS:
31623db86aabSstevel 		break;
31633db86aabSstevel 	case DDI_PROP_NO_MEMORY:
31643db86aabSstevel 		cardbus_err(dip, 1, "reg present, but unable to get memory\n");
31653db86aabSstevel 		return (PCICFG_FAILURE);
31663db86aabSstevel 	default:
31673db86aabSstevel 		cardbus_err(dip, 1, "no reg property\n");
31683db86aabSstevel 		return (PCICFG_FAILURE);
31693db86aabSstevel 	}
31703db86aabSstevel 
31713db86aabSstevel 	anode = dip;
31723db86aabSstevel 
31733db86aabSstevel 	/*
31743db86aabSstevel 	 * Find the attachment point node
31753db86aabSstevel 	 */
31763db86aabSstevel 	while ((anode != NULL) && (strcmp(ddi_binding_name(anode),
31773db86aabSstevel 	    "hp_attachment") != 0)) {
31783db86aabSstevel 		anode = ddi_get_parent(anode);
31793db86aabSstevel 	}
31803db86aabSstevel 
31813db86aabSstevel 	if (anode == NULL) {
31823db86aabSstevel 		cardbus_err(dip, 1, "Tree not in PROBE state\n");
31833db86aabSstevel 		kmem_free((caddr_t)reg, rlen);
31843db86aabSstevel 		return (PCICFG_FAILURE);
31853db86aabSstevel 	}
31863db86aabSstevel 
31873db86aabSstevel 	if ((ret = ndi_prop_update_int_array(DDI_DEV_T_NONE, anode,
31883db86aabSstevel 	    "reg", (int *)reg, 5)) != 0) {
31893db86aabSstevel 		cardbus_err(dip, 1,
31903db86aabSstevel 		    "Failed to update reg property, error code %d\n", ret);
31913db86aabSstevel 		kmem_free((caddr_t)reg, rlen);
31923db86aabSstevel 		return (PCICFG_FAILURE);
31933db86aabSstevel 	}
31943db86aabSstevel 
31953db86aabSstevel 	attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
31963db86aabSstevel 	attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
31973db86aabSstevel 	attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
31983db86aabSstevel 
31993db86aabSstevel 	if (ddi_regs_map_setup(anode, 0, &cfgaddr,
32003db86aabSstevel 	    0, /* PCI_CONF_HDR_SIZE */
32013db86aabSstevel 	    0,
32023db86aabSstevel 	    &attr, handle) != DDI_SUCCESS) {
32033db86aabSstevel 		cardbus_err(dip, 1,
32043db86aabSstevel 		    "Failed to setup registers for [0x%x][0x%x][0x%x]\n",
32053db86aabSstevel 		    PCI_REG_BUS_G(reg->pci_phys_hi),
32063db86aabSstevel 		    PCI_REG_DEV_G(reg->pci_phys_hi),
32073db86aabSstevel 		    PCI_REG_FUNC_G(reg->pci_phys_hi));
32083db86aabSstevel 		kmem_free((caddr_t)reg, rlen);
32093db86aabSstevel 		return (PCICFG_FAILURE);
32103db86aabSstevel 	}
32113db86aabSstevel 
32123db86aabSstevel 	cardbus_err(dip, 9,
32133db86aabSstevel 	    "PROBING =>->->->->->-> [0x%x][0x%x][0x%x] 0x%x 0x%p\n",
32143db86aabSstevel 	    PCI_REG_BUS_G(reg->pci_phys_hi),
32153db86aabSstevel 	    PCI_REG_DEV_G(reg->pci_phys_hi),
32163db86aabSstevel 	    PCI_REG_FUNC_G(reg->pci_phys_hi),
32173db86aabSstevel 	    reg->pci_phys_hi, (void *) cfgaddr);
32183db86aabSstevel 
32193db86aabSstevel 	/*
32203db86aabSstevel 	 * must do peek16 otherwise the system crashes when probing
32213db86aabSstevel 	 * a non zero function on a non-multi-function card.
32223db86aabSstevel 	 */
32233db86aabSstevel #ifdef sparc
32243db86aabSstevel 	if (ddi_peek16(anode, (int16_t *)cfgaddr, &val) != DDI_SUCCESS) {
32253db86aabSstevel 		cardbus_err(dip, 8,
32263db86aabSstevel 		    "cardbus_config_setup peek failed\n");
32273db86aabSstevel 		ret = PCICFG_NODEVICE;
32283db86aabSstevel 	} else if (ddi_get16(*handle, (uint16_t *)cfgaddr) == 0xffff) {
32293db86aabSstevel 		cardbus_err(dip, 8,
32303db86aabSstevel 		    "cardbus_config_setup PCICFG_NODEVICE\n");
32313db86aabSstevel 		ret = PCICFG_NODEVICE;
32323db86aabSstevel #elif defined(__x86) || defined(__amd64)
32333db86aabSstevel 	if (ddi_get16(*handle, (uint16_t *)cfgaddr) == 0xffff) {
32343db86aabSstevel 		cardbus_err(dip, 8,
32353db86aabSstevel 		    "cardbus_config_setup PCICFG_NODEVICE\n");
32363db86aabSstevel 		ret = PCICFG_NODEVICE;
32373db86aabSstevel #endif
32383db86aabSstevel 	} else {
32393db86aabSstevel 		cardbus_err(dip, 1,
32403db86aabSstevel 		    "cardbus_config_setup found device at:[0x%x][0x%x][0x%x]\n",
32413db86aabSstevel 		    PCI_REG_BUS_G(reg->pci_phys_hi),
32423db86aabSstevel 		    PCI_REG_DEV_G(reg->pci_phys_hi),
32433db86aabSstevel 		    PCI_REG_FUNC_G(reg->pci_phys_hi));
32443db86aabSstevel 
32453db86aabSstevel 		ret = PCICFG_SUCCESS;
32463db86aabSstevel 	}
32473db86aabSstevel 
32483db86aabSstevel 	kmem_free((caddr_t)reg, rlen);
32493db86aabSstevel 	if (ret != PCICFG_SUCCESS) {
32503db86aabSstevel 		cardbus_config_teardown(handle);
32513db86aabSstevel 	}
32523db86aabSstevel 
32533db86aabSstevel 	cardbus_err(dip, 7,
32543db86aabSstevel 	    "cardbus_config_setup returning %d\n", ret);
32553db86aabSstevel 
32563db86aabSstevel 	return (ret);
32573db86aabSstevel }
32583db86aabSstevel 
32593db86aabSstevel static void
32603db86aabSstevel cardbus_config_teardown(ddi_acc_handle_t *handle)
32613db86aabSstevel {
32623db86aabSstevel 	(void) ddi_regs_map_free(handle);
32633db86aabSstevel }
32643db86aabSstevel 
32653db86aabSstevel static void
32663db86aabSstevel cardbus_reparent_children(dev_info_t *dip, dev_info_t *parent)
32673db86aabSstevel {
32683db86aabSstevel 	dev_info_t *child;
32693db86aabSstevel 	int circ;
32703db86aabSstevel 
32713db86aabSstevel 	while (child = ddi_get_child(dip)) {
32723db86aabSstevel 		ASSERT(i_ddi_node_state(child) <= DS_LINKED);
32733db86aabSstevel 		/*
32743db86aabSstevel 		 * Unlink node from tree before reparenting
32753db86aabSstevel 		 */
32763db86aabSstevel 		ndi_devi_enter(dip, &circ);
32773db86aabSstevel 		(void) i_ndi_unconfig_node(child, DS_PROTO, 0);
32783db86aabSstevel 		ndi_devi_exit(dip, circ);
32793db86aabSstevel 		DEVI(child)->devi_parent = DEVI(parent);
32803db86aabSstevel 		DEVI(child)->devi_bus_ctl = DEVI(parent);
32813db86aabSstevel 		ndi_devi_enter(parent, &circ);
32823db86aabSstevel 		(void) i_ndi_config_node(child, DS_LINKED, 0);
32833db86aabSstevel 		ndi_devi_exit(parent, circ);
32843db86aabSstevel 	}
32853db86aabSstevel }
32863db86aabSstevel 
32873db86aabSstevel static int
32883db86aabSstevel cardbus_update_assigned_prop(dev_info_t *dip, pci_regspec_t *newone)
32893db86aabSstevel {
32903db86aabSstevel 	int		alen;
32913db86aabSstevel 	pci_regspec_t	*assigned;
32923db86aabSstevel 	caddr_t		newreg;
32933db86aabSstevel 	uint_t		status;
32943db86aabSstevel 
32953db86aabSstevel 	status = ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS,
32963db86aabSstevel 	    "assigned-addresses", (caddr_t)&assigned, &alen);
32973db86aabSstevel 	switch (status) {
32983db86aabSstevel 	case DDI_PROP_SUCCESS:
32993db86aabSstevel 		cardbus_err(dip, 5,
33003db86aabSstevel 		    "cardbus_update_assigned_prop: found prop len %d\n",
33013db86aabSstevel 		    alen);
33023db86aabSstevel 		/*
33033db86aabSstevel 		 * Allocate memory for the existing
33043db86aabSstevel 		 * assigned-addresses(s) plus one and then
33053db86aabSstevel 		 * build it.
33063db86aabSstevel 		 */
33073db86aabSstevel 		newreg = kmem_zalloc(alen+sizeof (*newone), KM_SLEEP);
33083db86aabSstevel 
33093db86aabSstevel 		bcopy(assigned, newreg, alen);
33103db86aabSstevel 		bcopy(newone, newreg + alen, sizeof (*newone));
33113db86aabSstevel 		break;
33123db86aabSstevel 
33133db86aabSstevel 	case DDI_PROP_NO_MEMORY:
33143db86aabSstevel 		cardbus_err(dip, 1,
33153db86aabSstevel 		    "no memory for assigned-addresses property\n");
33163db86aabSstevel 		return (PCICFG_FAILURE);
33173db86aabSstevel 
33183db86aabSstevel 	default:
33193db86aabSstevel 		cardbus_err(dip, 5,
33203db86aabSstevel 		    "cardbus_update_assigned_prop: creating prop\n");
33213db86aabSstevel 		alen = 0;
33223db86aabSstevel 		newreg = (caddr_t)newone;
33233db86aabSstevel 		break;
33243db86aabSstevel 	}
33253db86aabSstevel 
33263db86aabSstevel 	/*
33273db86aabSstevel 	 * Write out the new "assigned-addresses" spec
33283db86aabSstevel 	 */
33293db86aabSstevel 	(void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
33303db86aabSstevel 	    "assigned-addresses", (int *)newreg,
33313db86aabSstevel 	    (alen + sizeof (*newone))/sizeof (int));
33323db86aabSstevel 
33333db86aabSstevel 	if (status == DDI_PROP_SUCCESS)
33343db86aabSstevel 		kmem_free((caddr_t)newreg, alen+sizeof (*newone));
33353db86aabSstevel 
33363db86aabSstevel 	if (alen)
33373db86aabSstevel 		kmem_free(assigned, alen);
33383db86aabSstevel 
33393db86aabSstevel 	return (PCICFG_SUCCESS);
33403db86aabSstevel }
33413db86aabSstevel 
33423db86aabSstevel static int
33433db86aabSstevel cardbus_update_available_prop(dev_info_t *dip, uint32_t hi_type,
33443db86aabSstevel 				uint64_t base, uint64_t size)
33453db86aabSstevel {
33463db86aabSstevel 	int		alen, rlen;
33473db86aabSstevel 	pci_regspec_t	*available, *reg;
33483db86aabSstevel 	pci_regspec_t	addition;
33493db86aabSstevel 	caddr_t		newreg;
33503db86aabSstevel 	uint_t		status;
33513db86aabSstevel 
33523db86aabSstevel 	cardbus_err(dip, 6, "cardbus_update_available_prop\n");
33533db86aabSstevel 
33543db86aabSstevel 	status = ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS,
33553db86aabSstevel 	    "reg", (caddr_t)&reg, &rlen);
33563db86aabSstevel 
33573db86aabSstevel 	switch (status) {
33583db86aabSstevel 	case DDI_PROP_SUCCESS:
33593db86aabSstevel 		break;
33603db86aabSstevel 	case DDI_PROP_NO_MEMORY:
33613db86aabSstevel 		cardbus_err(dip, 1, "reg present, but unable to get memory\n");
33623db86aabSstevel 		return (PCICFG_FAILURE);
33633db86aabSstevel 	default:
33643db86aabSstevel 		cardbus_err(dip, 1, "no reg property\n");
33653db86aabSstevel 		return (PCICFG_FAILURE);
33663db86aabSstevel 	}
33673db86aabSstevel 
33683db86aabSstevel 	status = ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS,
33693db86aabSstevel 	    "available", (caddr_t)&available, &alen);
33703db86aabSstevel 	switch (status) {
33713db86aabSstevel 	case DDI_PROP_SUCCESS:
33723db86aabSstevel 		break;
33733db86aabSstevel 	case DDI_PROP_NO_MEMORY:
33743db86aabSstevel 		cardbus_err(dip, 1, "no memory for available property\n");
33753db86aabSstevel 		kmem_free((caddr_t)reg, rlen);
33763db86aabSstevel 		return (PCICFG_FAILURE);
33773db86aabSstevel 	default:
33783db86aabSstevel 		alen = 0;
33793db86aabSstevel 	}
33803db86aabSstevel 
33813db86aabSstevel 	/*
33823db86aabSstevel 	 * Allocate memory for the existing
33833db86aabSstevel 	 * available(s) plus one and then
33843db86aabSstevel 	 * build it.
33853db86aabSstevel 	 */
33863db86aabSstevel 	newreg = kmem_zalloc(alen + sizeof (pci_regspec_t), KM_SLEEP);
33873db86aabSstevel 
33883db86aabSstevel 	/*
33893db86aabSstevel 	 * Build the regspec, then add it to the existing one(s)
33903db86aabSstevel 	 */
33913db86aabSstevel 	addition.pci_phys_hi = hi_type |
33923db86aabSstevel 	    PCICFG_MAKE_REG_HIGH(PCI_REG_BUS_G(reg->pci_phys_hi),
33933db86aabSstevel 	    PCI_REG_DEV_G(reg->pci_phys_hi),
33943db86aabSstevel 	    PCI_REG_FUNC_G(reg->pci_phys_hi), 0);
33953db86aabSstevel 
33963db86aabSstevel 	addition.pci_phys_mid = (uint32_t)((base>>32) & 0xffffffff);
33973db86aabSstevel 	addition.pci_phys_low = (uint32_t)(base & 0xffffffff);
33983db86aabSstevel 	addition.pci_size_hi = (uint32_t)((size>>32) & 0xffffffff);
33993db86aabSstevel 	addition.pci_size_low = (uint32_t)(size & 0xffffffff);
34003db86aabSstevel 
34013db86aabSstevel #ifdef DEBUG
34023db86aabSstevel 	cardbus_dump_reg(dip, &addition, 1);
34033db86aabSstevel #endif
34043db86aabSstevel 
34053db86aabSstevel 	if (alen)
34063db86aabSstevel 		bcopy(available, newreg, alen);
34073db86aabSstevel 	bcopy(&addition, newreg + alen, sizeof (pci_regspec_t));
34083db86aabSstevel 
34093db86aabSstevel 	/*
34103db86aabSstevel 	 * Write out the new "available" spec
34113db86aabSstevel 	 */
34123db86aabSstevel 	(void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
34133db86aabSstevel 	    "available", (int *)newreg,
34143db86aabSstevel 	    (alen + sizeof (pci_regspec_t))/sizeof (int));
34153db86aabSstevel 
34163db86aabSstevel 	if (alen)
34173db86aabSstevel 		kmem_free((caddr_t)available, alen);
34183db86aabSstevel 	kmem_free((caddr_t)reg, rlen);
34193db86aabSstevel 	kmem_free((caddr_t)newreg, alen + sizeof (pci_regspec_t));
34203db86aabSstevel 
34213db86aabSstevel 	return (PCICFG_SUCCESS);
34223db86aabSstevel }
34233db86aabSstevel 
34243db86aabSstevel static int
34253db86aabSstevel cardbus_update_ranges_prop(dev_info_t *dip, cardbus_range_t *addition)
34263db86aabSstevel {
34273db86aabSstevel 	int		rlen;
34283db86aabSstevel 	cardbus_range_t	*ranges;
34293db86aabSstevel 	caddr_t		newreg;
34303db86aabSstevel 	uint_t		status;
34313db86aabSstevel #if defined(CARDBUS_DEBUG)
34323db86aabSstevel 	int	i, nrange;
34333db86aabSstevel 	const cardbus_range_t	*nr;
34343db86aabSstevel #endif
34353db86aabSstevel 
34363db86aabSstevel 	cardbus_err(dip, 6, "cardbus_update_ranges_prop\n");
34373db86aabSstevel 
34383db86aabSstevel 	status = ddi_getlongprop(DDI_DEV_T_NONE,
34393db86aabSstevel 	    dip, DDI_PROP_DONTPASS, "ranges",
34403db86aabSstevel 	    (caddr_t)&ranges, &rlen);
34413db86aabSstevel 
34423db86aabSstevel 	switch (status) {
34433db86aabSstevel 	case DDI_PROP_SUCCESS:
34443db86aabSstevel 		break;
34453db86aabSstevel 	case DDI_PROP_NO_MEMORY:
34463db86aabSstevel 		cardbus_err(dip, 1,
34473db86aabSstevel 		    "ranges present, but unable to get memory\n");
34483db86aabSstevel 		return (PCICFG_FAILURE);
34493db86aabSstevel 	default:
34503db86aabSstevel 		cardbus_err(dip, 8, "no ranges property - creating one\n");
34513db86aabSstevel 		if (ndi_prop_update_int_array(DDI_DEV_T_NONE,
34523db86aabSstevel 		    dip, "ranges", (int *)addition,
34533db86aabSstevel 		    sizeof (cardbus_range_t)/sizeof (int))
34543db86aabSstevel 		    != DDI_SUCCESS) {
34553db86aabSstevel 			cardbus_err(dip, 1, "Did'nt create ranges property\n");
34563db86aabSstevel 			return (PCICFG_FAILURE);
34573db86aabSstevel 		}
34583db86aabSstevel 		return (PCICFG_SUCCESS);
34593db86aabSstevel 	}
34603db86aabSstevel 
34613db86aabSstevel 	/*
34623db86aabSstevel 	 * Allocate memory for the existing reg(s) plus one and then
34633db86aabSstevel 	 * build it.
34643db86aabSstevel 	 */
34653db86aabSstevel 	newreg = kmem_zalloc(rlen+sizeof (cardbus_range_t), KM_SLEEP);
34663db86aabSstevel 
34673db86aabSstevel 	bcopy(ranges, newreg, rlen);
34683db86aabSstevel 	bcopy(addition, newreg + rlen, sizeof (cardbus_range_t));
34693db86aabSstevel 
34703db86aabSstevel 	/*
34713db86aabSstevel 	 * Write out the new "ranges" property
34723db86aabSstevel 	 */
34733db86aabSstevel 	(void) ndi_prop_update_int_array(DDI_DEV_T_NONE,
34743db86aabSstevel 	    dip, "ranges", (int *)newreg,
34753db86aabSstevel 	    (rlen + sizeof (cardbus_range_t))/sizeof (int));
34763db86aabSstevel 
34773db86aabSstevel #if defined(CARDBUS_DEBUG)
34783db86aabSstevel 	cardbus_err(dip, 8, "cardbus_update_ranges_prop ranges property:\n");
34793db86aabSstevel 
34803db86aabSstevel 	nrange = rlen / sizeof (cardbus_range_t);
34813db86aabSstevel 	nr = (cardbus_range_t *)newreg;
34823db86aabSstevel 	for (i = 0; i <= nrange; i++) {
34833db86aabSstevel 		/* nrange is one higher for new entry */
34843db86aabSstevel 		cardbus_err(dip, 9,
34853db86aabSstevel 		    "\trange parent addr 0x%x.0x%x.0x%x "
34863db86aabSstevel 		    "child addr 0x%x.0x%x.0x%x size 0x%x.0x%x\n",
34873db86aabSstevel 		    nr->parent_hi,
34883db86aabSstevel 		    nr->parent_mid, nr->parent_lo,
34893db86aabSstevel 		    nr->child_hi,
34903db86aabSstevel 		    nr->child_mid, nr->child_lo,
34913db86aabSstevel 		    nr->size_hi, nr->size_lo);
34923db86aabSstevel 		nr++;
34933db86aabSstevel 	}
34943db86aabSstevel #endif
34953db86aabSstevel 
34963db86aabSstevel 	kmem_free((caddr_t)newreg, rlen+sizeof (cardbus_range_t));
34973db86aabSstevel 	kmem_free((caddr_t)ranges, rlen);
34983db86aabSstevel 
34993db86aabSstevel 	return (PCICFG_SUCCESS);
35003db86aabSstevel }
35013db86aabSstevel 
35023db86aabSstevel static int
35033db86aabSstevel cardbus_update_reg_prop(dev_info_t *dip, uint32_t regvalue, uint_t reg_offset)
35043db86aabSstevel {
35053db86aabSstevel 	int	rlen;
35063db86aabSstevel 	pci_regspec_t	*reg;
35073db86aabSstevel 	caddr_t		newreg;
35083db86aabSstevel 	uint32_t	hiword;
35093db86aabSstevel 	pci_regspec_t	addition;
35103db86aabSstevel 	uint32_t	size;
35113db86aabSstevel 	uint_t		status;
35123db86aabSstevel 
35133db86aabSstevel 	status = ddi_getlongprop(DDI_DEV_T_NONE,
35143db86aabSstevel 	    dip, DDI_PROP_DONTPASS, "reg", (caddr_t)&reg, &rlen);
35153db86aabSstevel 
35163db86aabSstevel 	switch (status) {
35173db86aabSstevel 	case DDI_PROP_SUCCESS:
35183db86aabSstevel 		break;
35193db86aabSstevel 	case DDI_PROP_NO_MEMORY:
35203db86aabSstevel 		cardbus_err(dip, 1, "reg present, but unable to get memory\n");
35213db86aabSstevel 		return (PCICFG_FAILURE);
35223db86aabSstevel 	default:
35233db86aabSstevel 		cardbus_err(dip, 1, "no reg property\n");
35243db86aabSstevel 		return (PCICFG_FAILURE);
35253db86aabSstevel 	}
35263db86aabSstevel 
35273db86aabSstevel 	/*
35283db86aabSstevel 	 * Allocate memory for the existing reg(s) plus one and then
35293db86aabSstevel 	 * build it.
35303db86aabSstevel 	 */
35313db86aabSstevel 	newreg = kmem_zalloc(rlen+sizeof (pci_regspec_t), KM_SLEEP);
35323db86aabSstevel 
35333db86aabSstevel 	/*
35343db86aabSstevel 	 * Build the regspec, then add it to the existing one(s)
35353db86aabSstevel 	 */
35363db86aabSstevel 	hiword = PCICFG_MAKE_REG_HIGH(PCI_REG_BUS_G(reg->pci_phys_hi),
35373db86aabSstevel 			PCI_REG_DEV_G(reg->pci_phys_hi),
35383db86aabSstevel 			PCI_REG_FUNC_G(reg->pci_phys_hi),
35393db86aabSstevel 			reg_offset);
35403db86aabSstevel 
35413db86aabSstevel 	if (reg_offset == PCI_CONF_ROM) {
35423db86aabSstevel 		size = (~(PCI_BASE_ROM_ADDR_M & regvalue))+1;
35433db86aabSstevel 		hiword |= PCI_ADDR_MEM32;
35443db86aabSstevel 	} else {
35453db86aabSstevel 		size = (~(PCI_BASE_M_ADDR_M & regvalue))+1;
35463db86aabSstevel 
35473db86aabSstevel 		if ((PCI_BASE_SPACE_M & regvalue) == PCI_BASE_SPACE_MEM) {
35483db86aabSstevel 			if ((PCI_BASE_TYPE_M & regvalue) == PCI_BASE_TYPE_MEM) {
35493db86aabSstevel 				hiword |= PCI_ADDR_MEM32;
35503db86aabSstevel 			} else if ((PCI_BASE_TYPE_M & regvalue)
35513db86aabSstevel 				    == PCI_BASE_TYPE_ALL) {
35523db86aabSstevel 				/*
35533db86aabSstevel 				 * This is a 64 bit PCI memory space.
35543db86aabSstevel 				 * It needs to be allocated as 32 bit
35553db86aabSstevel 				 * for bus map purposes.
35563db86aabSstevel 				 */
35573db86aabSstevel 				hiword |= PCI_ADDR_MEM32;
35583db86aabSstevel 			}
35593db86aabSstevel 		} else {
35603db86aabSstevel 			hiword |= PCI_ADDR_IO;
35613db86aabSstevel 		}
35623db86aabSstevel 	}
35633db86aabSstevel 
35643db86aabSstevel 	addition.pci_phys_hi = hiword;
35653db86aabSstevel 	addition.pci_phys_mid = 0;
35663db86aabSstevel 	addition.pci_phys_low = 0;
35673db86aabSstevel 	addition.pci_size_hi = 0;
35683db86aabSstevel 	addition.pci_size_low = size;
35693db86aabSstevel 
35703db86aabSstevel 	cardbus_err(dip, 8,
35713db86aabSstevel 	    "cardbus_update_reg_prop, phys_hi 0x%08x,"
35723db86aabSstevel 	    " phys_mid 0x%08x, phys_low 0x%08x, size_hi 0x%08x,"
35733db86aabSstevel 	    " size_low 0x%08x\n", hiword, 0, 0, 0, size);
35743db86aabSstevel 
35753db86aabSstevel 	bcopy(reg, newreg, rlen);
35763db86aabSstevel 	bcopy(&addition, newreg + rlen, sizeof (pci_regspec_t));
35773db86aabSstevel 
35783db86aabSstevel 	/*
35793db86aabSstevel 	 * Write out the new "reg" property
35803db86aabSstevel 	 */
35813db86aabSstevel 	(void) ndi_prop_update_int_array(DDI_DEV_T_NONE,
35823db86aabSstevel 	    dip, "reg", (int *)newreg,
35833db86aabSstevel 	    (rlen + sizeof (pci_regspec_t))/sizeof (int));
35843db86aabSstevel 
35853db86aabSstevel 	kmem_free((caddr_t)reg, rlen);
35863db86aabSstevel 	kmem_free((caddr_t)newreg, rlen+sizeof (pci_regspec_t));
35873db86aabSstevel 
35883db86aabSstevel 	return (PCICFG_SUCCESS);
35893db86aabSstevel }
35903db86aabSstevel 
35913db86aabSstevel /*
35923db86aabSstevel  * Setup the basic 1275 properties based on information found in the config
35933db86aabSstevel  * header of the PCI device
35943db86aabSstevel  */
35953db86aabSstevel static int
35963db86aabSstevel cardbus_set_standard_props(dev_info_t *parent, dev_info_t *dip,
35973db86aabSstevel 			ddi_acc_handle_t config_handle)
35983db86aabSstevel {
35993db86aabSstevel 	int ret;
36003db86aabSstevel 	uint16_t val;
36013db86aabSstevel 	uint32_t wordval;
36023db86aabSstevel 	uint8_t byteval;
36033db86aabSstevel 
36043db86aabSstevel 	/* These two exists only for non-bridges */
36053db86aabSstevel 	if ((pci_config_get8(config_handle,
36063db86aabSstevel 	    PCI_CONF_HEADER) & PCI_HEADER_TYPE_M) == PCI_HEADER_ZERO) {
36073db86aabSstevel 		byteval = pci_config_get8(config_handle, PCI_CONF_MIN_G);
36083db86aabSstevel 		if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
36093db86aabSstevel 		    "min-grant", byteval)) != DDI_SUCCESS) {
36103db86aabSstevel 			cardbus_err(dip, 1, "Failed to sent min-grant\n");
36113db86aabSstevel 			return (ret);
36123db86aabSstevel 		}
36133db86aabSstevel 
36143db86aabSstevel 		byteval = pci_config_get8(config_handle, PCI_CONF_MAX_L);
36153db86aabSstevel 		if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
36163db86aabSstevel 		    "max-latency", byteval)) != DDI_SUCCESS) {
36173db86aabSstevel 			return (ret);
36183db86aabSstevel 		}
36193db86aabSstevel 	}
36203db86aabSstevel 
36213db86aabSstevel 	/*
36223db86aabSstevel 	 * These should always exist and have the value of the
36233db86aabSstevel 	 * corresponding register value
36243db86aabSstevel 	 */
36253db86aabSstevel 	val = pci_config_get16(config_handle, PCI_CONF_VENID);
36263db86aabSstevel 
36273db86aabSstevel 	/*
36283db86aabSstevel 	 * according to section 6.2.1 of revision 2 of the PCI local
36293db86aabSstevel 	 * bus specification - 0FFFFh is an invalid value for the vendor ID
36303db86aabSstevel 	 */
36313db86aabSstevel 	if (val == 0xffff) {
36323db86aabSstevel 		cardbus_err(dip, 1, "Illegal vendor-id 0x%x\n", val);
36333db86aabSstevel 		return (PCICFG_FAILURE);
36343db86aabSstevel 	}
36353db86aabSstevel 	if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
36363db86aabSstevel 	    "vendor-id", val)) != DDI_SUCCESS) {
36373db86aabSstevel 		return (ret);
36383db86aabSstevel 	}
36393db86aabSstevel 
36403db86aabSstevel 	val = pci_config_get16(config_handle, PCI_CONF_DEVID);
36413db86aabSstevel 	if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
36423db86aabSstevel 	    "device-id", val)) != DDI_SUCCESS) {
36433db86aabSstevel 		return (ret);
36443db86aabSstevel 	}
36453db86aabSstevel 	byteval = pci_config_get8(config_handle, PCI_CONF_REVID);
36463db86aabSstevel 	if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
36473db86aabSstevel 	    "revision-id", byteval)) != DDI_SUCCESS) {
36483db86aabSstevel 		return (ret);
36493db86aabSstevel 	}
36503db86aabSstevel 
36513db86aabSstevel 	wordval = (pci_config_get16(config_handle, PCI_CONF_SUBCLASS)<< 8) |
36523db86aabSstevel 		(pci_config_get8(config_handle, PCI_CONF_PROGCLASS));
36533db86aabSstevel 
36543db86aabSstevel 	if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
36553db86aabSstevel 	    "class-code", wordval)) != DDI_SUCCESS) {
36563db86aabSstevel 		return (ret);
36573db86aabSstevel 	}
36583db86aabSstevel 	val = (pci_config_get16(config_handle,
3659*11c2b4c0Srw148561 	    PCI_CONF_STAT) & PCI_STAT_DEVSELT) >> 9;
36603db86aabSstevel 	if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
36613db86aabSstevel 	    "devsel-speed", val)) != DDI_SUCCESS) {
36623db86aabSstevel 		return (ret);
36633db86aabSstevel 	}
36643db86aabSstevel 
36653db86aabSstevel 	/*
36663db86aabSstevel 	 * The next three are bits set in the status register.  The property is
36673db86aabSstevel 	 * present (but with no value other than its own existence) if the bit
36683db86aabSstevel 	 * is set, non-existent otherwise
36693db86aabSstevel 	 */
36703db86aabSstevel 	if (ddi_prop_exists(DDI_DEV_T_ANY, parent, DDI_PROP_DONTPASS,
36713db86aabSstevel 	    "fast-back-to-back") &&
36723db86aabSstevel 	    pci_config_get16(config_handle, PCI_CONF_STAT) & PCI_STAT_FBBC) {
36733db86aabSstevel 
36743db86aabSstevel 		if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
36753db86aabSstevel 		    "fast-back-to-back", 0)) != DDI_SUCCESS) {
36763db86aabSstevel 			return (ret);
36773db86aabSstevel 		}
36783db86aabSstevel 	}
36793db86aabSstevel 	if (pci_config_get16(config_handle, PCI_CONF_STAT) & PCI_STAT_66MHZ) {
36803db86aabSstevel 		if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
36813db86aabSstevel 		    "66mhz-capable", 0)) != DDI_SUCCESS) {
36823db86aabSstevel 			return (ret);
36833db86aabSstevel 		}
36843db86aabSstevel 	}
36853db86aabSstevel 	if (pci_config_get16(config_handle, PCI_CONF_STAT) & PCI_STAT_UDF) {
36863db86aabSstevel 		if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
36873db86aabSstevel 		    "udf-supported", 0)) != DDI_SUCCESS) {
36883db86aabSstevel 			return (ret);
36893db86aabSstevel 		}
36903db86aabSstevel 	}
36913db86aabSstevel 
36923db86aabSstevel 	/*
36933db86aabSstevel 	 * These next three are optional and are not present
36943db86aabSstevel 	 * if the corresponding register is zero.  If the value
36953db86aabSstevel 	 * is non-zero then the property exists with the value
36963db86aabSstevel 	 * of the register.
36973db86aabSstevel 	 */
36983db86aabSstevel 
36993db86aabSstevel 	/* look in the correct place for header type 2 */
37003db86aabSstevel 	byteval = pci_config_get8(config_handle, PCI_CONF_HEADER);
37013db86aabSstevel 	if ((byteval & PCI_HEADER_TYPE_M) == PCI_HEADER_TWO) {
37023db86aabSstevel 		if ((val = pci_config_get16(config_handle,
37033db86aabSstevel 		    PCI_CBUS_SUBVENID)) != 0) {
37043db86aabSstevel 			if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
37053db86aabSstevel 			    "subsystem-vendor-id", val)) != DDI_SUCCESS) {
37063db86aabSstevel 				return (ret);
37073db86aabSstevel 			}
37083db86aabSstevel 		}
37093db86aabSstevel 		if ((val = pci_config_get16(config_handle,
37103db86aabSstevel 		    PCI_CBUS_SUBSYSID)) != 0) {
37113db86aabSstevel 			if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
37123db86aabSstevel 			    "subsystem-id", val)) != DDI_SUCCESS) {
37133db86aabSstevel 				return (ret);
37143db86aabSstevel 			}
37153db86aabSstevel 		}
37163db86aabSstevel 	} else {
37173db86aabSstevel 		if ((val = pci_config_get16(config_handle,
37183db86aabSstevel 		    PCI_CONF_SUBVENID)) != 0) {
37193db86aabSstevel 			if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
37203db86aabSstevel 			    "subsystem-vendor-id", val)) != DDI_SUCCESS) {
37213db86aabSstevel 				return (ret);
37223db86aabSstevel 			}
37233db86aabSstevel 		}
37243db86aabSstevel 		if ((val = pci_config_get16(config_handle,
37253db86aabSstevel 		    PCI_CONF_SUBSYSID)) != 0) {
37263db86aabSstevel 			if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
37273db86aabSstevel 			    "subsystem-id", val)) != DDI_SUCCESS) {
37283db86aabSstevel 				return (ret);
37293db86aabSstevel 			}
37303db86aabSstevel 		}
37313db86aabSstevel 	}
37323db86aabSstevel 
37333db86aabSstevel 	if ((val = pci_config_get8(config_handle,
37343db86aabSstevel 	    PCI_CONF_CACHE_LINESZ)) != 0) {
37353db86aabSstevel 		if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
37363db86aabSstevel 		    "cache-line-size", val)) != DDI_SUCCESS) {
37373db86aabSstevel 			return (ret);
37383db86aabSstevel 		}
37393db86aabSstevel 	}
37403db86aabSstevel 
37413db86aabSstevel 	/*
37423db86aabSstevel 	 * If the Interrupt Pin register is non-zero then the
37433db86aabSstevel 	 * interrupts property exists
37443db86aabSstevel 	 */
37453db86aabSstevel 	if ((byteval = pci_config_get8(config_handle, PCI_CONF_IPIN)) != 0) {
37463db86aabSstevel 		/*
37473db86aabSstevel 		 * If interrupt pin is non-zero,
37483db86aabSstevel 		 * record the interrupt line used
37493db86aabSstevel 		 */
37503db86aabSstevel 		cardbus_err(dip, 8, "Adding interrupts property\n");
37513db86aabSstevel 		if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
37523db86aabSstevel 		    "interrupts", byteval)) != DDI_SUCCESS) {
37533db86aabSstevel 			return (ret);
37543db86aabSstevel 		}
37553db86aabSstevel 	}
37563db86aabSstevel 	return (PCICFG_SUCCESS);
37573db86aabSstevel }
37583db86aabSstevel 
37593db86aabSstevel /*
37603db86aabSstevel  * Setup the basic properties required by the ISA node.
37613db86aabSstevel  */
37623db86aabSstevel static int
37633db86aabSstevel cardbus_set_isa_props(dev_info_t *parent, dev_info_t *dip,
37643db86aabSstevel 			char *name, char *compat[])
37653db86aabSstevel {
37663db86aabSstevel 	int ret, n;
37673db86aabSstevel 
37683db86aabSstevel 	_NOTE(ARGUNUSED(parent))
37693db86aabSstevel 
37703db86aabSstevel 	cardbus_err(dip, 8, "Adding interrupts property\n");
37713db86aabSstevel 	if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
37723db86aabSstevel 	    "interrupts", 1)) != DDI_SUCCESS) {
37733db86aabSstevel 		return (ret);
37743db86aabSstevel 	}
37753db86aabSstevel 
37763db86aabSstevel 	/*
37773db86aabSstevel 	 * The node name field needs to be filled in with the name
37783db86aabSstevel 	 */
37793db86aabSstevel 	if (ndi_devi_set_nodename(dip, name, 0) != NDI_SUCCESS) {
37803db86aabSstevel 		cardbus_err(dip, 1, "Failed to set nodename for node\n");
37813db86aabSstevel 		return (PCICFG_FAILURE);
37823db86aabSstevel 	}
37833db86aabSstevel 
37843db86aabSstevel 	/*
37853db86aabSstevel 	 * Create the compatible property as an array of pointers
37863db86aabSstevel 	 * to strings.  Start with the buffer created above.
37873db86aabSstevel 	 */
37883db86aabSstevel 	n = 0;
37893db86aabSstevel 	while (compat[n] != NULL)
37903db86aabSstevel 		n++;
37913db86aabSstevel 
37923db86aabSstevel 	if (n != 0)
37933db86aabSstevel 		if ((ret = ndi_prop_update_string_array(DDI_DEV_T_NONE, dip,
37943db86aabSstevel 		    "compatible", compat, n)) != DDI_SUCCESS)
37953db86aabSstevel 			return (ret);
37963db86aabSstevel 
37973db86aabSstevel 	return (PCICFG_SUCCESS);
37983db86aabSstevel }
37993db86aabSstevel 
38003db86aabSstevel static int
38013db86aabSstevel cardbus_set_busnode_props(dev_info_t *dip)
38023db86aabSstevel {
38033db86aabSstevel 	cardbus_err(dip, 6, "cardbus_set_busnode_props\n");
38043db86aabSstevel 
38053db86aabSstevel 	cardbus_force_stringprop(dip, "device_type", "pci");
38063db86aabSstevel 
38073db86aabSstevel 	if (ndi_prop_update_int(DDI_DEV_T_NONE, dip,
38083db86aabSstevel 	    "#address-cells", 3) != DDI_SUCCESS) {
38093db86aabSstevel 		cardbus_err(dip, 4, "Failed to set #address-cells\n");
38103db86aabSstevel 	}
38113db86aabSstevel 	if (ndi_prop_update_int(DDI_DEV_T_NONE, dip,
38123db86aabSstevel 	    "#size-cells", 2) != DDI_SUCCESS) {
38133db86aabSstevel 		cardbus_err(dip, 4, "Failed to set #size-cells\n");
38143db86aabSstevel 	}
38153db86aabSstevel 	return (PCICFG_SUCCESS);
38163db86aabSstevel }
38173db86aabSstevel 
38183db86aabSstevel static int
38193db86aabSstevel cardbus_set_busnode_isaprops(dev_info_t *dip)
38203db86aabSstevel {
38213db86aabSstevel 	cardbus_err(dip, 6, "cardbus_set_busnode_props\n");
38223db86aabSstevel 
38233db86aabSstevel 	cardbus_force_stringprop(dip, "device_type", "isa");
38243db86aabSstevel 
38253db86aabSstevel 	if (ndi_prop_update_int(DDI_DEV_T_NONE, dip,
38263db86aabSstevel 	    "#address-cells", 2) != DDI_SUCCESS) {
38273db86aabSstevel 		cardbus_err(dip, 4, "Failed to set #address-cells\n");
38283db86aabSstevel 	}
38293db86aabSstevel 	if (ndi_prop_update_int(DDI_DEV_T_NONE, dip,
38303db86aabSstevel 	    "#size-cells", 1) != DDI_SUCCESS) {
38313db86aabSstevel 		cardbus_err(dip, 4, "Failed to set #size-cells\n");
38323db86aabSstevel 	}
38333db86aabSstevel 	return (PCICFG_SUCCESS);
38343db86aabSstevel }
38353db86aabSstevel 
38363db86aabSstevel /*
38373db86aabSstevel  * Use cb%x,%x rather than pci%x,%x so that we can use specific cardbus
38383db86aabSstevel  * drivers in /etc/driver_aliases if required
38393db86aabSstevel  */
38403db86aabSstevel static int
38413db86aabSstevel cardbus_set_childnode_props(dev_info_t *dip, ddi_acc_handle_t config_handle)
38423db86aabSstevel {
38433db86aabSstevel 	int		ret;
38443db86aabSstevel #ifndef _DONT_USE_1275_GENERIC_NAMES
38453db86aabSstevel 	uint32_t	wordval;
38463db86aabSstevel #endif
38473db86aabSstevel 	char		*name;
38483db86aabSstevel 	char		buffer[64];
38493db86aabSstevel 	uint32_t	classcode;
38503db86aabSstevel 	char		*compat[8];
38513db86aabSstevel 	int		i, n;
38523db86aabSstevel 	uint16_t	subsysid, subvenid, devid, venid;
38533db86aabSstevel 	uint8_t		header_type;
38543db86aabSstevel 
38553db86aabSstevel 	/*
38563db86aabSstevel 	 * NOTE: These are for both a child and PCI-PCI bridge node
38573db86aabSstevel 	 */
38583db86aabSstevel #ifndef _DONT_USE_1275_GENERIC_NAMES
38593db86aabSstevel 	wordval = (pci_config_get16(config_handle, PCI_CONF_SUBCLASS)<< 8) |
38603db86aabSstevel 	    (pci_config_get8(config_handle, PCI_CONF_PROGCLASS));
38613db86aabSstevel #endif
38623db86aabSstevel 
38633db86aabSstevel 	/* Cardbus support */
38643db86aabSstevel 	venid = pci_config_get16(config_handle, PCI_CONF_VENID);
38653db86aabSstevel 	devid = pci_config_get16(config_handle, PCI_CONF_DEVID);
38663db86aabSstevel 
38673db86aabSstevel 	header_type = pci_config_get8(config_handle, PCI_CONF_HEADER);
38683db86aabSstevel 	if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_TWO) {
38693db86aabSstevel 		subvenid = pci_config_get16(config_handle, PCI_CBUS_SUBVENID);
38703db86aabSstevel 		subsysid = pci_config_get16(config_handle, PCI_CBUS_SUBSYSID);
38713db86aabSstevel 	} else {
38723db86aabSstevel 		subvenid = pci_config_get16(config_handle, PCI_CONF_SUBVENID);
38733db86aabSstevel 		subsysid = pci_config_get16(config_handle, PCI_CONF_SUBSYSID);
38743db86aabSstevel 	}
38753db86aabSstevel 
38763db86aabSstevel 	if (subsysid != 0) {
38773db86aabSstevel 		(void) sprintf(buffer, "pci%x,%x", subvenid, subsysid);
38783db86aabSstevel 	} else {
38793db86aabSstevel 		(void) sprintf(buffer, "pci%x,%x", venid, devid);
38803db86aabSstevel 	}
38813db86aabSstevel 
38823db86aabSstevel 	cardbus_err(dip, 8, "Childname is %s\n", buffer);
38833db86aabSstevel 
38843db86aabSstevel 	/*
38853db86aabSstevel 	 * In some environments, trying to use "generic" 1275 names is
38863db86aabSstevel 	 * not the convention.  In those cases use the name as created
38873db86aabSstevel 	 * above.  In all the rest of the cases, check to see if there
38883db86aabSstevel 	 * is a generic name first.
38893db86aabSstevel 	 */
38903db86aabSstevel #ifdef _DONT_USE_1275_GENERIC_NAMES
38913db86aabSstevel 	name = buffer;
38923db86aabSstevel #else
38933db86aabSstevel 	if ((name = cardbus_get_class_name(wordval>>8)) == NULL) {
38943db86aabSstevel 		/*
38953db86aabSstevel 		 * Set name to the above fabricated name
38963db86aabSstevel 		 */
38973db86aabSstevel 		name = buffer;
38983db86aabSstevel 	}
38993db86aabSstevel 
39003db86aabSstevel 	cardbus_err(dip, 8, "Set nodename to %s\n", name);
39013db86aabSstevel #endif
39023db86aabSstevel 
39033db86aabSstevel 	/*
39043db86aabSstevel 	 * The node name field needs to be filled in with the name
39053db86aabSstevel 	 */
39063db86aabSstevel 	if (ndi_devi_set_nodename(dip, name, 0) != NDI_SUCCESS) {
39073db86aabSstevel 		cardbus_err(dip, 1, "Failed to set nodename for node\n");
39083db86aabSstevel 		return (PCICFG_FAILURE);
39093db86aabSstevel 	}
39103db86aabSstevel 
39113db86aabSstevel 	/*
39123db86aabSstevel 	 * Create the compatible property as an array of pointers
39133db86aabSstevel 	 * to strings.  Start with the cb name.
39143db86aabSstevel 	 */
39153db86aabSstevel 	n = 0;
39163db86aabSstevel 
39173db86aabSstevel 	if (subsysid != 0) {
39183db86aabSstevel 		(void) sprintf(buffer, "cb%x,%x", subvenid, subsysid);
39193db86aabSstevel 	} else {
39203db86aabSstevel 		(void) sprintf(buffer, "cb%x,%x", venid, devid);
39213db86aabSstevel 	}
39223db86aabSstevel 
39233db86aabSstevel 	compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
39243db86aabSstevel 	(void) strcpy(compat[n++], buffer);
39253db86aabSstevel 
39263db86aabSstevel 	if (subsysid != 0) {
39273db86aabSstevel 		/*
39283db86aabSstevel 		 * Add subsys numbers as pci compatible.
39293db86aabSstevel 		 */
39303db86aabSstevel 		(void) sprintf(buffer, "pci%x,%x", subvenid, subsysid);
39313db86aabSstevel 		compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
39323db86aabSstevel 		(void) strcpy(compat[n++], buffer);
39333db86aabSstevel 	}
39343db86aabSstevel 
39353db86aabSstevel 	/*
39363db86aabSstevel 	 * Add in the VendorID/DeviceID compatible name.
39373db86aabSstevel 	 */
39383db86aabSstevel 	(void) sprintf(buffer, "pci%x,%x", venid, devid);
39393db86aabSstevel 
39403db86aabSstevel 	compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
39413db86aabSstevel 	(void) strcpy(compat[n++], buffer);
39423db86aabSstevel 
39433db86aabSstevel 	classcode = (pci_config_get16(config_handle, PCI_CONF_SUBCLASS)<< 8) |
39443db86aabSstevel 	    (pci_config_get8(config_handle, PCI_CONF_PROGCLASS));
39453db86aabSstevel 
39463db86aabSstevel 	/*
39473db86aabSstevel 	 * Add in the Classcode
39483db86aabSstevel 	 */
39493db86aabSstevel 	(void) sprintf(buffer, "pciclass,%06x", classcode);
39503db86aabSstevel 
39513db86aabSstevel 	cardbus_err(dip, 8, "class code %s\n", buffer);
39523db86aabSstevel 
39533db86aabSstevel 	compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
39543db86aabSstevel 	(void) strcpy(compat[n++], buffer);
39553db86aabSstevel 
39563db86aabSstevel 	if ((ret = ndi_prop_update_string_array(DDI_DEV_T_NONE, dip,
39573db86aabSstevel 	    "compatible", (char **)compat, n)) != DDI_SUCCESS) {
39583db86aabSstevel 		return (ret);
39593db86aabSstevel 	}
39603db86aabSstevel 
39613db86aabSstevel 	for (i = 0; i < n; i++) {
39623db86aabSstevel 		kmem_free(compat[i], strlen(compat[i]) + 1);
39633db86aabSstevel 	}
39643db86aabSstevel 
39653db86aabSstevel 	return (PCICFG_SUCCESS);
39663db86aabSstevel }
39673db86aabSstevel 
39683db86aabSstevel /*
39693db86aabSstevel  * Program the bus numbers into the bridge
39703db86aabSstevel  */
39713db86aabSstevel static void
39723db86aabSstevel cardbus_set_bus_numbers(ddi_acc_handle_t config_handle,
39733db86aabSstevel 			uint_t primary, uint_t secondary)
39743db86aabSstevel {
39753db86aabSstevel 	cardbus_err(NULL, 8,
39763db86aabSstevel 	    "cardbus_set_bus_numbers [%d->%d]\n", primary, secondary);
39773db86aabSstevel 
39783db86aabSstevel 	/*
39793db86aabSstevel 	 * Primary bus#
39803db86aabSstevel 	 */
39813db86aabSstevel 	pci_config_put8(config_handle, PCI_BCNF_PRIBUS, primary);
39823db86aabSstevel 
39833db86aabSstevel 	/*
39843db86aabSstevel 	 * Secondary bus#
39853db86aabSstevel 	 */
39863db86aabSstevel 	pci_config_put8(config_handle, PCI_BCNF_SECBUS, secondary);
39873db86aabSstevel 
39883db86aabSstevel 	/*
39893db86aabSstevel 	 * Set the subordinate bus number to ff in order to pass through any
39903db86aabSstevel 	 * type 1 cycle with a bus number higher than the secondary bus#
39913db86aabSstevel 	 * Note that this is reduced once the probe is complete in the
39923db86aabSstevel 	 * cardbus_setup_bridge() function.
39933db86aabSstevel 	 */
39943db86aabSstevel 	pci_config_put8(config_handle, PCI_BCNF_SUBBUS, 0xFF);
39953db86aabSstevel }
39963db86aabSstevel 
39973db86aabSstevel static void
39983db86aabSstevel enable_pci_isa_bridge(dev_info_t *dip, ddi_acc_handle_t config_handle)
39993db86aabSstevel {
40003db86aabSstevel 	uint16_t comm, stat;
40013db86aabSstevel 
40023db86aabSstevel 	stat = pci_config_get16(config_handle, PCI_CONF_STAT);
40033db86aabSstevel 	comm = pci_config_get16(config_handle, PCI_CONF_COMM);
40043db86aabSstevel 
40053db86aabSstevel 	/*
40063db86aabSstevel 	 * Enable memory, IO, bus mastership and error detection.
40073db86aabSstevel 	 */
40083db86aabSstevel 	comm |= (PCI_COMM_ME | PCI_COMM_MAE | PCI_COMM_IO |
40093db86aabSstevel 	    PCI_COMM_PARITY_DETECT | PCI_COMM_SERR_ENABLE);
40103db86aabSstevel 	if (ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
40113db86aabSstevel 	    "fast-back-to-back"))
40123db86aabSstevel 		comm |= PCI_COMM_BACK2BACK_ENAB;
40133db86aabSstevel 	pci_config_put16(config_handle, PCI_CONF_COMM, comm);
40143db86aabSstevel 	cardbus_err(NULL, 8,
40153db86aabSstevel 	    "enable_pci_isa_bridge stat 0x%04x comm 0x%04x\n", stat, comm);
40163db86aabSstevel 
40173db86aabSstevel 	/*
40183db86aabSstevel 	 * ITE8888 Specific registers.
40193db86aabSstevel 	 */
40203db86aabSstevel 	pci_config_put8(config_handle, 0x50, 0x00); /* Timing Control */
40213db86aabSstevel 	pci_config_put8(config_handle, 0x52, 0x00); /* Master DMA Access */
40223db86aabSstevel 	pci_config_put8(config_handle, 0x53, 0x01); /* ROMCS */
40233db86aabSstevel }
40243db86aabSstevel 
40253db86aabSstevel static void
40263db86aabSstevel enable_pci_pci_bridge(dev_info_t *dip, ddi_acc_handle_t config_handle)
40273db86aabSstevel {
40283db86aabSstevel 	uint16_t comm, stat, bctrl;
40293db86aabSstevel 
40303db86aabSstevel 	stat = pci_config_get16(config_handle, PCI_CONF_STAT);
40313db86aabSstevel 	comm = pci_config_get16(config_handle, PCI_CONF_COMM);
40323db86aabSstevel 	bctrl = pci_config_get16(config_handle, PCI_CBUS_BRIDGE_CTRL);
40333db86aabSstevel 
40343db86aabSstevel 	comm &= ~(PCI_COMM_IO | PCI_COMM_MAE);
40353db86aabSstevel 	comm |= (PCI_COMM_ME | PCI_COMM_PARITY_DETECT | PCI_COMM_SERR_ENABLE);
40363db86aabSstevel 
40373db86aabSstevel 	/*
40383db86aabSstevel 	 * Enable back to back.
40393db86aabSstevel 	 */
40403db86aabSstevel 	if (stat & PCI_STAT_FBBC)
40413db86aabSstevel 		comm |= PCI_COMM_BACK2BACK_ENAB;
40423db86aabSstevel 
40433db86aabSstevel 	pci_config_put16(config_handle, PCI_CONF_COMM, comm);
40443db86aabSstevel 
40453db86aabSstevel 	/*
40463db86aabSstevel 	 * Reset the sub-ordinate bus.
40473db86aabSstevel 	 */
40483db86aabSstevel 	if (!(bctrl & PCI_BCNF_BCNTRL_RESET))
40493db86aabSstevel 		pci_config_put16(config_handle, PCI_CBUS_BRIDGE_CTRL,
40503db86aabSstevel 			bctrl | PCI_BCNF_BCNTRL_RESET);
40513db86aabSstevel 	else
40523db86aabSstevel 		bctrl &= ~PCI_BCNF_BCNTRL_RESET;
40533db86aabSstevel 
40543db86aabSstevel 	/*
40553db86aabSstevel 	 * Enable error reporting.
40563db86aabSstevel 	 */
40573db86aabSstevel 	bctrl |= (PCI_BCNF_BCNTRL_PARITY_ENABLE | PCI_BCNF_BCNTRL_SERR_ENABLE |
40583db86aabSstevel 	    PCI_BCNF_BCNTRL_MAST_AB_MODE);
40593db86aabSstevel 
40603db86aabSstevel 	/*
40613db86aabSstevel 	 * Enable back to back on secondary bus.
40623db86aabSstevel 	 */
40633db86aabSstevel 	if (stat & PCI_STAT_FBBC)
40643db86aabSstevel 		bctrl |= PCI_BCNF_BCNTRL_B2B_ENAB;
40653db86aabSstevel 
40663db86aabSstevel 	pci_config_put16(config_handle, PCI_CBUS_BRIDGE_CTRL, bctrl);
40673db86aabSstevel 	cardbus_err(dip, 8,
40683db86aabSstevel 	    "enable_pci_pci_bridge stat 0x%04x comm 0x%04x bctrl 0x%04x\n",
40693db86aabSstevel 	    stat, comm, bctrl);
40703db86aabSstevel }
40713db86aabSstevel 
40723db86aabSstevel static int	cardbus_reset_wait = 20;
40733db86aabSstevel 
40743db86aabSstevel static void
40753db86aabSstevel enable_cardbus_bridge(dev_info_t *dip, ddi_acc_handle_t config_handle)
40763db86aabSstevel {
40773db86aabSstevel 	uint16_t comm, stat, bctrl;
40783db86aabSstevel 
40793db86aabSstevel 	stat = pci_config_get16(config_handle, PCI_CONF_STAT);
40803db86aabSstevel 	comm = pci_config_get16(config_handle, PCI_CONF_COMM);
40813db86aabSstevel 	bctrl = pci_config_get16(config_handle, PCI_CBUS_BRIDGE_CTRL);
40823db86aabSstevel 
40833db86aabSstevel 	/*
40843db86aabSstevel 	 * Don't mess with the command register on the cardbus bridge
40853db86aabSstevel 	 * itself. This should have been done when it's parent
40863db86aabSstevel 	 * did the setup. Some devices *require* certain things to
40873db86aabSstevel 	 * disabled, this can be done using the "command-preserve"
40883db86aabSstevel 	 * property and if we mess with it here it breaks that.
40893db86aabSstevel 	 *
40903db86aabSstevel 	 * comm |= (PCI_COMM_ME | PCI_COMM_PARITY_DETECT |
40913db86aabSstevel 	 *	PCI_COMM_SERR_ENABLE);
40923db86aabSstevel 	 */
40933db86aabSstevel 
40943db86aabSstevel 	/*
40953db86aabSstevel 	 * Reset the sub-ordinate bus.
40963db86aabSstevel 	 */
40973db86aabSstevel 	if (!(bctrl & PCI_BCNF_BCNTRL_RESET))
40983db86aabSstevel 		pci_config_put16(config_handle, PCI_CBUS_BRIDGE_CTRL,
40993db86aabSstevel 			bctrl | PCI_BCNF_BCNTRL_RESET);
41003db86aabSstevel 	else
41013db86aabSstevel 		bctrl &= ~PCI_BCNF_BCNTRL_RESET;
41023db86aabSstevel 
41033db86aabSstevel 	/*
41043db86aabSstevel 	 * Turn off pre-fetch.
41053db86aabSstevel 	 */
41063db86aabSstevel 	bctrl &= ~(CB_BCNF_BCNTRL_MEM0_PREF | CB_BCNF_BCNTRL_MEM1_PREF |
41073db86aabSstevel 	    PCI_BCNF_BCNTRL_PARITY_ENABLE | PCI_BCNF_BCNTRL_SERR_ENABLE);
41083db86aabSstevel 
41093db86aabSstevel 	/*
41103db86aabSstevel 	 * Enable error reporting.
41113db86aabSstevel 	 */
41123db86aabSstevel 	bctrl |= (PCI_BCNF_BCNTRL_MAST_AB_MODE | CB_BCNF_BCNTRL_WRITE_POST);
41133db86aabSstevel 	if (comm & PCI_COMM_PARITY_DETECT)
41143db86aabSstevel 		bctrl |= PCI_BCNF_BCNTRL_PARITY_ENABLE;
41153db86aabSstevel 	if (comm & PCI_COMM_SERR_ENABLE)
41163db86aabSstevel 		bctrl |= PCI_BCNF_BCNTRL_SERR_ENABLE;
41173db86aabSstevel 
41183db86aabSstevel 	pci_config_put16(config_handle, PCI_CBUS_BRIDGE_CTRL, bctrl);
41193db86aabSstevel 	pci_config_put8(config_handle, PCI_CBUS_LATENCY_TIMER,
41203db86aabSstevel 	    cardbus_latency_timer);
41213db86aabSstevel 
41223db86aabSstevel 	pci_config_put16(config_handle, PCI_CONF_STAT, stat);
41233db86aabSstevel 	pci_config_put16(config_handle, PCI_CONF_COMM, comm);
41243db86aabSstevel 
41253db86aabSstevel 	cardbus_err(dip, 8,
41263db86aabSstevel 	    "enable_cardbus_bridge() stat 0x%04x comm 0x%04x bctrl 0x%04x\n",
41273db86aabSstevel 	    stat, comm, bctrl);
41283db86aabSstevel 
41293db86aabSstevel 	/* after resetting the bridge, wait for everything to stablize */
41303db86aabSstevel 	delay(drv_usectohz(cardbus_reset_wait * 1000));
41313db86aabSstevel 
41323db86aabSstevel }
41333db86aabSstevel 
41343db86aabSstevel static void
41353db86aabSstevel disable_pci_pci_bridge(dev_info_t *dip, ddi_acc_handle_t config_handle)
41363db86aabSstevel {
41373db86aabSstevel 	uint16_t comm, bctrl;
41383db86aabSstevel 
41393db86aabSstevel 	comm = pci_config_get16(config_handle, PCI_CONF_COMM);
41403db86aabSstevel 	bctrl = pci_config_get16(config_handle, PCI_CBUS_BRIDGE_CTRL);
41413db86aabSstevel 
41423db86aabSstevel 	/*
41433db86aabSstevel 	 * Turn off subordinate bus access.
41443db86aabSstevel 	 */
41453db86aabSstevel 	pci_config_put8(config_handle, PCI_BCNF_SECBUS, 0);
41463db86aabSstevel 	pci_config_put8(config_handle, PCI_BCNF_SUBBUS, 0);
41473db86aabSstevel 
41483db86aabSstevel 	/*
41493db86aabSstevel 	 * Disable error reporting.
41503db86aabSstevel 	 */
41513db86aabSstevel 	bctrl &= ~(PCI_BCNF_BCNTRL_PARITY_ENABLE | PCI_BCNF_BCNTRL_SERR_ENABLE |
41523db86aabSstevel 	    PCI_BCNF_BCNTRL_MAST_AB_MODE);
41533db86aabSstevel 	comm = 0;
41543db86aabSstevel 
41553db86aabSstevel 	pci_config_put16(config_handle, PCI_CONF_COMM, comm);
41563db86aabSstevel 	pci_config_put16(config_handle, PCI_CBUS_BRIDGE_CTRL, bctrl);
41573db86aabSstevel 
41583db86aabSstevel 	cardbus_err(dip, 6,
41593db86aabSstevel 	    "disable_pci_pci_bridge() stat 0x%04x comm 0x%04x bctrl 0x%04x\n",
41603db86aabSstevel 	    pci_config_get16(config_handle, PCI_CONF_STAT), comm, bctrl);
41613db86aabSstevel }
41623db86aabSstevel 
41633db86aabSstevel static void
41643db86aabSstevel disable_cardbus_bridge(dev_info_t *dip, ddi_acc_handle_t config_handle)
41653db86aabSstevel {
41663db86aabSstevel 	uint16_t comm, bctrl;
41673db86aabSstevel 
41683db86aabSstevel 	comm = pci_config_get16(config_handle, PCI_CONF_COMM);
41693db86aabSstevel 	bctrl = pci_config_get16(config_handle, PCI_CBUS_BRIDGE_CTRL);
41703db86aabSstevel 
41713db86aabSstevel 	/*
41723db86aabSstevel 	 * Turn off subordinate bus access.
41733db86aabSstevel 	 */
41743db86aabSstevel 	pci_config_put8(config_handle, PCI_BCNF_SECBUS, 0);
41753db86aabSstevel 	pci_config_put8(config_handle, PCI_BCNF_SUBBUS, 0);
41763db86aabSstevel 
41773db86aabSstevel 	/*
41783db86aabSstevel 	 * Disable error reporting.
41793db86aabSstevel 	 */
41803db86aabSstevel 	bctrl &= ~(PCI_BCNF_BCNTRL_PARITY_ENABLE | PCI_BCNF_BCNTRL_SERR_ENABLE |
41813db86aabSstevel 	    PCI_BCNF_BCNTRL_MAST_AB_MODE);
41823db86aabSstevel 
41833db86aabSstevel 	pci_config_put32(config_handle, PCI_CBUS_MEM_LIMIT0, 0);
41843db86aabSstevel 	pci_config_put32(config_handle, PCI_CBUS_MEM_BASE0, 0);
41853db86aabSstevel 	pci_config_put32(config_handle, PCI_CBUS_IO_LIMIT0, 0);
41863db86aabSstevel 	pci_config_put32(config_handle, PCI_CBUS_IO_BASE0, 0);
41873db86aabSstevel 	pci_config_put16(config_handle, PCI_CONF_COMM, comm);
41883db86aabSstevel 	pci_config_put16(config_handle, PCI_CBUS_BRIDGE_CTRL, bctrl);
41893db86aabSstevel 
41903db86aabSstevel 	cardbus_err(dip, 6,
41913db86aabSstevel 	    "disable_cardbus_bridge() stat 0x%04x comm 0x%04x bctrl 0x%04x\n",
41923db86aabSstevel 	    pci_config_get16(config_handle, PCI_CONF_STAT), comm, bctrl);
41933db86aabSstevel }
41943db86aabSstevel 
41953db86aabSstevel static void
41963db86aabSstevel enable_cardbus_device(dev_info_t *dip, ddi_acc_handle_t config_handle)
41973db86aabSstevel {
41983db86aabSstevel 	uint16_t comm, stat;
41993db86aabSstevel 
42003db86aabSstevel 	stat = pci_config_get16(config_handle, PCI_CONF_STAT);
42013db86aabSstevel 	comm = pci_config_get16(config_handle, PCI_CONF_COMM);
42023db86aabSstevel 
42033db86aabSstevel 	/*
42043db86aabSstevel 	 * Enable memory, IO, bus mastership and error detection.
42053db86aabSstevel 	 */
42063db86aabSstevel 	comm |= (PCI_COMM_ME | PCI_COMM_MAE | PCI_COMM_IO |
42073db86aabSstevel 	    PCI_COMM_PARITY_DETECT | PCI_COMM_SERR_ENABLE);
42083db86aabSstevel 	if (ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
42093db86aabSstevel 	    "fast-back-to-back"))
42103db86aabSstevel 		comm |= PCI_COMM_BACK2BACK_ENAB;
42113db86aabSstevel 	pci_config_put16(config_handle, PCI_CONF_COMM, comm);
42123db86aabSstevel 	cardbus_err(NULL, 8,
42133db86aabSstevel 	    "enable_cardbus_device stat 0x%04x comm 0x%04x\n", stat, comm);
42143db86aabSstevel }
42153db86aabSstevel 
42163db86aabSstevel static void
42173db86aabSstevel disable_cardbus_device(ddi_acc_handle_t config_handle)
42183db86aabSstevel {
42193db86aabSstevel 	cardbus_err(NULL, 8, "disable_cardbus_device\n");
42203db86aabSstevel 
42213db86aabSstevel 	/*
42223db86aabSstevel 	 * Turn off everything in the command register.
42233db86aabSstevel 	 */
42243db86aabSstevel 	pci_config_put16(config_handle, PCI_CONF_COMM, 0x0);
42253db86aabSstevel }
42263db86aabSstevel 
42273db86aabSstevel #ifndef _DONT_USE_1275_GENERIC_NAMES
42283db86aabSstevel static char *
42293db86aabSstevel cardbus_get_class_name(uint32_t classcode)
42303db86aabSstevel {
42313db86aabSstevel 	struct cardbus_name_entry *ptr;
42323db86aabSstevel 
42333db86aabSstevel 	for (ptr = &cardbus_class_lookup[0]; ptr->name != NULL; ptr++) {
42343db86aabSstevel 		if (ptr->class_code == classcode) {
42353db86aabSstevel 			return (ptr->name);
42363db86aabSstevel 		}
42373db86aabSstevel 	}
42383db86aabSstevel 	return (NULL);
42393db86aabSstevel }
42403db86aabSstevel #endif /* _DONT_USE_1275_GENERIC_NAMES */
42413db86aabSstevel 
42423db86aabSstevel static void
42433db86aabSstevel cardbus_force_boolprop(dev_info_t *dip, char *pname)
42443db86aabSstevel {
42453db86aabSstevel 	int ret;
42463db86aabSstevel 
42473db86aabSstevel 	if ((ret = ndi_prop_create_boolean(DDI_DEV_T_NONE, dip,
42483db86aabSstevel 	    pname)) != DDI_SUCCESS) {
42493db86aabSstevel 		if (ret == DDI_PROP_NOT_FOUND)
42503db86aabSstevel 			if (ddi_prop_create(DDI_DEV_T_NONE, dip,
42513db86aabSstevel 			    DDI_PROP_CANSLEEP, pname,
42523db86aabSstevel 			    (caddr_t)NULL, 0) != DDI_SUCCESS)
42533db86aabSstevel 				cardbus_err(dip, 4,
42543db86aabSstevel 				    "Failed to set boolean property "
42553db86aabSstevel 				    "\"%s\"\n", pname);
42563db86aabSstevel 	}
42573db86aabSstevel }
42583db86aabSstevel 
42593db86aabSstevel static void
42603db86aabSstevel cardbus_force_intprop(dev_info_t *dip, char *pname, int *pval, int len)
42613db86aabSstevel {
42623db86aabSstevel 	int ret;
42633db86aabSstevel 
42643db86aabSstevel 	if ((ret = ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
42653db86aabSstevel 	    pname, pval, len)) != DDI_SUCCESS) {
42663db86aabSstevel 		if (ret == DDI_PROP_NOT_FOUND)
42673db86aabSstevel 			if (ddi_prop_create(DDI_DEV_T_NONE, dip,
42683db86aabSstevel 			    DDI_PROP_CANSLEEP, pname,
42693db86aabSstevel 			    (caddr_t)pval, len*sizeof (int))
42703db86aabSstevel 			    != DDI_SUCCESS)
42713db86aabSstevel 				cardbus_err(dip, 4,
42723db86aabSstevel 				    "Failed to set int property \"%s\"\n",
42733db86aabSstevel 				    pname);
42743db86aabSstevel 	}
42753db86aabSstevel }
42763db86aabSstevel 
42773db86aabSstevel static void
42783db86aabSstevel cardbus_force_stringprop(dev_info_t *dip, char *pname, char *pval)
42793db86aabSstevel {
42803db86aabSstevel 	int ret;
42813db86aabSstevel 
42823db86aabSstevel 	if ((ret = ndi_prop_update_string(DDI_DEV_T_NONE, dip,
42833db86aabSstevel 	    pname, pval)) != DDI_SUCCESS) {
42843db86aabSstevel 		if (ret == DDI_PROP_NOT_FOUND)
42853db86aabSstevel 			if (ddi_prop_create(DDI_DEV_T_NONE, dip,
42863db86aabSstevel 			    DDI_PROP_CANSLEEP, pname,
42873db86aabSstevel 			    pval, strlen(pval) + 1) != DDI_SUCCESS)
42883db86aabSstevel 				cardbus_err(dip, 4,
42893db86aabSstevel 				    "Failed to set string property "
42903db86aabSstevel 				    "\"%s\" to \"%s\"\n",
42913db86aabSstevel 				    pname, pval);
42923db86aabSstevel 	}
42933db86aabSstevel }
42943db86aabSstevel 
42953db86aabSstevel static void
42963db86aabSstevel split_addr(char *naddr, int *dev, int *func)
42973db86aabSstevel {
42983db86aabSstevel 	char	c;
42993db86aabSstevel 	int	*ip = dev;
43003db86aabSstevel 
43013db86aabSstevel 	*dev = 0;
43023db86aabSstevel 	*func = 0;
43033db86aabSstevel 
43043db86aabSstevel 	while (c = *naddr++) {
43053db86aabSstevel 		if (c == ',') {
43063db86aabSstevel 			ip = func;
43073db86aabSstevel 			continue;
43083db86aabSstevel 		}
43093db86aabSstevel 		if (c >= '0' && c <= '9') {
43103db86aabSstevel 			*ip = (*ip * 16) + (c - '0');
43113db86aabSstevel 		} else if (c >= 'a' && c <= 'f') {
43123db86aabSstevel 			*ip = (*ip * 16) + 10 + (c - 'a');
43133db86aabSstevel 		} else
43143db86aabSstevel 			break;
43153db86aabSstevel 	}
43163db86aabSstevel }
43173db86aabSstevel 
43183db86aabSstevel #ifdef DEBUG
43193db86aabSstevel static void
43203db86aabSstevel cardbus_dump_common_config(ddi_acc_handle_t config_handle)
43213db86aabSstevel {
43223db86aabSstevel 	cardbus_err(NULL, 1,
43233db86aabSstevel 	    " Vendor ID   = [0x%04x]        "
43243db86aabSstevel 	    "Device ID   = [0x%04x]\n",
43253db86aabSstevel 	    pci_config_get16(config_handle, PCI_CONF_VENID),
43263db86aabSstevel 	    pci_config_get16(config_handle, PCI_CONF_DEVID));
43273db86aabSstevel 	cardbus_err(NULL, 1,
43283db86aabSstevel 	    " Command REG = [0x%04x]        "
43293db86aabSstevel 	    "Status  REG = [0x%04x]\n",
43303db86aabSstevel 	    pci_config_get16(config_handle, PCI_CONF_COMM),
43313db86aabSstevel 	    pci_config_get16(config_handle, PCI_CONF_STAT));
43323db86aabSstevel 	cardbus_err(NULL, 1,
43333db86aabSstevel 	    " Revision ID = [0x%02x]          "
43343db86aabSstevel 	    "Prog Class  = [0x%02x]\n",
43353db86aabSstevel 	    pci_config_get8(config_handle, PCI_CONF_REVID),
43363db86aabSstevel 	    pci_config_get8(config_handle, PCI_CONF_PROGCLASS));
43373db86aabSstevel 	cardbus_err(NULL, 1,
43383db86aabSstevel 	    " Dev Class   = [0x%02x]          "
43393db86aabSstevel 	    "Base Class  = [0x%02x]\n",
43403db86aabSstevel 	    pci_config_get8(config_handle, PCI_CONF_SUBCLASS),
43413db86aabSstevel 	    pci_config_get8(config_handle, PCI_CONF_BASCLASS));
43423db86aabSstevel 	cardbus_err(NULL, 1,
43433db86aabSstevel 	    " Cache LnSz  = [0x%02x]          "
43443db86aabSstevel 	    "Latency Tmr = [0x%02x]\n",
43453db86aabSstevel 	    pci_config_get8(config_handle, PCI_CONF_CACHE_LINESZ),
43463db86aabSstevel 	    pci_config_get8(config_handle, PCI_CONF_LATENCY_TIMER));
43473db86aabSstevel 	cardbus_err(NULL, 1,
43483db86aabSstevel 	    " Header Type = [0x%02x]          "
43493db86aabSstevel 	    "BIST        = [0x%02x]\n",
43503db86aabSstevel 	    pci_config_get8(config_handle, PCI_CONF_HEADER),
43513db86aabSstevel 	    pci_config_get8(config_handle, PCI_CONF_BIST));
43523db86aabSstevel }
43533db86aabSstevel 
43543db86aabSstevel static void
43553db86aabSstevel cardbus_dump_device_config(ddi_acc_handle_t config_handle)
43563db86aabSstevel {
43573db86aabSstevel 	cardbus_dump_common_config(config_handle);
43583db86aabSstevel 
43593db86aabSstevel 	cardbus_err(NULL, 1,
43603db86aabSstevel 	    " BASE 0      = [0x%08x]	BASE 1      = [0x%08x]\n",
43613db86aabSstevel 	    pci_config_get32(config_handle, PCI_CONF_BASE0),
43623db86aabSstevel 	    pci_config_get32(config_handle, PCI_CONF_BASE1));
43633db86aabSstevel 	cardbus_err(NULL, 1,
43643db86aabSstevel 	    " BASE 2      = [0x%08x]	BASE 3      = [0x%08x]\n",
43653db86aabSstevel 	    pci_config_get32(config_handle, PCI_CONF_BASE2),
43663db86aabSstevel 	    pci_config_get32(config_handle, PCI_CONF_BASE3));
43673db86aabSstevel 	cardbus_err(NULL, 1,
43683db86aabSstevel 	    " BASE 4      = [0x%08x]	BASE 5      = [0x%08x]\n",
43693db86aabSstevel 	    pci_config_get32(config_handle, PCI_CONF_BASE4),
43703db86aabSstevel 	    pci_config_get32(config_handle, PCI_CONF_BASE5));
43713db86aabSstevel 	cardbus_err(NULL, 1,
43723db86aabSstevel 	    " Cardbus CIS = [0x%08x]	ROM         = [0x%08x]\n",
43733db86aabSstevel 	    pci_config_get32(config_handle, PCI_CONF_CIS),
43743db86aabSstevel 	    pci_config_get32(config_handle, PCI_CONF_ROM));
43753db86aabSstevel 	cardbus_err(NULL, 1,
43763db86aabSstevel 	    " Sub VID     = [0x%04x]	Sub SID     = [0x%04x]\n",
43773db86aabSstevel 	    pci_config_get16(config_handle, PCI_CONF_SUBVENID),
43783db86aabSstevel 	    pci_config_get16(config_handle, PCI_CONF_SUBSYSID));
43793db86aabSstevel 	cardbus_err(NULL, 1,
43803db86aabSstevel 	    " I Line      = [0x%02x]	I Pin       = [0x%02x]\n",
43813db86aabSstevel 	    pci_config_get8(config_handle, PCI_CONF_ILINE),
43823db86aabSstevel 	    pci_config_get8(config_handle, PCI_CONF_IPIN));
43833db86aabSstevel 	cardbus_err(NULL, 1,
43843db86aabSstevel 	    " Max Grant   = [0x%02x]	Max Latent  = [0x%02x]\n",
43853db86aabSstevel 	    pci_config_get8(config_handle, PCI_CONF_MIN_G),
43863db86aabSstevel 	    pci_config_get8(config_handle, PCI_CONF_MAX_L));
43873db86aabSstevel }
43883db86aabSstevel 
43893db86aabSstevel static void
43903db86aabSstevel cardbus_dump_bridge_config(ddi_acc_handle_t config_handle,
43913db86aabSstevel 			uint8_t header_type)
43923db86aabSstevel {
43933db86aabSstevel 	if (header_type == PCI_HEADER_PPB) {
43943db86aabSstevel 		cardbus_dump_common_config(config_handle);
43953db86aabSstevel 		cardbus_err(NULL, 1,
43963db86aabSstevel 		    "........................................\n");
43973db86aabSstevel 	} else {
43983db86aabSstevel 		cardbus_dump_common_config(config_handle);
43993db86aabSstevel 		cardbus_err(NULL, 1,
44003db86aabSstevel 		    " Mem Base    = [0x%08x]	CBus Status = [0x%04x]\n",
44013db86aabSstevel 		    pci_config_get32(config_handle, PCI_CBUS_SOCK_REG),
44023db86aabSstevel 		    pci_config_get16(config_handle, PCI_CBUS_SEC_STATUS));
44033db86aabSstevel 	}
44043db86aabSstevel 
44053db86aabSstevel 	cardbus_err(NULL, 1,
44063db86aabSstevel 	    " Pri Bus	= [0x%02x]		Sec Bus	= [0x%02x]\n",
44073db86aabSstevel 	    pci_config_get8(config_handle, PCI_BCNF_PRIBUS),
44083db86aabSstevel 	    pci_config_get8(config_handle, PCI_BCNF_SECBUS));
44093db86aabSstevel 	cardbus_err(NULL, 1,
44103db86aabSstevel 	    " Sub Bus     = [0x%02x]		Sec Latency = [0x%02x]\n",
44113db86aabSstevel 	    pci_config_get8(config_handle, PCI_BCNF_SUBBUS),
44123db86aabSstevel 	    pci_config_get8(config_handle, PCI_BCNF_LATENCY_TIMER));
44133db86aabSstevel 
44143db86aabSstevel 	switch (header_type) {
44153db86aabSstevel 	case PCI_HEADER_PPB:
44163db86aabSstevel 		cardbus_err(NULL, 1,
44173db86aabSstevel 		    " I/O Base LO = [0x%02x]	I/O Lim LO  = [0x%02x]\n",
44183db86aabSstevel 		    pci_config_get8(config_handle, PCI_BCNF_IO_BASE_LOW),
44193db86aabSstevel 		    pci_config_get8(config_handle, PCI_BCNF_IO_LIMIT_LOW));
44203db86aabSstevel 		cardbus_err(NULL, 1,
44213db86aabSstevel 		    " Sec. Status = [0x%04x]\n",
44223db86aabSstevel 		    pci_config_get16(config_handle, PCI_BCNF_SEC_STATUS));
44233db86aabSstevel 		cardbus_err(NULL, 1,
44243db86aabSstevel 		    " Mem Base    = [0x%04x]	Mem Limit   = [0x%04x]\n",
44253db86aabSstevel 		    pci_config_get16(config_handle, PCI_BCNF_MEM_BASE),
44263db86aabSstevel 		    pci_config_get16(config_handle, PCI_BCNF_MEM_LIMIT));
44273db86aabSstevel 		cardbus_err(NULL, 1,
44283db86aabSstevel 		    " PF Mem Base = [0x%04x]	PF Mem Lim  = [0x%04x]\n",
44293db86aabSstevel 		    pci_config_get16(config_handle, PCI_BCNF_PF_BASE_LOW),
44303db86aabSstevel 		    pci_config_get16(config_handle, PCI_BCNF_PF_LIMIT_LOW));
44313db86aabSstevel 		cardbus_err(NULL, 1,
44323db86aabSstevel 		    " PF Base HI  = [0x%08x]	PF Lim  HI  = [0x%08x]\n",
44333db86aabSstevel 		    pci_config_get32(config_handle, PCI_BCNF_PF_BASE_HIGH),
44343db86aabSstevel 		    pci_config_get32(config_handle, PCI_BCNF_PF_LIMIT_HIGH));
44353db86aabSstevel 		cardbus_err(NULL, 1,
44363db86aabSstevel 		    " I/O Base HI = [0x%04x]	I/O Lim HI  = [0x%04x]\n",
44373db86aabSstevel 		    pci_config_get16(config_handle, PCI_BCNF_IO_BASE_HI),
44383db86aabSstevel 		    pci_config_get16(config_handle, PCI_BCNF_IO_LIMIT_HI));
44393db86aabSstevel 		cardbus_err(NULL, 1,
44403db86aabSstevel 		    " ROM addr    = [0x%08x]\n",
44413db86aabSstevel 		    pci_config_get32(config_handle, PCI_BCNF_ROM));
44423db86aabSstevel 		break;
44433db86aabSstevel 	case PCI_HEADER_CARDBUS:
44443db86aabSstevel 		cardbus_err(NULL, 1,
44453db86aabSstevel 		    " Mem Base 0  = [0x%08x]	Mem Limit 0 = [0x%08x]\n",
44463db86aabSstevel 		    pci_config_get32(config_handle, PCI_CBUS_MEM_BASE0),
44473db86aabSstevel 		    pci_config_get32(config_handle, PCI_CBUS_MEM_LIMIT0));
44483db86aabSstevel 		cardbus_err(NULL, 1,
44493db86aabSstevel 		    " Mem Base 1  = [0x%08x]	Mem Limit 1 = [0x%08x]\n",
44503db86aabSstevel 		    pci_config_get32(config_handle, PCI_CBUS_MEM_BASE1),
44513db86aabSstevel 		    pci_config_get32(config_handle, PCI_CBUS_MEM_LIMIT1));
44523db86aabSstevel 		cardbus_err(NULL, 1,
44533db86aabSstevel 		    " IO Base 0   = [0x%08x]	IO Limit 0  = [0x%08x]\n",
44543db86aabSstevel 		    pci_config_get32(config_handle, PCI_CBUS_IO_BASE0),
44553db86aabSstevel 		    pci_config_get32(config_handle, PCI_CBUS_IO_LIMIT0));
44563db86aabSstevel 		cardbus_err(NULL, 1,
44573db86aabSstevel 		    " IO Base 1   = [0x%08x]	IO Limit 1  = [0x%08x]\n",
44583db86aabSstevel 		    pci_config_get32(config_handle, PCI_CBUS_IO_BASE1),
44593db86aabSstevel 		    pci_config_get32(config_handle, PCI_CBUS_IO_LIMIT1));
44603db86aabSstevel 		break;
44613db86aabSstevel 	}
44623db86aabSstevel 	cardbus_err(NULL, 1,
44633db86aabSstevel 	    " Intr Line   = [0x%02x]		Intr Pin    = [0x%02x]\n",
44643db86aabSstevel 	    pci_config_get8(config_handle, PCI_BCNF_ILINE),
44653db86aabSstevel 	    pci_config_get8(config_handle, PCI_BCNF_IPIN));
44663db86aabSstevel 	cardbus_err(NULL, 1,
44673db86aabSstevel 	    " Bridge Ctrl = [0x%04x]\n",
44683db86aabSstevel 	    pci_config_get16(config_handle, PCI_BCNF_BCNTRL));
44693db86aabSstevel 
44703db86aabSstevel 	switch (header_type) {
44713db86aabSstevel 	case PCI_HEADER_CARDBUS:
44723db86aabSstevel 		cardbus_err(NULL, 1,
44733db86aabSstevel 		    " Sub VID     = [0x%04x]	Sub SID     = [0x%04x]\n",
44743db86aabSstevel 		    pci_config_get16(config_handle, PCI_CBUS_SUBVENID),
44753db86aabSstevel 		    pci_config_get16(config_handle, PCI_CBUS_SUBSYSID));
44763db86aabSstevel 		/* LATER: TI1250 only */
44773db86aabSstevel 		cardbus_err(NULL, 1,
44783db86aabSstevel 		    " Sys Control = [0x%08x]\n",
44793db86aabSstevel 		    pci_config_get32(config_handle, 0x80));
44803db86aabSstevel 	}
44813db86aabSstevel }
44823db86aabSstevel 
44833db86aabSstevel static void
44843db86aabSstevel cardbus_dump_config(ddi_acc_handle_t config_handle)
44853db86aabSstevel {
44863db86aabSstevel 	uint8_t header_type = pci_config_get8(config_handle,
44873db86aabSstevel 	    PCI_CONF_HEADER) & PCI_HEADER_TYPE_M;
44883db86aabSstevel 
44893db86aabSstevel 	if (header_type == PCI_HEADER_PPB || header_type == PCI_HEADER_CARDBUS)
44903db86aabSstevel 		cardbus_dump_bridge_config(config_handle, header_type);
44913db86aabSstevel 	else
44923db86aabSstevel 		cardbus_dump_device_config(config_handle);
44933db86aabSstevel }
44943db86aabSstevel 
44953db86aabSstevel static void
44963db86aabSstevel cardbus_dump_reg(dev_info_t *dip, const pci_regspec_t *regspec, int nelems)
44973db86aabSstevel {
44983db86aabSstevel 	/* int rlen = nelems * sizeof(pci_regspec_t); */
44993db86aabSstevel 
45003db86aabSstevel 	cardbus_err(dip, 6,
45013db86aabSstevel 	    "cardbus_dump_reg: \"reg\" has %d elements\n", nelems);
45023db86aabSstevel 
45033db86aabSstevel #if defined(CARDBUS_DEBUG)
45043db86aabSstevel 	if (cardbus_debug >= 1) {
45053db86aabSstevel 		int	i;
45063db86aabSstevel 		uint32_t *regs = (uint32_t *)regspec;
45073db86aabSstevel 
45083db86aabSstevel 		for (i = 0; i < nelems; i++) {
45093db86aabSstevel 
45103db86aabSstevel 			cardbus_err(NULL, 6,
45113db86aabSstevel 			    "\t%d:%08x %08x %08x %08x %08x\n",
45123db86aabSstevel 			    i, regs[0], regs[1], regs[2], regs[3], regs[4]);
45133db86aabSstevel 		}
45143db86aabSstevel 	}
45153db86aabSstevel #endif
45163db86aabSstevel }
45173db86aabSstevel 
45183db86aabSstevel #endif
45193db86aabSstevel 
45203db86aabSstevel #if defined(CARDBUS_DEBUG)
45213db86aabSstevel void
45223db86aabSstevel cardbus_dump_children(dev_info_t *dip, int level)
45233db86aabSstevel {
45243db86aabSstevel 	dev_info_t *next;
45253db86aabSstevel 
45263db86aabSstevel 	cardbus_err(dip, 1,
45273db86aabSstevel 	    "\t%d: %s: 0x%p\n", level, ddi_node_name(dip), (void *) dip);
45283db86aabSstevel 	for (next = ddi_get_child(dip); next;
45293db86aabSstevel 	    next = ddi_get_next_sibling(next))
45303db86aabSstevel 		cardbus_dump_children(next, level + 1);
45313db86aabSstevel }
45323db86aabSstevel 
45333db86aabSstevel void
45343db86aabSstevel cardbus_dump_family_tree(dev_info_t *dip)
45353db86aabSstevel {
45363db86aabSstevel 	cardbus_err(dip, 1, "0x%p family tree:\n", (void *) dip);
45373db86aabSstevel 	cardbus_dump_children(dip, 1);
45383db86aabSstevel }
45393db86aabSstevel #endif
4540