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