1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25/*
26 *     PCI configurator (pcicfg)
27 */
28
29#include <sys/isa_defs.h>
30
31#include <sys/conf.h>
32#include <sys/kmem.h>
33#include <sys/debug.h>
34#include <sys/modctl.h>
35#include <sys/autoconf.h>
36#include <sys/hwconf.h>
37#include <sys/ddi_impldefs.h>
38#include <sys/fcode.h>
39#include <sys/pci.h>
40#include <sys/pcie.h>
41#include <sys/pcie_impl.h>
42#include <sys/ddi.h>
43#include <sys/sunddi.h>
44#include <sys/sunndi.h>
45#include <sys/pci_cap.h>
46#include <sys/hotplug/pci/pcicfg.h>
47#include <sys/ndi_impldefs.h>
48#include <sys/pci_cfgacc.h>
49
50#define	PCICFG_DEVICE_TYPE_PCI	1
51#define	PCICFG_DEVICE_TYPE_PCIE	2
52
53#define	EFCODE21554	/* changes for supporting 21554 */
54
55static int pcicfg_alloc_resource(dev_info_t *, pci_regspec_t);
56static int pcicfg_free_resource(dev_info_t *, pci_regspec_t, pcicfg_flags_t);
57static int pcicfg_remove_assigned_prop(dev_info_t *, pci_regspec_t *);
58
59#ifdef	PCICFG_INTERPRET_FCODE
60static int pcicfg_fcode_assign_bars(ddi_acc_handle_t, dev_info_t *,
61    uint_t, uint_t, uint_t, int32_t, pci_regspec_t *);
62#endif	/* PCICFG_INTERPRET_FCODE */
63
64/*
65 * ************************************************************************
66 * *** Implementation specific local data structures/definitions.	***
67 * ************************************************************************
68 */
69
70static	int	pcicfg_start_devno = 0;	/* for Debug only */
71
72#define	PCICFG_MAX_DEVICE 32
73#define	PCICFG_MAX_FUNCTION 8
74#define	PCICFG_MAX_ARI_FUNCTION 256
75#define	PCICFG_MAX_REGISTER 64
76#define	PCICFG_MAX_BUS_DEPTH 255
77
78#define	PCICFG_NODEVICE 42
79#define	PCICFG_NOMEMORY 43
80#define	PCICFG_NOMULTI	44
81
82#define	PCICFG_HIADDR(n) ((uint32_t)(((uint64_t)(n) & 0xFFFFFFFF00000000)>> 32))
83#define	PCICFG_LOADDR(n) ((uint32_t)((uint64_t)(n) & 0x00000000FFFFFFFF))
84#define	PCICFG_LADDR(lo, hi)	(((uint64_t)(hi) << 32) | (uint32_t)(lo))
85
86#define	PCICFG_HIWORD(n) ((uint16_t)(((uint32_t)(n) & 0xFFFF0000)>> 16))
87#define	PCICFG_LOWORD(n) ((uint16_t)((uint32_t)(n) & 0x0000FFFF))
88#define	PCICFG_HIBYTE(n) ((uint8_t)(((uint16_t)(n) & 0xFF00)>> 8))
89#define	PCICFG_LOBYTE(n) ((uint8_t)((uint16_t)(n) & 0x00FF))
90
91#define	PCICFG_ROUND_UP(addr, gran) ((uintptr_t)((gran+addr-1)&(~(gran-1))))
92#define	PCICFG_ROUND_DOWN(addr, gran) ((uintptr_t)((addr) & ~(gran-1)))
93
94#define	PCICFG_MEMGRAN 0x100000
95#define	PCICFG_IOGRAN 0x1000
96#define	PCICFG_4GIG_LIMIT 0xFFFFFFFFUL
97
98#define	PCICFG_MEM_MULT 4
99#define	PCICFG_IO_MULT 4
100#define	PCICFG_RANGE_LEN 2 /* Number of range entries */
101
102static int pcicfg_slot_busnums = 8;
103static int pcicfg_slot_memsize = 32 * PCICFG_MEMGRAN; /* 32MB per slot */
104static int pcicfg_slot_iosize = 16 * PCICFG_IOGRAN; /* 64K per slot */
105static int pcicfg_chassis_per_tree = 1;
106static int pcicfg_sec_reset_delay = 1000000;
107
108/*
109 * The following typedef is used to represent a
110 * 1275 "bus-range" property of a PCI Bus node.
111 * DAF - should be in generic include file...
112 */
113
114typedef struct pcicfg_bus_range {
115	uint32_t lo;
116	uint32_t hi;
117} pcicfg_bus_range_t;
118
119typedef struct pcicfg_range {
120
121	uint32_t child_hi;
122	uint32_t child_mid;
123	uint32_t child_lo;
124	uint32_t parent_hi;
125	uint32_t parent_mid;
126	uint32_t parent_lo;
127	uint32_t size_hi;
128	uint32_t size_lo;
129
130} pcicfg_range_t;
131
132typedef struct hole hole_t;
133
134struct hole {
135	uint64_t	start;
136	uint64_t	len;
137	hole_t		*next;
138};
139
140typedef struct pcicfg_phdl pcicfg_phdl_t;
141
142struct pcicfg_phdl {
143
144	dev_info_t	*dip;		/* Associated with the attach point */
145	pcicfg_phdl_t	*next;
146
147	uint64_t	memory_base;	/* Memory base for this attach point */
148	uint64_t	memory_last;
149	uint64_t	memory_len;
150	uint32_t	io_base;	/* I/O base for this attach point */
151	uint32_t	io_last;
152	uint32_t	io_len;
153
154	int		error;
155	uint_t		highest_bus;	/* Highest bus seen on the probe */
156
157	hole_t		mem_hole;	/* Memory hole linked list. */
158	hole_t		io_hole;	/* IO hole linked list */
159
160	ndi_ra_request_t mem_req;	/* allocator request for memory */
161	ndi_ra_request_t io_req;	/* allocator request for I/O */
162};
163
164struct pcicfg_standard_prop_entry {
165    uchar_t *name;
166    uint_t  config_offset;
167    uint_t  size;
168};
169
170
171struct pcicfg_name_entry {
172    uint32_t class_code;
173    char  *name;
174};
175
176struct pcicfg_find_ctrl {
177	uint_t		device;
178	uint_t		function;
179	dev_info_t	*dip;
180};
181
182typedef struct pcicfg_err_regs {
183	uint16_t cmd;
184	uint16_t bcntl;
185	uint16_t pcie_dev;
186	uint16_t devctl;
187	uint16_t pcie_cap_off;
188} pcicfg_err_regs_t;
189
190/*
191 * List of Indirect Config Map Devices. At least the intent of the
192 * design is to look for a device in this list during the configure
193 * operation, and if the device is listed here, then it is a nontransparent
194 * bridge, hence load the driver and avail the config map services from
195 * the driver. Class and Subclass should be as defined in the PCI specs
196 * ie. class is 0x6, and subclass is 0x9.
197 */
198static struct {
199	uint8_t		mem_range_bar_offset;
200	uint8_t		io_range_bar_offset;
201	uint8_t		prefetch_mem_range_bar_offset;
202} pcicfg_indirect_map_devs[] = {
203	PCI_CONF_BASE3, PCI_CONF_BASE2, PCI_CONF_BASE3,
204	0,	0,	0,
205};
206
207#define	PCICFG_MAKE_REG_HIGH(busnum, devnum, funcnum, register)\
208	(\
209	((ulong_t)(busnum & 0xff) << 16)    |\
210	((ulong_t)(devnum & 0x1f) << 11)    |\
211	((ulong_t)(funcnum & 0x7) <<  8)    |\
212	((ulong_t)(register & 0x3f)))
213
214/*
215 * debug macros:
216 */
217#if	defined(DEBUG)
218extern void prom_printf(const char *, ...);
219
220/*
221 * Following values are defined for this debug flag.
222 *
223 * 1 = dump configuration header only.
224 * 2 = dump generic debug data only (no config header dumped)
225 * 3 = dump everything (both 1 and 2)
226 */
227int pcicfg_debug = 0;
228int pcicfg_dump_fcode = 0;
229
230static void debug(char *, uintptr_t, uintptr_t,
231	uintptr_t, uintptr_t, uintptr_t);
232
233#define	DEBUG0(fmt)\
234	debug(fmt, 0, 0, 0, 0, 0);
235#define	DEBUG1(fmt, a1)\
236	debug(fmt, (uintptr_t)(a1), 0, 0, 0, 0);
237#define	DEBUG2(fmt, a1, a2)\
238	debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2), 0, 0, 0);
239#define	DEBUG3(fmt, a1, a2, a3)\
240	debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2),\
241		(uintptr_t)(a3), 0, 0);
242#define	DEBUG4(fmt, a1, a2, a3, a4)\
243	debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2),\
244		(uintptr_t)(a3), (uintptr_t)(a4), 0);
245#else
246#define	DEBUG0(fmt)
247#define	DEBUG1(fmt, a1)
248#define	DEBUG2(fmt, a1, a2)
249#define	DEBUG3(fmt, a1, a2, a3)
250#define	DEBUG4(fmt, a1, a2, a3, a4)
251#endif
252
253#ifdef PCICFG_INTERPRET_FCODE
254int pcicfg_dont_interpret = 0;
255#else
256int pcicfg_dont_interpret = 1;
257#endif
258
259/*
260 * forward declarations for routines defined in this module (called here)
261 */
262
263static int pcicfg_add_config_reg(dev_info_t *,
264    uint_t, uint_t, uint_t);
265static int pcicfg_probe_children(dev_info_t *, uint_t, uint_t, uint_t,
266    uint_t *, pcicfg_flags_t, boolean_t);
267
268#ifdef PCICFG_INTERPRET_FCODE
269static int pcicfg_load_fcode(dev_info_t *, uint_t, uint_t, uint_t,
270	uint16_t, uint16_t, uchar_t **, int *, int, int);
271#endif
272
273static int pcicfg_fcode_probe(dev_info_t *, uint_t, uint_t, uint_t,
274    uint_t *, pcicfg_flags_t, boolean_t);
275static int pcicfg_probe_bridge(dev_info_t *, ddi_acc_handle_t, uint_t,
276    uint_t *, boolean_t);
277static int pcicfg_free_all_resources(dev_info_t *);
278static int pcicfg_alloc_new_resources(dev_info_t *);
279static int pcicfg_match_dev(dev_info_t *, void *);
280static dev_info_t *pcicfg_devi_find(dev_info_t *, uint_t, uint_t);
281static pcicfg_phdl_t *pcicfg_find_phdl(dev_info_t *);
282static pcicfg_phdl_t *pcicfg_create_phdl(dev_info_t *);
283static int pcicfg_destroy_phdl(dev_info_t *);
284static int pcicfg_sum_resources(dev_info_t *, void *);
285static int pcicfg_find_resource_end(dev_info_t *, void *);
286static int pcicfg_allocate_chunk(dev_info_t *);
287static int pcicfg_program_ap(dev_info_t *);
288static int pcicfg_device_assign(dev_info_t *);
289static int pcicfg_bridge_assign(dev_info_t *, void *);
290static int pcicfg_device_assign_readonly(dev_info_t *);
291static int pcicfg_free_resources(dev_info_t *, pcicfg_flags_t);
292static void pcicfg_setup_bridge(pcicfg_phdl_t *, ddi_acc_handle_t,
293    dev_info_t *);
294static void pcicfg_update_bridge(pcicfg_phdl_t *, ddi_acc_handle_t);
295static void pcicfg_enable_bridge_probe_err(dev_info_t *dip,
296				ddi_acc_handle_t h, pcicfg_err_regs_t *regs);
297static void pcicfg_disable_bridge_probe_err(dev_info_t *dip,
298				ddi_acc_handle_t h, pcicfg_err_regs_t *regs);
299static int pcicfg_update_assigned_prop(dev_info_t *, pci_regspec_t *);
300static void pcicfg_device_on(ddi_acc_handle_t);
301static void pcicfg_device_off(ddi_acc_handle_t);
302static int pcicfg_set_busnode_props(dev_info_t *, uint8_t, int, int);
303static int pcicfg_free_bridge_resources(dev_info_t *);
304static int pcicfg_free_device_resources(dev_info_t *, pcicfg_flags_t);
305static int pcicfg_teardown_device(dev_info_t *, pcicfg_flags_t, boolean_t);
306static int pcicfg_config_setup(dev_info_t *, ddi_acc_handle_t *);
307static void pcicfg_config_teardown(ddi_acc_handle_t *);
308static void pcicfg_get_mem(pcicfg_phdl_t *, uint32_t, uint64_t *);
309static void pcicfg_get_io(pcicfg_phdl_t *, uint32_t, uint32_t *);
310static int pcicfg_update_ranges_prop(dev_info_t *, pcicfg_range_t *);
311static int pcicfg_map_phys(dev_info_t *, pci_regspec_t *, caddr_t *,
312    ddi_device_acc_attr_t *, ddi_acc_handle_t *);
313static void pcicfg_unmap_phys(ddi_acc_handle_t *, pci_regspec_t *);
314static int pcicfg_dump_assigned(dev_info_t *);
315static uint_t pcicfg_configure_ntbridge(dev_info_t *, uint_t, uint_t);
316static int pcicfg_indirect_map(dev_info_t *dip);
317static uint_t pcicfg_get_ntbridge_child_range(dev_info_t *, uint64_t *,
318				uint64_t *, uint_t);
319static int pcicfg_is_ntbridge(dev_info_t *);
320static int pcicfg_ntbridge_allocate_resources(dev_info_t *);
321static int pcicfg_ntbridge_configure_done(dev_info_t *);
322static int pcicfg_ntbridge_unconfigure(dev_info_t *);
323static int pcicfg_ntbridge_unconfigure_child(dev_info_t *, uint_t);
324static void pcicfg_free_hole(hole_t *);
325static uint64_t pcicfg_alloc_hole(hole_t *, uint64_t *, uint32_t);
326static int pcicfg_update_available_prop(dev_info_t *, pci_regspec_t *);
327static int pcicfg_ari_configure(dev_info_t *);
328static int pcicfg_populate_reg_props(dev_info_t *, ddi_acc_handle_t);
329static int pcicfg_populate_props_from_bar(dev_info_t *, ddi_acc_handle_t);
330static int pcicfg_update_assigned_prop_value(dev_info_t *, uint32_t,
331    uint32_t, uint32_t, uint_t);
332static boolean_t is_pcie_fabric(dev_info_t *dip);
333
334#ifdef DEBUG
335static void pcicfg_dump_common_config(ddi_acc_handle_t config_handle);
336static void pcicfg_dump_device_config(ddi_acc_handle_t);
337
338static void pcicfg_dump_bridge_config(ddi_acc_handle_t config_handle);
339static uint64_t pcicfg_unused_space(hole_t *, uint32_t *);
340
341#define	PCICFG_DUMP_COMMON_CONFIG(hdl) (void)pcicfg_dump_common_config(hdl)
342#define	PCICFG_DUMP_DEVICE_CONFIG(hdl) (void)pcicfg_dump_device_config(hdl)
343#define	PCICFG_DUMP_BRIDGE_CONFIG(hdl) (void)pcicfg_dump_bridge_config(hdl)
344#else
345#define	PCICFG_DUMP_COMMON_CONFIG(handle)
346#define	PCICFG_DUMP_DEVICE_CONFIG(handle)
347#define	PCICFG_DUMP_BRIDGE_CONFIG(handle)
348#endif
349
350static kmutex_t pcicfg_list_mutex; /* Protects the probe handle list */
351static pcicfg_phdl_t *pcicfg_phdl_list = NULL;
352
353#ifndef _DONT_USE_1275_GENERIC_NAMES
354/*
355 * Class code table
356 */
357static struct pcicfg_name_entry pcicfg_class_lookup [] = {
358
359	{ 0x001, "display" },
360	{ 0x100, "scsi" },
361	{ 0x101, "ide" },
362	{ 0x102, "fdc" },
363	{ 0x103, "ipi" },
364	{ 0x104, "raid" },
365	{ 0x200, "ethernet" },
366	{ 0x201, "token-ring" },
367	{ 0x202, "fddi" },
368	{ 0x203, "atm" },
369	{ 0x300, "display" },
370	{ 0x400, "video" },
371	{ 0x401, "sound" },
372	{ 0x500, "memory" },
373	{ 0x501, "flash" },
374	{ 0x600, "host" },
375	{ 0x601, "isa" },
376	{ 0x602, "eisa" },
377	{ 0x603, "mca" },
378	{ 0x604, "pci" },
379	{ 0x605, "pcmcia" },
380	{ 0x606, "nubus" },
381	{ 0x607, "cardbus" },
382	{ 0x609, "pci" },
383	{ 0x700, "serial" },
384	{ 0x701, "parallel" },
385	{ 0x800, "interrupt-controller" },
386	{ 0x801, "dma-controller" },
387	{ 0x802, "timer" },
388	{ 0x803, "rtc" },
389	{ 0x900, "keyboard" },
390	{ 0x901, "pen" },
391	{ 0x902, "mouse" },
392	{ 0xa00, "dock" },
393	{ 0xb00, "cpu" },
394	{ 0xc00, "firewire" },
395	{ 0xc01, "access-bus" },
396	{ 0xc02, "ssa" },
397	{ 0xc03, "usb" },
398	{ 0xc04, "fibre-channel" },
399	{ 0, 0 }
400};
401#endif /* _DONT_USE_1275_GENERIC_NAMES */
402
403/*
404 * Module control operations
405 */
406
407extern struct mod_ops mod_miscops;
408
409static struct modlmisc modlmisc = {
410	&mod_miscops, /* Type of module */
411	"PCIe/PCI Config (EFCode Enabled)"
412};
413
414static struct modlinkage modlinkage = {
415	MODREV_1, (void *)&modlmisc, NULL
416};
417
418#ifdef DEBUG
419
420static void
421pcicfg_dump_common_config(ddi_acc_handle_t config_handle)
422{
423	if ((pcicfg_debug & 1) == 0)
424		return;
425	cmn_err(CE_CONT, " Vendor ID   = [0x%x]\n",
426	    pci_config_get16(config_handle, PCI_CONF_VENID));
427	cmn_err(CE_CONT, " Device ID   = [0x%x]\n",
428	    pci_config_get16(config_handle, PCI_CONF_DEVID));
429	cmn_err(CE_CONT, " Command REG = [0x%x]\n",
430	    pci_config_get16(config_handle, PCI_CONF_COMM));
431	cmn_err(CE_CONT, " Status  REG = [0x%x]\n",
432	    pci_config_get16(config_handle, PCI_CONF_STAT));
433	cmn_err(CE_CONT, " Revision ID = [0x%x]\n",
434	    pci_config_get8(config_handle, PCI_CONF_REVID));
435	cmn_err(CE_CONT, " Prog Class  = [0x%x]\n",
436	    pci_config_get8(config_handle, PCI_CONF_PROGCLASS));
437	cmn_err(CE_CONT, " Dev Class   = [0x%x]\n",
438	    pci_config_get8(config_handle, PCI_CONF_SUBCLASS));
439	cmn_err(CE_CONT, " Base Class  = [0x%x]\n",
440	    pci_config_get8(config_handle, PCI_CONF_BASCLASS));
441	cmn_err(CE_CONT, " Device ID   = [0x%x]\n",
442	    pci_config_get8(config_handle, PCI_CONF_CACHE_LINESZ));
443	cmn_err(CE_CONT, " Header Type = [0x%x]\n",
444	    pci_config_get8(config_handle, PCI_CONF_HEADER));
445	cmn_err(CE_CONT, " BIST        = [0x%x]\n",
446	    pci_config_get8(config_handle, PCI_CONF_BIST));
447	cmn_err(CE_CONT, " BASE 0      = [0x%x]\n",
448	    pci_config_get32(config_handle, PCI_CONF_BASE0));
449	cmn_err(CE_CONT, " BASE 1      = [0x%x]\n",
450	    pci_config_get32(config_handle, PCI_CONF_BASE1));
451
452}
453
454static void
455pcicfg_dump_device_config(ddi_acc_handle_t config_handle)
456{
457	if ((pcicfg_debug & 1) == 0)
458		return;
459	pcicfg_dump_common_config(config_handle);
460
461	cmn_err(CE_CONT, " BASE 2      = [0x%x]\n",
462	    pci_config_get32(config_handle, PCI_CONF_BASE2));
463	cmn_err(CE_CONT, " BASE 3      = [0x%x]\n",
464	    pci_config_get32(config_handle, PCI_CONF_BASE3));
465	cmn_err(CE_CONT, " BASE 4      = [0x%x]\n",
466	    pci_config_get32(config_handle, PCI_CONF_BASE4));
467	cmn_err(CE_CONT, " BASE 5      = [0x%x]\n",
468	    pci_config_get32(config_handle, PCI_CONF_BASE5));
469	cmn_err(CE_CONT, " Cardbus CIS = [0x%x]\n",
470	    pci_config_get32(config_handle, PCI_CONF_CIS));
471	cmn_err(CE_CONT, " Sub VID     = [0x%x]\n",
472	    pci_config_get16(config_handle, PCI_CONF_SUBVENID));
473	cmn_err(CE_CONT, " Sub SID     = [0x%x]\n",
474	    pci_config_get16(config_handle, PCI_CONF_SUBSYSID));
475	cmn_err(CE_CONT, " ROM         = [0x%x]\n",
476	    pci_config_get32(config_handle, PCI_CONF_ROM));
477	cmn_err(CE_CONT, " I Line      = [0x%x]\n",
478	    pci_config_get8(config_handle, PCI_CONF_ILINE));
479	cmn_err(CE_CONT, " I Pin       = [0x%x]\n",
480	    pci_config_get8(config_handle, PCI_CONF_IPIN));
481	cmn_err(CE_CONT, " Max Grant   = [0x%x]\n",
482	    pci_config_get8(config_handle, PCI_CONF_MIN_G));
483	cmn_err(CE_CONT, " Max Latent  = [0x%x]\n",
484	    pci_config_get8(config_handle, PCI_CONF_MAX_L));
485}
486
487static void
488pcicfg_dump_bridge_config(ddi_acc_handle_t config_handle)
489{
490	if ((pcicfg_debug & 1) == 0)
491		return;
492
493	pcicfg_dump_common_config(config_handle);
494
495	cmn_err(CE_CONT, "........................................\n");
496
497	cmn_err(CE_CONT, " Pri Bus     = [0x%x]\n",
498	    pci_config_get8(config_handle, PCI_BCNF_PRIBUS));
499	cmn_err(CE_CONT, " Sec Bus     = [0x%x]\n",
500	    pci_config_get8(config_handle, PCI_BCNF_SECBUS));
501	cmn_err(CE_CONT, " Sub Bus     = [0x%x]\n",
502	    pci_config_get8(config_handle, PCI_BCNF_SUBBUS));
503	cmn_err(CE_CONT, " Latency     = [0x%x]\n",
504	    pci_config_get8(config_handle, PCI_BCNF_LATENCY_TIMER));
505	cmn_err(CE_CONT, " I/O Base LO = [0x%x]\n",
506	    pci_config_get8(config_handle, PCI_BCNF_IO_BASE_LOW));
507	cmn_err(CE_CONT, " I/O Lim LO  = [0x%x]\n",
508	    pci_config_get8(config_handle, PCI_BCNF_IO_LIMIT_LOW));
509	cmn_err(CE_CONT, " Sec. Status = [0x%x]\n",
510	    pci_config_get16(config_handle, PCI_BCNF_SEC_STATUS));
511	cmn_err(CE_CONT, " Mem Base    = [0x%x]\n",
512	    pci_config_get16(config_handle, PCI_BCNF_MEM_BASE));
513	cmn_err(CE_CONT, " Mem Limit   = [0x%x]\n",
514	    pci_config_get16(config_handle, PCI_BCNF_MEM_LIMIT));
515	cmn_err(CE_CONT, " PF Mem Base = [0x%x]\n",
516	    pci_config_get16(config_handle, PCI_BCNF_PF_BASE_LOW));
517	cmn_err(CE_CONT, " PF Mem Lim  = [0x%x]\n",
518	    pci_config_get16(config_handle, PCI_BCNF_PF_LIMIT_LOW));
519	cmn_err(CE_CONT, " PF Base HI  = [0x%x]\n",
520	    pci_config_get32(config_handle, PCI_BCNF_PF_BASE_HIGH));
521	cmn_err(CE_CONT, " PF Lim  HI  = [0x%x]\n",
522	    pci_config_get32(config_handle, PCI_BCNF_PF_LIMIT_HIGH));
523	cmn_err(CE_CONT, " I/O Base HI = [0x%x]\n",
524	    pci_config_get16(config_handle, PCI_BCNF_IO_BASE_HI));
525	cmn_err(CE_CONT, " I/O Lim HI  = [0x%x]\n",
526	    pci_config_get16(config_handle, PCI_BCNF_IO_LIMIT_HI));
527	cmn_err(CE_CONT, " ROM addr    = [0x%x]\n",
528	    pci_config_get32(config_handle, PCI_BCNF_ROM));
529	cmn_err(CE_CONT, " Intr Line   = [0x%x]\n",
530	    pci_config_get8(config_handle, PCI_BCNF_ILINE));
531	cmn_err(CE_CONT, " Intr Pin    = [0x%x]\n",
532	    pci_config_get8(config_handle, PCI_BCNF_IPIN));
533	cmn_err(CE_CONT, " Bridge Ctrl = [0x%x]\n",
534	    pci_config_get16(config_handle, PCI_BCNF_BCNTRL));
535}
536
537#endif
538
539
540int
541_init()
542{
543	DEBUG0("PCI configurator installed - Fcode Interpretation/21554\n");
544
545	mutex_init(&pcicfg_list_mutex, NULL, MUTEX_DRIVER, NULL);
546	return (mod_install(&modlinkage));
547}
548
549int
550_fini(void)
551{
552	int error;
553
554	error = mod_remove(&modlinkage);
555	if (error != 0) {
556		return (error);
557	}
558	mutex_destroy(&pcicfg_list_mutex);
559	return (0);
560}
561
562int
563_info(modinfop)
564struct modinfo *modinfop;
565{
566	return (mod_info(&modlinkage, modinfop));
567}
568
569/*ARGSUSED*/
570static uint8_t
571pcicfg_get_nslots(dev_info_t *dip, ddi_acc_handle_t handle)
572{
573	uint8_t num_slots = 0;
574	uint16_t cap_ptr;
575
576	if ((PCI_CAP_LOCATE(handle, PCI_CAP_ID_PCI_HOTPLUG,
577	    &cap_ptr)) == DDI_SUCCESS) {
578		uint32_t config;
579
580		PCI_CAP_PUT8(handle, NULL, cap_ptr, PCI_HP_DWORD_SELECT_OFF,
581		    PCI_HP_SLOT_CONFIGURATION_REG);
582		config = PCI_CAP_GET32(handle, NULL, cap_ptr,
583		    PCI_HP_DWORD_DATA_OFF);
584		num_slots = config & 0x1F;
585	} else if ((PCI_CAP_LOCATE(handle, PCI_CAP_ID_SLOT_ID, &cap_ptr))
586	    == DDI_SUCCESS) {
587		uint8_t esr_reg = PCI_CAP_GET8(handle, NULL,
588		    cap_ptr, PCI_CAP_ID_REGS_OFF);
589
590		num_slots = PCI_CAPSLOT_NSLOTS(esr_reg);
591	} else if ((PCI_CAP_LOCATE(handle, PCI_CAP_ID_PCI_E, &cap_ptr))
592	    == DDI_SUCCESS) {
593		int port_type = PCI_CAP_GET16(handle, NULL, cap_ptr,
594		    PCIE_PCIECAP) & PCIE_PCIECAP_DEV_TYPE_MASK;
595
596		if ((port_type == PCIE_PCIECAP_DEV_TYPE_DOWN) &&
597		    (PCI_CAP_GET16(handle, NULL, cap_ptr, PCIE_PCIECAP)
598		    & PCIE_PCIECAP_SLOT_IMPL))
599				num_slots = 1;
600	}
601
602	DEBUG3("%s#%d has %d slots",
603	    ddi_get_name(dip), ddi_get_instance(dip), num_slots);
604
605	return (num_slots);
606}
607
608/*ARGSUSED*/
609static uint8_t
610pcicfg_is_chassis(dev_info_t *dip, ddi_acc_handle_t handle)
611{
612	uint16_t cap_ptr;
613
614	if ((PCI_CAP_LOCATE(handle, PCI_CAP_ID_SLOT_ID, &cap_ptr)) !=
615	    DDI_FAILURE) {
616
617		uint8_t esr_reg = PCI_CAP_GET8(handle, NULL, cap_ptr, 2);
618		if (PCI_CAPSLOT_FIC(esr_reg))
619			return (B_TRUE);
620	}
621	return (B_FALSE);
622}
623
624/*ARGSUSED*/
625static int
626pcicfg_pcie_dev(dev_info_t *dip, int bus_type, pcicfg_err_regs_t *regs)
627{
628	/* get parent device's device_type property */
629	char *device_type;
630	int rc = DDI_FAILURE;
631	dev_info_t *pdip = ddi_get_parent(dip);
632
633	regs->pcie_dev = 0;
634	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip,
635	    DDI_PROP_DONTPASS, "device_type", &device_type)
636	    != DDI_PROP_SUCCESS) {
637		DEBUG2("device_type property missing for %s#%d",
638		    ddi_get_name(pdip), ddi_get_instance(pdip));
639		return (DDI_FAILURE);
640	}
641	switch (bus_type) {
642		case PCICFG_DEVICE_TYPE_PCIE:
643			if (strcmp(device_type, "pciex") == 0) {
644				rc = DDI_SUCCESS;
645				regs->pcie_dev = 1;
646			}
647			break;
648		case PCICFG_DEVICE_TYPE_PCI:
649			if (strcmp(device_type, "pci") == 0)
650				rc = DDI_SUCCESS;
651			break;
652		default:
653			break;
654	}
655	ddi_prop_free(device_type);
656	return (rc);
657}
658
659/*ARGSUSED*/
660static int
661pcicfg_pcie_port_type(dev_info_t *dip, ddi_acc_handle_t handle)
662{
663	int port_type = -1;
664	uint16_t cap_ptr;
665
666	if ((PCI_CAP_LOCATE(handle, PCI_CAP_ID_PCI_E, &cap_ptr)) !=
667	    DDI_FAILURE)
668		port_type = PCI_CAP_GET16(handle, NULL,
669		    cap_ptr, PCIE_PCIECAP) & PCIE_PCIECAP_DEV_TYPE_MASK;
670
671	return (port_type);
672}
673
674static int
675pcicfg_pcie_device_type(dev_info_t *dip, ddi_acc_handle_t handle)
676{
677	int port_type = pcicfg_pcie_port_type(dip, handle);
678
679	DEBUG1("device port_type = %x\n", port_type);
680	/* No PCIe CAP regs, we are not PCIe device_type */
681	if (port_type < 0)
682		return (DDI_FAILURE);
683
684	/* check for all PCIe device_types */
685	if ((port_type == PCIE_PCIECAP_DEV_TYPE_UP) ||
686	    (port_type == PCIE_PCIECAP_DEV_TYPE_DOWN) ||
687	    (port_type == PCIE_PCIECAP_DEV_TYPE_ROOT) ||
688	    (port_type == PCIE_PCIECAP_DEV_TYPE_PCI2PCIE))
689		return (DDI_SUCCESS);
690
691	return (DDI_FAILURE);
692
693}
694
695/*
696 * In the following functions ndi_devi_enter() without holding the
697 * parent dip is sufficient. This is because  pci dr is driven through
698 * opens on the nexus which is in the device tree path above the node
699 * being operated on, and implicitly held due to the open.
700 */
701
702/*
703 * This entry point is called to configure a device (and
704 * all its children) on the given bus. It is called when
705 * a new device is added to the PCI domain.  This routine
706 * will create the device tree and program the devices
707 * registers.
708 */
709
710int
711pcicfg_configure(dev_info_t *devi, uint_t device, uint_t function,
712    pcicfg_flags_t flags)
713{
714	uint_t bus;
715	int len;
716	int func;
717	int trans_device;
718	dev_info_t *new_device;
719	pcicfg_bus_range_t pci_bus_range;
720	int rv;
721	int circ;
722	uint_t highest_bus = 0;
723	int ari_mode = B_FALSE;
724	int max_function = PCICFG_MAX_FUNCTION;
725	boolean_t is_pcie;
726
727	if (flags == PCICFG_FLAG_ENABLE_ARI)
728		return (pcicfg_ari_configure(devi));
729
730	/*
731	 * Start probing at the device specified in "device" on the
732	 * "bus" specified.
733	 */
734	len = sizeof (pcicfg_bus_range_t);
735	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS,
736	    "bus-range", (caddr_t)&pci_bus_range, &len) != DDI_SUCCESS) {
737		DEBUG0("no bus-range property\n");
738		return (PCICFG_FAILURE);
739	}
740
741	bus = pci_bus_range.lo; /* primary bus number of this bus node */
742
743	is_pcie = is_pcie_fabric(devi);
744
745	ndi_devi_enter(devi, &circ);
746	for (func = 0; func < max_function; ) {
747		if ((function != PCICFG_ALL_FUNC) && (function != func))
748			goto next;
749
750		if (ari_mode)
751			trans_device = func >> 3;
752		else
753			trans_device = device;
754
755		DEBUG3("Configuring [0x%x][0x%x][0x%x]\n",
756		    bus, trans_device, func & 7);
757
758		/*
759		 * Try executing fcode if available.
760		 */
761		switch (rv = pcicfg_fcode_probe(devi, bus, trans_device,
762		    func & 7, &highest_bus, flags, is_pcie)) {
763			case PCICFG_FAILURE:
764				DEBUG2("configure failed: "
765				    "bus [0x%x] device [0x%x]\n",
766				    bus, trans_device);
767				break;
768			case PCICFG_NODEVICE:
769				DEBUG3("no device : bus "
770				    "[0x%x] slot [0x%x] func [0x%x]\n",
771				    bus, trans_device, func & 7);
772
773				/*
774				 * When walking the list of ARI functions
775				 * we don't expect to see a non-present
776				 * function, so we will stop walking
777				 * the function list.
778				 */
779				if (ari_mode == B_TRUE)
780					break;
781
782				if (func)
783					goto next;
784				break;
785			default:
786				DEBUG3("configure: bus => [%d] "
787				    "slot => [%d] func => [%d]\n",
788				    bus, trans_device, func & 7);
789				break;
790		}
791
792		if (rv != PCICFG_SUCCESS)
793			break;
794
795		if ((new_device = pcicfg_devi_find(devi,
796		    trans_device, (func & 7))) == NULL) {
797			DEBUG0("Did'nt find device node just created\n");
798			goto cleanup;
799		}
800
801next:
802		/*
803		 * Determine if ARI Forwarding should be enabled.
804		 */
805		if (func == 0) {
806			if ((pcie_ari_supported(devi)
807			    == PCIE_ARI_FORW_SUPPORTED) &&
808			    (pcie_ari_device(new_device) == PCIE_ARI_DEVICE)) {
809				if (pcie_ari_enable(devi) == DDI_SUCCESS) {
810					(void) ddi_prop_create(DDI_DEV_T_NONE,
811					    devi,  DDI_PROP_CANSLEEP,
812					    "ari-enabled", NULL, 0);
813
814					ari_mode = B_TRUE;
815					max_function = PCICFG_MAX_ARI_FUNCTION;
816				}
817			}
818		}
819
820		if (ari_mode == B_TRUE) {
821			int next_function;
822
823			DEBUG0("Next Function - ARI Device\n");
824			if (pcie_ari_get_next_function(new_device,
825			    &next_function) != DDI_SUCCESS)
826				goto cleanup;
827
828			/*
829			 * Check if there are more fucntions to probe.
830			 */
831			if (next_function == 0) {
832				DEBUG0("Next Function - "
833				    "No more ARI Functions\n");
834				break;
835			}
836			func = next_function;
837		} else {
838			func++;
839		}
840
841		DEBUG1("Next Function - %x\n", func);
842	}
843
844	ndi_devi_exit(devi, circ);
845
846	if (func == 0)
847		return (PCICFG_FAILURE);	/* probe failed */
848	else
849		return (PCICFG_SUCCESS);
850
851cleanup:
852	/*
853	 * Clean up a partially created "probe state" tree.
854	 * There are no resources allocated to the in the
855	 * probe state.
856	 */
857	if (pcie_ari_is_enabled(devi) == PCIE_ARI_FORW_ENABLED)
858		max_function = PCICFG_MAX_ARI_FUNCTION;
859	else
860		max_function = PCICFG_MAX_FUNCTION;
861
862	for (func = 0; func < max_function; func++) {
863
864		if (max_function == PCICFG_MAX_ARI_FUNCTION)
865			trans_device = func >> 3; /* ARI Device */
866		else
867			trans_device = device;
868
869		if ((new_device = pcicfg_devi_find(devi,
870		    trans_device, (func & 0x7))) == NULL) {
871			DEBUG0("No more devices to clean up\n");
872			continue;
873		}
874
875		DEBUG2("Cleaning up device [0x%x] function [0x%x]\n",
876		    trans_device, func & 7);
877		/*
878		 * If this was a bridge device it will have a
879		 * probe handle - if not, no harm in calling this.
880		 */
881		(void) pcicfg_destroy_phdl(new_device);
882
883		if (is_pcie) {
884			/*
885			 * Free bus_t structure
886			 */
887			if (ddi_get_child(new_device) != NULL)
888				pcie_fab_fini_bus(new_device, PCIE_BUS_ALL);
889
890			pcie_fini_bus(new_device, PCIE_BUS_ALL);
891		}
892		/*
893		 * This will free up the node
894		 */
895		(void) ndi_devi_offline(new_device, NDI_DEVI_REMOVE);
896	}
897	ndi_devi_exit(devi, circ);
898
899	return (PCICFG_FAILURE);
900}
901
902/*
903 * configure the child nodes of ntbridge. new_device points to ntbridge itself
904 */
905/*ARGSUSED*/
906static uint_t
907pcicfg_configure_ntbridge(dev_info_t *new_device, uint_t bus, uint_t device)
908{
909	int bus_range[2], rc = PCICFG_FAILURE, rc1, max_devs = 0;
910	int			devno;
911	dev_info_t		*new_ntbridgechild;
912	ddi_acc_handle_t	config_handle;
913	uint16_t		vid;
914	uint64_t		next_bus;
915	uint64_t		blen;
916	ndi_ra_request_t	req;
917	uint8_t			pcie_device_type = 0;
918
919	/*
920	 * If we need to do indirect config, lets create a property here
921	 * to let the child conf map routine know that it has to
922	 * go through the DDI calls, and not assume the devices are
923	 * mapped directly under the host.
924	 */
925	if ((rc = ndi_prop_update_int(DDI_DEV_T_NONE, new_device,
926	    PCI_DEV_CONF_MAP_PROP, (int)DDI_SUCCESS))
927	    != DDI_SUCCESS) {
928
929		DEBUG0("Cannot create indirect conf map property.\n");
930		return ((uint_t)PCICFG_FAILURE);
931	}
932	if (pci_config_setup(new_device, &config_handle) != DDI_SUCCESS)
933		return ((uint_t)PCICFG_FAILURE);
934	/* check if we are PCIe device */
935	if (pcicfg_pcie_device_type(new_device, config_handle) == DDI_SUCCESS)
936		pcie_device_type = 1;
937	pci_config_teardown(&config_handle);
938
939	/* create Bus node properties for ntbridge. */
940	if (pcicfg_set_busnode_props(new_device, pcie_device_type, -1, -1) !=
941	    PCICFG_SUCCESS) {
942		DEBUG0("Failed to set busnode props\n");
943		return (rc);
944	}
945
946	/* For now: Lets only support one layer of child */
947	bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
948	req.ra_len = 1;
949	if (ndi_ra_alloc(ddi_get_parent(new_device), &req,
950	    &next_bus, &blen, NDI_RA_TYPE_PCI_BUSNUM,
951	    NDI_RA_PASS) != NDI_SUCCESS) {
952		DEBUG0("ntbridge: Failed to get a bus number\n");
953		return (rc);
954	}
955
956	DEBUG1("ntbridge bus range start  ->[%d]\n", next_bus);
957
958	/*
959	 * Following will change, as we detect more bridges
960	 * on the way.
961	 */
962	bus_range[0] = (int)next_bus;
963	bus_range[1] = (int)next_bus;
964
965	if (ndi_prop_update_int_array(DDI_DEV_T_NONE, new_device,
966	    "bus-range", bus_range, 2) != DDI_SUCCESS) {
967		DEBUG0("Cannot set ntbridge bus-range property");
968		return (rc);
969	}
970
971	/*
972	 * The other interface (away from the host) will be
973	 * initialized by the nexus driver when it loads.
974	 * We just have to set the registers and the nexus driver
975	 * figures out the rest.
976	 */
977
978	/*
979	 * finally, lets load and attach the driver
980	 * before configuring children of ntbridge.
981	 */
982	rc = ndi_devi_online(new_device, NDI_NO_EVENT|NDI_CONFIG);
983	if (rc != NDI_SUCCESS) {
984		cmn_err(CE_WARN,
985		    "pcicfg: Fail: can\'t load non-transparent bridge \
986		    driver.\n");
987		rc = PCICFG_FAILURE;
988		return (rc);
989	}
990	DEBUG0("pcicfg: Success loading nontransparent bridge nexus driver..");
991
992	/* Now set aside pci resources for our children. */
993	if (pcicfg_ntbridge_allocate_resources(new_device) !=
994	    PCICFG_SUCCESS) {
995		max_devs = 0;
996		rc = PCICFG_FAILURE;
997	} else
998		max_devs = PCICFG_MAX_DEVICE;
999
1000	/* Probe devices on 2nd bus */
1001	for (devno = pcicfg_start_devno; devno < max_devs; devno++) {
1002
1003		if (ndi_devi_alloc(new_device, DEVI_PSEUDO_NEXNAME,
1004		    (pnode_t)DEVI_SID_NODEID, &new_ntbridgechild)
1005		    != NDI_SUCCESS) {
1006
1007			DEBUG0("pcicfg: Failed to alloc test node\n");
1008			rc = PCICFG_FAILURE;
1009			break;
1010		}
1011
1012		if (pcicfg_add_config_reg(new_ntbridgechild, next_bus, devno, 0)
1013		    != DDI_PROP_SUCCESS) {
1014			cmn_err(CE_WARN,
1015			    "Failed to add conf reg for ntbridge child.\n");
1016			(void) ndi_devi_free(new_ntbridgechild);
1017			rc = PCICFG_FAILURE;
1018			break;
1019		}
1020
1021		if ((rc = pci_config_setup(new_ntbridgechild,
1022		    &config_handle)) != PCICFG_SUCCESS) {
1023			cmn_err(CE_WARN,
1024			    "Cannot map ntbridge child %x\n", devno);
1025			(void) ndi_devi_free(new_ntbridgechild);
1026			rc = PCICFG_FAILURE;
1027			break;
1028		}
1029
1030		/*
1031		 * See if there is any PCI HW at this location
1032		 * by reading the Vendor ID.  If it returns with 0xffff
1033		 * then there is no hardware at this location.
1034		 */
1035		vid = pci_config_get16(config_handle, PCI_CONF_VENID);
1036
1037		pci_config_teardown(&config_handle);
1038		(void) ndi_devi_free(new_ntbridgechild);
1039		if (vid	== 0xffff)
1040			continue;
1041
1042		/* Lets fake attachments points for each child, */
1043		if (pcicfg_configure(new_device, devno, PCICFG_ALL_FUNC, 0)
1044		    != PCICFG_SUCCESS) {
1045			int old_dev = pcicfg_start_devno;
1046
1047			cmn_err(CE_WARN,
1048			"Error configuring ntbridge child dev=%d\n", devno);
1049
1050			rc = PCICFG_FAILURE;
1051			while (old_dev != devno) {
1052				if (pcicfg_ntbridge_unconfigure_child(
1053				    new_device, old_dev) == PCICFG_FAILURE)
1054
1055					cmn_err(CE_WARN,
1056					    "Unconfig Error ntbridge child "
1057					    "dev=%d\n", old_dev);
1058				old_dev++;
1059			}
1060			break;
1061		}
1062	} /* devno loop */
1063	DEBUG1("ntbridge: finish probing 2nd bus, rc=%d\n", rc);
1064
1065	if (rc != PCICFG_FAILURE)
1066		rc = pcicfg_ntbridge_configure_done(new_device);
1067	else {
1068		pcicfg_phdl_t *entry = pcicfg_find_phdl(new_device);
1069		uint_t			*bus;
1070		int			k;
1071
1072		if (ddi_getlongprop(DDI_DEV_T_ANY, new_device,
1073		    DDI_PROP_DONTPASS, "bus-range", (caddr_t)&bus,
1074		    &k) != DDI_PROP_SUCCESS) {
1075			DEBUG0("Failed to read bus-range property\n");
1076			rc = PCICFG_FAILURE;
1077			return (rc);
1078		}
1079
1080		DEBUG2("Need to free bus [%d] range [%d]\n",
1081		    bus[0], bus[1] - bus[0] + 1);
1082
1083		if (ndi_ra_free(ddi_get_parent(new_device),
1084		    (uint64_t)bus[0], (uint64_t)(bus[1] - bus[0] + 1),
1085		    NDI_RA_TYPE_PCI_BUSNUM, NDI_RA_PASS) != NDI_SUCCESS) {
1086			DEBUG0("Failed to free a bus number\n");
1087			rc = PCICFG_FAILURE;
1088			/*
1089			 * Don't forget to free up memory from ddi_getlongprop
1090			 */
1091			kmem_free((caddr_t)bus, k);
1092
1093			return (rc);
1094		}
1095
1096		/*
1097		 * Since no memory allocations are done for non transparent
1098		 * bridges (but instead we just set the handle with the
1099		 * already allocated memory, we just need to reset the
1100		 * following values before calling the destroy_phdl()
1101		 * function next, otherwise the it will try to free
1102		 * memory allocated as in case of a transparent bridge.
1103		 */
1104		entry->memory_len = 0;
1105		entry->io_len = 0;
1106		/* the following will free hole data. */
1107		(void) pcicfg_destroy_phdl(new_device);
1108		/*
1109		 * Don't forget to free up memory from ddi_getlongprop
1110		 */
1111		kmem_free((caddr_t)bus, k);
1112	}
1113
1114	/*
1115	 * Unload driver just in case child configure failed!
1116	 */
1117	rc1 = ndi_devi_offline(new_device, NDI_NO_EVENT);
1118	DEBUG1("pcicfg: now unloading the ntbridge driver. rc1=%d\n", rc1);
1119	if (rc1 != NDI_SUCCESS) {
1120		cmn_err(CE_WARN,
1121		    "pcicfg: can\'t unload ntbridge driver children.\n");
1122		rc = PCICFG_FAILURE;
1123	}
1124
1125	return (rc);
1126}
1127
1128static int
1129pcicfg_ntbridge_allocate_resources(dev_info_t *dip)
1130{
1131	pcicfg_phdl_t		*phdl;
1132	ndi_ra_request_t	*mem_request;
1133	ndi_ra_request_t	*io_request;
1134	uint64_t		boundbase, boundlen;
1135
1136	phdl = pcicfg_find_phdl(dip);
1137	ASSERT(phdl);
1138
1139	mem_request = &phdl->mem_req;
1140	io_request  = &phdl->io_req;
1141
1142	phdl->error = PCICFG_SUCCESS;
1143
1144	/* Set Memory space handle for ntbridge */
1145	if (pcicfg_get_ntbridge_child_range(dip, &boundbase, &boundlen,
1146	    PCI_BASE_SPACE_MEM) != DDI_SUCCESS) {
1147		cmn_err(CE_WARN,
1148		    "ntbridge: Mem resource information failure\n");
1149		phdl->memory_len  = 0;
1150		return (PCICFG_FAILURE);
1151	}
1152	mem_request->ra_boundbase = boundbase;
1153	mem_request->ra_boundlen = boundbase + boundlen;
1154	mem_request->ra_len = boundlen;
1155	mem_request->ra_align_mask =
1156	    PCICFG_MEMGRAN - 1; /* 1M alignment on memory space */
1157	mem_request->ra_flags |= NDI_RA_ALLOC_BOUNDED;
1158
1159	/*
1160	 * mem_request->ra_len =
1161	 * PCICFG_ROUND_UP(mem_request->ra_len, PCICFG_MEMGRAN);
1162	 */
1163
1164	phdl->memory_base = phdl->memory_last = boundbase;
1165	phdl->memory_len  = boundlen;
1166	phdl->mem_hole.start = phdl->memory_base;
1167	phdl->mem_hole.len = mem_request->ra_len;
1168	phdl->mem_hole.next = (hole_t *)NULL;
1169
1170	DEBUG2("Connector requested [0x%llx], needs [0x%llx] bytes of memory\n",
1171	    boundlen, mem_request->ra_len);
1172
1173	/* set up a memory resource map for NT bridge */
1174	if (ndi_ra_map_setup(dip, NDI_RA_TYPE_MEM) == NDI_FAILURE) {
1175		DEBUG0("Can not setup ntbridge memory resource map\n");
1176		return (PCICFG_FAILURE);
1177	}
1178	/* initialize the memory map */
1179	if (ndi_ra_free(dip, boundbase, boundlen, NDI_RA_TYPE_MEM,
1180	    NDI_RA_PASS) != NDI_SUCCESS) {
1181		DEBUG0("Can not initalize ntbridge memory resource map\n");
1182		return (PCICFG_FAILURE);
1183	}
1184	/* Set IO space handle for ntbridge */
1185	if (pcicfg_get_ntbridge_child_range(dip, &boundbase, &boundlen,
1186	    PCI_BASE_SPACE_IO) != DDI_SUCCESS) {
1187		cmn_err(CE_WARN, "ntbridge: IO resource information failure\n");
1188		phdl->io_len  = 0;
1189		return (PCICFG_FAILURE);
1190	}
1191	io_request->ra_len = boundlen;
1192	io_request->ra_align_mask =
1193	    PCICFG_IOGRAN - 1;   /* 4K alignment on I/O space */
1194	io_request->ra_boundbase = boundbase;
1195	io_request->ra_boundlen = boundbase + boundlen;
1196	io_request->ra_flags |= NDI_RA_ALLOC_BOUNDED;
1197
1198	/*
1199	 * io_request->ra_len =
1200	 * PCICFG_ROUND_UP(io_request->ra_len, PCICFG_IOGRAN);
1201	 */
1202
1203	phdl->io_base = phdl->io_last = (uint32_t)boundbase;
1204	phdl->io_len  = (uint32_t)boundlen;
1205	phdl->io_hole.start = phdl->io_base;
1206	phdl->io_hole.len = io_request->ra_len;
1207	phdl->io_hole.next = (hole_t *)NULL;
1208
1209	DEBUG2("Connector requested [0x%llx], needs [0x%llx] bytes of IO\n",
1210	    boundlen, io_request->ra_len);
1211
1212	DEBUG2("MEMORY BASE = [0x%x] length [0x%x]\n",
1213	    phdl->memory_base, phdl->memory_len);
1214	DEBUG2("IO     BASE = [0x%x] length [0x%x]\n",
1215	    phdl->io_base, phdl->io_len);
1216
1217	/* set up a IO resource map for NT bridge */
1218	if (ndi_ra_map_setup(dip, NDI_RA_TYPE_IO) == NDI_FAILURE) {
1219		DEBUG0("Can not setup ntbridge memory resource map\n");
1220		return (PCICFG_FAILURE);
1221	}
1222	/* initialize the IO map */
1223	if (ndi_ra_free(dip, boundbase, boundlen, NDI_RA_TYPE_IO,
1224	    NDI_RA_PASS) != NDI_SUCCESS) {
1225		DEBUG0("Can not initalize ntbridge memory resource map\n");
1226		return (PCICFG_FAILURE);
1227	}
1228
1229	return (PCICFG_SUCCESS);
1230}
1231
1232static int
1233pcicfg_ntbridge_configure_done(dev_info_t *dip)
1234{
1235	pcicfg_range_t range[PCICFG_RANGE_LEN];
1236	pcicfg_phdl_t		*entry;
1237	uint_t			len;
1238	pcicfg_bus_range_t	bus_range;
1239	int			new_bus_range[2];
1240
1241	DEBUG1("Configuring children for %llx\n", dip);
1242
1243	entry = pcicfg_find_phdl(dip);
1244	ASSERT(entry);
1245
1246	bzero((caddr_t)range,
1247	    sizeof (pcicfg_range_t) * PCICFG_RANGE_LEN);
1248	range[1].child_hi = range[1].parent_hi |=
1249	    (PCI_REG_REL_M | PCI_ADDR_MEM32);
1250	range[1].child_lo = range[1].parent_lo = (uint32_t)entry->memory_base;
1251
1252	range[0].child_hi = range[0].parent_hi |=
1253	    (PCI_REG_REL_M | PCI_ADDR_IO);
1254	range[0].child_lo = range[0].parent_lo = (uint32_t)entry->io_base;
1255
1256	len = sizeof (pcicfg_bus_range_t);
1257	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1258	    "bus-range", (caddr_t)&bus_range, (int *)&len) != DDI_SUCCESS) {
1259		DEBUG0("no bus-range property\n");
1260		return (PCICFG_FAILURE);
1261	}
1262
1263	new_bus_range[0] = bus_range.lo;	/* primary bus number */
1264	if (entry->highest_bus) {	/* secondary bus number */
1265		if (entry->highest_bus < bus_range.lo) {
1266			cmn_err(CE_WARN,
1267			    "ntbridge bus range invalid !(%d,%d)\n",
1268			    bus_range.lo, entry->highest_bus);
1269			new_bus_range[1] = bus_range.lo + entry->highest_bus;
1270		}
1271		else
1272			new_bus_range[1] = entry->highest_bus;
1273	}
1274	else
1275		new_bus_range[1] = bus_range.hi;
1276
1277	DEBUG2("ntbridge: bus range lo=%x, hi=%x\n",
1278	    new_bus_range[0], new_bus_range[1]);
1279
1280	if (ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
1281	    "bus-range", new_bus_range, 2) != DDI_SUCCESS) {
1282		DEBUG0("Failed to set bus-range property");
1283		entry->error = PCICFG_FAILURE;
1284		return (PCICFG_FAILURE);
1285	}
1286
1287#ifdef DEBUG
1288	{
1289		uint64_t	unused;
1290		unused = pcicfg_unused_space(&entry->io_hole, &len);
1291		DEBUG2("ntbridge: Unused IO space %llx bytes over %d holes\n",
1292		    unused, len);
1293	}
1294#endif
1295
1296	range[0].size_lo = entry->io_len;
1297	if (pcicfg_update_ranges_prop(dip, &range[0])) {
1298		DEBUG0("Failed to update ranges (i/o)\n");
1299		entry->error = PCICFG_FAILURE;
1300		return (PCICFG_FAILURE);
1301	}
1302
1303#ifdef DEBUG
1304	{
1305		uint64_t	unused;
1306		unused = pcicfg_unused_space(&entry->mem_hole, &len);
1307		DEBUG2("ntbridge: Unused Mem space %llx bytes over %d holes\n",
1308		    unused, len);
1309	}
1310#endif
1311
1312	range[1].size_lo = entry->memory_len;
1313	if (pcicfg_update_ranges_prop(dip, &range[1])) {
1314		DEBUG0("Failed to update ranges (memory)\n");
1315		entry->error = PCICFG_FAILURE;
1316		return (PCICFG_FAILURE);
1317	}
1318
1319	return (PCICFG_SUCCESS);
1320}
1321
1322static int
1323pcicfg_ntbridge_unconfigure_child(dev_info_t *new_device, uint_t devno)
1324{
1325
1326	dev_info_t	*new_ntbridgechild;
1327	int 		len, bus;
1328	uint16_t	vid;
1329	ddi_acc_handle_t	config_handle;
1330	pcicfg_bus_range_t pci_bus_range;
1331
1332	len = sizeof (pcicfg_bus_range_t);
1333	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, new_device, DDI_PROP_DONTPASS,
1334	    "bus-range", (caddr_t)&pci_bus_range, &len) != DDI_SUCCESS) {
1335		DEBUG0("no bus-range property\n");
1336		return (PCICFG_FAILURE);
1337	}
1338
1339	bus = pci_bus_range.lo; /* primary bus number of this bus node */
1340
1341	if (ndi_devi_alloc(new_device, DEVI_PSEUDO_NEXNAME,
1342	    (pnode_t)DEVI_SID_NODEID, &new_ntbridgechild) != NDI_SUCCESS) {
1343
1344		DEBUG0("pcicfg: Failed to alloc test node\n");
1345		return (PCICFG_FAILURE);
1346	}
1347
1348	if (pcicfg_add_config_reg(new_ntbridgechild, bus, devno, 0)
1349	    != DDI_PROP_SUCCESS) {
1350		cmn_err(CE_WARN,
1351		"Unconfigure: Failed to add conf reg prop for ntbridge "
1352		    "child.\n");
1353		(void) ndi_devi_free(new_ntbridgechild);
1354		return (PCICFG_FAILURE);
1355	}
1356
1357	if (pcicfg_config_setup(new_ntbridgechild, &config_handle)
1358	    != DDI_SUCCESS) {
1359		cmn_err(CE_WARN,
1360		    "pcicfg: Cannot map ntbridge child %x\n", devno);
1361		(void) ndi_devi_free(new_ntbridgechild);
1362		return (PCICFG_FAILURE);
1363	}
1364
1365	/*
1366	 * See if there is any PCI HW at this location
1367	 * by reading the Vendor ID.  If it returns with 0xffff
1368	 * then there is no hardware at this location.
1369	 */
1370	vid = pci_config_get16(config_handle, PCI_CONF_VENID);
1371
1372	pci_config_teardown(&config_handle);
1373	(void) ndi_devi_free(new_ntbridgechild);
1374	if (vid	== 0xffff)
1375		return (PCICFG_NODEVICE);
1376
1377	return (pcicfg_unconfigure(new_device, devno, PCICFG_ALL_FUNC, 0));
1378}
1379
1380static int
1381pcicfg_ntbridge_unconfigure(dev_info_t *dip)
1382{
1383	pcicfg_phdl_t *entry = pcicfg_find_phdl(dip);
1384	uint_t			*bus;
1385	int			k, rc = PCICFG_FAILURE;
1386
1387	if (entry->memory_len)
1388		if (ndi_ra_map_destroy(dip, NDI_RA_TYPE_MEM) == NDI_FAILURE) {
1389			DEBUG1("cannot destroy ntbridge memory map size=%x\n",
1390			    entry->memory_len);
1391			return (PCICFG_FAILURE);
1392		}
1393	if (entry->io_len)
1394		if (ndi_ra_map_destroy(dip, NDI_RA_TYPE_IO) == NDI_FAILURE) {
1395			DEBUG1("cannot destroy ntbridge io map size=%x\n",
1396			    entry->io_len);
1397			return (PCICFG_FAILURE);
1398		}
1399	if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
1400	    DDI_PROP_DONTPASS, "bus-range", (caddr_t)&bus,
1401	    &k) != DDI_PROP_SUCCESS) {
1402		DEBUG0("ntbridge: Failed to read bus-range property\n");
1403		return (rc);
1404	}
1405
1406	DEBUG2("ntbridge: Need to free bus [%d] range [%d]\n",
1407	    bus[0], bus[1] - bus[0] + 1);
1408
1409	if (ndi_ra_free(ddi_get_parent(dip),
1410	    (uint64_t)bus[0], (uint64_t)(bus[1] - bus[0] + 1),
1411	    NDI_RA_TYPE_PCI_BUSNUM, NDI_RA_PASS) != NDI_SUCCESS) {
1412		DEBUG0("ntbridge: Failed to free a bus number\n");
1413		/*
1414		 * Don't forget to free up memory from ddi_getlongprop
1415		 */
1416		kmem_free((caddr_t)bus, k);
1417
1418		return (rc);
1419	}
1420
1421	/*
1422	 * Don't forget to free up memory from ddi_getlongprop
1423	 */
1424	kmem_free((caddr_t)bus, k);
1425
1426	/*
1427	 * Since our resources will be freed at the parent level,
1428	 * just reset these values.
1429	 */
1430	entry->memory_len = 0;
1431	entry->io_len = 0;
1432	/* the following will also free hole data. */
1433	return (pcicfg_destroy_phdl(dip));
1434
1435}
1436
1437static int
1438pcicfg_is_ntbridge(dev_info_t *dip)
1439{
1440	ddi_acc_handle_t	config_handle;
1441	uint8_t		class, subclass;
1442	int		rc = DDI_SUCCESS;
1443
1444	if (pcicfg_config_setup(dip, &config_handle) != DDI_SUCCESS) {
1445		cmn_err(CE_WARN,
1446		    "pcicfg: cannot map config space, to get map type\n");
1447		return (DDI_FAILURE);
1448	}
1449	class = pci_config_get8(config_handle, PCI_CONF_BASCLASS);
1450	subclass = pci_config_get8(config_handle, PCI_CONF_SUBCLASS);
1451
1452	/* check for class=6, subclass=9, for non transparent bridges.  */
1453	if ((class != PCI_CLASS_BRIDGE) || (subclass != PCI_BRIDGE_STBRIDGE))
1454		rc = DDI_FAILURE;
1455
1456	DEBUG3("pcicfg: checking device %x,%x for indirect map. rc=%d\n",
1457	    pci_config_get16(config_handle, PCI_CONF_VENID),
1458	    pci_config_get16(config_handle, PCI_CONF_DEVID),
1459	    rc);
1460	pci_config_teardown(&config_handle);
1461	return (rc);
1462}
1463
1464/*
1465 * this function is called only for SPARC platforms, where we may have
1466 * a mix n' match of direct vs indirectly mapped configuration space.
1467 * On x86, this function does not get called. We always return TRUE
1468 * via a macro for x86.
1469 */
1470/*ARGSUSED*/
1471static int
1472pcicfg_indirect_map(dev_info_t *dip)
1473{
1474#if defined(__sparc)
1475	int rc = DDI_FAILURE;
1476
1477	if (ddi_prop_get_int(DDI_DEV_T_ANY, ddi_get_parent(dip), 0,
1478	    PCI_DEV_CONF_MAP_PROP, DDI_FAILURE) != DDI_FAILURE)
1479		rc = DDI_SUCCESS;
1480	else
1481		if (ddi_prop_get_int(DDI_DEV_T_ANY, ddi_get_parent(dip),
1482		    0, PCI_BUS_CONF_MAP_PROP,
1483		    DDI_FAILURE) != DDI_FAILURE)
1484			rc = DDI_SUCCESS;
1485	DEBUG1("pci conf map = %d", rc);
1486	return (rc);
1487#else
1488	return (DDI_SUCCESS);
1489#endif
1490}
1491
1492static uint_t
1493pcicfg_get_ntbridge_child_range(dev_info_t *dip, uint64_t *boundbase,
1494				uint64_t *boundlen, uint_t space_type)
1495{
1496	int		length, found = DDI_FAILURE, acount, i, ibridge;
1497	pci_regspec_t	*assigned;
1498
1499	if ((ibridge = pcicfg_is_ntbridge(dip)) == DDI_FAILURE)
1500		return (found);
1501
1502	if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
1503	    DDI_PROP_DONTPASS, "assigned-addresses", (caddr_t)&assigned,
1504	    &length) != DDI_PROP_SUCCESS) {
1505		DEBUG1("Failed to get assigned-addresses property %llx\n", dip);
1506		return (found);
1507	}
1508	DEBUG1("pcicfg: ntbridge child range: dip = %s\n",
1509	    ddi_driver_name(dip));
1510
1511	acount = length / sizeof (pci_regspec_t);
1512
1513	for (i = 0; i < acount; i++) {
1514		if ((PCI_REG_REG_G(assigned[i].pci_phys_hi) ==
1515		    pcicfg_indirect_map_devs[ibridge].mem_range_bar_offset) &&
1516		    (space_type == PCI_BASE_SPACE_MEM)) {
1517			found = DDI_SUCCESS;
1518			break;
1519		} else {
1520			if ((PCI_REG_REG_G(assigned[i].pci_phys_hi) ==
1521			    pcicfg_indirect_map_devs[ibridge].\
1522			    io_range_bar_offset) &&
1523			    (space_type == PCI_BASE_SPACE_IO)) {
1524				found = DDI_SUCCESS;
1525				break;
1526			}
1527		}
1528	}
1529	DEBUG3("pcicfg: ntbridge child range: space=%x, base=%lx, len=%lx\n",
1530	    space_type, assigned[i].pci_phys_low, assigned[i].pci_size_low);
1531
1532	if (found == DDI_SUCCESS)  {
1533		*boundbase = assigned[i].pci_phys_low;
1534		*boundlen = assigned[i].pci_size_low;
1535	}
1536
1537	kmem_free(assigned, length);
1538	return (found);
1539}
1540
1541/*
1542 * This will turn  resources allocated by pcicfg_configure()
1543 * and remove the device tree from the Hotplug Connection (CN)
1544 * and below.  The routine assumes the devices have their
1545 * drivers detached.
1546 */
1547int
1548pcicfg_unconfigure(dev_info_t *devi, uint_t device, uint_t function,
1549    pcicfg_flags_t flags)
1550{
1551	dev_info_t *child_dip;
1552	int func;
1553	int i;
1554	int max_function;
1555	int trans_device;
1556	int circ;
1557	boolean_t is_pcie;
1558
1559	if (pcie_ari_is_enabled(devi) == PCIE_ARI_FORW_ENABLED)
1560		max_function = PCICFG_MAX_ARI_FUNCTION;
1561	else
1562		max_function = PCICFG_MAX_FUNCTION;
1563
1564	/*
1565	 * Cycle through devices to make sure none are busy.
1566	 * If a single device is busy fail the whole unconfigure.
1567	 */
1568	is_pcie = is_pcie_fabric(devi);
1569
1570	ndi_devi_enter(devi, &circ);
1571	for (func = 0; func < max_function; func++) {
1572
1573		if (max_function == PCICFG_MAX_ARI_FUNCTION)
1574			trans_device = func >> 3; /* ARI Device */
1575		else
1576			trans_device = device;
1577
1578		if ((child_dip = pcicfg_devi_find(devi, trans_device,
1579		    (func & 0x7))) == NULL)
1580			continue;
1581
1582		if (ndi_devi_offline(child_dip, NDI_UNCONFIG) == NDI_SUCCESS)
1583			continue;
1584		/*
1585		 * Device function is busy. Before returning we have to
1586		 * put all functions back online which were taken
1587		 * offline during the process.
1588		 */
1589		DEBUG2("Device [0x%x] function [%x] is busy\n", device, func);
1590		/*
1591		 * If we are only asked to offline one specific function,
1592		 * and that fails, we just simply return.
1593		 */
1594		if (function != PCICFG_ALL_FUNC)
1595			return (PCICFG_FAILURE);
1596
1597		for (i = 0; i < func; i++) {
1598
1599			if (max_function == PCICFG_MAX_ARI_FUNCTION)
1600				trans_device = i >> 3;
1601
1602			if ((child_dip =
1603			    pcicfg_devi_find(devi, trans_device, (i & 7)))
1604			    == NULL) {
1605				DEBUG0(
1606				    "No more devices to put back on line!!\n");
1607				/*
1608				 * Made it through all functions
1609				 */
1610				continue;
1611			}
1612			if (ndi_devi_online(child_dip, NDI_CONFIG)
1613			    != NDI_SUCCESS) {
1614				DEBUG0("Failed to put back devices state\n");
1615				goto fail;
1616			}
1617		}
1618		goto fail;
1619	}
1620
1621	/*
1622	 * Now, tear down all devinfo nodes for this Connector.
1623	 */
1624	for (func = 0; func < max_function; func++) {
1625
1626		if (max_function == PCICFG_MAX_ARI_FUNCTION)
1627			trans_device = func >> 3; /* ARI Device */
1628		else
1629			trans_device = device;
1630
1631		if ((child_dip = pcicfg_devi_find(devi,
1632		    trans_device, (func & 7))) == NULL) {
1633			DEBUG0("No more devices to tear down!\n");
1634			continue;
1635		}
1636
1637		DEBUG2("Tearing down device [0x%x] function [0x%x]\n",
1638		    trans_device, (func & 7));
1639
1640		if (pcicfg_is_ntbridge(child_dip) != DDI_FAILURE)
1641			if (pcicfg_ntbridge_unconfigure(child_dip) !=
1642			    PCICFG_SUCCESS) {
1643				cmn_err(CE_WARN,
1644				    "ntbridge: unconfigure failed\n");
1645				goto fail;
1646			}
1647
1648		if (pcicfg_teardown_device(child_dip, flags, is_pcie)
1649		    != PCICFG_SUCCESS) {
1650			DEBUG2("Failed to tear down device [0x%x]"
1651			    "function [0x%x]\n",
1652			    trans_device, func & 7);
1653			goto fail;
1654		}
1655	}
1656
1657	if (pcie_ari_is_enabled(devi) == PCIE_ARI_FORW_ENABLED) {
1658		(void) ddi_prop_remove(DDI_DEV_T_NONE, devi, "ari-enabled");
1659		(void) pcie_ari_disable(devi);
1660	}
1661
1662	ndi_devi_exit(devi, circ);
1663	return (PCICFG_SUCCESS);
1664
1665fail:
1666	ndi_devi_exit(devi, circ);
1667	return (PCICFG_FAILURE);
1668}
1669
1670static int
1671pcicfg_teardown_device(dev_info_t *dip, pcicfg_flags_t flags, boolean_t is_pcie)
1672{
1673	ddi_acc_handle_t	config_handle;
1674
1675	/*
1676	 * Free up resources associated with 'dip'
1677	 */
1678	if (pcicfg_free_resources(dip, flags) != PCICFG_SUCCESS) {
1679		DEBUG0("Failed to free resources\n");
1680		return (PCICFG_FAILURE);
1681	}
1682
1683	/*
1684	 * This will disable the device
1685	 */
1686	if (pci_config_setup(dip, &config_handle) != PCICFG_SUCCESS) {
1687		return (PCICFG_FAILURE);
1688	}
1689
1690	pcicfg_device_off(config_handle);
1691	pci_config_teardown(&config_handle);
1692
1693	/*
1694	 * free pcie_bus_t for the sub-tree
1695	 */
1696	if (is_pcie) {
1697		if (ddi_get_child(dip) != NULL)
1698			pcie_fab_fini_bus(dip, PCIE_BUS_ALL);
1699
1700		pcie_fini_bus(dip, PCIE_BUS_ALL);
1701	}
1702
1703	/*
1704	 * The framework provides this routine which can
1705	 * tear down a sub-tree.
1706	 */
1707	if (ndi_devi_offline(dip, NDI_DEVI_REMOVE) != NDI_SUCCESS) {
1708		DEBUG0("Failed to offline and remove node\n");
1709		return (PCICFG_FAILURE);
1710	}
1711
1712	return (PCICFG_SUCCESS);
1713}
1714
1715/*
1716 * BEGIN GENERIC SUPPORT ROUTINES
1717 */
1718static pcicfg_phdl_t *
1719pcicfg_find_phdl(dev_info_t *dip)
1720{
1721	pcicfg_phdl_t *entry;
1722	mutex_enter(&pcicfg_list_mutex);
1723	for (entry = pcicfg_phdl_list; entry != NULL; entry = entry->next) {
1724		if (entry->dip == dip) {
1725			mutex_exit(&pcicfg_list_mutex);
1726			return (entry);
1727		}
1728	}
1729	mutex_exit(&pcicfg_list_mutex);
1730
1731	/*
1732	 * Did'nt find entry - create one
1733	 */
1734	return (pcicfg_create_phdl(dip));
1735}
1736
1737static pcicfg_phdl_t *
1738pcicfg_create_phdl(dev_info_t *dip)
1739{
1740	pcicfg_phdl_t *new;
1741
1742	new = (pcicfg_phdl_t *)kmem_zalloc(sizeof (pcicfg_phdl_t),
1743	    KM_SLEEP);
1744
1745	new->dip = dip;
1746	mutex_enter(&pcicfg_list_mutex);
1747	new->next = pcicfg_phdl_list;
1748	pcicfg_phdl_list = new;
1749	mutex_exit(&pcicfg_list_mutex);
1750
1751	return (new);
1752}
1753
1754static int
1755pcicfg_destroy_phdl(dev_info_t *dip)
1756{
1757	pcicfg_phdl_t *entry;
1758	pcicfg_phdl_t *follow = NULL;
1759
1760	mutex_enter(&pcicfg_list_mutex);
1761	for (entry = pcicfg_phdl_list; entry != NULL; follow = entry,
1762	    entry = entry->next) {
1763		if (entry->dip == dip) {
1764			if (entry == pcicfg_phdl_list) {
1765				pcicfg_phdl_list = entry->next;
1766			} else {
1767				follow->next = entry->next;
1768			}
1769			/*
1770			 * If this entry has any allocated memory
1771			 * or IO space associated with it, that
1772			 * must be freed up.
1773			 */
1774			if (entry->memory_len > 0) {
1775				(void) ndi_ra_free(ddi_get_parent(dip),
1776				    entry->memory_base,
1777				    entry->memory_len,
1778				    NDI_RA_TYPE_MEM, NDI_RA_PASS);
1779			}
1780			pcicfg_free_hole(&entry->mem_hole);
1781
1782			if (entry->io_len > 0) {
1783				(void) ndi_ra_free(ddi_get_parent(dip),
1784				    entry->io_base,
1785				    entry->io_len,
1786				    NDI_RA_TYPE_IO, NDI_RA_PASS);
1787			}
1788			pcicfg_free_hole(&entry->io_hole);
1789
1790			/*
1791			 * Destroy this entry
1792			 */
1793			kmem_free((caddr_t)entry, sizeof (pcicfg_phdl_t));
1794			mutex_exit(&pcicfg_list_mutex);
1795			return (PCICFG_SUCCESS);
1796		}
1797	}
1798	mutex_exit(&pcicfg_list_mutex);
1799	/*
1800	 * Did'nt find the entry
1801	 */
1802	return (PCICFG_FAILURE);
1803}
1804
1805static int
1806pcicfg_program_ap(dev_info_t *dip)
1807{
1808	pcicfg_phdl_t *phdl;
1809	uint8_t header_type;
1810	ddi_acc_handle_t handle;
1811	pcicfg_phdl_t *entry;
1812
1813	if (pcicfg_config_setup(dip, &handle) != DDI_SUCCESS) {
1814		DEBUG0("Failed to map config space!\n");
1815		return (PCICFG_FAILURE);
1816
1817	}
1818
1819	header_type = pci_config_get8(handle, PCI_CONF_HEADER);
1820
1821	(void) pcicfg_config_teardown(&handle);
1822
1823	if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
1824
1825		if (pcicfg_allocate_chunk(dip) != PCICFG_SUCCESS) {
1826			DEBUG0("Not enough memory to hotplug\n");
1827			(void) pcicfg_destroy_phdl(dip);
1828			return (PCICFG_FAILURE);
1829		}
1830
1831		phdl = pcicfg_find_phdl(dip);
1832		ASSERT(phdl);
1833
1834		(void) pcicfg_bridge_assign(dip, (void *)phdl);
1835
1836		if (phdl->error != PCICFG_SUCCESS) {
1837			DEBUG0("Problem assigning bridge\n");
1838			(void) pcicfg_destroy_phdl(dip);
1839			return (phdl->error);
1840		}
1841
1842		/*
1843		 * Successfully allocated and assigned
1844		 * memory.  Set the memory and IO length
1845		 * to zero so when the handle is freed up
1846		 * it will not de-allocate assigned resources.
1847		 */
1848		entry = (pcicfg_phdl_t *)phdl;
1849
1850		entry->memory_len = entry->io_len = 0;
1851
1852		/*
1853		 * Free up the "entry" structure.
1854		 */
1855		(void) pcicfg_destroy_phdl(dip);
1856	} else {
1857		if (pcicfg_device_assign(dip) != PCICFG_SUCCESS) {
1858			return (PCICFG_FAILURE);
1859		}
1860	}
1861	return (PCICFG_SUCCESS);
1862}
1863
1864static int
1865pcicfg_bridge_assign(dev_info_t *dip, void *hdl)
1866{
1867	ddi_acc_handle_t handle;
1868	pci_regspec_t *reg;
1869	int length;
1870	int rcount;
1871	int i;
1872	int offset;
1873	uint64_t mem_answer;
1874	uint32_t io_answer;
1875	int count;
1876	uint8_t header_type;
1877	pcicfg_range_t range[PCICFG_RANGE_LEN];
1878	int bus_range[2];
1879
1880	pcicfg_phdl_t *entry = (pcicfg_phdl_t *)hdl;
1881
1882	DEBUG1("bridge assign: assigning addresses to %s\n", ddi_get_name(dip));
1883
1884	if (entry == NULL) {
1885		DEBUG0("Failed to get entry\n");
1886		return (DDI_WALK_TERMINATE);
1887	}
1888
1889	entry->error = PCICFG_SUCCESS;
1890
1891	if (pcicfg_config_setup(dip, &handle) != DDI_SUCCESS) {
1892		DEBUG0("Failed to map config space!\n");
1893		entry->error = PCICFG_FAILURE;
1894		return (DDI_WALK_TERMINATE);
1895	}
1896
1897	header_type = pci_config_get8(handle, PCI_CONF_HEADER);
1898
1899	if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
1900
1901		bzero((caddr_t)range,
1902		    sizeof (pcicfg_range_t) * PCICFG_RANGE_LEN);
1903
1904		(void) pcicfg_setup_bridge(entry, handle, dip);
1905
1906		range[0].child_hi = range[0].parent_hi |=
1907		    (PCI_REG_REL_M | PCI_ADDR_IO);
1908		range[0].child_lo = range[0].parent_lo =
1909		    entry->io_last;
1910		range[1].child_hi = range[1].parent_hi |=
1911		    (PCI_REG_REL_M | PCI_ADDR_MEM32);
1912		range[1].child_lo = range[1].parent_lo =
1913		    entry->memory_last;
1914
1915		ndi_devi_enter(dip, &count);
1916		ddi_walk_devs(ddi_get_child(dip),
1917		    pcicfg_bridge_assign, (void *)entry);
1918		ndi_devi_exit(dip, count);
1919
1920		(void) pcicfg_update_bridge(entry, handle);
1921
1922		bus_range[0] = pci_config_get8(handle, PCI_BCNF_SECBUS);
1923		bus_range[1] = pci_config_get8(handle, PCI_BCNF_SUBBUS);
1924
1925		if (ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
1926		    "bus-range", bus_range, 2) != DDI_SUCCESS) {
1927			DEBUG0("Failed to set bus-range property");
1928			entry->error = PCICFG_FAILURE;
1929			return (DDI_WALK_TERMINATE);
1930		}
1931
1932		if (entry->io_len > 0) {
1933			range[0].size_lo = entry->io_last - entry->io_base;
1934			if (pcicfg_update_ranges_prop(dip, &range[0])) {
1935				DEBUG0("Failed to update ranges (i/o)\n");
1936				entry->error = PCICFG_FAILURE;
1937				return (DDI_WALK_TERMINATE);
1938			}
1939		}
1940		if (entry->memory_len > 0) {
1941			range[1].size_lo =
1942			    entry->memory_last - entry->memory_base;
1943			if (pcicfg_update_ranges_prop(dip, &range[1])) {
1944				DEBUG0("Failed to update ranges (memory)\n");
1945				entry->error = PCICFG_FAILURE;
1946				return (DDI_WALK_TERMINATE);
1947			}
1948		}
1949
1950		(void) pcicfg_device_on(handle);
1951
1952		PCICFG_DUMP_BRIDGE_CONFIG(handle);
1953
1954		return (DDI_WALK_PRUNECHILD);
1955	}
1956
1957	/*
1958	 * If there is an interrupt pin set program
1959	 * interrupt line with default values.
1960	 */
1961	if (pci_config_get8(handle, PCI_CONF_IPIN)) {
1962		pci_config_put8(handle, PCI_CONF_ILINE, 0xf);
1963	}
1964
1965	/*
1966	 * A single device (under a bridge).
1967	 * For each "reg" property with a length, allocate memory
1968	 * and program the base registers.
1969	 */
1970	if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
1971	    DDI_PROP_DONTPASS, "reg", (caddr_t)&reg,
1972	    &length) != DDI_PROP_SUCCESS) {
1973		DEBUG0("Failed to read reg property\n");
1974		entry->error = PCICFG_FAILURE;
1975		return (DDI_WALK_TERMINATE);
1976	}
1977
1978	rcount = length / sizeof (pci_regspec_t);
1979	offset = PCI_CONF_BASE0;
1980	for (i = 0; i < rcount; i++) {
1981		if ((reg[i].pci_size_low != 0)||
1982		    (reg[i].pci_size_hi != 0)) {
1983
1984			offset = PCI_REG_REG_G(reg[i].pci_phys_hi);
1985
1986			switch (PCI_REG_ADDR_G(reg[i].pci_phys_hi)) {
1987			case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
1988
1989				(void) pcicfg_get_mem(entry,
1990				    reg[i].pci_size_low, &mem_answer);
1991				pci_config_put64(handle, offset, mem_answer);
1992				DEBUG2("REGISTER off %x (64)LO ----> [0x%x]\n",
1993				    offset,
1994				    pci_config_get32(handle, offset));
1995				DEBUG2("REGISTER off %x (64)HI ----> [0x%x]\n",
1996				    offset + 4,
1997				    pci_config_get32(handle, offset + 4));
1998
1999				reg[i].pci_phys_low = PCICFG_HIADDR(mem_answer);
2000				reg[i].pci_phys_mid  =
2001				    PCICFG_LOADDR(mem_answer);
2002
2003				break;
2004
2005			case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
2006				/* allocate memory space from the allocator */
2007
2008				(void) pcicfg_get_mem(entry,
2009				    reg[i].pci_size_low, &mem_answer);
2010				pci_config_put32(handle,
2011				    offset, (uint32_t)mem_answer);
2012
2013				DEBUG2("REGISTER off %x(32)LO ----> [0x%x]\n",
2014				    offset,
2015				    pci_config_get32(handle, offset));
2016
2017				reg[i].pci_phys_low = (uint32_t)mem_answer;
2018
2019				break;
2020			case PCI_REG_ADDR_G(PCI_ADDR_IO):
2021				/* allocate I/O space from the allocator */
2022
2023				(void) pcicfg_get_io(entry,
2024				    reg[i].pci_size_low, &io_answer);
2025				pci_config_put32(handle, offset, io_answer);
2026
2027				DEBUG2("REGISTER off %x (I/O)LO ----> [0x%x]\n",
2028				    offset,
2029				    pci_config_get32(handle, offset));
2030
2031				reg[i].pci_phys_low = io_answer;
2032
2033				break;
2034			default:
2035				DEBUG0("Unknown register type\n");
2036				kmem_free(reg, length);
2037				(void) pcicfg_config_teardown(&handle);
2038				entry->error = PCICFG_FAILURE;
2039				return (DDI_WALK_TERMINATE);
2040			} /* switch */
2041
2042			/*
2043			 * Now that memory locations are assigned,
2044			 * update the assigned address property.
2045			 */
2046			if (pcicfg_update_assigned_prop(dip,
2047			    &reg[i]) != PCICFG_SUCCESS) {
2048				kmem_free(reg, length);
2049				(void) pcicfg_config_teardown(&handle);
2050				entry->error = PCICFG_FAILURE;
2051				return (DDI_WALK_TERMINATE);
2052			}
2053		}
2054	}
2055	(void) pcicfg_device_on(handle);
2056
2057	PCICFG_DUMP_DEVICE_CONFIG(handle);
2058
2059	(void) pcicfg_config_teardown(&handle);
2060	/*
2061	 * Don't forget to free up memory from ddi_getlongprop
2062	 */
2063	kmem_free((caddr_t)reg, length);
2064
2065	return (DDI_WALK_CONTINUE);
2066}
2067
2068static int
2069pcicfg_device_assign(dev_info_t *dip)
2070{
2071	ddi_acc_handle_t	handle;
2072	pci_regspec_t		*reg;
2073	int			length;
2074	int			rcount;
2075	int			i;
2076	int			offset;
2077	ndi_ra_request_t	request;
2078	uint64_t		answer;
2079	uint64_t		alen;
2080
2081	DEBUG1("%llx now under configuration\n", dip);
2082
2083	/*
2084	 * XXX Failure here should be noted
2085	 */
2086	if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
2087	    DDI_PROP_DONTPASS, "reg", (caddr_t)&reg,
2088	    &length) != DDI_PROP_SUCCESS) {
2089		DEBUG0("Failed to read reg property\n");
2090		return (PCICFG_FAILURE);
2091	}
2092
2093	if (pcicfg_config_setup(dip, &handle) != DDI_SUCCESS) {
2094		DEBUG0("Failed to map config space!\n");
2095		/*
2096		 * Don't forget to free up memory from ddi_getlongprop
2097		 */
2098		kmem_free((caddr_t)reg, length);
2099
2100		return (PCICFG_FAILURE);
2101	}
2102
2103	/*
2104	 * A single device
2105	 *
2106	 * For each "reg" property with a length, allocate memory
2107	 * and program the base registers.
2108	 */
2109
2110	/*
2111	 * If there is an interrupt pin set program
2112	 * interrupt line with default values.
2113	 */
2114	if (pci_config_get8(handle, PCI_CONF_IPIN)) {
2115		pci_config_put8(handle, PCI_CONF_ILINE, 0xf);
2116	}
2117
2118	bzero((caddr_t)&request, sizeof (ndi_ra_request_t));
2119
2120	request.ra_flags = NDI_RA_ALIGN_SIZE;
2121	request.ra_boundbase = 0;
2122	request.ra_boundlen = PCICFG_4GIG_LIMIT;
2123
2124	rcount = length / sizeof (pci_regspec_t);
2125	for (i = 0; i < rcount; i++) {
2126		if ((reg[i].pci_size_low != 0)||
2127		    (reg[i].pci_size_hi != 0)) {
2128
2129			offset = PCI_REG_REG_G(reg[i].pci_phys_hi);
2130			request.ra_len = reg[i].pci_size_low;
2131
2132			switch (PCI_REG_ADDR_G(reg[i].pci_phys_hi)) {
2133			case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
2134				request.ra_flags &= ~NDI_RA_ALLOC_BOUNDED;
2135				/* allocate memory space from the allocator */
2136				if (ndi_ra_alloc(ddi_get_parent(dip),
2137				    &request, &answer, &alen,
2138				    NDI_RA_TYPE_MEM, NDI_RA_PASS)
2139				    != NDI_SUCCESS) {
2140					DEBUG0("Failed to allocate 64b mem\n");
2141					kmem_free(reg, length);
2142					(void) pcicfg_config_teardown(&handle);
2143					return (PCICFG_FAILURE);
2144				}
2145				DEBUG3("64 addr = [0x%x.%x] len [0x%x]\n",
2146				    PCICFG_HIADDR(answer),
2147				    PCICFG_LOADDR(answer),
2148				    alen);
2149				/* program the low word */
2150				pci_config_put32(handle,
2151				    offset, PCICFG_LOADDR(answer));
2152
2153				/* program the high word */
2154				pci_config_put32(handle, offset + 4,
2155				    PCICFG_HIADDR(answer));
2156
2157				reg[i].pci_phys_low = PCICFG_LOADDR(answer);
2158				reg[i].pci_phys_mid = PCICFG_HIADDR(answer);
2159
2160				/* adjust to 32b address space when possible */
2161				if ((answer + alen) <= PCICFG_4GIG_LIMIT)
2162					reg[i].pci_phys_hi ^=
2163					    PCI_ADDR_MEM64 ^ PCI_ADDR_MEM32;
2164				break;
2165
2166			case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
2167				request.ra_flags |= NDI_RA_ALLOC_BOUNDED;
2168				/* allocate memory space from the allocator */
2169				if (ndi_ra_alloc(ddi_get_parent(dip),
2170				    &request, &answer, &alen,
2171				    NDI_RA_TYPE_MEM, NDI_RA_PASS)
2172				    != NDI_SUCCESS) {
2173					DEBUG0("Failed to allocate 32b mem\n");
2174					kmem_free(reg, length);
2175					(void) pcicfg_config_teardown(&handle);
2176					return (PCICFG_FAILURE);
2177				}
2178				DEBUG3("32 addr = [0x%x.%x] len [0x%x]\n",
2179				    PCICFG_HIADDR(answer),
2180				    PCICFG_LOADDR(answer),
2181				    alen);
2182				/* program the low word */
2183				pci_config_put32(handle,
2184				    offset, PCICFG_LOADDR(answer));
2185
2186				reg[i].pci_phys_low = PCICFG_LOADDR(answer);
2187				break;
2188
2189			case PCI_REG_ADDR_G(PCI_ADDR_IO):
2190				/* allocate I/O space from the allocator */
2191				request.ra_flags |= NDI_RA_ALLOC_BOUNDED;
2192				if (ndi_ra_alloc(ddi_get_parent(dip),
2193				    &request, &answer, &alen,
2194				    NDI_RA_TYPE_IO, NDI_RA_PASS)
2195				    != NDI_SUCCESS) {
2196					DEBUG0("Failed to allocate I/O\n");
2197					kmem_free(reg, length);
2198					(void) pcicfg_config_teardown(&handle);
2199					return (PCICFG_FAILURE);
2200				}
2201				DEBUG3("I/O addr = [0x%x.%x] len [0x%x]\n",
2202				    PCICFG_HIADDR(answer),
2203				    PCICFG_LOADDR(answer),
2204				    alen);
2205				pci_config_put32(handle,
2206				    offset, PCICFG_LOADDR(answer));
2207
2208				reg[i].pci_phys_low = PCICFG_LOADDR(answer);
2209				break;
2210
2211			default:
2212				DEBUG0("Unknown register type\n");
2213				kmem_free(reg, length);
2214				(void) pcicfg_config_teardown(&handle);
2215				return (PCICFG_FAILURE);
2216			} /* switch */
2217
2218			/*
2219			 * Now that memory locations are assigned,
2220			 * update the assigned address property.
2221			 */
2222
2223			if (pcicfg_update_assigned_prop(dip,
2224			    &reg[i]) != PCICFG_SUCCESS) {
2225				kmem_free(reg, length);
2226				(void) pcicfg_config_teardown(&handle);
2227				return (PCICFG_FAILURE);
2228			}
2229		}
2230	}
2231
2232	(void) pcicfg_device_on(handle);
2233	kmem_free(reg, length);
2234
2235	PCICFG_DUMP_DEVICE_CONFIG(handle);
2236
2237	(void) pcicfg_config_teardown(&handle);
2238	return (PCICFG_SUCCESS);
2239}
2240
2241static int
2242pcicfg_device_assign_readonly(dev_info_t *dip)
2243{
2244	ddi_acc_handle_t	handle;
2245	pci_regspec_t		*assigned;
2246	int			length;
2247	int			acount;
2248	int			i;
2249	ndi_ra_request_t	request;
2250	uint64_t		answer;
2251	uint64_t		alen;
2252
2253
2254	DEBUG1("%llx now under configuration\n", dip);
2255
2256	if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
2257	    DDI_PROP_DONTPASS, "assigned-addresses", (caddr_t)&assigned,
2258	    &length) != DDI_PROP_SUCCESS) {
2259		DEBUG0("Failed to read assigned-addresses property\n");
2260		return (PCICFG_FAILURE);
2261	}
2262
2263	if (pcicfg_config_setup(dip, &handle) != DDI_SUCCESS) {
2264		DEBUG0("Failed to map config space!\n");
2265		/*
2266		 * Don't forget to free up memory from ddi_getlongprop
2267		 */
2268		kmem_free((caddr_t)assigned, length);
2269
2270		return (PCICFG_FAILURE);
2271	}
2272
2273	/*
2274	 * For each "assigned-addresses" property entry with a length,
2275	 * call the memory allocation routines to return the
2276	 * resource.
2277	 */
2278	/*
2279	 * If there is an interrupt pin set program
2280	 * interrupt line with default values.
2281	 */
2282	if (pci_config_get8(handle, PCI_CONF_IPIN)) {
2283		pci_config_put8(handle, PCI_CONF_ILINE, 0xf);
2284	}
2285
2286	bzero((caddr_t)&request, sizeof (ndi_ra_request_t));
2287
2288	request.ra_flags = NDI_RA_ALLOC_SPECIFIED; /* specified addr */
2289	request.ra_boundbase = 0;
2290	request.ra_boundlen = PCICFG_4GIG_LIMIT;
2291
2292	acount = length / sizeof (pci_regspec_t);
2293	for (i = 0; i < acount; i++) {
2294		if ((assigned[i].pci_size_low != 0)||
2295		    (assigned[i].pci_size_hi != 0)) {
2296
2297			request.ra_len = assigned[i].pci_size_low;
2298
2299			switch (PCI_REG_ADDR_G(assigned[i].pci_phys_hi)) {
2300			case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
2301				request.ra_addr = (uint64_t)PCICFG_LADDR(
2302				    assigned[i].pci_phys_low,
2303				    assigned[i].pci_phys_mid);
2304
2305				/* allocate memory space from the allocator */
2306				if (ndi_ra_alloc(ddi_get_parent(dip),
2307				    &request, &answer, &alen,
2308				    NDI_RA_TYPE_MEM, NDI_RA_PASS)
2309				    != NDI_SUCCESS) {
2310					DEBUG0("Failed to allocate 64b mem\n");
2311					kmem_free(assigned, length);
2312					return (PCICFG_FAILURE);
2313				}
2314
2315				break;
2316			case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
2317				request.ra_addr = (uint64_t)
2318				    assigned[i].pci_phys_low;
2319
2320				/* allocate memory space from the allocator */
2321				if (ndi_ra_alloc(ddi_get_parent(dip),
2322				    &request, &answer, &alen,
2323				    NDI_RA_TYPE_MEM, NDI_RA_PASS)
2324				    != NDI_SUCCESS) {
2325					DEBUG0("Failed to allocate 32b mem\n");
2326					kmem_free(assigned, length);
2327					return (PCICFG_FAILURE);
2328				}
2329
2330				break;
2331			case PCI_REG_ADDR_G(PCI_ADDR_IO):
2332				request.ra_addr = (uint64_t)
2333				    assigned[i].pci_phys_low;
2334
2335				/* allocate I/O space from the allocator */
2336				if (ndi_ra_alloc(ddi_get_parent(dip),
2337				    &request, &answer, &alen,
2338				    NDI_RA_TYPE_IO, NDI_RA_PASS)
2339				    != NDI_SUCCESS) {
2340					DEBUG0("Failed to allocate I/O\n");
2341					kmem_free(assigned, length);
2342					return (PCICFG_FAILURE);
2343				}
2344
2345				break;
2346			default:
2347				DEBUG0("Unknown register type\n");
2348				kmem_free(assigned, length);
2349				return (PCICFG_FAILURE);
2350			} /* switch */
2351		}
2352	}
2353
2354	(void) pcicfg_device_on(handle);
2355	kmem_free(assigned, length);
2356
2357	PCICFG_DUMP_DEVICE_CONFIG(handle);
2358
2359	(void) pcicfg_config_teardown(&handle);
2360	return (PCICFG_SUCCESS);
2361}
2362
2363/*
2364 * The "dip" passed to this routine is assumed to be
2365 * the device at the Hotplug Connection (CN). Currently it is
2366 * assumed to be a bridge.
2367 */
2368static int
2369pcicfg_allocate_chunk(dev_info_t *dip)
2370{
2371	pcicfg_phdl_t		*phdl;
2372	ndi_ra_request_t	*mem_request;
2373	ndi_ra_request_t	*io_request;
2374	uint64_t		mem_answer;
2375	uint64_t		io_answer;
2376	int			count;
2377	uint64_t		alen;
2378
2379	/*
2380	 * This should not find an existing entry - so
2381	 * it will create a new one.
2382	 */
2383	phdl = pcicfg_find_phdl(dip);
2384	ASSERT(phdl);
2385
2386	mem_request = &phdl->mem_req;
2387	io_request  = &phdl->io_req;
2388
2389	/*
2390	 * From this point in the tree - walk the devices,
2391	 * The function passed in will read and "sum" up
2392	 * the memory and I/O requirements and put them in
2393	 * structure "phdl".
2394	 */
2395	ndi_devi_enter(ddi_get_parent(dip), &count);
2396	ddi_walk_devs(dip, pcicfg_sum_resources, (void *)phdl);
2397	ndi_devi_exit(ddi_get_parent(dip), count);
2398
2399	if (phdl->error != PCICFG_SUCCESS) {
2400		DEBUG0("Failure summing resources\n");
2401		return (phdl->error);
2402	}
2403
2404	/*
2405	 * Call into the memory allocator with the request.
2406	 * Record the addresses returned in the phdl
2407	 */
2408	DEBUG1("Connector requires [0x%x] bytes of memory space\n",
2409	    mem_request->ra_len);
2410	DEBUG1("Connector requires [0x%x] bytes of I/O space\n",
2411	    io_request->ra_len);
2412
2413	mem_request->ra_align_mask =
2414	    PCICFG_MEMGRAN - 1; /* 1M alignment on memory space */
2415	io_request->ra_align_mask =
2416	    PCICFG_IOGRAN - 1;   /* 4K alignment on I/O space */
2417	io_request->ra_boundbase = 0;
2418	io_request->ra_boundlen = PCICFG_4GIG_LIMIT;
2419	io_request->ra_flags |= NDI_RA_ALLOC_BOUNDED;
2420
2421	mem_request->ra_len =
2422	    PCICFG_ROUND_UP(mem_request->ra_len, PCICFG_MEMGRAN);
2423
2424	io_request->ra_len =
2425	    PCICFG_ROUND_UP(io_request->ra_len, PCICFG_IOGRAN);
2426
2427	if (ndi_ra_alloc(ddi_get_parent(dip),
2428	    mem_request, &mem_answer, &alen,
2429	    NDI_RA_TYPE_MEM, NDI_RA_PASS) != NDI_SUCCESS) {
2430		DEBUG0("Failed to allocate memory\n");
2431		return (PCICFG_FAILURE);
2432	}
2433
2434	phdl->memory_base = phdl->memory_last = mem_answer;
2435	phdl->memory_len  = alen;
2436
2437	phdl->mem_hole.start = phdl->memory_base;
2438	phdl->mem_hole.len = phdl->memory_len;
2439	phdl->mem_hole.next = (hole_t *)NULL;
2440
2441	if (ndi_ra_alloc(ddi_get_parent(dip), io_request, &io_answer,
2442	    &alen, NDI_RA_TYPE_IO, NDI_RA_PASS) != NDI_SUCCESS) {
2443
2444		DEBUG0("Failed to allocate I/O space\n");
2445		(void) ndi_ra_free(ddi_get_parent(dip), mem_answer,
2446		    alen, NDI_RA_TYPE_MEM, NDI_RA_PASS);
2447		phdl->memory_len = phdl->io_len = 0;
2448		return (PCICFG_FAILURE);
2449	}
2450
2451	phdl->io_base = phdl->io_last = (uint32_t)io_answer;
2452	phdl->io_len  = (uint32_t)alen;
2453
2454	phdl->io_hole.start = phdl->io_base;
2455	phdl->io_hole.len = phdl->io_len;
2456	phdl->io_hole.next = (hole_t *)NULL;
2457
2458	DEBUG2("MEMORY BASE = [0x%x] length [0x%x]\n",
2459	    phdl->memory_base, phdl->memory_len);
2460	DEBUG2("IO     BASE = [0x%x] length [0x%x]\n",
2461	    phdl->io_base, phdl->io_len);
2462
2463	return (PCICFG_SUCCESS);
2464}
2465
2466#ifdef	DEBUG
2467/*
2468 * This function is useful in debug mode, where we can measure how
2469 * much memory was wasted/unallocated in bridge device's domain.
2470 */
2471static uint64_t
2472pcicfg_unused_space(hole_t *hole, uint32_t *hole_count)
2473{
2474	uint64_t len = 0;
2475	uint32_t count = 0;
2476
2477	do {
2478		len += hole->len;
2479		hole = hole->next;
2480		count++;
2481	} while (hole);
2482	*hole_count = count;
2483	return (len);
2484}
2485#endif
2486
2487/*
2488 * This function frees data structures that hold the hole information
2489 * which are allocated in pcicfg_alloc_hole(). This is not freeing
2490 * any memory allocated through NDI calls.
2491 */
2492static void
2493pcicfg_free_hole(hole_t *addr_hole)
2494{
2495	hole_t *nhole, *hole = addr_hole->next;
2496
2497	while (hole) {
2498		nhole = hole->next;
2499		kmem_free(hole, sizeof (hole_t));
2500		hole = nhole;
2501	}
2502}
2503
2504static uint64_t
2505pcicfg_alloc_hole(hole_t *addr_hole, uint64_t *alast, uint32_t length)
2506{
2507	uint64_t actual_hole_start, ostart, olen;
2508	hole_t	*hole = addr_hole, *thole, *nhole;
2509
2510	do {
2511		actual_hole_start = PCICFG_ROUND_UP(hole->start, length);
2512		if (((actual_hole_start - hole->start) + length) <= hole->len) {
2513			DEBUG3("hole found. start %llx, len %llx, req=%x\n",
2514			    hole->start, hole->len, length);
2515			ostart = hole->start;
2516			olen = hole->len;
2517			/* current hole parameters adjust */
2518			if ((actual_hole_start - hole->start) == 0) {
2519				hole->start += length;
2520				hole->len -= length;
2521				if (hole->start > *alast)
2522					*alast = hole->start;
2523			} else {
2524				hole->len = actual_hole_start - hole->start;
2525				nhole = (hole_t *)kmem_zalloc(sizeof (hole_t),
2526				    KM_SLEEP);
2527				nhole->start = actual_hole_start + length;
2528				nhole->len = (ostart + olen) - nhole->start;
2529				nhole->next = NULL;
2530				thole = hole->next;
2531				hole->next = nhole;
2532				nhole->next = thole;
2533				if (nhole->start > *alast)
2534					*alast = nhole->start;
2535				DEBUG2("put new hole to %llx, %llx\n",
2536				    nhole->start, nhole->len);
2537			}
2538			DEBUG2("adjust current hole to %llx, %llx\n",
2539			    hole->start, hole->len);
2540			break;
2541		}
2542		actual_hole_start = 0;
2543		hole = hole->next;
2544	} while (hole);
2545
2546	DEBUG1("return hole at %llx\n", actual_hole_start);
2547	return (actual_hole_start);
2548}
2549
2550static void
2551pcicfg_get_mem(pcicfg_phdl_t *entry,
2552	uint32_t length, uint64_t *ans)
2553{
2554	uint64_t new_mem;
2555
2556	/* See if there is a hole, that can hold this request. */
2557	new_mem = pcicfg_alloc_hole(&entry->mem_hole, &entry->memory_last,
2558	    length);
2559	if (new_mem) {	/* if non-zero, found a hole. */
2560		if (ans != NULL)
2561			*ans = new_mem;
2562	} else
2563		cmn_err(CE_WARN, "No %u bytes memory window for %s\n",
2564		    length, ddi_get_name(entry->dip));
2565}
2566
2567static void
2568pcicfg_get_io(pcicfg_phdl_t *entry,
2569	uint32_t length, uint32_t *ans)
2570{
2571	uint32_t new_io;
2572	uint64_t io_last;
2573
2574	/*
2575	 * See if there is a hole, that can hold this request.
2576	 * Pass 64 bit parameters and then truncate to 32 bit.
2577	 */
2578	io_last = entry->io_last;
2579	new_io = (uint32_t)pcicfg_alloc_hole(&entry->io_hole, &io_last, length);
2580	if (new_io) {	/* if non-zero, found a hole. */
2581		entry->io_last = (uint32_t)io_last;
2582		if (ans != NULL)
2583			*ans = new_io;
2584	} else
2585		cmn_err(CE_WARN, "No %u bytes IO space window for %s\n",
2586		    length, ddi_get_name(entry->dip));
2587}
2588
2589static int
2590pcicfg_sum_resources(dev_info_t *dip, void *hdl)
2591{
2592	pcicfg_phdl_t *entry = (pcicfg_phdl_t *)hdl;
2593	pci_regspec_t *pci_rp;
2594	int length;
2595	int rcount;
2596	int i;
2597	ndi_ra_request_t *mem_request;
2598	ndi_ra_request_t *io_request;
2599	uint8_t header_type;
2600	ddi_acc_handle_t handle;
2601
2602	entry->error = PCICFG_SUCCESS;
2603
2604	mem_request = &entry->mem_req;
2605	io_request =  &entry->io_req;
2606
2607	if (pcicfg_config_setup(dip, &handle) != DDI_SUCCESS) {
2608		DEBUG0("Failed to map config space!\n");
2609		entry->error = PCICFG_FAILURE;
2610		return (DDI_WALK_TERMINATE);
2611	}
2612
2613	header_type = pci_config_get8(handle, PCI_CONF_HEADER);
2614
2615	/*
2616	 * If its a bridge - just record the highest bus seen
2617	 */
2618	if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
2619
2620		if (entry->highest_bus < pci_config_get8(handle,
2621		    PCI_BCNF_SECBUS)) {
2622			entry->highest_bus =
2623			    pci_config_get8(handle, PCI_BCNF_SECBUS);
2624		}
2625
2626		(void) pcicfg_config_teardown(&handle);
2627		entry->error = PCICFG_FAILURE;
2628		return (DDI_WALK_CONTINUE);
2629	} else {
2630		if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
2631		    DDI_PROP_DONTPASS, "reg", (caddr_t)&pci_rp,
2632		    &length) != DDI_PROP_SUCCESS) {
2633			/*
2634			 * If one node in (the subtree of nodes)
2635			 * does'nt have a "reg" property fail the
2636			 * allocation.
2637			 */
2638			entry->memory_len = 0;
2639			entry->io_len = 0;
2640			entry->error = PCICFG_FAILURE;
2641			return (DDI_WALK_TERMINATE);
2642		}
2643		/*
2644		 * For each "reg" property with a length, add that to the
2645		 * total memory (or I/O) to allocate.
2646		 */
2647		rcount = length / sizeof (pci_regspec_t);
2648
2649		for (i = 0; i < rcount; i++) {
2650
2651			switch (PCI_REG_ADDR_G(pci_rp[i].pci_phys_hi)) {
2652
2653			case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
2654				mem_request->ra_len =
2655				    pci_rp[i].pci_size_low +
2656				    PCICFG_ROUND_UP(mem_request->ra_len,
2657				    pci_rp[i].pci_size_low);
2658				DEBUG1("ADDING 32 --->0x%x\n",
2659				    pci_rp[i].pci_size_low);
2660
2661			break;
2662			case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
2663				mem_request->ra_len =
2664				    pci_rp[i].pci_size_low +
2665				    PCICFG_ROUND_UP(mem_request->ra_len,
2666				    pci_rp[i].pci_size_low);
2667				DEBUG1("ADDING 64 --->0x%x\n",
2668				    pci_rp[i].pci_size_low);
2669
2670			break;
2671			case PCI_REG_ADDR_G(PCI_ADDR_IO):
2672				io_request->ra_len =
2673				    pci_rp[i].pci_size_low +
2674				    PCICFG_ROUND_UP(io_request->ra_len,
2675				    pci_rp[i].pci_size_low);
2676				DEBUG1("ADDING I/O --->0x%x\n",
2677				    pci_rp[i].pci_size_low);
2678			break;
2679			default:
2680			    /* Config space register - not included */
2681			break;
2682			}
2683		}
2684
2685		/*
2686		 * free the memory allocated by ddi_getlongprop
2687		 */
2688		kmem_free(pci_rp, length);
2689
2690		/*
2691		 * continue the walk to the next sibling to sum memory
2692		 */
2693
2694		(void) pcicfg_config_teardown(&handle);
2695
2696		return (DDI_WALK_CONTINUE);
2697	}
2698}
2699
2700static int
2701pcicfg_find_resource_end(dev_info_t *dip, void *hdl)
2702{
2703	pcicfg_phdl_t *entry_p = (pcicfg_phdl_t *)hdl;
2704	pci_regspec_t *pci_ap;
2705	pcicfg_range_t *ranges;
2706	int length;
2707	int rcount;
2708	int i;
2709
2710	entry_p->error = PCICFG_SUCCESS;
2711
2712	if (dip == entry_p->dip) {
2713		DEBUG0("Don't include parent bridge node\n");
2714		return (DDI_WALK_CONTINUE);
2715	}
2716
2717	if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
2718	    DDI_PROP_DONTPASS, "ranges",
2719	    (caddr_t)&ranges,  &length) != DDI_PROP_SUCCESS) {
2720		DEBUG0("Node doesn't have ranges\n");
2721		goto ap;
2722	}
2723
2724	rcount = length / sizeof (pcicfg_range_t);
2725
2726	for (i = 0; i < rcount; i++) {
2727		uint64_t base;
2728		uint64_t mid = ranges[i].child_mid;
2729		uint64_t lo = ranges[i].child_lo;
2730		uint64_t size = ranges[i].size_lo;
2731
2732		switch (PCI_REG_ADDR_G(ranges[i].child_hi)) {
2733
2734		case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
2735			base = entry_p->memory_base;
2736			entry_p->memory_base = MAX(base, lo + size);
2737			break;
2738		case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
2739			base = entry_p->memory_base;
2740			entry_p->memory_base = MAX(base,
2741			    PCICFG_LADDR(lo, mid) + size);
2742			break;
2743		case PCI_REG_ADDR_G(PCI_ADDR_IO):
2744			base = entry_p->io_base;
2745			entry_p->io_base = MAX(base, lo + size);
2746			break;
2747		}
2748	}
2749
2750	kmem_free(ranges, length);
2751	return (DDI_WALK_CONTINUE);
2752
2753ap:	if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
2754	    DDI_PROP_DONTPASS, "assigned-addresses",
2755	    (caddr_t)&pci_ap,  &length) != DDI_PROP_SUCCESS) {
2756		DEBUG0("Node doesn't have assigned-addresses\n");
2757		return (DDI_WALK_CONTINUE);
2758	}
2759
2760	rcount = length / sizeof (pci_regspec_t);
2761
2762	for (i = 0; i < rcount; i++) {
2763
2764		switch (PCI_REG_ADDR_G(pci_ap[i].pci_phys_hi)) {
2765
2766		case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
2767			if ((pci_ap[i].pci_phys_low +
2768			    pci_ap[i].pci_size_low) >
2769			    entry_p->memory_base) {
2770				entry_p->memory_base =
2771				    pci_ap[i].pci_phys_low +
2772				    pci_ap[i].pci_size_low;
2773			}
2774		break;
2775		case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
2776			if ((PCICFG_LADDR(pci_ap[i].pci_phys_low,
2777			    pci_ap[i].pci_phys_mid) +
2778			    pci_ap[i].pci_size_low) >
2779			    entry_p->memory_base) {
2780				entry_p->memory_base = PCICFG_LADDR(
2781				    pci_ap[i].pci_phys_low,
2782				    pci_ap[i].pci_phys_mid) +
2783				    pci_ap[i].pci_size_low;
2784			}
2785		break;
2786		case PCI_REG_ADDR_G(PCI_ADDR_IO):
2787			if ((pci_ap[i].pci_phys_low +
2788			    pci_ap[i].pci_size_low) >
2789			    entry_p->io_base) {
2790				entry_p->io_base =
2791				    pci_ap[i].pci_phys_low +
2792				    pci_ap[i].pci_size_low;
2793			}
2794		break;
2795		}
2796	}
2797
2798	/*
2799	 * free the memory allocated by ddi_getlongprop
2800	 */
2801	kmem_free(pci_ap, length);
2802
2803	/*
2804	 * continue the walk to the next sibling to sum memory
2805	 */
2806	return (DDI_WALK_CONTINUE);
2807}
2808
2809static int
2810pcicfg_free_bridge_resources(dev_info_t *dip)
2811{
2812	pcicfg_range_t		*ranges;
2813	uint_t			*bus;
2814	int			k;
2815	int			length;
2816	int			i;
2817
2818
2819	if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
2820	    DDI_PROP_DONTPASS, "ranges", (caddr_t)&ranges,
2821	    &length) != DDI_PROP_SUCCESS) {
2822		DEBUG0("Failed to read ranges property\n");
2823		if (ddi_get_child(dip)) {
2824			cmn_err(CE_WARN, "No ranges property found for %s",
2825			    ddi_get_name(dip));
2826			/*
2827			 * strictly speaking, we can check for children with
2828			 * assigned-addresses but for now it is better to
2829			 * be conservative and assume that if there are child
2830			 * nodes, then they do consume PCI memory or IO
2831			 * resources, Hence return failure.
2832			 */
2833			return (PCICFG_FAILURE);
2834		}
2835		length = 0;
2836
2837	}
2838
2839	for (i = 0; i < length / sizeof (pcicfg_range_t); i++) {
2840		if (ranges[i].size_lo != 0 ||
2841		    ranges[i].size_hi != 0) {
2842			switch (ranges[i].parent_hi & PCI_REG_ADDR_M) {
2843				case PCI_ADDR_IO:
2844					DEBUG2("Free I/O    "
2845					    "base/length = [0x%x]/[0x%x]\n",
2846					    ranges[i].child_lo,
2847					    ranges[i].size_lo);
2848					if (ndi_ra_free(ddi_get_parent(dip),
2849					    (uint64_t)ranges[i].child_lo,
2850					    (uint64_t)ranges[i].size_lo,
2851					    NDI_RA_TYPE_IO, NDI_RA_PASS)
2852					    != NDI_SUCCESS) {
2853						DEBUG0("Trouble freeing "
2854						    "PCI i/o space\n");
2855						kmem_free(ranges, length);
2856						return (PCICFG_FAILURE);
2857					}
2858				break;
2859				case PCI_ADDR_MEM32:
2860				case PCI_ADDR_MEM64:
2861					DEBUG3("Free Memory base/length = "
2862					    "[0x%x.%x]/[0x%x]\n",
2863					    ranges[i].child_mid,
2864					    ranges[i].child_lo,
2865					    ranges[i].size_lo)
2866					if (ndi_ra_free(ddi_get_parent(dip),
2867					    PCICFG_LADDR(ranges[i].child_lo,
2868					    ranges[i].child_mid),
2869					    (uint64_t)ranges[i].size_lo,
2870					    NDI_RA_TYPE_MEM, NDI_RA_PASS)
2871					    != NDI_SUCCESS) {
2872						DEBUG0("Trouble freeing "
2873						    "PCI memory space\n");
2874						kmem_free(ranges, length);
2875						return (PCICFG_FAILURE);
2876					}
2877				break;
2878				default:
2879					DEBUG0("Unknown memory space\n");
2880				break;
2881			}
2882		}
2883	}
2884
2885	if (length)
2886		kmem_free(ranges, length);
2887
2888	if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
2889	    DDI_PROP_DONTPASS, "bus-range", (caddr_t)&bus,
2890	    &k) != DDI_PROP_SUCCESS) {
2891		DEBUG0("Failed to read bus-range property\n");
2892		return (PCICFG_FAILURE);
2893	}
2894
2895	DEBUG2("Need to free bus [%d] range [%d]\n",
2896	    bus[0], bus[1] - bus[0] + 1);
2897
2898	if (ndi_ra_free(ddi_get_parent(dip),
2899	    (uint64_t)bus[0], (uint64_t)(bus[1] - bus[0] + 1),
2900	    NDI_RA_TYPE_PCI_BUSNUM, NDI_RA_PASS) != NDI_SUCCESS) {
2901		/*EMPTY*/
2902		DEBUG0("Failed to free a bus number\n");
2903	}
2904	/*
2905	 * Don't forget to free up memory from ddi_getlongprop
2906	 */
2907	kmem_free((caddr_t)bus, k);
2908
2909	return (PCICFG_SUCCESS);
2910}
2911
2912static int
2913pcicfg_free_device_resources(dev_info_t *dip, pcicfg_flags_t flags)
2914{
2915	pci_regspec_t *assigned;
2916
2917	int length;
2918	int acount;
2919	int i;
2920
2921	if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
2922	    DDI_PROP_DONTPASS, "assigned-addresses", (caddr_t)&assigned,
2923	    &length) != DDI_PROP_SUCCESS) {
2924		DEBUG0("Failed to read assigned-addresses property\n");
2925		return (PCICFG_FAILURE);
2926	}
2927
2928	/*
2929	 * For each "assigned-addresses" property entry with a length,
2930	 * call the memory allocation routines to return the
2931	 * resource.
2932	 */
2933	acount = length / sizeof (pci_regspec_t);
2934	for (i = 0; i < acount; i++) {
2935		/*
2936		 * Workaround for Devconf (x86) bug to skip extra entries
2937		 * beyond the PCI_CONF_BASE5 offset. But we want to free up
2938		 * any memory for expansion roms if allocated.
2939		 */
2940		if ((PCI_REG_REG_G(assigned[i].pci_phys_hi) > PCI_CONF_BASE5) &&
2941		    (PCI_REG_REG_G(assigned[i].pci_phys_hi) != PCI_CONF_ROM))
2942			break;
2943
2944		if (pcicfg_free_resource(dip, assigned[i], flags)) {
2945			DEBUG1("pcicfg_free_device_resources - Trouble freeing "
2946			    "%x\n", assigned[i].pci_phys_hi);
2947			/*
2948			 * Don't forget to free up memory from ddi_getlongprop
2949			 */
2950			kmem_free((caddr_t)assigned, length);
2951
2952			return (PCICFG_FAILURE);
2953		}
2954	}
2955	kmem_free(assigned, length);
2956	return (PCICFG_SUCCESS);
2957}
2958
2959static int
2960pcicfg_free_resources(dev_info_t *dip, pcicfg_flags_t flags)
2961{
2962	ddi_acc_handle_t handle;
2963	uint8_t header_type;
2964
2965	if (pcicfg_config_setup(dip, &handle) != DDI_SUCCESS) {
2966		DEBUG0("Failed to map config space!\n");
2967		return (PCICFG_FAILURE);
2968	}
2969
2970	header_type = pci_config_get8(handle, PCI_CONF_HEADER);
2971
2972	(void) pci_config_teardown(&handle);
2973
2974	/*
2975	 * A different algorithm is used for bridges and leaf devices.
2976	 */
2977	if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
2978		/*
2979		 * We only support readonly probing for leaf devices.
2980		 */
2981		if (flags & PCICFG_FLAG_READ_ONLY)
2982			return (PCICFG_FAILURE);
2983
2984		if (pcicfg_free_bridge_resources(dip) != PCICFG_SUCCESS) {
2985			DEBUG0("Failed freeing up bridge resources\n");
2986			return (PCICFG_FAILURE);
2987		}
2988	} else {
2989		if (pcicfg_free_device_resources(dip, flags)
2990		    != PCICFG_SUCCESS) {
2991			DEBUG0("Failed freeing up device resources\n");
2992			return (PCICFG_FAILURE);
2993		}
2994	}
2995	return (PCICFG_SUCCESS);
2996}
2997
2998#ifndef _DONT_USE_1275_GENERIC_NAMES
2999static char *
3000pcicfg_get_class_name(uint32_t classcode)
3001{
3002	struct pcicfg_name_entry *ptr;
3003
3004	for (ptr = &pcicfg_class_lookup[0]; ptr->name != NULL; ptr++) {
3005		if (ptr->class_code == classcode) {
3006			return (ptr->name);
3007		}
3008	}
3009	return (NULL);
3010}
3011#endif /* _DONT_USE_1275_GENERIC_NAMES */
3012
3013static dev_info_t *
3014pcicfg_devi_find(dev_info_t *dip, uint_t device, uint_t function)
3015{
3016	struct pcicfg_find_ctrl ctrl;
3017	int count;
3018
3019	ctrl.device = device;
3020	ctrl.function = function;
3021	ctrl.dip = NULL;
3022
3023	ndi_devi_enter(dip, &count);
3024	ddi_walk_devs(ddi_get_child(dip), pcicfg_match_dev, (void *)&ctrl);
3025	ndi_devi_exit(dip, count);
3026
3027	return (ctrl.dip);
3028}
3029
3030static int
3031pcicfg_match_dev(dev_info_t *dip, void *hdl)
3032{
3033	struct pcicfg_find_ctrl *ctrl = (struct pcicfg_find_ctrl *)hdl;
3034	pci_regspec_t *pci_rp;
3035	int length;
3036	int pci_dev;
3037	int pci_func;
3038
3039	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
3040	    DDI_PROP_DONTPASS, "reg", (int **)&pci_rp,
3041	    (uint_t *)&length) != DDI_PROP_SUCCESS) {
3042		ctrl->dip = NULL;
3043		return (DDI_WALK_TERMINATE);
3044	}
3045
3046	/* get the PCI device address info */
3047	pci_dev = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
3048	pci_func = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
3049
3050	/*
3051	 * free the memory allocated by ddi_prop_lookup_int_array
3052	 */
3053	ddi_prop_free(pci_rp);
3054
3055
3056	if ((pci_dev == ctrl->device) && (pci_func == ctrl->function)) {
3057		/* found the match for the specified device address */
3058		ctrl->dip = dip;
3059		return (DDI_WALK_TERMINATE);
3060	}
3061
3062	/*
3063	 * continue the walk to the next sibling to look for a match.
3064	 */
3065	return (DDI_WALK_PRUNECHILD);
3066}
3067
3068static int
3069pcicfg_update_assigned_prop(dev_info_t *dip, pci_regspec_t *newone)
3070{
3071	int		alen;
3072	pci_regspec_t	*assigned;
3073	caddr_t		newreg;
3074	uint_t		status;
3075
3076	DEBUG0("pcicfg_update_assigned_prop()\n");
3077	status = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
3078	    "assigned-addresses", (caddr_t)&assigned, &alen);
3079	switch (status) {
3080		case DDI_PROP_SUCCESS:
3081		break;
3082		case DDI_PROP_NO_MEMORY:
3083			DEBUG0("no memory for assigned-addresses property\n");
3084			return (PCICFG_FAILURE);
3085		default:
3086			(void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
3087			    "assigned-addresses", (int *)newone,
3088			    sizeof (*newone)/sizeof (int));
3089
3090			(void) pcicfg_dump_assigned(dip);
3091
3092			return (PCICFG_SUCCESS);
3093	}
3094
3095	/*
3096	 * Allocate memory for the existing
3097	 * assigned-addresses(s) plus one and then
3098	 * build it.
3099	 */
3100
3101	newreg = kmem_zalloc(alen+sizeof (*newone), KM_SLEEP);
3102
3103	bcopy(assigned, newreg, alen);
3104	bcopy(newone, newreg + alen, sizeof (*newone));
3105
3106	/*
3107	 * Write out the new "assigned-addresses" spec
3108	 */
3109	(void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
3110	    "assigned-addresses", (int *)newreg,
3111	    (alen + sizeof (*newone))/sizeof (int));
3112
3113	kmem_free((caddr_t)newreg, alen+sizeof (*newone));
3114
3115	/*
3116	 * Don't forget to free up memory from ddi_getlongprop
3117	 */
3118	kmem_free((caddr_t)assigned, alen);
3119
3120	(void) pcicfg_dump_assigned(dip);
3121
3122	return (PCICFG_SUCCESS);
3123}
3124static int
3125pcicfg_update_ranges_prop(dev_info_t *dip, pcicfg_range_t *addition)
3126{
3127	int		rlen;
3128	pcicfg_range_t	*ranges;
3129	caddr_t		newreg;
3130	uint_t		status;
3131
3132	status = ddi_getlongprop(DDI_DEV_T_ANY,
3133	    dip, DDI_PROP_DONTPASS, "ranges", (caddr_t)&ranges, &rlen);
3134
3135
3136	switch (status) {
3137		case DDI_PROP_SUCCESS:
3138		break;
3139		case DDI_PROP_NO_MEMORY:
3140			DEBUG0("ranges present, but unable to get memory\n");
3141			return (PCICFG_FAILURE);
3142		default:
3143			DEBUG0("no ranges property - creating one\n");
3144			if (ndi_prop_update_int_array(DDI_DEV_T_NONE,
3145			    dip, "ranges", (int *)addition,
3146			    sizeof (pcicfg_range_t)/sizeof (int))
3147			    != DDI_SUCCESS) {
3148				DEBUG0("Did'nt create ranges property\n");
3149				return (PCICFG_FAILURE);
3150			}
3151			return (PCICFG_SUCCESS);
3152	}
3153
3154	/*
3155	 * Allocate memory for the existing reg(s) plus one and then
3156	 * build it.
3157	 */
3158	newreg = kmem_zalloc(rlen + sizeof (pcicfg_range_t), KM_SLEEP);
3159
3160	bcopy(ranges, newreg, rlen);
3161	bcopy(addition, newreg + rlen, sizeof (pcicfg_range_t));
3162
3163	/*
3164	 * Write out the new "ranges" property
3165	 */
3166	(void) ndi_prop_update_int_array(DDI_DEV_T_NONE,
3167	    dip, "ranges", (int *)newreg,
3168	    (rlen + sizeof (pcicfg_range_t))/sizeof (int));
3169
3170	kmem_free((caddr_t)newreg, rlen+sizeof (pcicfg_range_t));
3171
3172	kmem_free((caddr_t)ranges, rlen);
3173
3174	return (PCICFG_SUCCESS);
3175}
3176
3177static int
3178pcicfg_update_reg_prop(dev_info_t *dip, uint32_t regvalue, uint_t reg_offset)
3179{
3180	int		rlen;
3181	pci_regspec_t	*reg;
3182	caddr_t		newreg;
3183	uint32_t	hiword;
3184	pci_regspec_t	addition;
3185	uint32_t	size;
3186	uint_t		status;
3187
3188	status = ddi_getlongprop(DDI_DEV_T_ANY,
3189	    dip, DDI_PROP_DONTPASS, "reg", (caddr_t)&reg, &rlen);
3190
3191	switch (status) {
3192		case DDI_PROP_SUCCESS:
3193		break;
3194		case DDI_PROP_NO_MEMORY:
3195			DEBUG0("reg present, but unable to get memory\n");
3196			return (PCICFG_FAILURE);
3197		default:
3198			DEBUG0("no reg property\n");
3199			return (PCICFG_FAILURE);
3200	}
3201
3202	/*
3203	 * Allocate memory for the existing reg(s) plus one and then
3204	 * build it.
3205	 */
3206	newreg = kmem_zalloc(rlen+sizeof (pci_regspec_t), KM_SLEEP);
3207
3208	/*
3209	 * Build the regspec, then add it to the existing one(s)
3210	 */
3211
3212	hiword = PCICFG_MAKE_REG_HIGH(PCI_REG_BUS_G(reg->pci_phys_hi),
3213	    PCI_REG_DEV_G(reg->pci_phys_hi),
3214	    PCI_REG_FUNC_G(reg->pci_phys_hi), reg_offset);
3215
3216	if (reg_offset == PCI_CONF_ROM) {
3217		size = (~(PCI_BASE_ROM_ADDR_M & regvalue))+1;
3218		hiword |= PCI_ADDR_MEM32;
3219	} else {
3220		size = (~(PCI_BASE_M_ADDR_M & regvalue))+1;
3221
3222		if ((PCI_BASE_SPACE_M & regvalue) == PCI_BASE_SPACE_MEM) {
3223			if ((PCI_BASE_TYPE_M & regvalue) == PCI_BASE_TYPE_MEM) {
3224				hiword |= PCI_ADDR_MEM32;
3225			} else if ((PCI_BASE_TYPE_M & regvalue)
3226			    == PCI_BASE_TYPE_ALL) {
3227				hiword |= PCI_ADDR_MEM64;
3228			}
3229		} else {
3230			hiword |= PCI_ADDR_IO;
3231		}
3232	}
3233
3234	addition.pci_phys_hi = hiword;
3235	addition.pci_phys_mid = 0;
3236	addition.pci_phys_low = 0;
3237	addition.pci_size_hi = 0;
3238	addition.pci_size_low = size;
3239
3240	bcopy(reg, newreg, rlen);
3241	bcopy(&addition, newreg + rlen, sizeof (pci_regspec_t));
3242
3243	/*
3244	 * Write out the new "reg" property
3245	 */
3246	(void) ndi_prop_update_int_array(DDI_DEV_T_NONE,
3247	    dip, "reg", (int *)newreg,
3248	    (rlen + sizeof (pci_regspec_t))/sizeof (int));
3249
3250	kmem_free((caddr_t)newreg, rlen+sizeof (pci_regspec_t));
3251	kmem_free((caddr_t)reg, rlen);
3252
3253	return (PCICFG_SUCCESS);
3254}
3255static int
3256pcicfg_update_available_prop(dev_info_t *dip, pci_regspec_t *newone)
3257{
3258	int		alen;
3259	pci_regspec_t	*avail_p;
3260	caddr_t		new_avail;
3261	uint_t		status;
3262
3263	DEBUG2("pcicfg_update_available_prop() - Address %lx Size %x\n",
3264	    newone->pci_phys_low, newone->pci_size_low);
3265	status = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
3266	    "available", (caddr_t)&avail_p, &alen);
3267	switch (status) {
3268		case DDI_PROP_SUCCESS:
3269			break;
3270		case DDI_PROP_NO_MEMORY:
3271			DEBUG0("no memory for available property\n");
3272			return (PCICFG_FAILURE);
3273		default:
3274			(void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
3275			    "available", (int *)newone,
3276			    sizeof (*newone)/sizeof (int));
3277
3278			return (PCICFG_SUCCESS);
3279	}
3280
3281	/*
3282	 * Allocate memory for the existing available plus one and then
3283	 * build it.
3284	 */
3285	new_avail = kmem_zalloc(alen+sizeof (*newone), KM_SLEEP);
3286
3287	bcopy(avail_p, new_avail, alen);
3288	bcopy(newone, new_avail + alen, sizeof (*newone));
3289
3290	/* Write out the new "available" spec */
3291	(void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
3292	    "available", (int *)new_avail,
3293	    (alen + sizeof (*newone))/sizeof (int));
3294
3295	kmem_free((caddr_t)new_avail, alen+sizeof (*newone));
3296
3297	/* Don't forget to free up memory from ddi_getlongprop */
3298	kmem_free((caddr_t)avail_p, alen);
3299
3300	return (PCICFG_SUCCESS);
3301}
3302
3303static int
3304pcicfg_update_assigned_prop_value(dev_info_t *dip, uint32_t size,
3305    uint32_t base, uint32_t base_hi, uint_t reg_offset)
3306{
3307	int		rlen;
3308	pci_regspec_t	*reg;
3309	uint32_t	hiword;
3310	pci_regspec_t	addition;
3311	uint_t		status;
3312
3313	status = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
3314	    "reg", (caddr_t)&reg, &rlen);
3315
3316	switch (status) {
3317		case DDI_PROP_SUCCESS:
3318		break;
3319		case DDI_PROP_NO_MEMORY:
3320			DEBUG0("reg present, but unable to get memory\n");
3321			return (PCICFG_FAILURE);
3322		default:
3323			/*
3324			 * Since the config space "reg" entry should have been
3325			 * created, we expect a "reg" property already
3326			 * present here.
3327			 */
3328			DEBUG0("no reg property\n");
3329			return (PCICFG_FAILURE);
3330	}
3331
3332	/*
3333	 * Build the regspec, then add it to the existing one(s)
3334	 */
3335
3336	hiword = PCICFG_MAKE_REG_HIGH(PCI_REG_BUS_G(reg->pci_phys_hi),
3337	    PCI_REG_DEV_G(reg->pci_phys_hi),
3338	    PCI_REG_FUNC_G(reg->pci_phys_hi), reg_offset);
3339
3340	hiword |= PCI_REG_REL_M;
3341
3342	if (reg_offset == PCI_CONF_ROM) {
3343		hiword |= PCI_ADDR_MEM32;
3344
3345		base = PCI_BASE_ROM_ADDR_M & base;
3346	} else {
3347		if ((PCI_BASE_SPACE_M & base) == PCI_BASE_SPACE_MEM) {
3348			if ((PCI_BASE_TYPE_M & base) == PCI_BASE_TYPE_MEM) {
3349				hiword |= PCI_ADDR_MEM32;
3350			} else if ((PCI_BASE_TYPE_M & base)
3351			    == PCI_BASE_TYPE_ALL) {
3352				hiword |= PCI_ADDR_MEM64;
3353			}
3354
3355			if (base & PCI_BASE_PREF_M)
3356				hiword |= PCI_REG_PF_M;
3357
3358			base = PCI_BASE_M_ADDR_M & base;
3359		} else {
3360			hiword |= PCI_ADDR_IO;
3361
3362			base = PCI_BASE_IO_ADDR_M & base;
3363			base_hi = 0;
3364		}
3365	}
3366
3367	addition.pci_phys_hi = hiword;
3368	addition.pci_phys_mid = base_hi;
3369	addition.pci_phys_low = base;
3370	addition.pci_size_hi = 0;
3371	addition.pci_size_low = size;
3372
3373	DEBUG3("updating BAR@off %x with %x,%x\n", reg_offset, hiword, size);
3374
3375	kmem_free((caddr_t)reg, rlen);
3376
3377	return (pcicfg_update_assigned_prop(dip, &addition));
3378}
3379
3380static void
3381pcicfg_device_on(ddi_acc_handle_t config_handle)
3382{
3383	/*
3384	 * Enable memory, IO, and bus mastership
3385	 * XXX should we enable parity, SERR#,
3386	 * fast back-to-back, and addr. stepping?
3387	 */
3388	pci_config_put16(config_handle, PCI_CONF_COMM,
3389	    pci_config_get16(config_handle, PCI_CONF_COMM) | 0x7);
3390}
3391
3392static void
3393pcicfg_device_off(ddi_acc_handle_t config_handle)
3394{
3395	/*
3396	 * Disable I/O and memory traffic through the bridge
3397	 */
3398	pci_config_put16(config_handle, PCI_CONF_COMM, 0x0);
3399}
3400
3401/*
3402 * Setup the basic 1275 properties based on information found in the config
3403 * header of the PCI device
3404 */
3405static int
3406pcicfg_set_standard_props(dev_info_t *dip, ddi_acc_handle_t config_handle,
3407	uint8_t pcie_dev)
3408{
3409	int ret;
3410	uint16_t val, cap_ptr;
3411	uint32_t wordval;
3412	uint8_t byteval;
3413
3414	/* These two exists only for non-bridges */
3415	if (((pci_config_get8(config_handle, PCI_CONF_HEADER)
3416	    & PCI_HEADER_TYPE_M) == PCI_HEADER_ZERO) && !pcie_dev) {
3417		byteval = pci_config_get8(config_handle, PCI_CONF_MIN_G);
3418		if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3419		    "min-grant", byteval)) != DDI_SUCCESS) {
3420			return (ret);
3421		}
3422
3423		byteval = pci_config_get8(config_handle, PCI_CONF_MAX_L);
3424		if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3425		    "max-latency", byteval)) != DDI_SUCCESS) {
3426			return (ret);
3427		}
3428	}
3429
3430	/*
3431	 * These should always exist and have the value of the
3432	 * corresponding register value
3433	 */
3434	val = pci_config_get16(config_handle, PCI_CONF_VENID);
3435
3436	if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3437	    "vendor-id", val)) != DDI_SUCCESS) {
3438		return (ret);
3439	}
3440	val = pci_config_get16(config_handle, PCI_CONF_DEVID);
3441	if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3442	    "device-id", val)) != DDI_SUCCESS) {
3443		return (ret);
3444	}
3445	byteval = pci_config_get8(config_handle, PCI_CONF_REVID);
3446	if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3447	    "revision-id", byteval)) != DDI_SUCCESS) {
3448		return (ret);
3449	}
3450
3451	wordval = (pci_config_get16(config_handle, PCI_CONF_SUBCLASS)<< 8) |
3452	    (pci_config_get8(config_handle, PCI_CONF_PROGCLASS));
3453
3454	if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3455	    "class-code", wordval)) != DDI_SUCCESS) {
3456		return (ret);
3457	}
3458	/* devsel-speed starts at the 9th bit */
3459	val = (pci_config_get16(config_handle,
3460	    PCI_CONF_STAT) & PCI_STAT_DEVSELT) >> 9;
3461	if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3462	    "devsel-speed", val)) != DDI_SUCCESS) {
3463		return (ret);
3464	}
3465
3466	/*
3467	 * The next three are bits set in the status register.  The property is
3468	 * present (but with no value other than its own existence) if the bit
3469	 * is set, non-existent otherwise
3470	 */
3471	if ((!pcie_dev) &&
3472	    (pci_config_get16(config_handle, PCI_CONF_STAT) &
3473	    PCI_STAT_FBBC)) {
3474		if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3475		    "fast-back-to-back", 0)) != DDI_SUCCESS) {
3476			return (ret);
3477		}
3478	}
3479	if ((!pcie_dev) &&
3480	    (pci_config_get16(config_handle, PCI_CONF_STAT) &
3481	    PCI_STAT_66MHZ)) {
3482		if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3483		    "66mhz-capable", 0)) != DDI_SUCCESS) {
3484			return (ret);
3485		}
3486	}
3487	if (pci_config_get16(config_handle, PCI_CONF_STAT) & PCI_STAT_UDF) {
3488		if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3489		    "udf-supported", 0)) != DDI_SUCCESS) {
3490			return (ret);
3491		}
3492	}
3493
3494	/*
3495	 * These next three are optional and are not present
3496	 * if the corresponding register is zero.  If the value
3497	 * is non-zero then the property exists with the value
3498	 * of the register.
3499	 */
3500	if ((val = pci_config_get16(config_handle,
3501	    PCI_CONF_SUBVENID)) != 0) {
3502		if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3503		    "subsystem-vendor-id", val)) != DDI_SUCCESS) {
3504			return (ret);
3505		}
3506	}
3507	if ((val = pci_config_get16(config_handle,
3508	    PCI_CONF_SUBSYSID)) != 0) {
3509		if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3510		    "subsystem-id", val)) != DDI_SUCCESS) {
3511			return (ret);
3512		}
3513	}
3514	if ((val = pci_config_get16(config_handle,
3515	    PCI_CONF_CACHE_LINESZ)) != 0) {
3516		if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3517		    "cache-line-size", val)) != DDI_SUCCESS) {
3518			return (ret);
3519		}
3520	}
3521
3522	/*
3523	 * If the Interrupt Pin register is non-zero then the
3524	 * interrupts property exists
3525	 */
3526	if ((byteval = pci_config_get8(config_handle, PCI_CONF_IPIN)) != 0) {
3527		/*
3528		 * If interrupt pin is non-zero,
3529		 * record the interrupt line used
3530		 */
3531		if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3532		    "interrupts", byteval)) != DDI_SUCCESS) {
3533			return (ret);
3534		}
3535	}
3536
3537	ret = PCI_CAP_LOCATE(config_handle, PCI_CAP_ID_PCI_E, &cap_ptr);
3538
3539	if (pcie_dev && (ret == DDI_SUCCESS)) {
3540		val = PCI_CAP_GET16(config_handle, NULL, cap_ptr,
3541		    PCIE_PCIECAP) & PCIE_PCIECAP_SLOT_IMPL;
3542		/* if slot implemented, get physical slot number */
3543		if (val) {
3544			wordval = (PCI_CAP_GET32(config_handle, NULL,
3545			    cap_ptr, PCIE_SLOTCAP) >>
3546			    PCIE_SLOTCAP_PHY_SLOT_NUM_SHIFT) &
3547			    PCIE_SLOTCAP_PHY_SLOT_NUM_MASK;
3548			if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE,
3549			    dip, "physical-slot#", wordval))
3550			    != DDI_SUCCESS) {
3551				return (ret);
3552			}
3553		}
3554	}
3555	return (PCICFG_SUCCESS);
3556}
3557static int
3558pcicfg_set_busnode_props(dev_info_t *dip, uint8_t pcie_device_type,
3559    int pbus, int sbus)
3560{
3561	int ret;
3562	char device_type[8];
3563
3564	if (pcie_device_type)
3565		(void) strcpy(device_type, "pciex");
3566	else
3567		(void) strcpy(device_type, "pci");
3568
3569	if ((ret = ndi_prop_update_string(DDI_DEV_T_NONE, dip,
3570	    "device_type", device_type)) != DDI_SUCCESS) {
3571		return (ret);
3572	}
3573	if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3574	    "#address-cells", 3)) != DDI_SUCCESS) {
3575		return (ret);
3576	}
3577	if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3578	    "#size-cells", 2)) != DDI_SUCCESS) {
3579		return (ret);
3580	}
3581
3582	/*
3583	 * Create primary-bus and secondary-bus properties to be used
3584	 * to restore bus numbers in the pcicfg_setup_bridge() routine.
3585	 */
3586	if (pbus != -1 && sbus != -1) {
3587		if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3588		    "primary-bus", pbus)) != DDI_SUCCESS) {
3589				return (ret);
3590		}
3591		if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3592		    "secondary-bus", sbus)) != DDI_SUCCESS) {
3593				return (ret);
3594		}
3595	}
3596	return (PCICFG_SUCCESS);
3597}
3598
3599static int
3600pcicfg_set_childnode_props(dev_info_t *dip, ddi_acc_handle_t config_handle,
3601	uint8_t pcie_dev)
3602{
3603
3604	int		ret;
3605	char		*name;
3606	char		buffer[64], pprefix[8];
3607	uint16_t	classcode;
3608	uint8_t		revid, pif, pclass, psubclass;
3609	char		*compat[24];
3610	int		i;
3611	int		n;
3612	uint16_t		sub_vid, sub_sid, vid, did;
3613
3614	/* set the property prefix based on the device type */
3615	if (pcie_dev)
3616		(void) sprintf(pprefix, "pciex");
3617	else
3618		(void) sprintf(pprefix, "pci");
3619	sub_vid = pci_config_get16(config_handle, PCI_CONF_SUBVENID);
3620	sub_sid = pci_config_get16(config_handle, PCI_CONF_SUBSYSID);
3621	vid = pci_config_get16(config_handle, PCI_CONF_VENID);
3622	did = pci_config_get16(config_handle, PCI_CONF_DEVID);
3623	revid = pci_config_get8(config_handle, PCI_CONF_REVID);
3624	pif = pci_config_get8(config_handle, PCI_CONF_PROGCLASS);
3625	classcode = pci_config_get16(config_handle, PCI_CONF_SUBCLASS);
3626	pclass = pci_config_get8(config_handle, PCI_CONF_BASCLASS);
3627	psubclass = pci_config_get8(config_handle, PCI_CONF_SUBCLASS);
3628
3629	/*
3630	 * NOTE: These are for both a child and PCI-PCI bridge node
3631	 */
3632
3633	/*
3634	 *	"name" property rule
3635	 *	--------------------
3636	 *
3637	 *
3638	 * |	  \svid |
3639	 * |	   \    |
3640	 * |	    \   |
3641	 * |	ssid \  |	=0		|	!= 0		|
3642	 * |------------|-----------------------|-----------------------|
3643	 * |		|			|			|
3644	 * |	=0	|	vid,did		|	svid,ssid	|
3645	 * |		|			|			|
3646	 * |------------|-----------------------|-----------------------|
3647	 * |		|			|			|
3648	 * |	!=0	|	svid,ssid	|	svid,ssid	|
3649	 * |		|			|			|
3650	 * |------------|-----------------------|-----------------------|
3651	 *
3652	 * where:
3653	 *    vid = vendor id
3654	 *    did = device id
3655	 *   svid = subsystem vendor id
3656	 *   ssid = subsystem id
3657	 */
3658
3659	if ((sub_sid != 0) || (sub_vid != 0)) {
3660		(void) sprintf(buffer, "%s%x,%x", pprefix, sub_vid, sub_sid);
3661	} else {
3662		(void) sprintf(buffer, "%s%x,%x", pprefix, vid, did);
3663	}
3664
3665	/*
3666	 * In some environments, trying to use "generic" 1275 names is
3667	 * not the convention.  In those cases use the name as created
3668	 * above.  In all the rest of the cases, check to see if there
3669	 * is a generic name first.
3670	 */
3671#ifdef _DONT_USE_1275_GENERIC_NAMES
3672	name = buffer;
3673#else
3674	if ((name = pcicfg_get_class_name(classcode)) == NULL) {
3675		/*
3676		 * Set name to the above fabricated name
3677		 */
3678		name = buffer;
3679	}
3680#endif
3681
3682	/*
3683	 * The node name field needs to be filled in with the name
3684	 */
3685	if (ndi_devi_set_nodename(dip, name, 0) != NDI_SUCCESS) {
3686		DEBUG0("Failed to set nodename for node\n");
3687		return (PCICFG_FAILURE);
3688	}
3689
3690	/*
3691	 * Create the compatible property as an array of pointers
3692	 * to strings.  Start with the buffer created above.
3693	 */
3694	n = 0;
3695	compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3696	(void) strcpy(compat[n++], buffer);
3697
3698	/*
3699	 * Setup 'compatible' as per the PCI2.1 bindings document.
3700	 *	pci[ex]VVVV,DDDD.SSSS.ssss.RR
3701	 *	pci[ex]VVVV,DDDD.SSSS.ssss
3702	 *	pciSSSS.ssss  -> not created for PCIe as per PCIe bindings
3703	 *	pci[ex]VVVV,DDDD.RR
3704	 *	pci[ex]VVVV,DDDD
3705	 *	pci[ex]class,CCSSPP
3706	 *	pci[ex]class,CCSS
3707	 */
3708
3709	/* pci[ex]VVVV,DDDD.SSSS.ssss.RR */
3710	(void) sprintf(buffer, "%s%x,%x.%x.%x.%x", pprefix,  vid, did,
3711	    sub_vid, sub_sid, revid);
3712	compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3713	(void) strcpy(compat[n++], buffer);
3714
3715	/* pci[ex]VVVV,DDDD.SSSS.ssss */
3716	(void) sprintf(buffer, "%s%x,%x.%x.%x", pprefix,  vid, did,
3717	    sub_vid, sub_sid);
3718	compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3719	(void) strcpy(compat[n++], buffer);
3720
3721	/* pciSSSS.ssss  -> not created for PCIe as per PCIe bindings */
3722	if (!pcie_dev) {
3723		(void) sprintf(buffer, "pci%x,%x", sub_vid, sub_sid);
3724		compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3725		(void) strcpy(compat[n++], buffer);
3726	}
3727
3728	/* pci[ex]VVVV,DDDD.RR */
3729	(void) sprintf(buffer, "%s%x,%x.%x", pprefix,  vid, did, revid);
3730	compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3731	(void) strcpy(compat[n++], buffer);
3732
3733	/* pci[ex]VVVV,DDDD */
3734	(void) sprintf(buffer, "%s%x,%x", pprefix, vid, did);
3735	compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3736	(void) strcpy(compat[n++], buffer);
3737
3738	/* pci[ex]class,CCSSPP */
3739	(void) sprintf(buffer, "%sclass,%02x%02x%02x", pprefix,
3740	    pclass, psubclass, pif);
3741	compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3742	(void) strcpy(compat[n++], buffer);
3743
3744	/* pci[ex]class,CCSS */
3745	(void) sprintf(buffer, "%sclass,%04x", pprefix, classcode);
3746	compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3747	(void) strcpy(compat[n++], buffer);
3748
3749	if ((ret = ndi_prop_update_string_array(DDI_DEV_T_NONE, dip,
3750	    "compatible", (char **)compat, n)) != DDI_SUCCESS) {
3751		return (ret);
3752	}
3753
3754	for (i = 0; i < n; i++) {
3755		kmem_free(compat[i], strlen(compat[i]) + 1);
3756	}
3757
3758	DEBUG1("pcicfg_set_childnode_props - creating name=%s\n", name);
3759	if ((ret = ndi_prop_update_string(DDI_DEV_T_NONE, dip,
3760	    "name", name)) != DDI_SUCCESS) {
3761
3762		DEBUG0("pcicfg_set_childnode_props - Unable to create name "
3763		    "property\n");
3764
3765		return (ret);
3766	}
3767
3768	return (PCICFG_SUCCESS);
3769}
3770
3771/*
3772 * Program the bus numbers into the bridge
3773 */
3774
3775static void
3776pcicfg_set_bus_numbers(ddi_acc_handle_t config_handle,
3777uint_t primary, uint_t secondary, uint_t subordinate)
3778{
3779	DEBUG3("Setting bridge bus-range %d,%d,%d\n", primary, secondary,
3780	    subordinate);
3781	/*
3782	 * Primary bus#
3783	 */
3784	pci_config_put8(config_handle, PCI_BCNF_PRIBUS, primary);
3785
3786	/*
3787	 * Secondary bus#
3788	 */
3789	pci_config_put8(config_handle, PCI_BCNF_SECBUS, secondary);
3790
3791	/*
3792	 * Subordinate bus#
3793	 */
3794	pci_config_put8(config_handle, PCI_BCNF_SUBBUS, subordinate);
3795}
3796
3797/*
3798 * Put bridge registers into initial state
3799 */
3800static void
3801pcicfg_setup_bridge(pcicfg_phdl_t *entry,
3802    ddi_acc_handle_t handle, dev_info_t *dip)
3803{
3804	int pbus, sbus;
3805
3806	/*
3807	 * The highest bus seen during probing is the max-subordinate bus
3808	 */
3809	pci_config_put8(handle, PCI_BCNF_SUBBUS, entry->highest_bus);
3810
3811
3812	/*
3813	 * If there exists more than 1 downstream bridge, it
3814	 * will be reset by the below secondary bus reset which
3815	 * will clear the bus numbers assumed to be programmed in
3816	 * the pcicfg_probe_children() routine.  We therefore restore
3817	 * them here.
3818	 */
3819	if (pci_config_get8(handle, PCI_BCNF_SECBUS) == 0) {
3820		pbus = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
3821		    DDI_PROP_DONTPASS, "primary-bus", -1);
3822		sbus = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
3823		    DDI_PROP_DONTPASS, "secondary-bus", -1);
3824		if (pbus != -1 && sbus != -1) {
3825			pci_config_put8(handle, PCI_BCNF_PRIBUS, (uint_t)pbus);
3826			pci_config_put8(handle, PCI_BCNF_SECBUS, (uint_t)sbus);
3827		} else {
3828			cmn_err(CE_WARN, "Invalid Bridge number detected: \
3829			    %s%d: pbus = 0x%x, sbus = 0x%x",
3830			    ddi_get_name(dip), ddi_get_instance(dip), pbus,
3831			    sbus);
3832		}
3833	}
3834
3835	/*
3836	 * Reset the secondary bus
3837	 */
3838	pci_config_put16(handle, PCI_BCNF_BCNTRL,
3839	    pci_config_get16(handle, PCI_BCNF_BCNTRL) | 0x40);
3840
3841	drv_usecwait(100);
3842
3843	pci_config_put16(handle, PCI_BCNF_BCNTRL,
3844	    pci_config_get16(handle, PCI_BCNF_BCNTRL) & ~0x40);
3845
3846	/*
3847	 * Program the memory base register with the
3848	 * start of the memory range
3849	 */
3850	pci_config_put16(handle, PCI_BCNF_MEM_BASE,
3851	    PCICFG_HIWORD(PCICFG_LOADDR(entry->memory_last)));
3852
3853	/*
3854	 * Program the I/O base register with the start of the I/O range
3855	 */
3856	pci_config_put8(handle, PCI_BCNF_IO_BASE_LOW,
3857	    PCICFG_HIBYTE(PCICFG_LOWORD(PCICFG_LOADDR(entry->io_last))));
3858	pci_config_put16(handle, PCI_BCNF_IO_BASE_HI,
3859	    PCICFG_HIWORD(PCICFG_LOADDR(entry->io_last)));
3860
3861	/*
3862	 * Clear status bits
3863	 */
3864	pci_config_put16(handle, PCI_BCNF_SEC_STATUS, 0xffff);
3865
3866	/*
3867	 * Turn off prefetchable range
3868	 */
3869	pci_config_put32(handle, PCI_BCNF_PF_BASE_LOW, 0x0000ffff);
3870	pci_config_put32(handle, PCI_BCNF_PF_BASE_HIGH, 0xffffffff);
3871	pci_config_put32(handle, PCI_BCNF_PF_LIMIT_HIGH, 0x0);
3872
3873	/*
3874	 * Needs to be set to this value
3875	 */
3876	pci_config_put8(handle, PCI_CONF_ILINE, 0xf);
3877
3878	/*
3879	 * After a Reset, we need to wait 2^25 clock cycles before the
3880	 * first Configuration access.  The worst case is 33MHz, which
3881	 * is a 1 second wait.
3882	 */
3883	drv_usecwait(pcicfg_sec_reset_delay);
3884
3885}
3886
3887static void
3888pcicfg_update_bridge(pcicfg_phdl_t *entry,
3889	ddi_acc_handle_t handle)
3890{
3891	uint_t length;
3892
3893	/*
3894	 * Program the memory limit register with the end of the memory range
3895	 */
3896
3897	DEBUG1("DOWN ROUNDED ===>[0x%x]\n",
3898	    PCICFG_ROUND_DOWN(entry->memory_last,
3899	    PCICFG_MEMGRAN));
3900
3901	pci_config_put16(handle, PCI_BCNF_MEM_LIMIT,
3902	    PCICFG_HIWORD(PCICFG_LOADDR(
3903	    PCICFG_ROUND_DOWN(entry->memory_last,
3904	    PCICFG_MEMGRAN))));
3905	/*
3906	 * Since this is a bridge, the rest of this range will
3907	 * be responded to by the bridge.  We have to round up
3908	 * so no other device claims it.
3909	 */
3910	if ((length = (PCICFG_ROUND_UP(entry->memory_last,
3911	    PCICFG_MEMGRAN) - entry->memory_last)) > 0) {
3912		(void) pcicfg_get_mem(entry, length, NULL);
3913		DEBUG1("Added [0x%x]at the top of "
3914		    "the bridge (mem)\n", length);
3915	}
3916
3917	/*
3918	 * Program the I/O limit register with the end of the I/O range
3919	 */
3920	pci_config_put8(handle, PCI_BCNF_IO_LIMIT_LOW,
3921	    PCICFG_HIBYTE(PCICFG_LOWORD(
3922	    PCICFG_LOADDR(PCICFG_ROUND_DOWN(entry->io_last,
3923	    PCICFG_IOGRAN)))));
3924
3925	pci_config_put16(handle, PCI_BCNF_IO_LIMIT_HI,
3926	    PCICFG_HIWORD(PCICFG_LOADDR(PCICFG_ROUND_DOWN(entry->io_last,
3927	    PCICFG_IOGRAN))));
3928
3929	/*
3930	 * Same as above for I/O space. Since this is a
3931	 * bridge, the rest of this range will be responded
3932	 * to by the bridge.  We have to round up so no
3933	 * other device claims it.
3934	 */
3935	if ((length = (PCICFG_ROUND_UP(entry->io_last,
3936	    PCICFG_IOGRAN) - entry->io_last)) > 0) {
3937		(void) pcicfg_get_io(entry, length, NULL);
3938		DEBUG1("Added [0x%x]at the top of "
3939		    "the bridge (I/O)\n",  length);
3940	}
3941}
3942
3943/*ARGSUSED*/
3944static void
3945pcicfg_disable_bridge_probe_err(dev_info_t *dip, ddi_acc_handle_t h,
3946	pcicfg_err_regs_t *regs)
3947{
3948	uint16_t val;
3949
3950	/* disable SERR generated in the context of Master Aborts. */
3951	regs->cmd = val = pci_config_get16(h, PCI_CONF_COMM);
3952	val &= ~PCI_COMM_SERR_ENABLE;
3953	pci_config_put16(h, PCI_CONF_COMM, val);
3954	regs->bcntl = val = pci_config_get16(h, PCI_BCNF_BCNTRL);
3955	val &= ~PCI_BCNF_BCNTRL_SERR_ENABLE;
3956	pci_config_put16(h, PCI_BCNF_BCNTRL, val);
3957	/* clear any current pending errors */
3958	pci_config_put16(h, PCI_CONF_STAT, PCI_STAT_S_TARG_AB|
3959	    PCI_STAT_R_TARG_AB | PCI_STAT_R_MAST_AB | PCI_STAT_S_SYSERR);
3960	pci_config_put16(h, PCI_BCNF_SEC_STATUS, PCI_STAT_S_TARG_AB|
3961	    PCI_STAT_R_TARG_AB | PCI_STAT_R_MAST_AB | PCI_STAT_S_SYSERR);
3962	/* if we are a PCIe device, disable the generation of UR, CE and NFE */
3963	if (regs->pcie_dev) {
3964		uint16_t devctl;
3965		uint16_t cap_ptr;
3966
3967		if ((PCI_CAP_LOCATE(h, PCI_CAP_ID_PCI_E, &cap_ptr)) ==
3968		    DDI_FAILURE)
3969			return;
3970
3971		regs->pcie_cap_off = cap_ptr;
3972		regs->devctl = devctl = PCI_CAP_GET16(h, NULL, cap_ptr,
3973		    PCIE_DEVCTL);
3974		devctl &= ~(PCIE_DEVCTL_UR_REPORTING_EN |
3975		    PCIE_DEVCTL_CE_REPORTING_EN |
3976		    PCIE_DEVCTL_NFE_REPORTING_EN |
3977		    PCIE_DEVCTL_FE_REPORTING_EN);
3978		PCI_CAP_PUT16(h, NULL, cap_ptr, PCIE_DEVCTL, devctl);
3979	}
3980}
3981
3982/*ARGSUSED*/
3983static void
3984pcicfg_enable_bridge_probe_err(dev_info_t *dip, ddi_acc_handle_t h,
3985	pcicfg_err_regs_t *regs)
3986{
3987	/* clear any pending errors */
3988	pci_config_put16(h, PCI_CONF_STAT, PCI_STAT_S_TARG_AB|
3989	    PCI_STAT_R_TARG_AB | PCI_STAT_R_MAST_AB | PCI_STAT_S_SYSERR);
3990	pci_config_put16(h, PCI_BCNF_SEC_STATUS, PCI_STAT_S_TARG_AB|
3991	    PCI_STAT_R_TARG_AB | PCI_STAT_R_MAST_AB | PCI_STAT_S_SYSERR);
3992
3993	/* restore original settings */
3994	if (regs->pcie_dev) {
3995		pcie_clear_errors(dip);
3996		pci_config_put16(h, regs->pcie_cap_off + PCIE_DEVCTL,
3997		    regs->devctl);
3998	}
3999
4000	pci_config_put16(h, PCI_BCNF_BCNTRL, regs->bcntl);
4001	pci_config_put16(h, PCI_CONF_COMM, regs->cmd);
4002
4003}
4004
4005static int
4006pcicfg_probe_children(dev_info_t *parent, uint_t bus, uint_t device,
4007    uint_t func, uint_t *highest_bus, pcicfg_flags_t flags, boolean_t is_pcie)
4008{
4009	dev_info_t		*new_child;
4010	ddi_acc_handle_t	config_handle;
4011	uint8_t			header_type, pcie_dev = 0;
4012	int			ret;
4013	pcicfg_err_regs_t	regs;
4014
4015	/*
4016	 * This node will be put immediately below
4017	 * "parent". Allocate a blank device node.  It will either
4018	 * be filled in or freed up based on further probing.
4019	 */
4020	/*
4021	 * Note: in usr/src/uts/common/io/hotplug/pcicfg/pcicfg.c
4022	 * ndi_devi_alloc() is called as ndi_devi_alloc_sleep()
4023	 */
4024	if (ndi_devi_alloc(parent, DEVI_PSEUDO_NEXNAME,
4025	    (pnode_t)DEVI_SID_NODEID, &new_child)
4026	    != NDI_SUCCESS) {
4027		DEBUG0("pcicfg_probe_children(): Failed to alloc child node\n");
4028		return (PCICFG_FAILURE);
4029	}
4030
4031	if (pcicfg_add_config_reg(new_child, bus,
4032	    device, func) != DDI_SUCCESS) {
4033		DEBUG0("pcicfg_probe_children():"
4034		    "Failed to add candidate REG\n");
4035		goto failedconfig;
4036	}
4037
4038	if ((ret = pcicfg_config_setup(new_child, &config_handle))
4039	    != PCICFG_SUCCESS) {
4040		if (ret == PCICFG_NODEVICE) {
4041			(void) ndi_devi_free(new_child);
4042			return (ret);
4043		}
4044		DEBUG0("pcicfg_probe_children():"
4045		    "Failed to setup config space\n");
4046		goto failedconfig;
4047	}
4048
4049	if (is_pcie)
4050		(void) pcie_init_bus(new_child, PCI_GETBDF(bus, device, func),
4051		    PCIE_BUS_INITIAL);
4052
4053	/*
4054	 * As soon as we have access to config space,
4055	 * turn off device. It will get turned on
4056	 * later (after memory is assigned).
4057	 */
4058	(void) pcicfg_device_off(config_handle);
4059
4060	/* check if we are PCIe device */
4061	if (pcicfg_pcie_dev(new_child, PCICFG_DEVICE_TYPE_PCIE, &regs)
4062	    == DDI_SUCCESS) {
4063		DEBUG0("PCIe device detected\n");
4064		pcie_dev = 1;
4065	}
4066
4067	/*
4068	 * Set 1275 properties common to all devices
4069	 */
4070	if (pcicfg_set_standard_props(new_child, config_handle,
4071	    pcie_dev) != PCICFG_SUCCESS) {
4072		DEBUG0("Failed to set standard properties\n");
4073		goto failedchild;
4074	}
4075
4076	/*
4077	 * Child node properties  NOTE: Both for PCI-PCI bridge and child node
4078	 */
4079	if (pcicfg_set_childnode_props(new_child, config_handle,
4080	    pcie_dev) != PCICFG_SUCCESS) {
4081		goto failedchild;
4082	}
4083
4084	header_type = pci_config_get8(config_handle, PCI_CONF_HEADER);
4085
4086	/*
4087	 * If this is not a multi-function card only probe function zero.
4088	 */
4089	if ((!(header_type & PCI_HEADER_MULTI)) && (func != 0)) {
4090
4091		(void) pcicfg_config_teardown(&config_handle);
4092		(void) ndi_devi_free(new_child);
4093		return (PCICFG_NODEVICE);
4094	}
4095
4096	DEBUG1("---Vendor ID = [0x%x]\n",
4097	    pci_config_get16(config_handle, PCI_CONF_VENID));
4098	DEBUG1("---Device ID = [0x%x]\n",
4099	    pci_config_get16(config_handle, PCI_CONF_DEVID));
4100
4101	/*
4102	 * Attach the child to its parent
4103	 */
4104	(void) i_ndi_config_node(new_child, DS_LINKED, 0);
4105
4106	if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
4107
4108		DEBUG3("--Bridge found bus [0x%x] device"
4109		    "[0x%x] func [0x%x]\n", bus, device, func);
4110
4111		/* Only support read-only probe for leaf device */
4112		if (flags & PCICFG_FLAG_READ_ONLY)
4113			goto failedchild;
4114
4115		if (pcicfg_probe_bridge(new_child, config_handle,
4116		    bus, highest_bus, is_pcie) != PCICFG_SUCCESS) {
4117			(void) pcicfg_free_bridge_resources(new_child);
4118			goto failedchild;
4119		}
4120
4121	} else {
4122
4123		DEBUG3("--Leaf device found bus [0x%x] device"
4124		    "[0x%x] func [0x%x]\n",
4125		    bus, device, func);
4126
4127		if (flags & PCICFG_FLAG_READ_ONLY) {
4128			/*
4129			 * with read-only probe, don't do any resource
4130			 * allocation, just read the BARs and update props.
4131			 */
4132			ret = pcicfg_populate_props_from_bar(new_child,
4133			    config_handle);
4134			if (ret != PCICFG_SUCCESS)
4135				goto failedchild;
4136
4137			/*
4138			 * for readonly probe "assigned-addresses" property
4139			 * has already been setup by reading the BAR, here
4140			 * just substract the resource from its parent here.
4141			 */
4142			ret = pcicfg_device_assign_readonly(new_child);
4143			if (ret != PCICFG_SUCCESS) {
4144				(void) pcicfg_free_device_resources(new_child,
4145				    flags);
4146				goto failedchild;
4147			}
4148		} else {
4149			/*
4150			 * update "reg" property by sizing the BARs.
4151			 */
4152			ret = pcicfg_populate_reg_props(new_child,
4153			    config_handle);
4154			if (ret != PCICFG_SUCCESS)
4155				goto failedchild;
4156
4157			/* now allocate & program the resources */
4158			ret = pcicfg_device_assign(new_child);
4159			if (ret != PCICFG_SUCCESS) {
4160				(void) pcicfg_free_device_resources(new_child,
4161				    flags);
4162				goto failedchild;
4163			}
4164		}
4165
4166		(void) ndi_devi_bind_driver(new_child, 0);
4167	}
4168
4169	(void) pcicfg_config_teardown(&config_handle);
4170
4171	/*
4172	 * Properties have been setted up, so initilize the rest fields
4173	 * in bus_t.
4174	 */
4175	if (is_pcie)
4176		(void) pcie_init_bus(new_child, 0, PCIE_BUS_FINAL);
4177
4178	return (PCICFG_SUCCESS);
4179
4180failedchild:
4181
4182	(void) pcicfg_config_teardown(&config_handle);
4183	if (is_pcie)
4184		pcie_fini_bus(new_child, PCIE_BUS_FINAL);
4185
4186failedconfig:
4187
4188	(void) ndi_devi_free(new_child);
4189	return (PCICFG_FAILURE);
4190}
4191
4192/*
4193 * Sizing the BARs and update "reg" property
4194 */
4195static int
4196pcicfg_populate_reg_props(dev_info_t *new_child,
4197    ddi_acc_handle_t config_handle)
4198{
4199	int		i;
4200	uint32_t	request;
4201
4202	i = PCI_CONF_BASE0;
4203
4204	while (i <= PCI_CONF_BASE5) {
4205
4206		pci_config_put32(config_handle, i, 0xffffffff);
4207
4208		request = pci_config_get32(config_handle, i);
4209		/*
4210		 * If its a zero length, don't do
4211		 * any programming.
4212		 */
4213		if (request != 0) {
4214			/*
4215			 * Add to the "reg" property
4216			 */
4217			if (pcicfg_update_reg_prop(new_child,
4218			    request, i) != PCICFG_SUCCESS) {
4219				goto failedchild;
4220			}
4221		} else {
4222			DEBUG1("BASE register [0x%x] asks for "
4223			    "[0x0]=[0x0](32)\n", i);
4224			i += 4;
4225			continue;
4226		}
4227
4228		/*
4229		 * Increment by eight if it is 64 bit address space
4230		 */
4231		if ((PCI_BASE_TYPE_M & request) == PCI_BASE_TYPE_ALL) {
4232			DEBUG3("BASE register [0x%x] asks for "
4233			    "[0x%x]=[0x%x] (64)\n",
4234			    i, request,
4235			    (~(PCI_BASE_M_ADDR_M & request))+1)
4236			i += 8;
4237		} else {
4238			DEBUG3("BASE register [0x%x] asks for "
4239			    "[0x%x]=[0x%x](32)\n",
4240			    i, request,
4241			    (~(PCI_BASE_M_ADDR_M & request))+1)
4242			i += 4;
4243		}
4244	}
4245
4246	/*
4247	 * Get the ROM size and create register for it
4248	 */
4249	pci_config_put32(config_handle, PCI_CONF_ROM, 0xfffffffe);
4250
4251	request = pci_config_get32(config_handle, PCI_CONF_ROM);
4252	/*
4253	 * If its a zero length, don't do
4254	 * any programming.
4255	 */
4256
4257	if (request != 0) {
4258		DEBUG3("BASE register [0x%x] asks for [0x%x]=[0x%x]\n",
4259		    PCI_CONF_ROM, request,
4260		    (~(PCI_BASE_ROM_ADDR_M & request))+1);
4261		/*
4262		 * Add to the "reg" property
4263		 */
4264		if (pcicfg_update_reg_prop(new_child,
4265		    request, PCI_CONF_ROM) != PCICFG_SUCCESS) {
4266			goto failedchild;
4267		}
4268	}
4269
4270	return (PCICFG_SUCCESS);
4271
4272failedchild:
4273	return (PCICFG_FAILURE);
4274}
4275
4276static int
4277pcicfg_fcode_probe(dev_info_t *parent, uint_t bus, uint_t device,
4278    uint_t func, uint_t *highest_bus, pcicfg_flags_t flags, boolean_t is_pcie)
4279{
4280	dev_info_t		*new_child;
4281	int8_t			header_type;
4282	int			ret;
4283	ddi_acc_handle_t	h, ph;
4284	int			error = 0;
4285	extern int		pcicfg_dont_interpret;
4286	pcicfg_err_regs_t	parent_regs, regs;
4287	char			*status_prop = NULL;
4288#ifdef PCICFG_INTERPRET_FCODE
4289	struct pci_ops_bus_args	po;
4290	fco_handle_t		c;
4291	char			unit_address[64];
4292	int			fcode_size = 0;
4293	uchar_t			*fcode_addr;
4294	uint64_t		mem_answer, mem_alen;
4295	pci_regspec_t		p;
4296	int32_t			request;
4297	ndi_ra_request_t	req;
4298	int16_t			vendor_id, device_id;
4299#endif
4300
4301	/*
4302	 * check if our parent is of type pciex.
4303	 * if so, program config space to disable error msgs during probe.
4304	 */
4305	if (pcicfg_pcie_dev(parent, PCICFG_DEVICE_TYPE_PCIE, &parent_regs)
4306	    == DDI_SUCCESS) {
4307		DEBUG0("PCI/PCIe parent detected. Disable errors.\n");
4308		/*
4309		 * disable parent generating URs or SERR#s during probing
4310		 * alone.
4311		 */
4312		if (pci_config_setup(parent, &ph) != DDI_SUCCESS)
4313			return (DDI_FAILURE);
4314
4315		if ((flags & PCICFG_FLAG_READ_ONLY) == 0) {
4316			pcicfg_disable_bridge_probe_err(parent,
4317			    ph, &parent_regs);
4318		}
4319	}
4320
4321	/*
4322	 * This node will be put immediately below
4323	 * "parent". Allocate a blank device node.  It will either
4324	 * be filled in or freed up based on further probing.
4325	 */
4326
4327	if (ndi_devi_alloc(parent, DEVI_PSEUDO_NEXNAME,
4328	    (pnode_t)DEVI_SID_NODEID, &new_child)
4329	    != NDI_SUCCESS) {
4330		DEBUG0("pcicfg_fcode_probe(): Failed to alloc child node\n");
4331		/* return (PCICFG_FAILURE); */
4332		ret = PCICFG_FAILURE;
4333		goto failed2;
4334	}
4335
4336	/*
4337	 * Create a dummy reg property.  This will be replaced with
4338	 * a real reg property when fcode completes or if we need to
4339	 * produce one by hand.
4340	 */
4341	if (pcicfg_add_config_reg(new_child, bus,
4342	    device, func) != DDI_SUCCESS) {
4343		ret = PCICFG_FAILURE;
4344		goto failed3;
4345	}
4346#ifdef	EFCODE21554
4347	if ((ret = pcicfg_config_setup(new_child, &h))
4348	    != PCICFG_SUCCESS) {
4349		DEBUG0("pcicfg_fcode_probe():"
4350		    "Failed to setup config space\n");
4351		ret = PCICFG_NODEVICE;
4352		goto failed3;
4353	}
4354
4355#else
4356	p.pci_phys_hi = PCICFG_MAKE_REG_HIGH(bus, device, func, 0);
4357	p.pci_phys_mid = p.pci_phys_low = 0;
4358	p.pci_size_hi = p.pci_size_low = 0;
4359
4360	/*
4361	 * Map in configuration space (temporarily)
4362	 */
4363	acc.devacc_attr_version = DDI_DEVICE_ATTR_V0;
4364	acc.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
4365	acc.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
4366
4367	if (pcicfg_map_phys(new_child, &p, &virt, &acc, &h)) {
4368		DEBUG0("pcicfg_fcode_probe():"
4369		    "Failed to setup config space\n");
4370		ret = PCICFG_NODEVICE;
4371		goto failed3;
4372	}
4373
4374	/*
4375	 * First use ddi_peek16 so that if there is not a device there,
4376	 * a bus error will not cause a panic.
4377	 */
4378	v = virt + PCI_CONF_VENID;
4379	if (ddi_peek16(new_child, (int16_t *)v, &vendor_id)) {
4380		DEBUG0("Can not read Vendor ID");
4381		pcicfg_unmap_phys(&h, &p);
4382		ret = PCICFG_NODEVICE;
4383		goto failed3;
4384	}
4385#endif
4386
4387	if (is_pcie)
4388		(void) pcie_init_bus(new_child, PCI_GETBDF(bus, device, func),
4389		    PCIE_BUS_INITIAL);
4390
4391	DEBUG0("fcode_probe: conf space mapped.\n");
4392	/*
4393	 * As soon as we have access to config space,
4394	 * turn off device. It will get turned on
4395	 * later (after memory is assigned).
4396	 */
4397	(void) pcicfg_device_off(h);
4398
4399	/* check if we are PCIe device */
4400	if (pcicfg_pcie_dev(new_child, PCICFG_DEVICE_TYPE_PCIE, &regs)
4401	    == DDI_SUCCESS) {
4402		/*EMPTY*/
4403		DEBUG0("PCI/PCIe device detected\n");
4404	}
4405
4406	/*
4407	 * Set 1275 properties common to all devices
4408	 */
4409	if (pcicfg_set_standard_props(new_child,
4410	    h, regs.pcie_dev) != PCICFG_SUCCESS) {
4411		DEBUG0("Failed to set standard properties\n");
4412		goto failed;
4413	}
4414
4415	/*
4416	 * Child node properties  NOTE: Both for PCI-PCI bridge and child node
4417	 */
4418	if (pcicfg_set_childnode_props(new_child,
4419	    h, regs.pcie_dev) != PCICFG_SUCCESS) {
4420		ret = PCICFG_FAILURE;
4421		goto failed;
4422	}
4423
4424	header_type = pci_config_get8(h, PCI_CONF_HEADER);
4425
4426	/*
4427	 * If this is not a multi-function card only probe function zero.
4428	 */
4429	if (!(header_type & PCI_HEADER_MULTI) && (func > 0)) {
4430
4431		ret = PCICFG_NODEVICE;
4432		goto failed;
4433	}
4434
4435	if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
4436
4437		/*
4438		 * XXX - Transparent bridges are handled differently
4439		 * than other devices with regards to fcode.  Since
4440		 * no transparent bridge currently ships with fcode,
4441		 * there is no reason to try to extract it from its rom
4442		 * or call the fcode interpreter to try to load a drop-in.
4443		 * If fcode is developed to handle transparent bridges,
4444		 * this code will have to change.
4445		 */
4446
4447		DEBUG3("--Bridge found bus [0x%x] device"
4448		    "[0x%x] func [0x%x]\n", bus, device, func);
4449
4450		/* Only support read-only probe for leaf device */
4451		if (flags & PCICFG_FLAG_READ_ONLY)
4452			goto failed;
4453
4454		if ((ret = pcicfg_probe_bridge(new_child, h,
4455		    bus, highest_bus, is_pcie)) != PCICFG_SUCCESS)
4456			(void) pcicfg_free_bridge_resources(new_child);
4457		goto done;
4458	} else {
4459
4460		DEBUG3("--Leaf device found bus [0x%x] device"
4461		    "[0x%x] func [0x%x]\n",
4462		    bus, device, func);
4463
4464		/*
4465		 * link in tree, but don't bind driver
4466		 * We don't have compatible property yet
4467		 */
4468		(void) i_ndi_config_node(new_child, DS_LINKED, 0);
4469
4470		/* XXX for now, don't run Fcode in read-only probe. */
4471		if (flags & PCICFG_FLAG_READ_ONLY)
4472			goto no_fcode;
4473
4474		if (pci_config_get8(h, PCI_CONF_IPIN)) {
4475			pci_config_put8(h, PCI_CONF_ILINE, 0xf);
4476		}
4477
4478#ifdef PCICFG_INTERPRET_FCODE
4479		/*
4480		 * Some platforms (x86) don't run fcode, so don't interpret
4481		 * fcode that might be in the ROM.
4482		 */
4483		if (pcicfg_dont_interpret == 0) {
4484
4485			/* This platform supports fcode */
4486
4487			vendor_id = pci_config_get16(h, PCI_CONF_VENID);
4488			device_id = pci_config_get16(h, PCI_CONF_DEVID);
4489
4490			/*
4491			 * Get the ROM size and create register for it
4492			 */
4493			pci_config_put32(h, PCI_CONF_ROM, 0xfffffffe);
4494
4495			request = pci_config_get32(h, PCI_CONF_ROM);
4496
4497			/*
4498			 * If its a zero length, don't do
4499			 * any programming.
4500			 */
4501
4502			if (request != 0) {
4503				/*
4504				 * Add resource to assigned-addresses.
4505				 */
4506				if (pcicfg_fcode_assign_bars(h, new_child,
4507				    bus, device, func, request, &p)
4508				    != PCICFG_SUCCESS) {
4509					DEBUG0("Failed to assign addresses to "
4510					    "implemented BARs");
4511					ret = PCICFG_FAILURE;
4512					goto failed;
4513				}
4514
4515				/* Turn device on */
4516				(void) pcicfg_device_on(h);
4517
4518				/*
4519				 * Attempt to load fcode.
4520				 */
4521				(void) pcicfg_load_fcode(new_child, bus, device,
4522				    func, vendor_id, device_id, &fcode_addr,
4523				    &fcode_size, PCICFG_LOADDR(mem_answer),
4524				    (~(PCI_BASE_ROM_ADDR_M & request)) + 1);
4525
4526				/* Turn device off */
4527				(void) pcicfg_device_off(h);
4528
4529				/*
4530				 * Free the ROM resources.
4531				 */
4532				(void) pcicfg_free_resource(new_child, p, 0);
4533
4534				DEBUG2("configure: fcode addr %lx size %x\n",
4535				    fcode_addr, fcode_size);
4536
4537				/*
4538				 * Create the fcode-rom-offset property.  The
4539				 * buffer containing the fcode always starts
4540				 * with 0xF1, so the fcode offset is zero.
4541				 */
4542				if (ndi_prop_update_int(DDI_DEV_T_NONE,
4543				    new_child, "fcode-rom-offset", 0)
4544				    != DDI_SUCCESS) {
4545					DEBUG0("Failed to create "
4546					    "fcode-rom-offset property\n");
4547					ret = PCICFG_FAILURE;
4548					goto failed;
4549				}
4550			} else {
4551				DEBUG0("There is no Expansion ROM\n");
4552				fcode_addr = NULL;
4553				fcode_size = 0;
4554			}
4555
4556			/*
4557			 * Fill in the bus specific arguments. For
4558			 * PCI, it is the config address.
4559			 */
4560			po.config_address =
4561			    PCICFG_MAKE_REG_HIGH(bus, device, func, 0);
4562
4563			DEBUG1("config_address=%x\n", po.config_address);
4564
4565			/*
4566			 * Build unit address.
4567			 */
4568			(void) sprintf(unit_address, "%x,%x", device, func);
4569
4570			DEBUG3("pci_fc_ops_alloc_handle ap=%lx "
4571			    "new device=%lx unit address=%s\n",
4572			    parent, new_child, unit_address);
4573
4574			c = pci_fc_ops_alloc_handle(parent, new_child,
4575			    fcode_addr, fcode_size, unit_address, &po);
4576
4577			DEBUG0("calling fcode_interpreter()\n");
4578
4579			DEBUG3("Before int DIP=%lx binding name %s major %d\n",
4580			    new_child, ddi_binding_name(new_child),
4581			    ddi_driver_major(new_child));
4582
4583			error = fcode_interpreter(parent, &pci_fc_ops, c);
4584
4585			DEBUG1("returned from fcode_interpreter() - "
4586			    "returned %x\n", error);
4587
4588			pci_fc_ops_free_handle(c);
4589
4590			DEBUG1("fcode size = %x\n", fcode_size);
4591			/*
4592			 * We don't need the fcode anymore. While allocating
4593			 * we had rounded up to a page size.
4594			 */
4595			if (fcode_size) {
4596				kmem_free(fcode_addr, ptob(btopr(fcode_size)));
4597			}
4598		} else {
4599			/* This platform does not support fcode */
4600
4601			DEBUG0("NOT calling fcode_interpreter()\n");
4602		}
4603
4604#endif /* PCICFG_INTERPRET_FCODE */
4605
4606		if ((error == 0) && (pcicfg_dont_interpret == 0)) {
4607			/*
4608			 * The interpreter completed successfully.
4609			 * We need to redo the resources based on the new reg
4610			 * property.
4611			 */
4612			DEBUG3("DIP=%lx binding name %s major %d\n", new_child,
4613			    ddi_binding_name(new_child),
4614			    ddi_driver_major(new_child));
4615
4616			/*
4617			 * Readjust resources specified by reg property.
4618			 */
4619			if (pcicfg_alloc_new_resources(new_child) ==
4620			    PCICFG_FAILURE) {
4621				ret = PCICFG_FAILURE;
4622				goto failed;
4623			}
4624
4625			/*
4626			 * At this stage, there should be enough info to pull
4627			 * the status property if it exists.
4628			 */
4629			if (ddi_prop_lookup_string(DDI_DEV_T_ANY,
4630			    new_child, NULL, "status", &status_prop) ==
4631			    DDI_PROP_SUCCESS) {
4632				if ((strncmp("disabled", status_prop, 8) ==
4633				    0) || (strncmp("fail", status_prop, 4) ==
4634				    0)) {
4635					ret = PCICFG_FAILURE;
4636					ddi_prop_free(status_prop);
4637					goto failed;
4638				} else {
4639					ddi_prop_free(status_prop);
4640				}
4641			}
4642
4643			ret = PCICFG_SUCCESS;
4644			/* no fcode, bind driver now */
4645			(void) ndi_devi_bind_driver(new_child, 0);
4646
4647			goto done;
4648		} else if ((error != FC_NO_FCODE) &&
4649		    (pcicfg_dont_interpret == 0))  {
4650			/*
4651			 * The interpreter located fcode, but had an error in
4652			 * processing. Cleanup and fail the operation.
4653			 */
4654			DEBUG0("Interpreter detected fcode failure\n");
4655			(void) pcicfg_free_resources(new_child, flags);
4656			ret = PCICFG_FAILURE;
4657			goto failed;
4658		} else {
4659no_fcode:
4660			/*
4661			 * Either the interpreter failed with FC_NO_FCODE or we
4662			 * chose not to run the interpreter
4663			 * (pcicfg_dont_interpret).
4664			 *
4665			 * If the interpreter failed because there was no
4666			 * dropin, then we need to probe the device ourself.
4667			 */
4668
4669			/*
4670			 * Free any resources that may have been assigned
4671			 * during fcode loading/execution since we need
4672			 * to start over.
4673			 */
4674			(void) pcicfg_free_resources(new_child, flags);
4675
4676#ifdef	EFCODE21554
4677			pcicfg_config_teardown(&h);
4678#else
4679			pcicfg_unmap_phys(&h, &p);
4680#endif
4681			/* destroy the bus_t before the dev node is gone */
4682			if (is_pcie)
4683				pcie_fini_bus(new_child, PCIE_BUS_FINAL);
4684
4685			(void) ndi_devi_free(new_child);
4686
4687			DEBUG0("No Drop-in Probe device ourself\n");
4688
4689			ret = pcicfg_probe_children(parent, bus, device, func,
4690			    highest_bus, flags, is_pcie);
4691
4692			if (ret != PCICFG_SUCCESS) {
4693				DEBUG0("Could not self probe child\n");
4694				goto failed2;
4695			}
4696
4697			/*
4698			 * We successfully self probed the device.
4699			 */
4700			if ((new_child = pcicfg_devi_find(
4701			    parent, device, func)) == NULL) {
4702				DEBUG0("Did'nt find device node "
4703				    "just created\n");
4704				ret = PCICFG_FAILURE;
4705				goto failed2;
4706			}
4707#ifdef	EFCODE21554
4708			/*
4709			 * Till now, we have detected a non transparent bridge
4710			 * (ntbridge) as a part of the generic probe code and
4711			 * configured only one configuration
4712			 * header which is the side facing the host bus.
4713			 * Now, configure the other side and create children.
4714			 *
4715			 * To make the process simpler, lets load the device
4716			 * driver for the non transparent bridge as this is a
4717			 * Solaris bundled driver, and use its configuration map
4718			 * services rather than programming it here.
4719			 * If the driver is not bundled into Solaris, it must be
4720			 * first loaded and configured before performing any
4721			 * hotplug operations.
4722			 *
4723			 * This not only makes the code simpler but also more
4724			 * generic.
4725			 *
4726			 * So here we go.
4727			 */
4728			if (pcicfg_is_ntbridge(new_child) != DDI_FAILURE) {
4729
4730				DEBUG0("Found nontransparent bridge.\n");
4731
4732				ret = pcicfg_configure_ntbridge(new_child,
4733				    bus, device);
4734			}
4735			if (ret != PCICFG_SUCCESS) {
4736				/*
4737				 * Bridge configure failed. Free up the self
4738				 * probed entry. The bus resource allocation
4739				 * maps need to be cleaned up to prevent
4740				 * warnings on retries of the failed configure.
4741				 */
4742				(void) pcicfg_ntbridge_unconfigure(new_child);
4743				(void) pcicfg_teardown_device(new_child,
4744				    flags, is_pcie);
4745			}
4746#endif
4747			goto done2;
4748		}
4749	}
4750done:
4751failed:
4752	if (is_pcie) {
4753		if (ret == PCICFG_SUCCESS)
4754			(void) pcie_init_bus(new_child, 0, PCIE_BUS_FINAL);
4755		else
4756			pcie_fini_bus(new_child, PCIE_BUS_FINAL);
4757	}
4758
4759#ifdef	EFCODE21554
4760	pcicfg_config_teardown(&h);
4761#else
4762	pcicfg_unmap_phys(&h, &p);
4763#endif
4764failed3:
4765	if (ret != PCICFG_SUCCESS)
4766		(void) ndi_devi_free(new_child);
4767done2:
4768failed2:
4769	if (parent_regs.pcie_dev) {
4770		if ((flags & PCICFG_FLAG_READ_ONLY) == 0) {
4771			pcicfg_enable_bridge_probe_err(parent,
4772			    ph, &parent_regs);
4773		}
4774		pci_config_teardown(&ph);
4775	}
4776
4777	return (ret);
4778}
4779
4780/*
4781 * Read the BARs and update properties. Used in virtual hotplug.
4782 */
4783static int
4784pcicfg_populate_props_from_bar(dev_info_t *new_child,
4785    ddi_acc_handle_t config_handle)
4786{
4787	uint32_t request, base, base_hi, size;
4788	int i;
4789
4790	i = PCI_CONF_BASE0;
4791
4792	while (i <= PCI_CONF_BASE5) {
4793		/*
4794		 * determine the size of the address space
4795		 */
4796		base = pci_config_get32(config_handle, i);
4797		pci_config_put32(config_handle, i, 0xffffffff);
4798		request = pci_config_get32(config_handle, i);
4799		pci_config_put32(config_handle, i, base);
4800
4801		/*
4802		 * If its a zero length, don't do any programming.
4803		 */
4804		if (request != 0) {
4805			/*
4806			 * Add to the "reg" property
4807			 */
4808			if (pcicfg_update_reg_prop(new_child,
4809			    request, i) != PCICFG_SUCCESS) {
4810				goto failedchild;
4811			}
4812
4813			if ((PCI_BASE_SPACE_IO & request) == 0 &&
4814			    (PCI_BASE_TYPE_M & request) == PCI_BASE_TYPE_ALL) {
4815				base_hi = pci_config_get32(config_handle, i+4);
4816			} else {
4817				base_hi = 0;
4818			}
4819			/*
4820			 * Add to "assigned-addresses" property
4821			 */
4822			size = (~(PCI_BASE_M_ADDR_M & request))+1;
4823			if (pcicfg_update_assigned_prop_value(new_child,
4824			    size, base, base_hi, i) != PCICFG_SUCCESS) {
4825				goto failedchild;
4826			}
4827		} else {
4828			DEBUG1("BASE register [0x%x] asks for "
4829			"[0x0]=[0x0](32)\n", i);
4830			i += 4;
4831			continue;
4832		}
4833
4834		/*
4835		 * Increment by eight if it is 64 bit address space
4836		 */
4837		if ((PCI_BASE_TYPE_M & request) == PCI_BASE_TYPE_ALL) {
4838			DEBUG3("BASE register [0x%x] asks for "
4839			"[0x%x]=[0x%x] (64)\n",
4840			    i, request,
4841			    (~(PCI_BASE_M_ADDR_M & request))+1)
4842			i += 8;
4843		} else {
4844			DEBUG3("BASE register [0x%x] asks for "
4845			"[0x%x]=[0x%x](32)\n",
4846			    i, request,
4847			    (~(PCI_BASE_M_ADDR_M & request))+1)
4848			i += 4;
4849		}
4850	}
4851
4852	/*
4853	 * Get the ROM size and create register for it
4854	 */
4855	base = pci_config_get32(config_handle, PCI_CONF_ROM);
4856	pci_config_put32(config_handle, PCI_CONF_ROM, 0xfffffffe);
4857	request = pci_config_get32(config_handle, PCI_CONF_ROM);
4858	pci_config_put32(config_handle, PCI_CONF_ROM, base);
4859
4860	/*
4861	 * If its a zero length, don't do
4862	 * any programming.
4863	 */
4864	if (request != 0) {
4865		DEBUG3("BASE register [0x%x] asks for [0x%x]=[0x%x]\n",
4866		    PCI_CONF_ROM, request,
4867		    (~(PCI_BASE_ROM_ADDR_M & request))+1);
4868		/*
4869		 * Add to the "reg" property
4870		 */
4871		if (pcicfg_update_reg_prop(new_child,
4872		    request, PCI_CONF_ROM) != PCICFG_SUCCESS) {
4873			goto failedchild;
4874		}
4875		/*
4876		 * Add to "assigned-addresses" property
4877		 */
4878		size = (~(PCI_BASE_ROM_ADDR_M & request))+1;
4879		if (pcicfg_update_assigned_prop_value(new_child, size,
4880		    base, 0, PCI_CONF_ROM) != PCICFG_SUCCESS) {
4881			goto failedchild;
4882		}
4883	}
4884
4885	return (PCICFG_SUCCESS);
4886
4887failedchild:
4888	return (PCICFG_FAILURE);
4889}
4890
4891static int
4892pcicfg_probe_bridge(dev_info_t *new_child, ddi_acc_handle_t h, uint_t bus,
4893	uint_t *highest_bus, boolean_t is_pcie)
4894{
4895	uint64_t next_bus;
4896	uint_t new_bus, num_slots;
4897	ndi_ra_request_t req;
4898	int rval, i, j;
4899	uint64_t mem_answer, mem_base, mem_alen, mem_size, mem_end;
4900	uint64_t io_answer, io_base, io_alen, io_size, io_end;
4901	uint64_t round_answer, round_len;
4902	pcicfg_range_t range[PCICFG_RANGE_LEN];
4903	int bus_range[2];
4904	pcicfg_phdl_t phdl;
4905	int count;
4906	uint64_t pcibus_base, pcibus_alen;
4907	uint64_t max_bus;
4908	uint8_t pcie_device_type = 0;
4909	dev_info_t *new_device;
4910	int trans_device;
4911	int ari_mode = B_FALSE;
4912	int max_function = PCICFG_MAX_FUNCTION;
4913
4914	/*
4915	 * Set "device_type" to "pci", the actual type will be set later
4916	 * by pcicfg_set_busnode_props() below. This is needed as the
4917	 * pcicfg_ra_free() below would update "available" property based
4918	 * on "device_type".
4919	 *
4920	 * This code can be removed later after PCI configurator is changed
4921	 * to use PCIRM, which automatically update properties upon allocation
4922	 * and free, at that time we'll be able to remove the code inside
4923	 * ndi_ra_alloc/free() which currently updates "available" property
4924	 * for pci/pcie devices in pcie fabric.
4925	 */
4926	if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child,
4927	    "device_type", "pci") != DDI_SUCCESS) {
4928		DEBUG0("Failed to set \"device_type\" props\n");
4929		return (PCICFG_FAILURE);
4930	}
4931
4932	bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
4933	req.ra_flags = (NDI_RA_ALLOC_BOUNDED | NDI_RA_ALLOC_PARTIAL_OK);
4934	req.ra_boundbase = 0;
4935	req.ra_boundlen = PCICFG_MAX_BUS_DEPTH;
4936	req.ra_len = PCICFG_MAX_BUS_DEPTH;
4937	req.ra_align_mask = 0;  /* no alignment needed */
4938
4939	rval = ndi_ra_alloc(ddi_get_parent(new_child), &req,
4940	    &pcibus_base, &pcibus_alen, NDI_RA_TYPE_PCI_BUSNUM, NDI_RA_PASS);
4941
4942	if (rval != NDI_SUCCESS) {
4943		if (rval == NDI_RA_PARTIAL_REQ) {
4944			/*EMPTY*/
4945			DEBUG0("NDI_RA_PARTIAL_REQ returned for bus range\n");
4946		} else {
4947			DEBUG0(
4948			    "Failed to allocate bus range for bridge\n");
4949			return (PCICFG_FAILURE);
4950		}
4951	}
4952
4953	DEBUG2("Bus Range Allocated [base=%d] [len=%d]\n",
4954	    pcibus_base, pcibus_alen);
4955
4956	if (ndi_ra_map_setup(new_child, NDI_RA_TYPE_PCI_BUSNUM)
4957	    == NDI_FAILURE) {
4958		DEBUG0("Can not setup resource map - NDI_RA_TYPE_PCI_BUSNUM\n");
4959		return (PCICFG_FAILURE);
4960	}
4961
4962	/*
4963	 * Put available bus range into the pool.
4964	 * Take the first one for this bridge to use and don't give
4965	 * to child.
4966	 */
4967	(void) ndi_ra_free(new_child, pcibus_base+1, pcibus_alen-1,
4968	    NDI_RA_TYPE_PCI_BUSNUM, NDI_RA_PASS);
4969
4970	next_bus = pcibus_base;
4971	max_bus = pcibus_base + pcibus_alen - 1;
4972
4973	new_bus = next_bus;
4974
4975	DEBUG1("NEW bus found  ->[%d]\n", new_bus);
4976
4977	/* Keep track of highest bus for subordinate bus programming */
4978	*highest_bus = new_bus;
4979
4980	/*
4981	 * Allocate Memory Space for Bridge
4982	 */
4983	bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
4984	req.ra_flags = (NDI_RA_ALLOC_BOUNDED | NDI_RA_ALLOC_PARTIAL_OK);
4985	req.ra_boundbase = 0;
4986	/*
4987	 * Note: To support a 32b system, boundlen and len need to be
4988	 * 32b quantities
4989	 */
4990	req.ra_boundlen = PCICFG_4GIG_LIMIT + 1;
4991	req.ra_len = PCICFG_4GIG_LIMIT + 1; /* Get as big as possible */
4992	req.ra_align_mask =
4993	    PCICFG_MEMGRAN - 1; /* 1M alignment on memory space */
4994
4995	rval = ndi_ra_alloc(ddi_get_parent(new_child), &req,
4996	    &mem_answer, &mem_alen,  NDI_RA_TYPE_MEM, NDI_RA_PASS);
4997
4998	if (rval != NDI_SUCCESS) {
4999		if (rval == NDI_RA_PARTIAL_REQ) {
5000			/*EMPTY*/
5001			DEBUG0("NDI_RA_PARTIAL_REQ returned\n");
5002		} else {
5003			DEBUG0(
5004			    "Failed to allocate memory for bridge\n");
5005			return (PCICFG_FAILURE);
5006		}
5007	}
5008
5009	DEBUG3("Bridge Memory Allocated [0x%x.%x] len [0x%x]\n",
5010	    PCICFG_HIADDR(mem_answer),
5011	    PCICFG_LOADDR(mem_answer),
5012	    mem_alen);
5013
5014	if (ndi_ra_map_setup(new_child, NDI_RA_TYPE_MEM) == NDI_FAILURE) {
5015		DEBUG0("Can not setup resource map - NDI_RA_TYPE_MEM\n");
5016		return (PCICFG_FAILURE);
5017	}
5018
5019	/*
5020	 * Put available memory into the pool.
5021	 */
5022	(void) ndi_ra_free(new_child, mem_answer, mem_alen, NDI_RA_TYPE_MEM,
5023	    NDI_RA_PASS);
5024
5025	mem_base = mem_answer;
5026
5027	/*
5028	 * Allocate I/O Space for Bridge
5029	 */
5030	bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
5031	req.ra_align_mask = PCICFG_IOGRAN - 1; /* 4k alignment */
5032	req.ra_boundbase = 0;
5033	req.ra_boundlen = PCICFG_4GIG_LIMIT;
5034	req.ra_flags = (NDI_RA_ALLOC_BOUNDED | NDI_RA_ALLOC_PARTIAL_OK);
5035	req.ra_len = PCICFG_4GIG_LIMIT; /* Get as big as possible */
5036
5037	rval = ndi_ra_alloc(ddi_get_parent(new_child), &req, &io_answer,
5038	    &io_alen, NDI_RA_TYPE_IO, NDI_RA_PASS);
5039
5040	if (rval != NDI_SUCCESS) {
5041		if (rval == NDI_RA_PARTIAL_REQ) {
5042			/*EMPTY*/
5043			DEBUG0("NDI_RA_PARTIAL_REQ returned\n");
5044		} else {
5045			DEBUG0("Failed to allocate io space for bridge\n");
5046			io_base = io_answer = io_alen = 0;
5047			/* return (PCICFG_FAILURE); */
5048		}
5049	}
5050
5051	if (io_alen) {
5052		DEBUG3("Bridge IO Space Allocated [0x%x.%x] len [0x%x]\n",
5053		    PCICFG_HIADDR(io_answer), PCICFG_LOADDR(io_answer),
5054		    io_alen);
5055
5056		if (ndi_ra_map_setup(new_child, NDI_RA_TYPE_IO) ==
5057		    NDI_FAILURE) {
5058			DEBUG0("Can not setup resource map - NDI_RA_TYPE_IO\n");
5059			return (PCICFG_FAILURE);
5060		}
5061
5062		/*
5063		 * Put available I/O into the pool.
5064		 */
5065		(void) ndi_ra_free(new_child, io_answer, io_alen,
5066		    NDI_RA_TYPE_IO, NDI_RA_PASS);
5067		io_base = io_answer;
5068	}
5069
5070	pcicfg_set_bus_numbers(h, bus, new_bus, max_bus);
5071
5072	/*
5073	 * Setup "bus-range" property before onlining the bridge.
5074	 */
5075	bus_range[0] = new_bus;
5076	bus_range[1] = max_bus;
5077
5078	if (ndi_prop_update_int_array(DDI_DEV_T_NONE, new_child,
5079	    "bus-range", bus_range, 2) != DDI_SUCCESS) {
5080		DEBUG0("Failed to set bus-range property");
5081		return (PCICFG_FAILURE);
5082	}
5083
5084	/*
5085	 * Reset the secondary bus
5086	 */
5087	pci_config_put16(h, PCI_BCNF_BCNTRL,
5088	    pci_config_get16(h, PCI_BCNF_BCNTRL) | 0x40);
5089
5090	drv_usecwait(100);
5091
5092	pci_config_put16(h, PCI_BCNF_BCNTRL,
5093	    pci_config_get16(h, PCI_BCNF_BCNTRL) & ~0x40);
5094
5095	/*
5096	 * Program the memory base register with the
5097	 * start of the memory range
5098	 */
5099	pci_config_put16(h, PCI_BCNF_MEM_BASE,
5100	    PCICFG_HIWORD(PCICFG_LOADDR(mem_answer)));
5101
5102	/*
5103	 * Program the memory limit register with the
5104	 * end of the memory range.
5105	 */
5106
5107	pci_config_put16(h, PCI_BCNF_MEM_LIMIT,
5108	    PCICFG_HIWORD(PCICFG_LOADDR(
5109	    PCICFG_ROUND_DOWN((mem_answer + mem_alen), PCICFG_MEMGRAN) - 1)));
5110
5111	/*
5112	 * Allocate the chunk of memory (if any) not programmed into the
5113	 * bridge because of the round down.
5114	 */
5115	if (PCICFG_ROUND_DOWN((mem_answer + mem_alen), PCICFG_MEMGRAN)
5116	    != (mem_answer + mem_alen)) {
5117		DEBUG0("Need to allocate Memory round off chunk\n");
5118		bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
5119		req.ra_flags = NDI_RA_ALLOC_SPECIFIED;
5120		req.ra_addr = PCICFG_ROUND_DOWN((mem_answer + mem_alen),
5121		    PCICFG_MEMGRAN);
5122		req.ra_len =  (mem_answer + mem_alen) -
5123		    (PCICFG_ROUND_DOWN((mem_answer + mem_alen),
5124		    PCICFG_MEMGRAN));
5125
5126		(void) ndi_ra_alloc(new_child, &req,
5127		    &round_answer, &round_len,  NDI_RA_TYPE_MEM, NDI_RA_PASS);
5128	}
5129
5130	/*
5131	 * Program the I/O Space Base
5132	 */
5133	pci_config_put8(h, PCI_BCNF_IO_BASE_LOW,
5134	    PCICFG_HIBYTE(PCICFG_LOWORD(
5135	    PCICFG_LOADDR(io_answer))));
5136
5137	pci_config_put16(h, PCI_BCNF_IO_BASE_HI,
5138	    PCICFG_HIWORD(PCICFG_LOADDR(io_answer)));
5139
5140	/*
5141	 * Program the I/O Space Limit
5142	 */
5143	pci_config_put8(h, PCI_BCNF_IO_LIMIT_LOW,
5144	    PCICFG_HIBYTE(PCICFG_LOWORD(
5145	    PCICFG_LOADDR(PCICFG_ROUND_DOWN(io_answer + io_alen,
5146	    PCICFG_IOGRAN)))) - 1);
5147
5148	pci_config_put16(h, PCI_BCNF_IO_LIMIT_HI,
5149	    PCICFG_HIWORD(PCICFG_LOADDR(
5150	    PCICFG_ROUND_DOWN(io_answer + io_alen, PCICFG_IOGRAN)))
5151	    - 1);
5152
5153	/*
5154	 * Allocate the chunk of I/O (if any) not programmed into the
5155	 * bridge because of the round down.
5156	 */
5157	if (PCICFG_ROUND_DOWN((io_answer + io_alen), PCICFG_IOGRAN)
5158	    != (io_answer + io_alen)) {
5159		DEBUG0("Need to allocate I/O round off chunk\n");
5160		bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
5161		req.ra_flags = NDI_RA_ALLOC_SPECIFIED;
5162		req.ra_addr = PCICFG_ROUND_DOWN((io_answer + io_alen),
5163		    PCICFG_IOGRAN);
5164		req.ra_len =  (io_answer + io_alen) -
5165		    (PCICFG_ROUND_DOWN((io_answer + io_alen),
5166		    PCICFG_IOGRAN));
5167
5168		(void) ndi_ra_alloc(new_child, &req,
5169		    &round_answer, &round_len,  NDI_RA_TYPE_IO, NDI_RA_PASS);
5170	}
5171
5172	/*
5173	 * Setup "ranges" property before onlining the bridge.
5174	 */
5175	bzero((caddr_t)range, sizeof (pcicfg_range_t) * PCICFG_RANGE_LEN);
5176
5177	range[0].child_hi = range[0].parent_hi |= (PCI_REG_REL_M | PCI_ADDR_IO);
5178	range[0].child_lo = range[0].parent_lo = io_base;
5179	range[1].child_hi = range[1].parent_hi |=
5180	    (PCI_REG_REL_M | PCI_ADDR_MEM32);
5181	range[1].child_lo = range[1].parent_lo = mem_base;
5182
5183	range[0].size_lo = io_alen;
5184	if (pcicfg_update_ranges_prop(new_child, &range[0])) {
5185		DEBUG0("Failed to update ranges (io)\n");
5186		return (PCICFG_FAILURE);
5187	}
5188	range[1].size_lo = mem_alen;
5189	if (pcicfg_update_ranges_prop(new_child, &range[1])) {
5190		DEBUG0("Failed to update ranges (memory)\n");
5191		return (PCICFG_FAILURE);
5192	}
5193
5194	/*
5195	 * Clear status bits
5196	 */
5197	pci_config_put16(h, PCI_BCNF_SEC_STATUS, 0xffff);
5198
5199	/*
5200	 * Turn off prefetchable range
5201	 */
5202	pci_config_put32(h, PCI_BCNF_PF_BASE_LOW, 0x0000ffff);
5203	pci_config_put32(h, PCI_BCNF_PF_BASE_HIGH, 0xffffffff);
5204	pci_config_put32(h, PCI_BCNF_PF_LIMIT_HIGH, 0x0);
5205
5206	/*
5207	 * Needs to be set to this value
5208	 */
5209	pci_config_put8(h, PCI_CONF_ILINE, 0xf);
5210
5211	/* check our device_type as defined by Open Firmware */
5212	if (pcicfg_pcie_device_type(new_child, h) == DDI_SUCCESS)
5213		pcie_device_type = 1;
5214
5215	/*
5216	 * Set bus properties
5217	 */
5218	if (pcicfg_set_busnode_props(new_child, pcie_device_type,
5219	    (int)bus, (int)new_bus) != PCICFG_SUCCESS) {
5220		DEBUG0("Failed to set busnode props\n");
5221		return (PCICFG_FAILURE);
5222	}
5223
5224	(void) pcicfg_device_on(h);
5225
5226	if (is_pcie)
5227		(void) pcie_init_bus(new_child, 0, PCIE_BUS_FINAL);
5228	if (ndi_devi_online(new_child, NDI_NO_EVENT|NDI_CONFIG)
5229	    != NDI_SUCCESS) {
5230		DEBUG0("Unable to online bridge\n");
5231		return (PCICFG_FAILURE);
5232	}
5233
5234	DEBUG0("Bridge is ONLINE\n");
5235
5236	/*
5237	 * After a Reset, we need to wait 2^25 clock cycles before the
5238	 * first Configuration access.  The worst case is 33MHz, which
5239	 * is a 1 second wait.
5240	 */
5241	drv_usecwait(pcicfg_sec_reset_delay);
5242
5243	/*
5244	 * Probe all children devices
5245	 */
5246	DEBUG0("Bridge Programming Complete - probe children\n");
5247	ndi_devi_enter(new_child, &count);
5248	for (i = 0; ((i < PCICFG_MAX_DEVICE) && (ari_mode == B_FALSE));
5249	    i++) {
5250		for (j = 0; j < max_function; ) {
5251			if (ari_mode)
5252				trans_device = j >> 3;
5253			else
5254				trans_device = i;
5255
5256			if ((rval = pcicfg_fcode_probe(new_child,
5257			    new_bus, trans_device, (j & 7), highest_bus,
5258			    0, is_pcie))
5259			    != PCICFG_SUCCESS) {
5260				if (rval == PCICFG_NODEVICE) {
5261					DEBUG3("No Device at bus [0x%x]"
5262					    "device [0x%x] "
5263					    "func [0x%x]\n", new_bus,
5264					    trans_device, j & 7);
5265
5266					if (j)
5267						goto next;
5268				} else {
5269					DEBUG3("Failed to configure bus "
5270					    "[0x%x] device [0x%x] "
5271					    "func [0x%x]\n", new_bus,
5272					    trans_device, j & 7);
5273
5274					rval = PCICFG_FAILURE;
5275				}
5276				break;
5277			}
5278next:
5279			new_device = pcicfg_devi_find(new_child,
5280			    trans_device, (j & 7));
5281
5282			/*
5283			 * Determine if ARI Forwarding should be enabled.
5284			 */
5285			if (j == 0) {
5286				if (new_device == NULL)
5287					break;
5288
5289				if ((pcie_ari_supported(new_child) ==
5290				    PCIE_ARI_FORW_ENABLED) &&
5291				    (pcie_ari_device(new_device) ==
5292				    PCIE_ARI_DEVICE)) {
5293					if (pcie_ari_enable(new_child) ==
5294					    DDI_SUCCESS) {
5295						(void) ddi_prop_create(
5296						    DDI_DEV_T_NONE,
5297						    new_child,
5298						    DDI_PROP_CANSLEEP,
5299						    "ari-enabled", NULL, 0);
5300						ari_mode = B_TRUE;
5301						max_function =
5302						    PCICFG_MAX_ARI_FUNCTION;
5303					}
5304				}
5305			}
5306
5307			if (ari_mode == B_TRUE) {
5308				int next_function;
5309
5310				if (new_device == NULL)
5311					break;
5312
5313				if (pcie_ari_get_next_function(new_device,
5314				    &next_function) != DDI_SUCCESS)
5315					break;
5316
5317				j = next_function;
5318
5319				if (next_function == 0)
5320					break;
5321			} else
5322				j++;
5323		}
5324	}
5325
5326	ndi_devi_exit(new_child, count);
5327
5328	/* if empty topology underneath, it is still a success. */
5329	if (rval != PCICFG_FAILURE)
5330		rval = PCICFG_SUCCESS;
5331
5332	/*
5333	 * Offline the bridge to allow reprogramming of resources.
5334	 *
5335	 * This should always succeed since nobody else has started to
5336	 * use it yet, failing to detach the driver would indicate a bug.
5337	 * Also in that case it's better just panic than allowing the
5338	 * configurator to proceed with BAR reprogramming without bridge
5339	 * driver detached.
5340	 */
5341	VERIFY(ndi_devi_offline(new_child, NDI_NO_EVENT|NDI_UNCONFIG)
5342	    == NDI_SUCCESS);
5343	if (is_pcie)
5344		pcie_fini_bus(new_child, PCIE_BUS_INITIAL);
5345
5346	phdl.dip = new_child;
5347	phdl.memory_base = mem_answer;
5348	phdl.io_base = (uint32_t)io_answer;
5349	phdl.error = PCICFG_SUCCESS;    /* in case of empty child tree */
5350
5351	ndi_devi_enter(ddi_get_parent(new_child), &count);
5352	ddi_walk_devs(new_child, pcicfg_find_resource_end, (void *)&phdl);
5353	ndi_devi_exit(ddi_get_parent(new_child), count);
5354
5355	if (phdl.error != PCICFG_SUCCESS) {
5356		DEBUG0("Failure summing resources\n");
5357		return (PCICFG_FAILURE);
5358	}
5359
5360	num_slots = pcicfg_get_nslots(new_child, h);
5361	mem_end = PCICFG_ROUND_UP(phdl.memory_base, PCICFG_MEMGRAN);
5362	io_end = PCICFG_ROUND_UP(phdl.io_base, PCICFG_IOGRAN);
5363
5364	DEBUG3("Start of Unallocated Bridge(%d slots) Resources "
5365	    "Mem=0x%lx I/O=0x%lx\n", num_slots, mem_end, io_end);
5366
5367	/*
5368	 * Before probing the children we've allocated maximum MEM/IO
5369	 * resources from parent, and updated "available" property
5370	 * accordingly. Later we'll be giving up unused resources to
5371	 * the parent, thus we need to destroy "available" property
5372	 * here otherwise it will be out-of-sync with the actual free
5373	 * resources this bridge has. This property will be rebuilt below
5374	 * with the actual free resources reserved for hotplug slots
5375	 * (if any).
5376	 */
5377	(void) ndi_prop_remove(DDI_DEV_T_NONE, new_child, "available");
5378	/*
5379	 * if the bridge a slots, then preallocate. If not, assume static
5380	 * configuration. Also check for preallocation limits and spit
5381	 * warning messages appropriately (perhaps some can be in debug mode).
5382	 */
5383	if (num_slots) {
5384		pci_regspec_t reg;
5385		uint64_t mem_assigned = mem_end;
5386		uint64_t io_assigned = io_end;
5387		uint64_t mem_reqd = mem_answer + (num_slots *
5388		    pcicfg_slot_memsize);
5389		uint64_t io_reqd = io_answer + (num_slots *
5390		    pcicfg_slot_iosize);
5391		uint8_t highest_bus_reqd = new_bus + (num_slots *
5392		    pcicfg_slot_busnums);
5393#ifdef DEBUG
5394		if (mem_end > mem_reqd)
5395			DEBUG3("Memory space consumed by bridge"
5396			    " more than planned for %d slot(s)(%lx, %lx)",
5397			    num_slots, mem_answer, mem_end);
5398		if (io_end > io_reqd)
5399			DEBUG3("IO space consumed by bridge"
5400			    " more than planned for %d slot(s)(%lx, %lx)",
5401			    num_slots, io_answer, io_end);
5402		if (*highest_bus > highest_bus_reqd)
5403			DEBUG3("Buses consumed by bridge"
5404			    " more than planned for %d slot(s)(%x, %x)",
5405			    num_slots, new_bus, *highest_bus);
5406
5407		if (mem_reqd > (mem_answer + mem_alen))
5408			DEBUG3("Memory space required by bridge"
5409			    " more than available for %d slot(s)(%lx, %lx)",
5410			    num_slots, mem_answer, mem_end);
5411
5412		if (io_reqd > (io_answer + io_alen))
5413			DEBUG3("IO space required by bridge"
5414			    " more than available for %d slot(s)(%lx, %lx)",
5415			    num_slots, io_answer, io_end);
5416		if (highest_bus_reqd > max_bus)
5417			DEBUG3("Bus numbers required by bridge"
5418			    " more than available for %d slot(s)(%x, %x)",
5419			    num_slots, new_bus, *highest_bus);
5420#endif
5421		mem_end = MAX((MIN(mem_reqd, (mem_answer + mem_alen))),
5422		    mem_end);
5423		io_end = MAX((MIN(io_reqd, (io_answer + io_alen))), io_end);
5424		*highest_bus = MAX((MIN(highest_bus_reqd, max_bus)),
5425		    *highest_bus);
5426		DEBUG3("mem_end %lx, io_end %lx, highest_bus %x\n",
5427		    mem_end, io_end, *highest_bus);
5428
5429		mem_size = mem_end - mem_assigned;
5430		io_size = io_end - io_assigned;
5431
5432		reg.pci_phys_mid = reg.pci_size_hi = 0;
5433		if (io_size > 0) {
5434			reg.pci_phys_hi = (PCI_REG_REL_M | PCI_ADDR_IO);
5435			reg.pci_phys_low = io_assigned;
5436			reg.pci_size_low = io_size;
5437			if (pcicfg_update_available_prop(new_child, &reg)) {
5438				DEBUG0("Failed to update available prop "
5439				    "(io)\n");
5440				return (PCICFG_FAILURE);
5441			}
5442		}
5443		if (mem_size > 0) {
5444			reg.pci_phys_hi = (PCI_REG_REL_M | PCI_ADDR_MEM32);
5445			reg.pci_phys_low = mem_assigned;
5446			reg.pci_size_low = mem_size;
5447			if (pcicfg_update_available_prop(new_child, &reg)) {
5448				DEBUG0("Failed to update available prop "
5449				    "(memory)\n");
5450				return (PCICFG_FAILURE);
5451			}
5452		}
5453	}
5454
5455	/*
5456	 * Give back unused memory space to parent.
5457	 */
5458	(void) ndi_ra_free(ddi_get_parent(new_child),
5459	    mem_end, (mem_answer + mem_alen) - mem_end, NDI_RA_TYPE_MEM,
5460	    NDI_RA_PASS);
5461
5462	if (mem_end == mem_answer) {
5463		DEBUG0("No memory resources used\n");
5464		/*
5465		 * To prevent the bridge from forwarding any Memory
5466		 * transactions, the Memory Limit will be programmed
5467		 * with a smaller value than the Memory Base.
5468		 */
5469		pci_config_put16(h, PCI_BCNF_MEM_BASE, 0xffff);
5470		pci_config_put16(h, PCI_BCNF_MEM_LIMIT, 0);
5471
5472		mem_size = 0;
5473	} else {
5474		/*
5475		 * Reprogram the end of the memory.
5476		 */
5477		pci_config_put16(h, PCI_BCNF_MEM_LIMIT,
5478		    PCICFG_HIWORD(mem_end) - 1);
5479		mem_size = mem_end - mem_base;
5480	}
5481
5482	/*
5483	 * Give back unused io space to parent.
5484	 */
5485	(void) ndi_ra_free(ddi_get_parent(new_child),
5486	    io_end, (io_answer + io_alen) - io_end,
5487	    NDI_RA_TYPE_IO, NDI_RA_PASS);
5488
5489	if (io_end == io_answer) {
5490		DEBUG0("No IO Space resources used\n");
5491
5492		/*
5493		 * To prevent the bridge from forwarding any I/O
5494		 * transactions, the I/O Limit will be programmed
5495		 * with a smaller value than the I/O Base.
5496		 */
5497		pci_config_put8(h, PCI_BCNF_IO_LIMIT_LOW, 0);
5498		pci_config_put16(h, PCI_BCNF_IO_LIMIT_HI, 0);
5499		pci_config_put8(h, PCI_BCNF_IO_BASE_LOW, 0xff);
5500		pci_config_put16(h, PCI_BCNF_IO_BASE_HI, 0);
5501
5502		io_size = 0;
5503	} else {
5504		/*
5505		 * Reprogram the end of the io space.
5506		 */
5507		pci_config_put8(h, PCI_BCNF_IO_LIMIT_LOW,
5508		    PCICFG_HIBYTE(PCICFG_LOWORD(
5509		    PCICFG_LOADDR(io_end) - 1)));
5510
5511		pci_config_put16(h, PCI_BCNF_IO_LIMIT_HI,
5512		    PCICFG_HIWORD(PCICFG_LOADDR(io_end - 1)));
5513
5514		io_size = io_end - io_base;
5515	}
5516
5517	if ((max_bus - *highest_bus) > 0) {
5518		/*
5519		 * Give back unused bus numbers
5520		 */
5521		(void) ndi_ra_free(ddi_get_parent(new_child),
5522		    *highest_bus+1, max_bus - *highest_bus,
5523		    NDI_RA_TYPE_PCI_BUSNUM, NDI_RA_PASS);
5524	}
5525
5526	/*
5527	 * Set bus numbers to ranges encountered during scan
5528	 */
5529	pcicfg_set_bus_numbers(h, bus, new_bus, *highest_bus);
5530
5531	bus_range[0] = pci_config_get8(h, PCI_BCNF_SECBUS);
5532	bus_range[1] = pci_config_get8(h, PCI_BCNF_SUBBUS);
5533	DEBUG1("End of bridge probe: bus_range[0] =  %d\n", bus_range[0]);
5534	DEBUG1("End of bridge probe: bus_range[1] =  %d\n", bus_range[1]);
5535
5536	if (ndi_prop_update_int_array(DDI_DEV_T_NONE, new_child,
5537	    "bus-range", bus_range, 2) != DDI_SUCCESS) {
5538		DEBUG0("Failed to set bus-range property");
5539		return (PCICFG_FAILURE);
5540	}
5541
5542	/*
5543	 * Remove the ranges property if it exists since we will create
5544	 * a new one.
5545	 */
5546	(void) ndi_prop_remove(DDI_DEV_T_NONE, new_child, "ranges");
5547
5548	DEBUG2("Creating Ranges property - Mem Address %lx Mem Size %x\n",
5549	    mem_base, mem_size);
5550	DEBUG2("                         - I/O Address %lx I/O Size %x\n",
5551	    io_base, io_size);
5552
5553	bzero((caddr_t)range, sizeof (pcicfg_range_t) * PCICFG_RANGE_LEN);
5554
5555	range[0].child_hi = range[0].parent_hi |= (PCI_REG_REL_M | PCI_ADDR_IO);
5556	range[0].child_lo = range[0].parent_lo = io_base;
5557	range[1].child_hi = range[1].parent_hi |=
5558	    (PCI_REG_REL_M | PCI_ADDR_MEM32);
5559	range[1].child_lo = range[1].parent_lo = mem_base;
5560
5561	if (io_size > 0) {
5562		range[0].size_lo = io_size;
5563		if (pcicfg_update_ranges_prop(new_child, &range[0])) {
5564			DEBUG0("Failed to update ranges (io)\n");
5565			return (PCICFG_FAILURE);
5566		}
5567	}
5568	if (mem_size > 0) {
5569		range[1].size_lo = mem_size;
5570		if (pcicfg_update_ranges_prop(new_child, &range[1])) {
5571			DEBUG0("Failed to update ranges (memory)\n");
5572			return (PCICFG_FAILURE);
5573		}
5574	}
5575
5576	/*
5577	 * Remove the resource maps for the bridge since we no longer
5578	 * need them.  Note that the failure is ignored since the
5579	 * ndi_devi_offline above may have already taken care of it via
5580	 * driver detach.
5581	 * It has been checked that there are no other reasons for
5582	 * failure other than map itself being non-existent. So we are Ok.
5583	 */
5584	if (ndi_ra_map_destroy(new_child, NDI_RA_TYPE_MEM) == NDI_FAILURE) {
5585		/*EMPTY*/
5586		DEBUG0("Can not destroy resource map - NDI_RA_TYPE_MEM\n");
5587	}
5588
5589	if (ndi_ra_map_destroy(new_child, NDI_RA_TYPE_IO) == NDI_FAILURE) {
5590		/*EMPTY*/
5591		DEBUG0("Can not destroy resource map - NDI_RA_TYPE_IO\n");
5592	}
5593
5594	if (ndi_ra_map_destroy(new_child, NDI_RA_TYPE_PCI_BUSNUM)
5595	    == NDI_FAILURE) {
5596		/*EMPTY*/
5597		DEBUG0("Can't destroy resource map - NDI_RA_TYPE_PCI_BUSNUM\n");
5598	}
5599
5600	return (rval);
5601}
5602
5603/*
5604 * Return PCICFG_SUCCESS if device exists at the specified address.
5605 * Return PCICFG_NODEVICE is no device exists at the specified address.
5606 *
5607 */
5608int
5609pcicfg_config_setup(dev_info_t *dip, ddi_acc_handle_t *handle)
5610{
5611	caddr_t			virt;
5612	ddi_device_acc_attr_t	attr;
5613	int			status;
5614	int			rlen;
5615	pci_regspec_t		*reg;
5616	int			ret = DDI_SUCCESS;
5617	int16_t			tmp;
5618	/*
5619	 * flags = PCICFG_CONF_INDIRECT_MAP if configuration space is indirectly
5620	 * mapped, otherwise it is 0. "flags" is introduced in support of any
5621	 * non transparent bridges, where configuration space is indirectly
5622	 * mapped.
5623	 * Indirect mapping is always true on sun4v systems.
5624	 */
5625	int			flags = 0;
5626
5627
5628	/*
5629	 * Get the pci register spec from the node
5630	 */
5631	status = ddi_getlongprop(DDI_DEV_T_ANY,
5632	    dip, DDI_PROP_DONTPASS, "reg", (caddr_t)&reg, &rlen);
5633
5634	switch (status) {
5635		case DDI_PROP_SUCCESS:
5636		break;
5637		case DDI_PROP_NO_MEMORY:
5638			DEBUG0("reg present, but unable to get memory\n");
5639			return (PCICFG_FAILURE);
5640		default:
5641			DEBUG0("no reg property\n");
5642			return (PCICFG_FAILURE);
5643	}
5644
5645	if (pcicfg_indirect_map(dip) == DDI_SUCCESS)
5646		flags |= PCICFG_CONF_INDIRECT_MAP;
5647
5648	/*
5649	 * Map in configuration space (temporarily)
5650	 */
5651	attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
5652	attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
5653	attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
5654	attr.devacc_attr_access = DDI_CAUTIOUS_ACC;
5655
5656#ifdef	EFCODE21554
5657	if (ddi_regs_map_setup(dip, 0, &virt,
5658	    0, 0, &attr, handle) != DDI_SUCCESS)
5659#else
5660	if (pcicfg_map_phys(dip, reg, &virt, &attr, handle)
5661	    != DDI_SUCCESS)
5662#endif
5663	{
5664		DEBUG0("pcicfg_config_setup():"
5665		"Failed to setup config space\n");
5666
5667		kmem_free((caddr_t)reg, rlen);
5668		return (PCICFG_FAILURE);
5669	}
5670
5671	if (flags & PCICFG_CONF_INDIRECT_MAP) {
5672		/*
5673		 * need to use DDI interfaces as the conf space is
5674		 * cannot be directly accessed by the host.
5675		 */
5676		tmp = (int16_t)ddi_get16(*handle, (uint16_t *)virt);
5677	} else {
5678		ret = ddi_peek16(dip, (int16_t *)virt, &tmp);
5679	}
5680
5681	if (ret == DDI_SUCCESS) {
5682		if (tmp == -1) {
5683			DEBUG1("NO DEVICEFOUND, read %x\n", tmp);
5684			ret = PCICFG_NODEVICE;
5685		} else {
5686			/* XXX - Need to check why HV is returning 0 */
5687			if (tmp == 0) {
5688				DEBUG0("Device Not Ready yet ?");
5689				ret = PCICFG_NODEVICE;
5690			} else {
5691				DEBUG1("DEVICEFOUND, read %x\n", tmp);
5692				ret = PCICFG_SUCCESS;
5693			}
5694		}
5695	} else {
5696		DEBUG0("ddi_peek failed, must be NODEVICE\n");
5697		ret = PCICFG_NODEVICE;
5698	}
5699
5700	/*
5701	 * A bug in XMITS 3.0 causes us to miss the Master Abort Split
5702	 * Completion message.  The result is the error message being
5703	 * sent back as part of the config data.  If the first two words
5704	 * of the config space happen to be the same as the Master Abort
5705	 * message, then report back that there is no device there.
5706	 */
5707	if ((ret == PCICFG_SUCCESS) && !(flags & PCICFG_CONF_INDIRECT_MAP)) {
5708		int32_t	pcix_scm;
5709
5710#define		PCICFG_PCIX_SCM	0x10000004
5711
5712		pcix_scm = 0;
5713		(void) ddi_peek32(dip, (int32_t *)virt, &pcix_scm);
5714		if (pcix_scm == PCICFG_PCIX_SCM) {
5715			pcix_scm = 0;
5716			(void) ddi_peek32(dip,
5717			    (int32_t *)(virt + 4), &pcix_scm);
5718			if (pcix_scm == PCICFG_PCIX_SCM)
5719				ret = PCICFG_NODEVICE;
5720		}
5721	}
5722
5723	if (ret == PCICFG_NODEVICE)
5724#ifdef	EFCODE21554
5725		ddi_regs_map_free(handle);
5726#else
5727		pcicfg_unmap_phys(handle, reg);
5728#endif
5729
5730	kmem_free((caddr_t)reg, rlen);
5731
5732	return (ret);
5733
5734}
5735
5736static void
5737pcicfg_config_teardown(ddi_acc_handle_t *handle)
5738{
5739	(void) ddi_regs_map_free(handle);
5740}
5741
5742static int
5743pcicfg_add_config_reg(dev_info_t *dip,
5744	uint_t bus, uint_t device, uint_t func)
5745{
5746	int reg[10] = { PCI_ADDR_CONFIG, 0, 0, 0, 0};
5747
5748	reg[0] = PCICFG_MAKE_REG_HIGH(bus, device, func, 0);
5749
5750	return (ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
5751	    "reg", reg, 5));
5752}
5753
5754static int
5755pcicfg_dump_assigned(dev_info_t *dip)
5756{
5757	pci_regspec_t		*reg;
5758	int			length;
5759	int			rcount;
5760	int			i;
5761
5762	if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
5763	    DDI_PROP_DONTPASS, "assigned-addresses", (caddr_t)&reg,
5764	    &length) != DDI_PROP_SUCCESS) {
5765		DEBUG0("Failed to read assigned-addresses property\n");
5766		return (PCICFG_FAILURE);
5767	}
5768
5769	rcount = length / sizeof (pci_regspec_t);
5770	for (i = 0; i < rcount; i++) {
5771		DEBUG4("pcicfg_dump_assigned - size=%x low=%x mid=%x high=%x\n",
5772		    reg[i].pci_size_low, reg[i].pci_phys_low,
5773		    reg[i].pci_phys_mid, reg[i].pci_phys_hi);
5774	}
5775	/*
5776	 * Don't forget to free up memory from ddi_getlongprop
5777	 */
5778	kmem_free((caddr_t)reg, length);
5779
5780	return (PCICFG_SUCCESS);
5781}
5782
5783#ifdef PCICFG_INTERPRET_FCODE
5784static int
5785pcicfg_load_fcode(dev_info_t *dip, uint_t bus, uint_t device, uint_t func,
5786    uint16_t vendor_id, uint16_t device_id, uchar_t **fcode_addr,
5787    int *fcode_size, int rom_paddr, int rom_size)
5788{
5789	pci_regspec_t		p;
5790	int			pci_data;
5791	int			start_of_fcode;
5792	int			image_length;
5793	int			code_type;
5794	ddi_acc_handle_t	h;
5795	ddi_device_acc_attr_t	acc;
5796	uint8_t			*addr;
5797	int8_t			image_not_found, indicator;
5798	uint16_t		vendor_id_img, device_id_img;
5799	int16_t			rom_sig;
5800#ifdef DEBUG
5801	int i;
5802#endif
5803
5804	DEBUG4("pcicfg_load_fcode() - "
5805	    "bus %x device =%x func=%x rom_paddr=%lx\n",
5806	    bus, device, func, rom_paddr);
5807	DEBUG2("pcicfg_load_fcode() - vendor_id=%x device_id=%x\n",
5808	    vendor_id, device_id);
5809
5810	*fcode_size = 0;
5811	*fcode_addr = NULL;
5812
5813	acc.devacc_attr_version = DDI_DEVICE_ATTR_V0;
5814	acc.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
5815	acc.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
5816
5817	p.pci_phys_hi = PCI_ADDR_MEM32 | PCICFG_MAKE_REG_HIGH(bus, device,
5818	    func, PCI_CONF_ROM);
5819
5820	p.pci_phys_mid = 0;
5821	p.pci_phys_low = 0;
5822
5823	p.pci_size_low = rom_size;
5824	p.pci_size_hi = 0;
5825
5826	if (pcicfg_map_phys(dip, &p, (caddr_t *)&addr, &acc, &h)) {
5827		DEBUG1("Can Not map in ROM %x\n", p.pci_phys_low);
5828		return (PCICFG_FAILURE);
5829	}
5830
5831	/*
5832	 * Walk the ROM to find the proper image for this device.
5833	 */
5834	image_not_found = 1;
5835	while (image_not_found) {
5836		DEBUG1("Expansion ROM maps to %lx\n", addr);
5837
5838#ifdef DEBUG
5839		if (pcicfg_dump_fcode) {
5840			for (i = 0; i < 100; i++)
5841				DEBUG2("ROM 0x%x --> 0x%x\n", i,
5842				    ddi_get8(h, (uint8_t *)(addr + i)));
5843		}
5844#endif
5845
5846		/*
5847		 * Some device say they have an Expansion ROM, but do not, so
5848		 * for non-21554 devices use peek so we don't panic due to
5849		 * accessing non existent memory.
5850		 */
5851		if (pcicfg_indirect_map(dip) == DDI_SUCCESS) {
5852			rom_sig = ddi_get16(h,
5853			    (uint16_t *)(addr + PCI_ROM_SIGNATURE));
5854		} else {
5855			if (ddi_peek16(dip,
5856			    (int16_t *)(addr + PCI_ROM_SIGNATURE), &rom_sig)) {
5857				cmn_err(CE_WARN,
5858				    "PCI Expansion ROM is not accessible");
5859				pcicfg_unmap_phys(&h, &p);
5860				return (PCICFG_FAILURE);
5861			}
5862		}
5863
5864		/*
5865		 * Validate the ROM Signature.
5866		 */
5867		if ((uint16_t)rom_sig != 0xaa55) {
5868			DEBUG1("Invalid ROM Signature %x\n", (uint16_t)rom_sig);
5869			pcicfg_unmap_phys(&h, &p);
5870			return (PCICFG_FAILURE);
5871		}
5872
5873		DEBUG0("Valid ROM Signature Found\n");
5874
5875		start_of_fcode = ddi_get16(h, (uint16_t *)(addr + 2));
5876
5877		pci_data =  ddi_get16(h,
5878		    (uint16_t *)(addr + PCI_ROM_PCI_DATA_STRUCT_PTR));
5879
5880		DEBUG2("Pointer To PCI Data Structure %x %x\n", pci_data,
5881		    addr);
5882
5883		/*
5884		 * Validate the PCI Data Structure Signature.
5885		 * 0x52494350 = "PCIR"
5886		 */
5887
5888		if (ddi_get8(h, (uint8_t *)(addr + pci_data)) != 0x50) {
5889			DEBUG0("Invalid PCI Data Structure Signature\n");
5890			pcicfg_unmap_phys(&h, &p);
5891			return (PCICFG_FAILURE);
5892		}
5893
5894		if (ddi_get8(h, (uint8_t *)(addr + pci_data + 1)) != 0x43) {
5895			DEBUG0("Invalid PCI Data Structure Signature\n");
5896			pcicfg_unmap_phys(&h, &p);
5897			return (PCICFG_FAILURE);
5898		}
5899		if (ddi_get8(h, (uint8_t *)(addr + pci_data + 2)) != 0x49) {
5900			DEBUG0("Invalid PCI Data Structure Signature\n");
5901			pcicfg_unmap_phys(&h, &p);
5902			return (PCICFG_FAILURE);
5903		}
5904		if (ddi_get8(h, (uint8_t *)(addr + pci_data + 3)) != 0x52) {
5905			DEBUG0("Invalid PCI Data Structure Signature\n");
5906			pcicfg_unmap_phys(&h, &p);
5907			return (PCICFG_FAILURE);
5908		}
5909
5910		/*
5911		 * Is this image for this device?
5912		 */
5913		vendor_id_img = ddi_get16(h,
5914		    (uint16_t *)(addr + pci_data + PCI_PDS_VENDOR_ID));
5915		device_id_img = ddi_get16(h,
5916		    (uint16_t *)(addr + pci_data + PCI_PDS_DEVICE_ID));
5917
5918		DEBUG2("This image is for vendor_id=%x device_id=%x\n",
5919		    vendor_id_img, device_id_img);
5920
5921		code_type = ddi_get8(h, addr + pci_data + PCI_PDS_CODE_TYPE);
5922
5923		switch (code_type) {
5924		case PCI_PDS_CODE_TYPE_PCAT:
5925			DEBUG0("ROM is of x86/PC-AT Type\n");
5926			break;
5927		case PCI_PDS_CODE_TYPE_OPEN_FW:
5928			DEBUG0("ROM is of Open Firmware Type\n");
5929			break;
5930		default:
5931			DEBUG1("ROM is of Unknown Type 0x%x\n", code_type);
5932			break;
5933		}
5934
5935		if ((vendor_id_img != vendor_id) ||
5936		    (device_id_img != device_id) ||
5937		    (code_type != PCI_PDS_CODE_TYPE_OPEN_FW)) {
5938			DEBUG0("Firmware Image is not for this device..."
5939			    "goto next image\n");
5940			/*
5941			 * Read indicator byte to see if there is another
5942			 * image in the ROM
5943			 */
5944			indicator = ddi_get8(h,
5945			    (uint8_t *)(addr + pci_data + PCI_PDS_INDICATOR));
5946
5947			if (indicator != 1) {
5948				/*
5949				 * There is another image in the ROM.
5950				 */
5951				image_length = ddi_get16(h,  (uint16_t *)(addr +
5952				    pci_data + PCI_PDS_IMAGE_LENGTH)) * 512;
5953
5954				addr += image_length;
5955			} else {
5956				/*
5957				 * There are no more images.
5958				 */
5959				DEBUG0("There are no more images in the ROM\n");
5960				pcicfg_unmap_phys(&h, &p);
5961
5962				return (PCICFG_FAILURE);
5963			}
5964		} else {
5965			DEBUG0("Correct image was found\n");
5966			image_not_found = 0;  /* Image was found */
5967		}
5968	}
5969
5970	*fcode_size =  (ddi_get8(h, addr + start_of_fcode + 4) << 24) |
5971	    (ddi_get8(h, addr + start_of_fcode + 5) << 16) |
5972	    (ddi_get8(h, addr + start_of_fcode + 6) << 8) |
5973	    (ddi_get8(h, addr + start_of_fcode + 7));
5974
5975	DEBUG1("Fcode Size %x\n", *fcode_size);
5976
5977	/*
5978	 * Allocate page aligned buffer space
5979	 */
5980	*fcode_addr = kmem_zalloc(ptob(btopr(*fcode_size)), KM_SLEEP);
5981
5982	if (*fcode_addr == NULL) {
5983		DEBUG0("kmem_zalloc returned NULL\n");
5984		pcicfg_unmap_phys(&h, &p);
5985		return (PCICFG_FAILURE);
5986	}
5987
5988	DEBUG1("Fcode Addr %lx\n", *fcode_addr);
5989
5990	ddi_rep_get8(h, *fcode_addr, addr + start_of_fcode, *fcode_size,
5991	    DDI_DEV_AUTOINCR);
5992
5993	pcicfg_unmap_phys(&h, &p);
5994
5995	return (PCICFG_SUCCESS);
5996}
5997
5998static int
5999pcicfg_fcode_assign_bars(ddi_acc_handle_t h, dev_info_t *dip, uint_t bus,
6000    uint_t device, uint_t func, int32_t fc_request, pci_regspec_t *rom_regspec)
6001{
6002	/*
6003	 * Assign values to all BARs so that it is safe to turn on the
6004	 * device for accessing the fcode on the PROM. On successful
6005	 * exit from this function, "assigned-addresses" are created
6006	 * for all BARs and ROM BAR is enabled. Also, rom_regspec is
6007	 * filled with the values that can be used to free up this
6008	 * resource later.
6009	 */
6010	uint32_t request, hiword, size;
6011	pci_regspec_t phys_spec;
6012	ndi_ra_request_t req;
6013	uint64_t mem_answer, mem_alen;
6014	int i;
6015
6016	DEBUG1("pcicfg_fcode_assign_bars :%s\n", DEVI(dip)->devi_name);
6017
6018	/*
6019	 * Process the BARs.
6020	 */
6021	for (i = PCI_CONF_BASE0; i <= PCI_CONF_BASE5; ) {
6022		pci_config_put32(h, i, 0xffffffff);
6023		request = pci_config_get32(h, i);
6024		/*
6025		 * Check if implemented
6026		 */
6027		if (request == 0) {
6028			DEBUG1("pcicfg_fcode_assign_bars :"
6029			    "BASE register [0x%x] asks for 0(32)\n", i);
6030			i += 4;
6031			continue;
6032		}
6033		/*
6034		 * Build the phys_spec for this BAR
6035		 */
6036		hiword = PCICFG_MAKE_REG_HIGH(bus, device, func, i);
6037		size = (~(PCI_BASE_M_ADDR_M & request)) + 1;
6038
6039		DEBUG3("pcicfg_fcode_assign_bars :"
6040		    "BASE register [0x%x] asks for [0x%x]=[0x%x]\n",
6041		    i, request, size);
6042
6043		if ((PCI_BASE_SPACE_M & request) == PCI_BASE_SPACE_MEM) {
6044			if ((PCI_BASE_TYPE_M & request) == PCI_BASE_TYPE_MEM) {
6045				hiword |= PCI_ADDR_MEM32;
6046			} else if ((PCI_BASE_TYPE_M & request)
6047			    == PCI_BASE_TYPE_ALL) {
6048				hiword |= PCI_ADDR_MEM64;
6049			}
6050			if (request & PCI_BASE_PREF_M)
6051				hiword |= PCI_REG_PF_M;
6052		} else {
6053			hiword |= PCI_ADDR_IO;
6054		}
6055		phys_spec.pci_phys_hi = hiword;
6056		phys_spec.pci_phys_mid = 0;
6057		phys_spec.pci_phys_low = 0;
6058		phys_spec.pci_size_hi = 0;
6059		phys_spec.pci_size_low = size;
6060
6061		/*
6062		 * The following function
6063		 * - allocates address space
6064		 * - programs the BAR
6065		 * - adds an "assigned-addresses" property
6066		 */
6067		if (pcicfg_alloc_resource(dip, phys_spec)) {
6068			cmn_err(CE_WARN, "failed to allocate %d bytes"
6069			    " for dev %s BASE register [0x%x]\n",
6070			    size, DEVI(dip)->devi_name, i);
6071			goto failure;
6072		}
6073		if ((PCI_BASE_TYPE_M & request) == PCI_BASE_TYPE_ALL) {
6074			/*
6075			 * 64 bit, should be in memory space.
6076			 */
6077			i += 8;
6078		} else {
6079			/*
6080			 * 32 bit, either memory or I/O space.
6081			 */
6082			i += 4;
6083		}
6084	}
6085
6086	/*
6087	 * Handle ROM BAR. We do not use the common
6088	 * resource allocator function because we need to
6089	 * return reg spec to the caller.
6090	 */
6091	size = (~(PCI_BASE_ROM_ADDR_M & fc_request)) + 1;
6092
6093	DEBUG3("BASE register [0x%x] asks for "
6094	    "[0x%x]=[0x%x]\n", PCI_CONF_ROM, fc_request, size);
6095
6096	bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
6097
6098	req.ra_boundbase = 0;
6099	req.ra_boundlen = PCICFG_4GIG_LIMIT;
6100	req.ra_len = size;
6101	req.ra_flags = (NDI_RA_ALIGN_SIZE | NDI_RA_ALLOC_BOUNDED);
6102
6103	if (ndi_ra_alloc(ddi_get_parent(dip),
6104	    &req, &mem_answer, &mem_alen,
6105	    NDI_RA_TYPE_MEM, NDI_RA_PASS)) {
6106		cmn_err(CE_WARN, "failed to allocate %d bytes"
6107		    " for dev %s ROM BASE register\n",
6108		    size, DEVI(dip)->devi_name);
6109		goto failure;
6110	}
6111
6112	DEBUG3("ROM addr = [0x%x.%x] len [0x%x]\n",
6113	    PCICFG_HIADDR(mem_answer),
6114	    PCICFG_LOADDR(mem_answer), mem_alen);
6115
6116	/*
6117	 * Assign address space and enable ROM.
6118	 */
6119	pci_config_put32(h, PCI_CONF_ROM,
6120	    PCICFG_LOADDR(mem_answer) | PCI_BASE_ROM_ENABLE);
6121
6122	/*
6123	 * Add resource to assigned-addresses.
6124	 */
6125	phys_spec.pci_phys_hi = PCICFG_MAKE_REG_HIGH(bus, device, func, \
6126	    PCI_CONF_ROM) | PCI_ADDR_MEM32;
6127	if (fc_request & PCI_BASE_PREF_M)
6128		phys_spec.pci_phys_hi |= PCI_REG_PF_M;
6129	phys_spec.pci_phys_mid = 0;
6130	phys_spec.pci_phys_low = PCICFG_LOADDR(mem_answer);
6131	phys_spec.pci_size_hi = 0;
6132	phys_spec.pci_size_low = size;
6133
6134	if (pcicfg_update_assigned_prop(dip, &phys_spec)
6135	    != PCICFG_SUCCESS) {
6136		cmn_err(CE_WARN, "failed to update"
6137		    " assigned-address property for dev %s\n",
6138		    DEVI(dip)->devi_name);
6139		goto failure;
6140	}
6141	/*
6142	 * Copy out the reg spec.
6143	 */
6144	*rom_regspec = phys_spec;
6145
6146	return (PCICFG_SUCCESS);
6147
6148failure:
6149	/*
6150	 * We came in with no "assigned-addresses".
6151	 * Free up the resources we may have allocated.
6152	 */
6153	(void) pcicfg_free_device_resources(dip, 0);
6154
6155	return (PCICFG_FAILURE);
6156}
6157
6158#endif /* PCICFG_INTERPRET_FCODE */
6159
6160static int
6161pcicfg_free_all_resources(dev_info_t *dip)
6162{
6163	pci_regspec_t		*assigned;
6164	int			assigned_len;
6165	int			acount;
6166	int			i;
6167
6168	if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
6169	    DDI_PROP_DONTPASS, "assigned-addresses", (caddr_t)&assigned,
6170	    &assigned_len) != DDI_PROP_SUCCESS) {
6171		DEBUG0("Failed to read assigned-addresses property\n");
6172		return (PCICFG_FAILURE);
6173	}
6174
6175	acount = assigned_len / sizeof (pci_regspec_t);
6176
6177	for (i = 0; i < acount; i++) {
6178		if (pcicfg_free_resource(dip, assigned[i], 0)) {
6179			/*
6180			 * Dont forget to free mem from ddi_getlongprop
6181			 */
6182			kmem_free((caddr_t)assigned, assigned_len);
6183			return (PCICFG_FAILURE);
6184		}
6185	}
6186
6187	/*
6188	 * Don't forget to free up memory from ddi_getlongprop
6189	 */
6190	if (assigned_len)
6191		kmem_free((caddr_t)assigned, assigned_len);
6192
6193	return (PCICFG_SUCCESS);
6194}
6195static int
6196pcicfg_alloc_new_resources(dev_info_t *dip)
6197{
6198	pci_regspec_t		*assigned, *reg;
6199	int			assigned_len, reg_len;
6200	int			acount, rcount;
6201	int			i, j, alloc_size;
6202	boolean_t		alloc;
6203
6204	if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
6205	    DDI_PROP_DONTPASS, "reg", (caddr_t)&reg,
6206	    &reg_len) != DDI_PROP_SUCCESS) {
6207		DEBUG0("Failed to read reg property\n");
6208		return (PCICFG_FAILURE);
6209	}
6210	rcount = reg_len / sizeof (pci_regspec_t);
6211
6212	DEBUG2("pcicfg_alloc_new_resources() reg size=%x entries=%x\n",
6213	    reg_len, rcount);
6214
6215	if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
6216	    DDI_PROP_DONTPASS, "assigned-addresses", (caddr_t)&assigned,
6217	    &assigned_len) != DDI_PROP_SUCCESS) {
6218		acount = 0;
6219	} else {
6220		acount = assigned_len / sizeof (pci_regspec_t);
6221	}
6222
6223	DEBUG1("assigned-addresses property len=%x\n", acount);
6224
6225	/*
6226	 * For each address described by reg, search for it in the
6227	 * assigned-addresses property. If it does not exist, allocate
6228	 * resources for it. If it does exist, check the size in both.
6229	 * The size needs to be bigger of the two.
6230	 */
6231	for (i = 1; i < rcount; i++) {
6232		alloc = B_TRUE;
6233		alloc_size = reg[i].pci_size_low;
6234		for (j = 0; j < acount; j++) {
6235			if (assigned[j].pci_phys_hi == reg[i].pci_phys_hi) {
6236				/*
6237				 * There is an exact match. Check size.
6238				 */
6239				DEBUG1("pcicfg_alloc_new_resources "
6240				    "- %x - MATCH\n",
6241				    reg[i].pci_phys_hi);
6242
6243				if (reg[i].pci_size_low >
6244				    assigned[j].pci_size_low) {
6245					/*
6246					 * Fcode wants more.
6247					 */
6248					DEBUG3("pcicfg_alloc_new_resources"
6249					    " - %x - RESIZE"
6250					    " assigned 0x%x reg 0x%x\n",
6251					    assigned[j].pci_phys_hi,
6252					    assigned[j].pci_size_low,
6253					    reg[i].pci_size_low);
6254
6255					/*
6256					 * Free the old resource.
6257					 */
6258					(void) pcicfg_free_resource(dip,
6259					    assigned[j], 0);
6260				} else {
6261					DEBUG3("pcicfg_alloc_new_resources"
6262					    " - %x - ENOUGH"
6263					    " assigned 0x%x reg 0x%x\n",
6264					    assigned[j].pci_phys_hi,
6265					    assigned[j].pci_size_low,
6266					    reg[i].pci_size_low);
6267
6268					alloc = B_FALSE;
6269				}
6270				break;
6271			}
6272			/*
6273			 * Fcode may have set one or more of the
6274			 * NPT bits in phys.hi.
6275			 */
6276			if (PCI_REG_BDFR_G(assigned[j].pci_phys_hi) ==
6277			    PCI_REG_BDFR_G(reg[i].pci_phys_hi)) {
6278
6279				DEBUG2("pcicfg_alloc_new_resources "
6280				    "- PARTIAL MATCH assigned 0x%x "
6281				    "reg 0x%x\n", assigned[j].pci_phys_hi,
6282				    reg[i].pci_phys_hi);
6283				/*
6284				 * Changing the SS bits is an error
6285				 */
6286				if (PCI_REG_ADDR_G(
6287				    assigned[j].pci_phys_hi) !=
6288				    PCI_REG_ADDR_G(reg[i].pci_phys_hi)) {
6289
6290					DEBUG2("Fcode changing"
6291					    " SS bits of - 0x%x -"
6292					    " on %s\n", reg[i].pci_phys_hi,
6293					    DEVI(dip)->devi_name);
6294
6295				}
6296
6297
6298				/*
6299				 * We are going to allocate new resource.
6300				 * Free the old resource. Again, adjust
6301				 * the size to be safe.
6302				 */
6303				(void) pcicfg_free_resource(dip,
6304				    assigned[j], 0);
6305
6306				alloc_size = MAX(reg[i].pci_size_low,
6307				    assigned[j].pci_size_low);
6308
6309				break;
6310			}
6311		}
6312		/*
6313		 * We are allocating resources for one of three reasons -
6314		 * - Fcode wants a larger address space
6315		 * - Fcode has set changed/set n, p, t bits.
6316		 * - It is a new "reg", it should be only ROM bar, but
6317		 *   we don't do the checking.
6318		 */
6319		if (alloc == B_TRUE) {
6320			DEBUG1("pcicfg_alloc_new_resources : creating 0x%x\n",
6321			    reg[i].pci_phys_hi);
6322
6323			reg[i].pci_size_low = alloc_size;
6324			if (pcicfg_alloc_resource(dip, reg[i])) {
6325				/*
6326				 * Dont forget to free mem from
6327				 * ddi_getlongprop
6328				 */
6329				if (acount != 0)
6330					kmem_free((caddr_t)assigned,
6331					    assigned_len);
6332				kmem_free((caddr_t)reg, reg_len);
6333				return (PCICFG_FAILURE);
6334			}
6335		}
6336	}
6337
6338	/*
6339	 * Don't forget to free up memory from ddi_getlongprop
6340	 */
6341	if (acount != 0)
6342		kmem_free((caddr_t)assigned, assigned_len);
6343	kmem_free((caddr_t)reg, reg_len);
6344
6345	return (PCICFG_SUCCESS);
6346}
6347
6348static int
6349pcicfg_alloc_resource(dev_info_t *dip, pci_regspec_t phys_spec)
6350{
6351	uint64_t answer;
6352	uint64_t alen;
6353	int offset;
6354	pci_regspec_t config;
6355	caddr_t virt, v;
6356	ddi_device_acc_attr_t acc;
6357	ddi_acc_handle_t h;
6358	ndi_ra_request_t request;
6359	pci_regspec_t *assigned;
6360	int assigned_len, entries, i;
6361
6362	if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
6363	    DDI_PROP_DONTPASS, "assigned-addresses", (caddr_t)&assigned,
6364	    &assigned_len) == DDI_PROP_SUCCESS) {
6365		DEBUG0("pcicfg_alloc_resource - "
6366		    "searching assigned-addresses\n");
6367
6368		entries = assigned_len / (sizeof (pci_regspec_t));
6369
6370		/*
6371		 * Walk through the assigned-addresses entries. If there is
6372		 * a match, there is no need to allocate the resource.
6373		 */
6374		for (i = 0; i < entries; i++) {
6375			if (assigned[i].pci_phys_hi == phys_spec.pci_phys_hi) {
6376				DEBUG1("pcicfg_alloc_resource - MATCH %x\n",
6377				    assigned[i].pci_phys_hi);
6378				kmem_free(assigned, assigned_len);
6379				return (0);
6380			}
6381		}
6382		kmem_free(assigned, assigned_len);
6383	}
6384
6385	bzero((caddr_t)&request, sizeof (ndi_ra_request_t));
6386
6387	config.pci_phys_hi = PCI_CONF_ADDR_MASK & phys_spec.pci_phys_hi;
6388	config.pci_phys_hi &= ~PCI_REG_REG_M;
6389	config.pci_phys_mid = config.pci_phys_low = 0;
6390	config.pci_size_hi = config.pci_size_low = 0;
6391
6392	/*
6393	 * Map in configuration space (temporarily)
6394	 */
6395	acc.devacc_attr_version = DDI_DEVICE_ATTR_V0;
6396	acc.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
6397	acc.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
6398
6399	if (pcicfg_map_phys(dip, &config, &virt, &acc, &h)) {
6400		DEBUG0("Can not map in config space\n");
6401		return (1);
6402	}
6403
6404	request.ra_flags = NDI_RA_ALIGN_SIZE;
6405	request.ra_boundbase = 0;
6406	request.ra_boundlen = PCICFG_4GIG_LIMIT;
6407	/*
6408	 * Use size stored in phys_spec parameter.
6409	 */
6410	request.ra_len = phys_spec.pci_size_low;
6411
6412	offset = PCI_REG_REG_G(phys_spec.pci_phys_hi);
6413
6414	v = virt + offset;
6415
6416	if (PCI_REG_REG_G(phys_spec.pci_phys_hi) == PCI_CONF_ROM) {
6417
6418		request.ra_flags |= NDI_RA_ALLOC_BOUNDED;
6419
6420		/* allocate memory space from the allocator */
6421
6422		if (ndi_ra_alloc(ddi_get_parent(dip),
6423		    &request, &answer, &alen,
6424		    NDI_RA_TYPE_MEM, NDI_RA_PASS)
6425		    != NDI_SUCCESS) {
6426			DEBUG0("(ROM)Failed to allocate 32b mem");
6427			pcicfg_unmap_phys(&h, &config);
6428			return (1);
6429		}
6430		DEBUG3("ROM addr = [0x%x.%x] len [0x%x]\n",
6431		    PCICFG_HIADDR(answer),
6432		    PCICFG_LOADDR(answer),
6433		    alen);
6434
6435		/* program the low word */
6436
6437		ddi_put32(h, (uint32_t *)v, (uint32_t)PCICFG_LOADDR(answer));
6438
6439		phys_spec.pci_phys_low = PCICFG_LOADDR(answer);
6440		phys_spec.pci_phys_mid = PCICFG_HIADDR(answer);
6441	} else {
6442
6443		switch (PCI_REG_ADDR_G(phys_spec.pci_phys_hi)) {
6444		case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
6445			request.ra_flags &= ~NDI_RA_ALLOC_BOUNDED;
6446			/* allocate memory space from the allocator */
6447			if (ndi_ra_alloc(ddi_get_parent(dip),
6448			    &request, &answer, &alen,
6449			    NDI_RA_TYPE_MEM, NDI_RA_PASS)
6450			    != NDI_SUCCESS) {
6451				DEBUG0("Failed to allocate 64b mem\n");
6452				pcicfg_unmap_phys(&h, &config);
6453				return (1);
6454			}
6455			DEBUG3("64 addr = [0x%x.%x] len [0x%x]\n",
6456			    PCICFG_HIADDR(answer),
6457			    PCICFG_LOADDR(answer),
6458			    alen);
6459
6460			/* program the low word */
6461
6462			ddi_put32(h, (uint32_t *)v,
6463			    (uint32_t)PCICFG_LOADDR(answer));
6464
6465			/* program the high word with value zero */
6466			v += 4;
6467			ddi_put32(h, (uint32_t *)v,
6468			    (uint32_t)PCICFG_HIADDR(answer));
6469
6470			phys_spec.pci_phys_low = PCICFG_LOADDR(answer);
6471			phys_spec.pci_phys_mid = PCICFG_HIADDR(answer);
6472			/*
6473			 * currently support 32b address space
6474			 * assignments only.
6475			 */
6476			phys_spec.pci_phys_hi ^= PCI_ADDR_MEM64 ^
6477			    PCI_ADDR_MEM32;
6478
6479			break;
6480
6481		case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
6482			request.ra_flags |= NDI_RA_ALLOC_BOUNDED;
6483			/* allocate memory space from the allocator */
6484			if (ndi_ra_alloc(ddi_get_parent(dip),
6485			    &request, &answer, &alen,
6486			    NDI_RA_TYPE_MEM, NDI_RA_PASS)
6487			    != NDI_SUCCESS) {
6488				DEBUG0("Failed to allocate 32b mem\n");
6489				pcicfg_unmap_phys(&h, &config);
6490				return (1);
6491			}
6492
6493			DEBUG3("32 addr = [0x%x.%x] len [0x%x]\n",
6494			    PCICFG_HIADDR(answer),
6495			    PCICFG_LOADDR(answer),
6496			    alen);
6497
6498			/* program the low word */
6499
6500			ddi_put32(h, (uint32_t *)v,
6501			    (uint32_t)PCICFG_LOADDR(answer));
6502
6503			phys_spec.pci_phys_low = PCICFG_LOADDR(answer);
6504
6505			break;
6506		case PCI_REG_ADDR_G(PCI_ADDR_IO):
6507			/* allocate I/O space from the allocator */
6508			request.ra_flags |= NDI_RA_ALLOC_BOUNDED;
6509			if (ndi_ra_alloc(ddi_get_parent(dip),
6510			    &request, &answer, &alen,
6511			    NDI_RA_TYPE_IO, NDI_RA_PASS)
6512			    != NDI_SUCCESS) {
6513				DEBUG0("Failed to allocate I/O\n");
6514				pcicfg_unmap_phys(&h, &config);
6515				return (1);
6516			}
6517			DEBUG3("I/O addr = [0x%x.%x] len [0x%x]\n",
6518			    PCICFG_HIADDR(answer),
6519			    PCICFG_LOADDR(answer),
6520			    alen);
6521
6522			ddi_put32(h, (uint32_t *)v,
6523			    (uint32_t)PCICFG_LOADDR(answer));
6524
6525			phys_spec.pci_phys_low = PCICFG_LOADDR(answer);
6526
6527			break;
6528		default:
6529			DEBUG0("Unknown register type\n");
6530			pcicfg_unmap_phys(&h, &config);
6531			return (1);
6532		} /* switch */
6533	}
6534
6535	/*
6536	 * Now that memory locations are assigned,
6537	 * update the assigned address property.
6538	 */
6539
6540	DEBUG1("updating assigned-addresss for %x\n",  phys_spec.pci_phys_hi);
6541
6542	if (pcicfg_update_assigned_prop(dip, &phys_spec)) {
6543		pcicfg_unmap_phys(&h, &config);
6544		return (1);
6545	}
6546
6547	pcicfg_unmap_phys(&h, &config);
6548
6549	return (0);
6550}
6551
6552static int
6553pcicfg_free_resource(dev_info_t *dip, pci_regspec_t phys_spec,
6554    pcicfg_flags_t flags)
6555{
6556	int offset;
6557	pci_regspec_t config;
6558	caddr_t virt, v;
6559	ddi_device_acc_attr_t acc;
6560	ddi_acc_handle_t h;
6561	ndi_ra_request_t request;
6562	int l;
6563
6564	bzero((caddr_t)&request, sizeof (ndi_ra_request_t));
6565
6566	config.pci_phys_hi = PCI_CONF_ADDR_MASK & phys_spec.pci_phys_hi;
6567	config.pci_phys_hi &= ~PCI_REG_REG_M;
6568	config.pci_phys_mid = config.pci_phys_low = 0;
6569	config.pci_size_hi = config.pci_size_low = 0;
6570
6571	/*
6572	 * Map in configuration space (temporarily)
6573	 */
6574	acc.devacc_attr_version = DDI_DEVICE_ATTR_V0;
6575	acc.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
6576	acc.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
6577
6578	if (pcicfg_map_phys(dip, &config, &virt, &acc, &h)) {
6579		DEBUG0("Can not map in config space\n");
6580		return (1);
6581	}
6582
6583	offset = PCI_REG_REG_G(phys_spec.pci_phys_hi);
6584
6585	v = virt + offset;
6586
6587	/*
6588	 * Use size stored in phys_spec parameter.
6589	 */
6590	l = phys_spec.pci_size_low;
6591
6592	if (PCI_REG_REG_G(phys_spec.pci_phys_hi) == PCI_CONF_ROM) {
6593
6594		/* free memory back to the allocator */
6595		if (ndi_ra_free(ddi_get_parent(dip), phys_spec.pci_phys_low,
6596		    l, NDI_RA_TYPE_MEM, NDI_RA_PASS) != NDI_SUCCESS) {
6597			DEBUG0("(ROM)Can not free 32b mem");
6598			pcicfg_unmap_phys(&h, &config);
6599			return (1);
6600		}
6601
6602		/* Unmap the BAR by writing a zero */
6603
6604		if ((flags & PCICFG_FLAG_READ_ONLY) == 0)
6605			ddi_put32(h, (uint32_t *)v, (uint32_t)0);
6606	} else {
6607
6608		switch (PCI_REG_ADDR_G(phys_spec.pci_phys_hi)) {
6609
6610		case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
6611		case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
6612			/* free memory back to the allocator */
6613			if (ndi_ra_free(ddi_get_parent(dip),
6614			    PCICFG_LADDR(phys_spec.pci_phys_low,
6615			    phys_spec.pci_phys_mid),
6616			    l, NDI_RA_TYPE_MEM,
6617			    NDI_RA_PASS) != NDI_SUCCESS) {
6618				DEBUG0("Cannot free mem");
6619				pcicfg_unmap_phys(&h, &config);
6620				return (1);
6621			}
6622			break;
6623
6624		case PCI_REG_ADDR_G(PCI_ADDR_IO):
6625			/* free I/O space back to the allocator */
6626			if (ndi_ra_free(ddi_get_parent(dip),
6627			    phys_spec.pci_phys_low,
6628			    l, NDI_RA_TYPE_IO,
6629			    NDI_RA_PASS) != NDI_SUCCESS) {
6630				DEBUG0("Can not free I/O space");
6631				pcicfg_unmap_phys(&h, &config);
6632				return (1);
6633			}
6634			break;
6635
6636		default:
6637			DEBUG0("Unknown register type\n");
6638			pcicfg_unmap_phys(&h, &config);
6639			return (1);
6640		} /* switch */
6641	}
6642
6643	/*
6644	 * Now that memory locations are assigned,
6645	 * update the assigned address property.
6646	 */
6647
6648	DEBUG1("updating assigned-addresss for %x\n", phys_spec.pci_phys_hi);
6649
6650	if (pcicfg_remove_assigned_prop(dip, &phys_spec)) {
6651		pcicfg_unmap_phys(&h, &config);
6652		return (1);
6653	}
6654
6655	pcicfg_unmap_phys(&h, &config);
6656
6657	return (0);
6658}
6659
6660static int
6661pcicfg_remove_assigned_prop(dev_info_t *dip, pci_regspec_t *oldone)
6662{
6663	int		alen, num_entries, i;
6664	pci_regspec_t	*assigned, *assigned_copy;
6665	uint_t		status;
6666
6667	status = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
6668	    "assigned-addresses", (caddr_t)&assigned, &alen);
6669	switch (status) {
6670		case DDI_PROP_SUCCESS:
6671		break;
6672		case DDI_PROP_NO_MEMORY:
6673			DEBUG0("no memory for assigned-addresses property\n");
6674			return (1);
6675		default:
6676			DEBUG0("assigned-addresses property does not exist\n");
6677			return (0);
6678	}
6679
6680	/*
6681	 * Make a copy of old assigned-addresses property.
6682	 */
6683	assigned_copy = kmem_alloc(alen, KM_SLEEP);
6684	bcopy(assigned, assigned_copy, alen);
6685
6686	status = ndi_prop_remove(DDI_DEV_T_NONE, dip, "assigned-addresses");
6687
6688	if (status != DDI_PROP_SUCCESS) {
6689		/*
6690		 * If "assigned-addresses" is retrieved from PROM, the
6691		 * ndi_prop_remove() will fail.
6692		 */
6693		DEBUG1("pcicfg_remove_assigned_prop: 0x%x not removed\n",
6694		    oldone->pci_phys_hi);
6695
6696		/*
6697		 * Free up allocated memory
6698		 */
6699		kmem_free(assigned_copy, alen);
6700		kmem_free((caddr_t)assigned, alen);
6701
6702		return (0);
6703	}
6704
6705	num_entries = alen / sizeof (pci_regspec_t);
6706
6707	/*
6708	 * Rebuild the assigned-addresses property.
6709	 */
6710	for (i = 0; i < num_entries; i++) {
6711		if (assigned_copy[i].pci_phys_hi != oldone->pci_phys_hi) {
6712			(void) pcicfg_update_assigned_prop(dip,
6713			    &assigned_copy[i]);
6714		}
6715	}
6716
6717	/*
6718	 * Free the copy of the original assigned-addresses.
6719	 */
6720	kmem_free(assigned_copy, alen);
6721
6722	/*
6723	 * Don't forget to free up memory from ddi_getlongprop
6724	 */
6725	kmem_free((caddr_t)assigned, alen);
6726
6727	return (0);
6728}
6729
6730static int
6731pcicfg_map_phys(dev_info_t *dip, pci_regspec_t *phys_spec,
6732	caddr_t *addrp, ddi_device_acc_attr_t *accattrp,
6733	ddi_acc_handle_t *handlep)
6734{
6735	ddi_map_req_t mr;
6736	ddi_acc_hdl_t *hp;
6737	int result;
6738
6739	*handlep = impl_acc_hdl_alloc(KM_SLEEP, NULL);
6740	hp = impl_acc_hdl_get(*handlep);
6741	hp->ah_vers = VERS_ACCHDL;
6742	hp->ah_dip = dip;
6743	hp->ah_rnumber = 0;
6744	hp->ah_offset = 0;
6745	hp->ah_len = 0;
6746	hp->ah_acc = *accattrp;
6747
6748	mr.map_op = DDI_MO_MAP_LOCKED;
6749	mr.map_type = DDI_MT_REGSPEC;
6750	mr.map_obj.rp = (struct regspec *)phys_spec;
6751	mr.map_prot = PROT_READ | PROT_WRITE;
6752	mr.map_flags = DDI_MF_KERNEL_MAPPING;
6753	mr.map_handlep = hp;
6754	mr.map_vers = DDI_MAP_VERSION;
6755
6756	result = ddi_map(dip, &mr, 0, 0, addrp);
6757
6758	if (result != DDI_SUCCESS) {
6759		impl_acc_hdl_free(*handlep);
6760		*handlep = (ddi_acc_handle_t)NULL;
6761	} else {
6762		hp->ah_addr = *addrp;
6763	}
6764
6765	return (result);
6766}
6767
6768void
6769pcicfg_unmap_phys(ddi_acc_handle_t *handlep,  pci_regspec_t *ph)
6770{
6771	ddi_map_req_t mr;
6772	ddi_acc_hdl_t *hp;
6773
6774	hp = impl_acc_hdl_get(*handlep);
6775	ASSERT(hp);
6776
6777	mr.map_op = DDI_MO_UNMAP;
6778	mr.map_type = DDI_MT_REGSPEC;
6779	mr.map_obj.rp = (struct regspec *)ph;
6780	mr.map_prot = PROT_READ | PROT_WRITE;
6781	mr.map_flags = DDI_MF_KERNEL_MAPPING;
6782	mr.map_handlep = hp;
6783	mr.map_vers = DDI_MAP_VERSION;
6784
6785	(void) ddi_map(hp->ah_dip, &mr, hp->ah_offset,
6786	    hp->ah_len, &hp->ah_addr);
6787
6788	impl_acc_hdl_free(*handlep);
6789	*handlep = (ddi_acc_handle_t)NULL;
6790}
6791
6792static int
6793pcicfg_ari_configure(dev_info_t *dip)
6794{
6795	if (pcie_ari_supported(dip) == PCIE_ARI_FORW_NOT_SUPPORTED)
6796		return (DDI_FAILURE);
6797
6798	/*
6799	 * Until we have resource balancing, dynamically configure
6800	 * ARI functions without firmware assistamce.
6801	 */
6802	return (DDI_FAILURE);
6803}
6804
6805#ifdef DEBUG
6806static void
6807debug(char *fmt, uintptr_t a1, uintptr_t a2, uintptr_t a3,
6808	uintptr_t a4, uintptr_t a5)
6809{
6810	if (pcicfg_debug == 1) {
6811		prom_printf("pcicfg: ");
6812		prom_printf(fmt, a1, a2, a3, a4, a5);
6813	} else
6814		if (pcicfg_debug)
6815			cmn_err(CE_CONT, fmt, a1, a2, a3, a4, a5);
6816}
6817#endif
6818
6819/*
6820 * Return true if the devinfo node is in a PCI Express hierarchy.
6821 */
6822static boolean_t
6823is_pcie_fabric(dev_info_t *dip)
6824{
6825	dev_info_t *root = ddi_root_node();
6826	dev_info_t *pdip;
6827	boolean_t found = B_FALSE;
6828	char *bus;
6829
6830	/*
6831	 * Does this device reside in a pcie fabric ?
6832	 */
6833	for (pdip = dip; pdip && (pdip != root) && !found;
6834	    pdip = ddi_get_parent(pdip)) {
6835		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip,
6836		    DDI_PROP_DONTPASS, "device_type", &bus) !=
6837		    DDI_PROP_SUCCESS)
6838			break;
6839
6840		if (strcmp(bus, "pciex") == 0)
6841			found = B_TRUE;
6842
6843		ddi_prop_free(bus);
6844	}
6845
6846	return (found);
6847}
6848