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