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.
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.
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]
22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
26 * PCI configurator (pcicfg)
29 #include <sys/isa_defs.h>
33 #include <sys/debug.h>
34 #include <sys/modctl.h>
35 #include <sys/autoconf.h>
36 #include <sys/hwconf.h>
37 #include <sys/ddi_impldefs.h>
38 #include <sys/fcode.h>
41 #include <sys/pcie_impl.h>
43 #include <sys/sunddi.h>
44 #include <sys/sunndi.h>
45 #include <sys/pci_cap.h>
46 #include <sys/hotplug/pci/pcicfg.h>
47 #include <sys/ndi_impldefs.h>
48 #include <sys/pci_cfgacc.h>
50 #define PCICFG_DEVICE_TYPE_PCI 1
51 #define PCICFG_DEVICE_TYPE_PCIE 2
53 #define EFCODE21554 /* changes for supporting 21554 */
55 static int pcicfg_alloc_resource(dev_info_t
*, pci_regspec_t
);
56 static int pcicfg_free_resource(dev_info_t
*, pci_regspec_t
, pcicfg_flags_t
);
57 static int pcicfg_remove_assigned_prop(dev_info_t
*, pci_regspec_t
*);
59 #ifdef PCICFG_INTERPRET_FCODE
60 static int pcicfg_fcode_assign_bars(ddi_acc_handle_t
, dev_info_t
*,
61 uint_t
, uint_t
, uint_t
, int32_t, pci_regspec_t
*);
62 #endif /* PCICFG_INTERPRET_FCODE */
65 * ************************************************************************
66 * *** Implementation specific local data structures/definitions. ***
67 * ************************************************************************
70 static int pcicfg_start_devno
= 0; /* for Debug only */
72 #define PCICFG_MAX_DEVICE 32
73 #define PCICFG_MAX_FUNCTION 8
74 #define PCICFG_MAX_ARI_FUNCTION 256
75 #define PCICFG_MAX_REGISTER 64
76 #define PCICFG_MAX_BUS_DEPTH 255
78 #define PCICFG_NODEVICE 42
79 #define PCICFG_NOMEMORY 43
80 #define PCICFG_NOMULTI 44
82 #define PCICFG_HIADDR(n) ((uint32_t)(((uint64_t)(n) & 0xFFFFFFFF00000000)>> 32))
83 #define PCICFG_LOADDR(n) ((uint32_t)((uint64_t)(n) & 0x00000000FFFFFFFF))
84 #define PCICFG_LADDR(lo, hi) (((uint64_t)(hi) << 32) | (uint32_t)(lo))
86 #define PCICFG_HIWORD(n) ((uint16_t)(((uint32_t)(n) & 0xFFFF0000)>> 16))
87 #define PCICFG_LOWORD(n) ((uint16_t)((uint32_t)(n) & 0x0000FFFF))
88 #define PCICFG_HIBYTE(n) ((uint8_t)(((uint16_t)(n) & 0xFF00)>> 8))
89 #define PCICFG_LOBYTE(n) ((uint8_t)((uint16_t)(n) & 0x00FF))
91 #define PCICFG_ROUND_UP(addr, gran) ((uintptr_t)((gran+addr-1)&(~(gran-1))))
92 #define PCICFG_ROUND_DOWN(addr, gran) ((uintptr_t)((addr) & ~(gran-1)))
94 #define PCICFG_MEMGRAN 0x100000
95 #define PCICFG_IOGRAN 0x1000
96 #define PCICFG_4GIG_LIMIT 0xFFFFFFFFUL
98 #define PCICFG_MEM_MULT 4
99 #define PCICFG_IO_MULT 4
100 #define PCICFG_RANGE_LEN 2 /* Number of range entries */
102 static int pcicfg_slot_busnums
= 8;
103 static int pcicfg_slot_memsize
= 32 * PCICFG_MEMGRAN
; /* 32MB per slot */
104 static int pcicfg_slot_iosize
= 16 * PCICFG_IOGRAN
; /* 64K per slot */
105 static int pcicfg_chassis_per_tree
= 1;
106 static int pcicfg_sec_reset_delay
= 1000000;
109 * The following typedef is used to represent a
110 * 1275 "bus-range" property of a PCI Bus node.
111 * DAF - should be in generic include file...
114 typedef struct pcicfg_bus_range
{
117 } pcicfg_bus_range_t
;
119 typedef struct pcicfg_range
{
132 typedef struct hole hole_t
;
140 typedef struct pcicfg_phdl pcicfg_phdl_t
;
144 dev_info_t
*dip
; /* Associated with the attach point */
147 uint64_t memory_base
; /* Memory base for this attach point */
148 uint64_t memory_last
;
150 uint32_t io_base
; /* I/O base for this attach point */
155 uint_t highest_bus
; /* Highest bus seen on the probe */
157 hole_t mem_hole
; /* Memory hole linked list. */
158 hole_t io_hole
; /* IO hole linked list */
160 ndi_ra_request_t mem_req
; /* allocator request for memory */
161 ndi_ra_request_t io_req
; /* allocator request for I/O */
164 struct pcicfg_standard_prop_entry
{
166 uint_t config_offset
;
171 struct pcicfg_name_entry
{
176 struct pcicfg_find_ctrl
{
182 typedef struct pcicfg_err_regs
{
187 uint16_t pcie_cap_off
;
191 * List of Indirect Config Map Devices. At least the intent of the
192 * design is to look for a device in this list during the configure
193 * operation, and if the device is listed here, then it is a nontransparent
194 * bridge, hence load the driver and avail the config map services from
195 * the driver. Class and Subclass should be as defined in the PCI specs
196 * ie. class is 0x6, and subclass is 0x9.
199 uint8_t mem_range_bar_offset
;
200 uint8_t io_range_bar_offset
;
201 uint8_t prefetch_mem_range_bar_offset
;
202 } pcicfg_indirect_map_devs
[] = {
203 PCI_CONF_BASE3
, PCI_CONF_BASE2
, PCI_CONF_BASE3
,
207 #define PCICFG_MAKE_REG_HIGH(busnum, devnum, funcnum, register)\
209 ((ulong_t)(busnum & 0xff) << 16) |\
210 ((ulong_t)(devnum & 0x1f) << 11) |\
211 ((ulong_t)(funcnum & 0x7) << 8) |\
212 ((ulong_t)(register & 0x3f)))
218 extern void prom_printf(const char *, ...);
221 * Following values are defined for this debug flag.
223 * 1 = dump configuration header only.
224 * 2 = dump generic debug data only (no config header dumped)
225 * 3 = dump everything (both 1 and 2)
227 int pcicfg_debug
= 0;
228 int pcicfg_dump_fcode
= 0;
230 static void debug(char *, uintptr_t, uintptr_t,
231 uintptr_t, uintptr_t, uintptr_t);
234 debug(fmt, 0, 0, 0, 0, 0);
235 #define DEBUG1(fmt, a1)\
236 debug(fmt, (uintptr_t)(a1), 0, 0, 0, 0);
237 #define DEBUG2(fmt, a1, a2)\
238 debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2), 0, 0, 0);
239 #define DEBUG3(fmt, a1, a2, a3)\
240 debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2),\
241 (uintptr_t)(a3), 0, 0);
242 #define DEBUG4(fmt, a1, a2, a3, a4)\
243 debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2),\
244 (uintptr_t)(a3), (uintptr_t)(a4), 0);
247 #define DEBUG1(fmt, a1)
248 #define DEBUG2(fmt, a1, a2)
249 #define DEBUG3(fmt, a1, a2, a3)
250 #define DEBUG4(fmt, a1, a2, a3, a4)
253 #ifdef PCICFG_INTERPRET_FCODE
254 int pcicfg_dont_interpret
= 0;
256 int pcicfg_dont_interpret
= 1;
260 * forward declarations for routines defined in this module (called here)
263 static int pcicfg_add_config_reg(dev_info_t
*,
264 uint_t
, uint_t
, uint_t
);
265 static int pcicfg_probe_children(dev_info_t
*, uint_t
, uint_t
, uint_t
,
266 uint_t
*, pcicfg_flags_t
, boolean_t
);
268 #ifdef PCICFG_INTERPRET_FCODE
269 static int pcicfg_load_fcode(dev_info_t
*, uint_t
, uint_t
, uint_t
,
270 uint16_t, uint16_t, uchar_t
**, int *, int, int);
273 static int pcicfg_fcode_probe(dev_info_t
*, uint_t
, uint_t
, uint_t
,
274 uint_t
*, pcicfg_flags_t
, boolean_t
);
275 static int pcicfg_probe_bridge(dev_info_t
*, ddi_acc_handle_t
, uint_t
,
276 uint_t
*, boolean_t
);
277 static int pcicfg_free_all_resources(dev_info_t
*);
278 static int pcicfg_alloc_new_resources(dev_info_t
*);
279 static int pcicfg_match_dev(dev_info_t
*, void *);
280 static dev_info_t
*pcicfg_devi_find(dev_info_t
*, uint_t
, uint_t
);
281 static pcicfg_phdl_t
*pcicfg_find_phdl(dev_info_t
*);
282 static pcicfg_phdl_t
*pcicfg_create_phdl(dev_info_t
*);
283 static int pcicfg_destroy_phdl(dev_info_t
*);
284 static int pcicfg_sum_resources(dev_info_t
*, void *);
285 static int pcicfg_find_resource_end(dev_info_t
*, void *);
286 static int pcicfg_allocate_chunk(dev_info_t
*);
287 static int pcicfg_program_ap(dev_info_t
*);
288 static int pcicfg_device_assign(dev_info_t
*);
289 static int pcicfg_bridge_assign(dev_info_t
*, void *);
290 static int pcicfg_device_assign_readonly(dev_info_t
*);
291 static int pcicfg_free_resources(dev_info_t
*, pcicfg_flags_t
);
292 static void pcicfg_setup_bridge(pcicfg_phdl_t
*, ddi_acc_handle_t
,
294 static void pcicfg_update_bridge(pcicfg_phdl_t
*, ddi_acc_handle_t
);
295 static void pcicfg_enable_bridge_probe_err(dev_info_t
*dip
,
296 ddi_acc_handle_t h
, pcicfg_err_regs_t
*regs
);
297 static void pcicfg_disable_bridge_probe_err(dev_info_t
*dip
,
298 ddi_acc_handle_t h
, pcicfg_err_regs_t
*regs
);
299 static int pcicfg_update_assigned_prop(dev_info_t
*, pci_regspec_t
*);
300 static void pcicfg_device_on(ddi_acc_handle_t
);
301 static void pcicfg_device_off(ddi_acc_handle_t
);
302 static int pcicfg_set_busnode_props(dev_info_t
*, uint8_t, int, int);
303 static int pcicfg_free_bridge_resources(dev_info_t
*);
304 static int pcicfg_free_device_resources(dev_info_t
*, pcicfg_flags_t
);
305 static int pcicfg_teardown_device(dev_info_t
*, pcicfg_flags_t
, boolean_t
);
306 static int pcicfg_config_setup(dev_info_t
*, ddi_acc_handle_t
*);
307 static void pcicfg_config_teardown(ddi_acc_handle_t
*);
308 static void pcicfg_get_mem(pcicfg_phdl_t
*, uint32_t, uint64_t *);
309 static void pcicfg_get_io(pcicfg_phdl_t
*, uint32_t, uint32_t *);
310 static int pcicfg_update_ranges_prop(dev_info_t
*, pcicfg_range_t
*);
311 static int pcicfg_map_phys(dev_info_t
*, pci_regspec_t
*, caddr_t
*,
312 ddi_device_acc_attr_t
*, ddi_acc_handle_t
*);
313 static void pcicfg_unmap_phys(ddi_acc_handle_t
*, pci_regspec_t
*);
314 static int pcicfg_dump_assigned(dev_info_t
*);
315 static uint_t
pcicfg_configure_ntbridge(dev_info_t
*, uint_t
, uint_t
);
316 static int pcicfg_indirect_map(dev_info_t
*dip
);
317 static uint_t
pcicfg_get_ntbridge_child_range(dev_info_t
*, uint64_t *,
319 static int pcicfg_is_ntbridge(dev_info_t
*);
320 static int pcicfg_ntbridge_allocate_resources(dev_info_t
*);
321 static int pcicfg_ntbridge_configure_done(dev_info_t
*);
322 static int pcicfg_ntbridge_unconfigure(dev_info_t
*);
323 static int pcicfg_ntbridge_unconfigure_child(dev_info_t
*, uint_t
);
324 static void pcicfg_free_hole(hole_t
*);
325 static uint64_t pcicfg_alloc_hole(hole_t
*, uint64_t *, uint32_t);
326 static int pcicfg_update_available_prop(dev_info_t
*, pci_regspec_t
*);
327 static int pcicfg_ari_configure(dev_info_t
*);
328 static int pcicfg_populate_reg_props(dev_info_t
*, ddi_acc_handle_t
);
329 static int pcicfg_populate_props_from_bar(dev_info_t
*, ddi_acc_handle_t
);
330 static int pcicfg_update_assigned_prop_value(dev_info_t
*, uint32_t,
331 uint32_t, uint32_t, uint_t
);
332 static boolean_t
is_pcie_fabric(dev_info_t
*dip
);
335 static void pcicfg_dump_common_config(ddi_acc_handle_t config_handle
);
336 static void pcicfg_dump_device_config(ddi_acc_handle_t
);
338 static void pcicfg_dump_bridge_config(ddi_acc_handle_t config_handle
);
339 static uint64_t pcicfg_unused_space(hole_t
*, uint32_t *);
341 #define PCICFG_DUMP_COMMON_CONFIG(hdl) (void)pcicfg_dump_common_config(hdl)
342 #define PCICFG_DUMP_DEVICE_CONFIG(hdl) (void)pcicfg_dump_device_config(hdl)
343 #define PCICFG_DUMP_BRIDGE_CONFIG(hdl) (void)pcicfg_dump_bridge_config(hdl)
345 #define PCICFG_DUMP_COMMON_CONFIG(handle)
346 #define PCICFG_DUMP_DEVICE_CONFIG(handle)
347 #define PCICFG_DUMP_BRIDGE_CONFIG(handle)
350 static kmutex_t pcicfg_list_mutex
; /* Protects the probe handle list */
351 static pcicfg_phdl_t
*pcicfg_phdl_list
= NULL
;
353 #ifndef _DONT_USE_1275_GENERIC_NAMES
357 static struct pcicfg_name_entry pcicfg_class_lookup
[] = {
359 { 0x001, "display" },
365 { 0x200, "ethernet" },
366 { 0x201, "token-ring" },
369 { 0x300, "display" },
381 { 0x607, "cardbus" },
384 { 0x701, "parallel" },
385 { 0x800, "interrupt-controller" },
386 { 0x801, "dma-controller" },
389 { 0x900, "keyboard" },
394 { 0xc00, "firewire" },
395 { 0xc01, "access-bus" },
398 { 0xc04, "fibre-channel" },
401 #endif /* _DONT_USE_1275_GENERIC_NAMES */
404 * Module control operations
407 extern struct mod_ops mod_miscops
;
409 static struct modlmisc modlmisc
= {
410 &mod_miscops
, /* Type of module */
411 "PCIe/PCI Config (EFCode Enabled)"
414 static struct modlinkage modlinkage
= {
415 MODREV_1
, (void *)&modlmisc
, NULL
421 pcicfg_dump_common_config(ddi_acc_handle_t config_handle
)
423 if ((pcicfg_debug
& 1) == 0)
425 cmn_err(CE_CONT
, " Vendor ID = [0x%x]\n",
426 pci_config_get16(config_handle
, PCI_CONF_VENID
));
427 cmn_err(CE_CONT
, " Device ID = [0x%x]\n",
428 pci_config_get16(config_handle
, PCI_CONF_DEVID
));
429 cmn_err(CE_CONT
, " Command REG = [0x%x]\n",
430 pci_config_get16(config_handle
, PCI_CONF_COMM
));
431 cmn_err(CE_CONT
, " Status REG = [0x%x]\n",
432 pci_config_get16(config_handle
, PCI_CONF_STAT
));
433 cmn_err(CE_CONT
, " Revision ID = [0x%x]\n",
434 pci_config_get8(config_handle
, PCI_CONF_REVID
));
435 cmn_err(CE_CONT
, " Prog Class = [0x%x]\n",
436 pci_config_get8(config_handle
, PCI_CONF_PROGCLASS
));
437 cmn_err(CE_CONT
, " Dev Class = [0x%x]\n",
438 pci_config_get8(config_handle
, PCI_CONF_SUBCLASS
));
439 cmn_err(CE_CONT
, " Base Class = [0x%x]\n",
440 pci_config_get8(config_handle
, PCI_CONF_BASCLASS
));
441 cmn_err(CE_CONT
, " Device ID = [0x%x]\n",
442 pci_config_get8(config_handle
, PCI_CONF_CACHE_LINESZ
));
443 cmn_err(CE_CONT
, " Header Type = [0x%x]\n",
444 pci_config_get8(config_handle
, PCI_CONF_HEADER
));
445 cmn_err(CE_CONT
, " BIST = [0x%x]\n",
446 pci_config_get8(config_handle
, PCI_CONF_BIST
));
447 cmn_err(CE_CONT
, " BASE 0 = [0x%x]\n",
448 pci_config_get32(config_handle
, PCI_CONF_BASE0
));
449 cmn_err(CE_CONT
, " BASE 1 = [0x%x]\n",
450 pci_config_get32(config_handle
, PCI_CONF_BASE1
));
455 pcicfg_dump_device_config(ddi_acc_handle_t config_handle
)
457 if ((pcicfg_debug
& 1) == 0)
459 pcicfg_dump_common_config(config_handle
);
461 cmn_err(CE_CONT
, " BASE 2 = [0x%x]\n",
462 pci_config_get32(config_handle
, PCI_CONF_BASE2
));
463 cmn_err(CE_CONT
, " BASE 3 = [0x%x]\n",
464 pci_config_get32(config_handle
, PCI_CONF_BASE3
));
465 cmn_err(CE_CONT
, " BASE 4 = [0x%x]\n",
466 pci_config_get32(config_handle
, PCI_CONF_BASE4
));
467 cmn_err(CE_CONT
, " BASE 5 = [0x%x]\n",
468 pci_config_get32(config_handle
, PCI_CONF_BASE5
));
469 cmn_err(CE_CONT
, " Cardbus CIS = [0x%x]\n",
470 pci_config_get32(config_handle
, PCI_CONF_CIS
));
471 cmn_err(CE_CONT
, " Sub VID = [0x%x]\n",
472 pci_config_get16(config_handle
, PCI_CONF_SUBVENID
));
473 cmn_err(CE_CONT
, " Sub SID = [0x%x]\n",
474 pci_config_get16(config_handle
, PCI_CONF_SUBSYSID
));
475 cmn_err(CE_CONT
, " ROM = [0x%x]\n",
476 pci_config_get32(config_handle
, PCI_CONF_ROM
));
477 cmn_err(CE_CONT
, " I Line = [0x%x]\n",
478 pci_config_get8(config_handle
, PCI_CONF_ILINE
));
479 cmn_err(CE_CONT
, " I Pin = [0x%x]\n",
480 pci_config_get8(config_handle
, PCI_CONF_IPIN
));
481 cmn_err(CE_CONT
, " Max Grant = [0x%x]\n",
482 pci_config_get8(config_handle
, PCI_CONF_MIN_G
));
483 cmn_err(CE_CONT
, " Max Latent = [0x%x]\n",
484 pci_config_get8(config_handle
, PCI_CONF_MAX_L
));
488 pcicfg_dump_bridge_config(ddi_acc_handle_t config_handle
)
490 if ((pcicfg_debug
& 1) == 0)
493 pcicfg_dump_common_config(config_handle
);
495 cmn_err(CE_CONT
, "........................................\n");
497 cmn_err(CE_CONT
, " Pri Bus = [0x%x]\n",
498 pci_config_get8(config_handle
, PCI_BCNF_PRIBUS
));
499 cmn_err(CE_CONT
, " Sec Bus = [0x%x]\n",
500 pci_config_get8(config_handle
, PCI_BCNF_SECBUS
));
501 cmn_err(CE_CONT
, " Sub Bus = [0x%x]\n",
502 pci_config_get8(config_handle
, PCI_BCNF_SUBBUS
));
503 cmn_err(CE_CONT
, " Latency = [0x%x]\n",
504 pci_config_get8(config_handle
, PCI_BCNF_LATENCY_TIMER
));
505 cmn_err(CE_CONT
, " I/O Base LO = [0x%x]\n",
506 pci_config_get8(config_handle
, PCI_BCNF_IO_BASE_LOW
));
507 cmn_err(CE_CONT
, " I/O Lim LO = [0x%x]\n",
508 pci_config_get8(config_handle
, PCI_BCNF_IO_LIMIT_LOW
));
509 cmn_err(CE_CONT
, " Sec. Status = [0x%x]\n",
510 pci_config_get16(config_handle
, PCI_BCNF_SEC_STATUS
));
511 cmn_err(CE_CONT
, " Mem Base = [0x%x]\n",
512 pci_config_get16(config_handle
, PCI_BCNF_MEM_BASE
));
513 cmn_err(CE_CONT
, " Mem Limit = [0x%x]\n",
514 pci_config_get16(config_handle
, PCI_BCNF_MEM_LIMIT
));
515 cmn_err(CE_CONT
, " PF Mem Base = [0x%x]\n",
516 pci_config_get16(config_handle
, PCI_BCNF_PF_BASE_LOW
));
517 cmn_err(CE_CONT
, " PF Mem Lim = [0x%x]\n",
518 pci_config_get16(config_handle
, PCI_BCNF_PF_LIMIT_LOW
));
519 cmn_err(CE_CONT
, " PF Base HI = [0x%x]\n",
520 pci_config_get32(config_handle
, PCI_BCNF_PF_BASE_HIGH
));
521 cmn_err(CE_CONT
, " PF Lim HI = [0x%x]\n",
522 pci_config_get32(config_handle
, PCI_BCNF_PF_LIMIT_HIGH
));
523 cmn_err(CE_CONT
, " I/O Base HI = [0x%x]\n",
524 pci_config_get16(config_handle
, PCI_BCNF_IO_BASE_HI
));
525 cmn_err(CE_CONT
, " I/O Lim HI = [0x%x]\n",
526 pci_config_get16(config_handle
, PCI_BCNF_IO_LIMIT_HI
));
527 cmn_err(CE_CONT
, " ROM addr = [0x%x]\n",
528 pci_config_get32(config_handle
, PCI_BCNF_ROM
));
529 cmn_err(CE_CONT
, " Intr Line = [0x%x]\n",
530 pci_config_get8(config_handle
, PCI_BCNF_ILINE
));
531 cmn_err(CE_CONT
, " Intr Pin = [0x%x]\n",
532 pci_config_get8(config_handle
, PCI_BCNF_IPIN
));
533 cmn_err(CE_CONT
, " Bridge Ctrl = [0x%x]\n",
534 pci_config_get16(config_handle
, PCI_BCNF_BCNTRL
));
543 DEBUG0("PCI configurator installed - Fcode Interpretation/21554\n");
545 mutex_init(&pcicfg_list_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
546 return (mod_install(&modlinkage
));
554 error
= mod_remove(&modlinkage
);
558 mutex_destroy(&pcicfg_list_mutex
);
564 struct modinfo
*modinfop
;
566 return (mod_info(&modlinkage
, modinfop
));
571 pcicfg_get_nslots(dev_info_t
*dip
, ddi_acc_handle_t handle
)
573 uint8_t num_slots
= 0;
576 if ((PCI_CAP_LOCATE(handle
, PCI_CAP_ID_PCI_HOTPLUG
,
577 &cap_ptr
)) == DDI_SUCCESS
) {
580 PCI_CAP_PUT8(handle
, NULL
, cap_ptr
, PCI_HP_DWORD_SELECT_OFF
,
581 PCI_HP_SLOT_CONFIGURATION_REG
);
582 config
= PCI_CAP_GET32(handle
, NULL
, cap_ptr
,
583 PCI_HP_DWORD_DATA_OFF
);
584 num_slots
= config
& 0x1F;
585 } else if ((PCI_CAP_LOCATE(handle
, PCI_CAP_ID_SLOT_ID
, &cap_ptr
))
587 uint8_t esr_reg
= PCI_CAP_GET8(handle
, NULL
,
588 cap_ptr
, PCI_CAP_ID_REGS_OFF
);
590 num_slots
= PCI_CAPSLOT_NSLOTS(esr_reg
);
591 } else if ((PCI_CAP_LOCATE(handle
, PCI_CAP_ID_PCI_E
, &cap_ptr
))
593 int port_type
= PCI_CAP_GET16(handle
, NULL
, cap_ptr
,
594 PCIE_PCIECAP
) & PCIE_PCIECAP_DEV_TYPE_MASK
;
596 if ((port_type
== PCIE_PCIECAP_DEV_TYPE_DOWN
) &&
597 (PCI_CAP_GET16(handle
, NULL
, cap_ptr
, PCIE_PCIECAP
)
598 & PCIE_PCIECAP_SLOT_IMPL
))
602 DEBUG3("%s#%d has %d slots",
603 ddi_get_name(dip
), ddi_get_instance(dip
), num_slots
);
610 pcicfg_is_chassis(dev_info_t
*dip
, ddi_acc_handle_t handle
)
614 if ((PCI_CAP_LOCATE(handle
, PCI_CAP_ID_SLOT_ID
, &cap_ptr
)) !=
617 uint8_t esr_reg
= PCI_CAP_GET8(handle
, NULL
, cap_ptr
, 2);
618 if (PCI_CAPSLOT_FIC(esr_reg
))
626 pcicfg_pcie_dev(dev_info_t
*dip
, int bus_type
, pcicfg_err_regs_t
*regs
)
628 /* get parent device's device_type property */
630 int rc
= DDI_FAILURE
;
631 dev_info_t
*pdip
= ddi_get_parent(dip
);
634 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, pdip
,
635 DDI_PROP_DONTPASS
, "device_type", &device_type
)
636 != DDI_PROP_SUCCESS
) {
637 DEBUG2("device_type property missing for %s#%d",
638 ddi_get_name(pdip
), ddi_get_instance(pdip
));
639 return (DDI_FAILURE
);
642 case PCICFG_DEVICE_TYPE_PCIE
:
643 if (strcmp(device_type
, "pciex") == 0) {
648 case PCICFG_DEVICE_TYPE_PCI
:
649 if (strcmp(device_type
, "pci") == 0)
655 ddi_prop_free(device_type
);
661 pcicfg_pcie_port_type(dev_info_t
*dip
, ddi_acc_handle_t handle
)
666 if ((PCI_CAP_LOCATE(handle
, PCI_CAP_ID_PCI_E
, &cap_ptr
)) !=
668 port_type
= PCI_CAP_GET16(handle
, NULL
,
669 cap_ptr
, PCIE_PCIECAP
) & PCIE_PCIECAP_DEV_TYPE_MASK
;
675 pcicfg_pcie_device_type(dev_info_t
*dip
, ddi_acc_handle_t handle
)
677 int port_type
= pcicfg_pcie_port_type(dip
, handle
);
679 DEBUG1("device port_type = %x\n", port_type
);
680 /* No PCIe CAP regs, we are not PCIe device_type */
682 return (DDI_FAILURE
);
684 /* check for all PCIe device_types */
685 if ((port_type
== PCIE_PCIECAP_DEV_TYPE_UP
) ||
686 (port_type
== PCIE_PCIECAP_DEV_TYPE_DOWN
) ||
687 (port_type
== PCIE_PCIECAP_DEV_TYPE_ROOT
) ||
688 (port_type
== PCIE_PCIECAP_DEV_TYPE_PCI2PCIE
))
689 return (DDI_SUCCESS
);
691 return (DDI_FAILURE
);
696 * In the following functions ndi_devi_enter() without holding the
697 * parent dip is sufficient. This is because pci dr is driven through
698 * opens on the nexus which is in the device tree path above the node
699 * being operated on, and implicitly held due to the open.
703 * This entry point is called to configure a device (and
704 * all its children) on the given bus. It is called when
705 * a new device is added to the PCI domain. This routine
706 * will create the device tree and program the devices
711 pcicfg_configure(dev_info_t
*devi
, uint_t device
, uint_t function
,
712 pcicfg_flags_t flags
)
718 dev_info_t
*new_device
;
719 pcicfg_bus_range_t pci_bus_range
;
722 uint_t highest_bus
= 0;
723 int ari_mode
= B_FALSE
;
724 int max_function
= PCICFG_MAX_FUNCTION
;
727 if (flags
== PCICFG_FLAG_ENABLE_ARI
)
728 return (pcicfg_ari_configure(devi
));
731 * Start probing at the device specified in "device" on the
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
);
741 bus
= pci_bus_range
.lo
; /* primary bus number of this bus node */
743 is_pcie
= is_pcie_fabric(devi
);
745 ndi_devi_enter(devi
, &circ
);
746 for (func
= 0; func
< max_function
; ) {
747 if ((function
!= PCICFG_ALL_FUNC
) && (function
!= func
))
751 trans_device
= func
>> 3;
753 trans_device
= device
;
755 DEBUG3("Configuring [0x%x][0x%x][0x%x]\n",
756 bus
, trans_device
, func
& 7);
759 * Try executing fcode if available.
761 switch (rv
= pcicfg_fcode_probe(devi
, bus
, trans_device
,
762 func
& 7, &highest_bus
, flags
, is_pcie
)) {
764 DEBUG2("configure failed: "
765 "bus [0x%x] device [0x%x]\n",
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);
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
779 if (ari_mode
== B_TRUE
)
786 DEBUG3("configure: bus => [%d] "
787 "slot => [%d] func => [%d]\n",
788 bus
, trans_device
, func
& 7);
792 if (rv
!= PCICFG_SUCCESS
)
795 if ((new_device
= pcicfg_devi_find(devi
,
796 trans_device
, (func
& 7))) == NULL
) {
797 DEBUG0("Did'nt find device node just created\n");
803 * Determine if ARI Forwarding should be enabled.
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);
815 max_function
= PCICFG_MAX_ARI_FUNCTION
;
820 if (ari_mode
== B_TRUE
) {
823 DEBUG0("Next Function - ARI Device\n");
824 if (pcie_ari_get_next_function(new_device
,
825 &next_function
) != DDI_SUCCESS
)
829 * Check if there are more fucntions to probe.
831 if (next_function
== 0) {
832 DEBUG0("Next Function - "
833 "No more ARI Functions\n");
836 func
= next_function
;
841 DEBUG1("Next Function - %x\n", func
);
844 ndi_devi_exit(devi
, circ
);
847 return (PCICFG_FAILURE
); /* probe failed */
849 return (PCICFG_SUCCESS
);
853 * Clean up a partially created "probe state" tree.
854 * There are no resources allocated to the in the
857 if (pcie_ari_is_enabled(devi
) == PCIE_ARI_FORW_ENABLED
)
858 max_function
= PCICFG_MAX_ARI_FUNCTION
;
860 max_function
= PCICFG_MAX_FUNCTION
;
862 for (func
= 0; func
< max_function
; func
++) {
864 if (max_function
== PCICFG_MAX_ARI_FUNCTION
)
865 trans_device
= func
>> 3; /* ARI Device */
867 trans_device
= device
;
869 if ((new_device
= pcicfg_devi_find(devi
,
870 trans_device
, (func
& 0x7))) == NULL
) {
871 DEBUG0("No more devices to clean up\n");
875 DEBUG2("Cleaning up device [0x%x] function [0x%x]\n",
876 trans_device
, func
& 7);
878 * If this was a bridge device it will have a
879 * probe handle - if not, no harm in calling this.
881 (void) pcicfg_destroy_phdl(new_device
);
885 * Free bus_t structure
887 if (ddi_get_child(new_device
) != NULL
)
888 pcie_fab_fini_bus(new_device
, PCIE_BUS_ALL
);
890 pcie_fini_bus(new_device
, PCIE_BUS_ALL
);
893 * This will free up the node
895 (void) ndi_devi_offline(new_device
, NDI_DEVI_REMOVE
);
897 ndi_devi_exit(devi
, circ
);
899 return (PCICFG_FAILURE
);
903 * configure the child nodes of ntbridge. new_device points to ntbridge itself
907 pcicfg_configure_ntbridge(dev_info_t
*new_device
, uint_t bus
, uint_t device
)
909 int bus_range
[2], rc
= PCICFG_FAILURE
, rc1
, max_devs
= 0;
911 dev_info_t
*new_ntbridgechild
;
912 ddi_acc_handle_t config_handle
;
916 ndi_ra_request_t req
;
917 uint8_t pcie_device_type
= 0;
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.
925 if ((rc
= ndi_prop_update_int(DDI_DEV_T_NONE
, new_device
,
926 PCI_DEV_CONF_MAP_PROP
, (int)DDI_SUCCESS
))
929 DEBUG0("Cannot create indirect conf map property.\n");
930 return ((uint_t
)PCICFG_FAILURE
);
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
);
939 /* create Bus node properties for ntbridge. */
940 if (pcicfg_set_busnode_props(new_device
, pcie_device_type
, -1, -1) !=
942 DEBUG0("Failed to set busnode props\n");
946 /* For now: Lets only support one layer of child */
947 bzero((caddr_t
)&req
, sizeof (ndi_ra_request_t
));
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");
956 DEBUG1("ntbridge bus range start ->[%d]\n", next_bus
);
959 * Following will change, as we detect more bridges
962 bus_range
[0] = (int)next_bus
;
963 bus_range
[1] = (int)next_bus
;
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");
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.
979 * finally, lets load and attach the driver
980 * before configuring children of ntbridge.
982 rc
= ndi_devi_online(new_device
, NDI_NO_EVENT
|NDI_CONFIG
);
983 if (rc
!= NDI_SUCCESS
) {
985 "pcicfg: Fail: can\'t load non-transparent bridge \
990 DEBUG0("pcicfg: Success loading nontransparent bridge nexus driver..");
992 /* Now set aside pci resources for our children. */
993 if (pcicfg_ntbridge_allocate_resources(new_device
) !=
998 max_devs
= PCICFG_MAX_DEVICE
;
1000 /* Probe devices on 2nd bus */
1001 for (devno
= pcicfg_start_devno
; devno
< max_devs
; devno
++) {
1003 if (ndi_devi_alloc(new_device
, DEVI_PSEUDO_NEXNAME
,
1004 (pnode_t
)DEVI_SID_NODEID
, &new_ntbridgechild
)
1007 DEBUG0("pcicfg: Failed to alloc test node\n");
1008 rc
= PCICFG_FAILURE
;
1012 if (pcicfg_add_config_reg(new_ntbridgechild
, next_bus
, devno
, 0)
1013 != DDI_PROP_SUCCESS
) {
1015 "Failed to add conf reg for ntbridge child.\n");
1016 (void) ndi_devi_free(new_ntbridgechild
);
1017 rc
= PCICFG_FAILURE
;
1021 if ((rc
= pci_config_setup(new_ntbridgechild
,
1022 &config_handle
)) != PCICFG_SUCCESS
) {
1024 "Cannot map ntbridge child %x\n", devno
);
1025 (void) ndi_devi_free(new_ntbridgechild
);
1026 rc
= PCICFG_FAILURE
;
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.
1035 vid
= pci_config_get16(config_handle
, PCI_CONF_VENID
);
1037 pci_config_teardown(&config_handle
);
1038 (void) ndi_devi_free(new_ntbridgechild
);
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
;
1048 "Error configuring ntbridge child dev=%d\n", devno
);
1050 rc
= PCICFG_FAILURE
;
1051 while (old_dev
!= devno
) {
1052 if (pcicfg_ntbridge_unconfigure_child(
1053 new_device
, old_dev
) == PCICFG_FAILURE
)
1056 "Unconfig Error ntbridge child "
1057 "dev=%d\n", old_dev
);
1063 DEBUG1("ntbridge: finish probing 2nd bus, rc=%d\n", rc
);
1065 if (rc
!= PCICFG_FAILURE
)
1066 rc
= pcicfg_ntbridge_configure_done(new_device
);
1068 pcicfg_phdl_t
*entry
= pcicfg_find_phdl(new_device
);
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
;
1080 DEBUG2("Need to free bus [%d] range [%d]\n",
1081 bus
[0], bus
[1] - bus
[0] + 1);
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
;
1089 * Don't forget to free up memory from ddi_getlongprop
1091 kmem_free((caddr_t
)bus
, k
);
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.
1104 entry
->memory_len
= 0;
1106 /* the following will free hole data. */
1107 (void) pcicfg_destroy_phdl(new_device
);
1109 * Don't forget to free up memory from ddi_getlongprop
1111 kmem_free((caddr_t
)bus
, k
);
1115 * Unload driver just in case child configure failed!
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
) {
1121 "pcicfg: can\'t unload ntbridge driver children.\n");
1122 rc
= PCICFG_FAILURE
;
1129 pcicfg_ntbridge_allocate_resources(dev_info_t
*dip
)
1131 pcicfg_phdl_t
*phdl
;
1132 ndi_ra_request_t
*mem_request
;
1133 ndi_ra_request_t
*io_request
;
1134 uint64_t boundbase
, boundlen
;
1136 phdl
= pcicfg_find_phdl(dip
);
1139 mem_request
= &phdl
->mem_req
;
1140 io_request
= &phdl
->io_req
;
1142 phdl
->error
= PCICFG_SUCCESS
;
1144 /* Set Memory space handle for ntbridge */
1145 if (pcicfg_get_ntbridge_child_range(dip
, &boundbase
, &boundlen
,
1146 PCI_BASE_SPACE_MEM
) != DDI_SUCCESS
) {
1148 "ntbridge: Mem resource information failure\n");
1149 phdl
->memory_len
= 0;
1150 return (PCICFG_FAILURE
);
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
;
1160 * mem_request->ra_len =
1161 * PCICFG_ROUND_UP(mem_request->ra_len, PCICFG_MEMGRAN);
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
;
1170 DEBUG2("Connector requested [0x%llx], needs [0x%llx] bytes of memory\n",
1171 boundlen
, mem_request
->ra_len
);
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
);
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
);
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");
1189 return (PCICFG_FAILURE
);
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
;
1199 * io_request->ra_len =
1200 * PCICFG_ROUND_UP(io_request->ra_len, PCICFG_IOGRAN);
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
;
1209 DEBUG2("Connector requested [0x%llx], needs [0x%llx] bytes of IO\n",
1210 boundlen
, io_request
->ra_len
);
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
);
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
);
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
);
1229 return (PCICFG_SUCCESS
);
1233 pcicfg_ntbridge_configure_done(dev_info_t
*dip
)
1235 pcicfg_range_t range
[PCICFG_RANGE_LEN
];
1236 pcicfg_phdl_t
*entry
;
1238 pcicfg_bus_range_t bus_range
;
1239 int new_bus_range
[2];
1241 DEBUG1("Configuring children for %llx\n", dip
);
1243 entry
= pcicfg_find_phdl(dip
);
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
;
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
;
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
);
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
) {
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
;
1272 new_bus_range
[1] = entry
->highest_bus
;
1275 new_bus_range
[1] = bus_range
.hi
;
1277 DEBUG2("ntbridge: bus range lo=%x, hi=%x\n",
1278 new_bus_range
[0], new_bus_range
[1]);
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
);
1290 unused
= pcicfg_unused_space(&entry
->io_hole
, &len
);
1291 DEBUG2("ntbridge: Unused IO space %llx bytes over %d holes\n",
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
);
1306 unused
= pcicfg_unused_space(&entry
->mem_hole
, &len
);
1307 DEBUG2("ntbridge: Unused Mem space %llx bytes over %d holes\n",
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
);
1319 return (PCICFG_SUCCESS
);
1323 pcicfg_ntbridge_unconfigure_child(dev_info_t
*new_device
, uint_t devno
)
1326 dev_info_t
*new_ntbridgechild
;
1329 ddi_acc_handle_t config_handle
;
1330 pcicfg_bus_range_t pci_bus_range
;
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
);
1339 bus
= pci_bus_range
.lo
; /* primary bus number of this bus node */
1341 if (ndi_devi_alloc(new_device
, DEVI_PSEUDO_NEXNAME
,
1342 (pnode_t
)DEVI_SID_NODEID
, &new_ntbridgechild
) != NDI_SUCCESS
) {
1344 DEBUG0("pcicfg: Failed to alloc test node\n");
1345 return (PCICFG_FAILURE
);
1348 if (pcicfg_add_config_reg(new_ntbridgechild
, bus
, devno
, 0)
1349 != DDI_PROP_SUCCESS
) {
1351 "Unconfigure: Failed to add conf reg prop for ntbridge "
1353 (void) ndi_devi_free(new_ntbridgechild
);
1354 return (PCICFG_FAILURE
);
1357 if (pcicfg_config_setup(new_ntbridgechild
, &config_handle
)
1360 "pcicfg: Cannot map ntbridge child %x\n", devno
);
1361 (void) ndi_devi_free(new_ntbridgechild
);
1362 return (PCICFG_FAILURE
);
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.
1370 vid
= pci_config_get16(config_handle
, PCI_CONF_VENID
);
1372 pci_config_teardown(&config_handle
);
1373 (void) ndi_devi_free(new_ntbridgechild
);
1375 return (PCICFG_NODEVICE
);
1377 return (pcicfg_unconfigure(new_device
, devno
, PCICFG_ALL_FUNC
, 0));
1381 pcicfg_ntbridge_unconfigure(dev_info_t
*dip
)
1383 pcicfg_phdl_t
*entry
= pcicfg_find_phdl(dip
);
1385 int k
, rc
= PCICFG_FAILURE
;
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",
1391 return (PCICFG_FAILURE
);
1394 if (ndi_ra_map_destroy(dip
, NDI_RA_TYPE_IO
) == NDI_FAILURE
) {
1395 DEBUG1("cannot destroy ntbridge io map size=%x\n",
1397 return (PCICFG_FAILURE
);
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");
1406 DEBUG2("ntbridge: Need to free bus [%d] range [%d]\n",
1407 bus
[0], bus
[1] - bus
[0] + 1);
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");
1414 * Don't forget to free up memory from ddi_getlongprop
1416 kmem_free((caddr_t
)bus
, k
);
1422 * Don't forget to free up memory from ddi_getlongprop
1424 kmem_free((caddr_t
)bus
, k
);
1427 * Since our resources will be freed at the parent level,
1428 * just reset these values.
1430 entry
->memory_len
= 0;
1432 /* the following will also free hole data. */
1433 return (pcicfg_destroy_phdl(dip
));
1438 pcicfg_is_ntbridge(dev_info_t
*dip
)
1440 ddi_acc_handle_t config_handle
;
1441 uint8_t class, subclass
;
1442 int rc
= DDI_SUCCESS
;
1444 if (pcicfg_config_setup(dip
, &config_handle
) != DDI_SUCCESS
) {
1446 "pcicfg: cannot map config space, to get map type\n");
1447 return (DDI_FAILURE
);
1449 class = pci_config_get8(config_handle
, PCI_CONF_BASCLASS
);
1450 subclass
= pci_config_get8(config_handle
, PCI_CONF_SUBCLASS
);
1452 /* check for class=6, subclass=9, for non transparent bridges. */
1453 if ((class != PCI_CLASS_BRIDGE
) || (subclass
!= PCI_BRIDGE_STBRIDGE
))
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
),
1460 pci_config_teardown(&config_handle
);
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.
1472 pcicfg_indirect_map(dev_info_t
*dip
)
1474 #if defined(__sparc)
1475 int rc
= DDI_FAILURE
;
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
)
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
)
1485 DEBUG1("pci conf map = %d", rc
);
1488 return (DDI_SUCCESS
);
1493 pcicfg_get_ntbridge_child_range(dev_info_t
*dip
, uint64_t *boundbase
,
1494 uint64_t *boundlen
, uint_t space_type
)
1496 int length
, found
= DDI_FAILURE
, acount
, i
, ibridge
;
1497 pci_regspec_t
*assigned
;
1499 if ((ibridge
= pcicfg_is_ntbridge(dip
)) == DDI_FAILURE
)
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
);
1508 DEBUG1("pcicfg: ntbridge child range: dip = %s\n",
1509 ddi_driver_name(dip
));
1511 acount
= length
/ sizeof (pci_regspec_t
);
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
;
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
;
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
);
1532 if (found
== DDI_SUCCESS
) {
1533 *boundbase
= assigned
[i
].pci_phys_low
;
1534 *boundlen
= assigned
[i
].pci_size_low
;
1537 kmem_free(assigned
, length
);
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
1548 pcicfg_unconfigure(dev_info_t
*devi
, uint_t device
, uint_t function
,
1549 pcicfg_flags_t flags
)
1551 dev_info_t
*child_dip
;
1559 if (pcie_ari_is_enabled(devi
) == PCIE_ARI_FORW_ENABLED
)
1560 max_function
= PCICFG_MAX_ARI_FUNCTION
;
1562 max_function
= PCICFG_MAX_FUNCTION
;
1565 * Cycle through devices to make sure none are busy.
1566 * If a single device is busy fail the whole unconfigure.
1568 is_pcie
= is_pcie_fabric(devi
);
1570 ndi_devi_enter(devi
, &circ
);
1571 for (func
= 0; func
< max_function
; func
++) {
1573 if (max_function
== PCICFG_MAX_ARI_FUNCTION
)
1574 trans_device
= func
>> 3; /* ARI Device */
1576 trans_device
= device
;
1578 if ((child_dip
= pcicfg_devi_find(devi
, trans_device
,
1579 (func
& 0x7))) == NULL
)
1582 if (ndi_devi_offline(child_dip
, NDI_UNCONFIG
) == NDI_SUCCESS
)
1585 * Device function is busy. Before returning we have to
1586 * put all functions back online which were taken
1587 * offline during the process.
1589 DEBUG2("Device [0x%x] function [%x] is busy\n", device
, func
);
1591 * If we are only asked to offline one specific function,
1592 * and that fails, we just simply return.
1594 if (function
!= PCICFG_ALL_FUNC
)
1595 return (PCICFG_FAILURE
);
1597 for (i
= 0; i
< func
; i
++) {
1599 if (max_function
== PCICFG_MAX_ARI_FUNCTION
)
1600 trans_device
= i
>> 3;
1603 pcicfg_devi_find(devi
, trans_device
, (i
& 7)))
1606 "No more devices to put back on line!!\n");
1608 * Made it through all functions
1612 if (ndi_devi_online(child_dip
, NDI_CONFIG
)
1614 DEBUG0("Failed to put back devices state\n");
1622 * Now, tear down all devinfo nodes for this Connector.
1624 for (func
= 0; func
< max_function
; func
++) {
1626 if (max_function
== PCICFG_MAX_ARI_FUNCTION
)
1627 trans_device
= func
>> 3; /* ARI Device */
1629 trans_device
= device
;
1631 if ((child_dip
= pcicfg_devi_find(devi
,
1632 trans_device
, (func
& 7))) == NULL
) {
1633 DEBUG0("No more devices to tear down!\n");
1637 DEBUG2("Tearing down device [0x%x] function [0x%x]\n",
1638 trans_device
, (func
& 7));
1640 if (pcicfg_is_ntbridge(child_dip
) != DDI_FAILURE
)
1641 if (pcicfg_ntbridge_unconfigure(child_dip
) !=
1644 "ntbridge: unconfigure failed\n");
1648 if (pcicfg_teardown_device(child_dip
, flags
, is_pcie
)
1649 != PCICFG_SUCCESS
) {
1650 DEBUG2("Failed to tear down device [0x%x]"
1651 "function [0x%x]\n",
1652 trans_device
, func
& 7);
1657 if (pcie_ari_is_enabled(devi
) == PCIE_ARI_FORW_ENABLED
) {
1658 (void) ddi_prop_remove(DDI_DEV_T_NONE
, devi
, "ari-enabled");
1659 (void) pcie_ari_disable(devi
);
1662 ndi_devi_exit(devi
, circ
);
1663 return (PCICFG_SUCCESS
);
1666 ndi_devi_exit(devi
, circ
);
1667 return (PCICFG_FAILURE
);
1671 pcicfg_teardown_device(dev_info_t
*dip
, pcicfg_flags_t flags
, boolean_t is_pcie
)
1673 ddi_acc_handle_t config_handle
;
1676 * Free up resources associated with 'dip'
1678 if (pcicfg_free_resources(dip
, flags
) != PCICFG_SUCCESS
) {
1679 DEBUG0("Failed to free resources\n");
1680 return (PCICFG_FAILURE
);
1684 * This will disable the device
1686 if (pci_config_setup(dip
, &config_handle
) != PCICFG_SUCCESS
) {
1687 return (PCICFG_FAILURE
);
1690 pcicfg_device_off(config_handle
);
1691 pci_config_teardown(&config_handle
);
1694 * free pcie_bus_t for the sub-tree
1697 if (ddi_get_child(dip
) != NULL
)
1698 pcie_fab_fini_bus(dip
, PCIE_BUS_ALL
);
1700 pcie_fini_bus(dip
, PCIE_BUS_ALL
);
1704 * The framework provides this routine which can
1705 * tear down a sub-tree.
1707 if (ndi_devi_offline(dip
, NDI_DEVI_REMOVE
) != NDI_SUCCESS
) {
1708 DEBUG0("Failed to offline and remove node\n");
1709 return (PCICFG_FAILURE
);
1712 return (PCICFG_SUCCESS
);
1716 * BEGIN GENERIC SUPPORT ROUTINES
1718 static pcicfg_phdl_t
*
1719 pcicfg_find_phdl(dev_info_t
*dip
)
1721 pcicfg_phdl_t
*entry
;
1722 mutex_enter(&pcicfg_list_mutex
);
1723 for (entry
= pcicfg_phdl_list
; entry
!= NULL
; entry
= entry
->next
) {
1724 if (entry
->dip
== dip
) {
1725 mutex_exit(&pcicfg_list_mutex
);
1729 mutex_exit(&pcicfg_list_mutex
);
1732 * Did'nt find entry - create one
1734 return (pcicfg_create_phdl(dip
));
1737 static pcicfg_phdl_t
*
1738 pcicfg_create_phdl(dev_info_t
*dip
)
1742 new = (pcicfg_phdl_t
*)kmem_zalloc(sizeof (pcicfg_phdl_t
),
1746 mutex_enter(&pcicfg_list_mutex
);
1747 new->next
= pcicfg_phdl_list
;
1748 pcicfg_phdl_list
= new;
1749 mutex_exit(&pcicfg_list_mutex
);
1755 pcicfg_destroy_phdl(dev_info_t
*dip
)
1757 pcicfg_phdl_t
*entry
;
1758 pcicfg_phdl_t
*follow
= NULL
;
1760 mutex_enter(&pcicfg_list_mutex
);
1761 for (entry
= pcicfg_phdl_list
; entry
!= NULL
; follow
= entry
,
1762 entry
= entry
->next
) {
1763 if (entry
->dip
== dip
) {
1764 if (entry
== pcicfg_phdl_list
) {
1765 pcicfg_phdl_list
= entry
->next
;
1767 follow
->next
= entry
->next
;
1770 * If this entry has any allocated memory
1771 * or IO space associated with it, that
1774 if (entry
->memory_len
> 0) {
1775 (void) ndi_ra_free(ddi_get_parent(dip
),
1778 NDI_RA_TYPE_MEM
, NDI_RA_PASS
);
1780 pcicfg_free_hole(&entry
->mem_hole
);
1782 if (entry
->io_len
> 0) {
1783 (void) ndi_ra_free(ddi_get_parent(dip
),
1786 NDI_RA_TYPE_IO
, NDI_RA_PASS
);
1788 pcicfg_free_hole(&entry
->io_hole
);
1791 * Destroy this entry
1793 kmem_free((caddr_t
)entry
, sizeof (pcicfg_phdl_t
));
1794 mutex_exit(&pcicfg_list_mutex
);
1795 return (PCICFG_SUCCESS
);
1798 mutex_exit(&pcicfg_list_mutex
);
1800 * Did'nt find the entry
1802 return (PCICFG_FAILURE
);
1806 pcicfg_program_ap(dev_info_t
*dip
)
1808 pcicfg_phdl_t
*phdl
;
1809 uint8_t header_type
;
1810 ddi_acc_handle_t handle
;
1811 pcicfg_phdl_t
*entry
;
1813 if (pcicfg_config_setup(dip
, &handle
) != DDI_SUCCESS
) {
1814 DEBUG0("Failed to map config space!\n");
1815 return (PCICFG_FAILURE
);
1819 header_type
= pci_config_get8(handle
, PCI_CONF_HEADER
);
1821 (void) pcicfg_config_teardown(&handle
);
1823 if ((header_type
& PCI_HEADER_TYPE_M
) == PCI_HEADER_PPB
) {
1825 if (pcicfg_allocate_chunk(dip
) != PCICFG_SUCCESS
) {
1826 DEBUG0("Not enough memory to hotplug\n");
1827 (void) pcicfg_destroy_phdl(dip
);
1828 return (PCICFG_FAILURE
);
1831 phdl
= pcicfg_find_phdl(dip
);
1834 (void) pcicfg_bridge_assign(dip
, (void *)phdl
);
1836 if (phdl
->error
!= PCICFG_SUCCESS
) {
1837 DEBUG0("Problem assigning bridge\n");
1838 (void) pcicfg_destroy_phdl(dip
);
1839 return (phdl
->error
);
1843 * Successfully allocated and assigned
1844 * memory. Set the memory and IO length
1845 * to zero so when the handle is freed up
1846 * it will not de-allocate assigned resources.
1848 entry
= (pcicfg_phdl_t
*)phdl
;
1850 entry
->memory_len
= entry
->io_len
= 0;
1853 * Free up the "entry" structure.
1855 (void) pcicfg_destroy_phdl(dip
);
1857 if (pcicfg_device_assign(dip
) != PCICFG_SUCCESS
) {
1858 return (PCICFG_FAILURE
);
1861 return (PCICFG_SUCCESS
);
1865 pcicfg_bridge_assign(dev_info_t
*dip
, void *hdl
)
1867 ddi_acc_handle_t handle
;
1873 uint64_t mem_answer
;
1876 uint8_t header_type
;
1877 pcicfg_range_t range
[PCICFG_RANGE_LEN
];
1880 pcicfg_phdl_t
*entry
= (pcicfg_phdl_t
*)hdl
;
1882 DEBUG1("bridge assign: assigning addresses to %s\n", ddi_get_name(dip
));
1884 if (entry
== NULL
) {
1885 DEBUG0("Failed to get entry\n");
1886 return (DDI_WALK_TERMINATE
);
1889 entry
->error
= PCICFG_SUCCESS
;
1891 if (pcicfg_config_setup(dip
, &handle
) != DDI_SUCCESS
) {
1892 DEBUG0("Failed to map config space!\n");
1893 entry
->error
= PCICFG_FAILURE
;
1894 return (DDI_WALK_TERMINATE
);
1897 header_type
= pci_config_get8(handle
, PCI_CONF_HEADER
);
1899 if ((header_type
& PCI_HEADER_TYPE_M
) == PCI_HEADER_PPB
) {
1901 bzero((caddr_t
)range
,
1902 sizeof (pcicfg_range_t
) * PCICFG_RANGE_LEN
);
1904 (void) pcicfg_setup_bridge(entry
, handle
, dip
);
1906 range
[0].child_hi
= range
[0].parent_hi
|=
1907 (PCI_REG_REL_M
| PCI_ADDR_IO
);
1908 range
[0].child_lo
= range
[0].parent_lo
=
1910 range
[1].child_hi
= range
[1].parent_hi
|=
1911 (PCI_REG_REL_M
| PCI_ADDR_MEM32
);
1912 range
[1].child_lo
= range
[1].parent_lo
=
1915 ndi_devi_enter(dip
, &count
);
1916 ddi_walk_devs(ddi_get_child(dip
),
1917 pcicfg_bridge_assign
, (void *)entry
);
1918 ndi_devi_exit(dip
, count
);
1920 (void) pcicfg_update_bridge(entry
, handle
);
1922 bus_range
[0] = pci_config_get8(handle
, PCI_BCNF_SECBUS
);
1923 bus_range
[1] = pci_config_get8(handle
, PCI_BCNF_SUBBUS
);
1925 if (ndi_prop_update_int_array(DDI_DEV_T_NONE
, dip
,
1926 "bus-range", bus_range
, 2) != DDI_SUCCESS
) {
1927 DEBUG0("Failed to set bus-range property");
1928 entry
->error
= PCICFG_FAILURE
;
1929 return (DDI_WALK_TERMINATE
);
1932 if (entry
->io_len
> 0) {
1933 range
[0].size_lo
= entry
->io_last
- entry
->io_base
;
1934 if (pcicfg_update_ranges_prop(dip
, &range
[0])) {
1935 DEBUG0("Failed to update ranges (i/o)\n");
1936 entry
->error
= PCICFG_FAILURE
;
1937 return (DDI_WALK_TERMINATE
);
1940 if (entry
->memory_len
> 0) {
1942 entry
->memory_last
- entry
->memory_base
;
1943 if (pcicfg_update_ranges_prop(dip
, &range
[1])) {
1944 DEBUG0("Failed to update ranges (memory)\n");
1945 entry
->error
= PCICFG_FAILURE
;
1946 return (DDI_WALK_TERMINATE
);
1950 (void) pcicfg_device_on(handle
);
1952 PCICFG_DUMP_BRIDGE_CONFIG(handle
);
1954 return (DDI_WALK_PRUNECHILD
);
1958 * If there is an interrupt pin set program
1959 * interrupt line with default values.
1961 if (pci_config_get8(handle
, PCI_CONF_IPIN
)) {
1962 pci_config_put8(handle
, PCI_CONF_ILINE
, 0xf);
1966 * A single device (under a bridge).
1967 * For each "reg" property with a length, allocate memory
1968 * and program the base registers.
1970 if (ddi_getlongprop(DDI_DEV_T_ANY
, dip
,
1971 DDI_PROP_DONTPASS
, "reg", (caddr_t
)®
,
1972 &length
) != DDI_PROP_SUCCESS
) {
1973 DEBUG0("Failed to read reg property\n");
1974 entry
->error
= PCICFG_FAILURE
;
1975 return (DDI_WALK_TERMINATE
);
1978 rcount
= length
/ sizeof (pci_regspec_t
);
1979 offset
= PCI_CONF_BASE0
;
1980 for (i
= 0; i
< rcount
; i
++) {
1981 if ((reg
[i
].pci_size_low
!= 0)||
1982 (reg
[i
].pci_size_hi
!= 0)) {
1984 offset
= PCI_REG_REG_G(reg
[i
].pci_phys_hi
);
1986 switch (PCI_REG_ADDR_G(reg
[i
].pci_phys_hi
)) {
1987 case PCI_REG_ADDR_G(PCI_ADDR_MEM64
):
1989 (void) pcicfg_get_mem(entry
,
1990 reg
[i
].pci_size_low
, &mem_answer
);
1991 pci_config_put64(handle
, offset
, mem_answer
);
1992 DEBUG2("REGISTER off %x (64)LO ----> [0x%x]\n",
1994 pci_config_get32(handle
, offset
));
1995 DEBUG2("REGISTER off %x (64)HI ----> [0x%x]\n",
1997 pci_config_get32(handle
, offset
+ 4));
1999 reg
[i
].pci_phys_low
= PCICFG_HIADDR(mem_answer
);
2000 reg
[i
].pci_phys_mid
=
2001 PCICFG_LOADDR(mem_answer
);
2005 case PCI_REG_ADDR_G(PCI_ADDR_MEM32
):
2006 /* allocate memory space from the allocator */
2008 (void) pcicfg_get_mem(entry
,
2009 reg
[i
].pci_size_low
, &mem_answer
);
2010 pci_config_put32(handle
,
2011 offset
, (uint32_t)mem_answer
);
2013 DEBUG2("REGISTER off %x(32)LO ----> [0x%x]\n",
2015 pci_config_get32(handle
, offset
));
2017 reg
[i
].pci_phys_low
= (uint32_t)mem_answer
;
2020 case PCI_REG_ADDR_G(PCI_ADDR_IO
):
2021 /* allocate I/O space from the allocator */
2023 (void) pcicfg_get_io(entry
,
2024 reg
[i
].pci_size_low
, &io_answer
);
2025 pci_config_put32(handle
, offset
, io_answer
);
2027 DEBUG2("REGISTER off %x (I/O)LO ----> [0x%x]\n",
2029 pci_config_get32(handle
, offset
));
2031 reg
[i
].pci_phys_low
= io_answer
;
2035 DEBUG0("Unknown register type\n");
2036 kmem_free(reg
, length
);
2037 (void) pcicfg_config_teardown(&handle
);
2038 entry
->error
= PCICFG_FAILURE
;
2039 return (DDI_WALK_TERMINATE
);
2043 * Now that memory locations are assigned,
2044 * update the assigned address property.
2046 if (pcicfg_update_assigned_prop(dip
,
2047 ®
[i
]) != PCICFG_SUCCESS
) {
2048 kmem_free(reg
, length
);
2049 (void) pcicfg_config_teardown(&handle
);
2050 entry
->error
= PCICFG_FAILURE
;
2051 return (DDI_WALK_TERMINATE
);
2055 (void) pcicfg_device_on(handle
);
2057 PCICFG_DUMP_DEVICE_CONFIG(handle
);
2059 (void) pcicfg_config_teardown(&handle
);
2061 * Don't forget to free up memory from ddi_getlongprop
2063 kmem_free((caddr_t
)reg
, length
);
2065 return (DDI_WALK_CONTINUE
);
2069 pcicfg_device_assign(dev_info_t
*dip
)
2071 ddi_acc_handle_t handle
;
2077 ndi_ra_request_t request
;
2081 DEBUG1("%llx now under configuration\n", dip
);
2084 * XXX Failure here should be noted
2086 if (ddi_getlongprop(DDI_DEV_T_ANY
, dip
,
2087 DDI_PROP_DONTPASS
, "reg", (caddr_t
)®
,
2088 &length
) != DDI_PROP_SUCCESS
) {
2089 DEBUG0("Failed to read reg property\n");
2090 return (PCICFG_FAILURE
);
2093 if (pcicfg_config_setup(dip
, &handle
) != DDI_SUCCESS
) {
2094 DEBUG0("Failed to map config space!\n");
2096 * Don't forget to free up memory from ddi_getlongprop
2098 kmem_free((caddr_t
)reg
, length
);
2100 return (PCICFG_FAILURE
);
2106 * For each "reg" property with a length, allocate memory
2107 * and program the base registers.
2111 * If there is an interrupt pin set program
2112 * interrupt line with default values.
2114 if (pci_config_get8(handle
, PCI_CONF_IPIN
)) {
2115 pci_config_put8(handle
, PCI_CONF_ILINE
, 0xf);
2118 bzero((caddr_t
)&request
, sizeof (ndi_ra_request_t
));
2120 request
.ra_flags
= NDI_RA_ALIGN_SIZE
;
2121 request
.ra_boundbase
= 0;
2122 request
.ra_boundlen
= PCICFG_4GIG_LIMIT
;
2124 rcount
= length
/ sizeof (pci_regspec_t
);
2125 for (i
= 0; i
< rcount
; i
++) {
2126 if ((reg
[i
].pci_size_low
!= 0)||
2127 (reg
[i
].pci_size_hi
!= 0)) {
2129 offset
= PCI_REG_REG_G(reg
[i
].pci_phys_hi
);
2130 request
.ra_len
= reg
[i
].pci_size_low
;
2132 switch (PCI_REG_ADDR_G(reg
[i
].pci_phys_hi
)) {
2133 case PCI_REG_ADDR_G(PCI_ADDR_MEM64
):
2134 request
.ra_flags
&= ~NDI_RA_ALLOC_BOUNDED
;
2135 /* allocate memory space from the allocator */
2136 if (ndi_ra_alloc(ddi_get_parent(dip
),
2137 &request
, &answer
, &alen
,
2138 NDI_RA_TYPE_MEM
, NDI_RA_PASS
)
2140 DEBUG0("Failed to allocate 64b mem\n");
2141 kmem_free(reg
, length
);
2142 (void) pcicfg_config_teardown(&handle
);
2143 return (PCICFG_FAILURE
);
2145 DEBUG3("64 addr = [0x%x.%x] len [0x%x]\n",
2146 PCICFG_HIADDR(answer
),
2147 PCICFG_LOADDR(answer
),
2149 /* program the low word */
2150 pci_config_put32(handle
,
2151 offset
, PCICFG_LOADDR(answer
));
2153 /* program the high word */
2154 pci_config_put32(handle
, offset
+ 4,
2155 PCICFG_HIADDR(answer
));
2157 reg
[i
].pci_phys_low
= PCICFG_LOADDR(answer
);
2158 reg
[i
].pci_phys_mid
= PCICFG_HIADDR(answer
);
2160 /* adjust to 32b address space when possible */
2161 if ((answer
+ alen
) <= PCICFG_4GIG_LIMIT
)
2162 reg
[i
].pci_phys_hi
^=
2163 PCI_ADDR_MEM64
^ PCI_ADDR_MEM32
;
2166 case PCI_REG_ADDR_G(PCI_ADDR_MEM32
):
2167 request
.ra_flags
|= NDI_RA_ALLOC_BOUNDED
;
2168 /* allocate memory space from the allocator */
2169 if (ndi_ra_alloc(ddi_get_parent(dip
),
2170 &request
, &answer
, &alen
,
2171 NDI_RA_TYPE_MEM
, NDI_RA_PASS
)
2173 DEBUG0("Failed to allocate 32b mem\n");
2174 kmem_free(reg
, length
);
2175 (void) pcicfg_config_teardown(&handle
);
2176 return (PCICFG_FAILURE
);
2178 DEBUG3("32 addr = [0x%x.%x] len [0x%x]\n",
2179 PCICFG_HIADDR(answer
),
2180 PCICFG_LOADDR(answer
),
2182 /* program the low word */
2183 pci_config_put32(handle
,
2184 offset
, PCICFG_LOADDR(answer
));
2186 reg
[i
].pci_phys_low
= PCICFG_LOADDR(answer
);
2189 case PCI_REG_ADDR_G(PCI_ADDR_IO
):
2190 /* allocate I/O space from the allocator */
2191 request
.ra_flags
|= NDI_RA_ALLOC_BOUNDED
;
2192 if (ndi_ra_alloc(ddi_get_parent(dip
),
2193 &request
, &answer
, &alen
,
2194 NDI_RA_TYPE_IO
, NDI_RA_PASS
)
2196 DEBUG0("Failed to allocate I/O\n");
2197 kmem_free(reg
, length
);
2198 (void) pcicfg_config_teardown(&handle
);
2199 return (PCICFG_FAILURE
);
2201 DEBUG3("I/O addr = [0x%x.%x] len [0x%x]\n",
2202 PCICFG_HIADDR(answer
),
2203 PCICFG_LOADDR(answer
),
2205 pci_config_put32(handle
,
2206 offset
, PCICFG_LOADDR(answer
));
2208 reg
[i
].pci_phys_low
= PCICFG_LOADDR(answer
);
2212 DEBUG0("Unknown register type\n");
2213 kmem_free(reg
, length
);
2214 (void) pcicfg_config_teardown(&handle
);
2215 return (PCICFG_FAILURE
);
2219 * Now that memory locations are assigned,
2220 * update the assigned address property.
2223 if (pcicfg_update_assigned_prop(dip
,
2224 ®
[i
]) != PCICFG_SUCCESS
) {
2225 kmem_free(reg
, length
);
2226 (void) pcicfg_config_teardown(&handle
);
2227 return (PCICFG_FAILURE
);
2232 (void) pcicfg_device_on(handle
);
2233 kmem_free(reg
, length
);
2235 PCICFG_DUMP_DEVICE_CONFIG(handle
);
2237 (void) pcicfg_config_teardown(&handle
);
2238 return (PCICFG_SUCCESS
);
2242 pcicfg_device_assign_readonly(dev_info_t
*dip
)
2244 ddi_acc_handle_t handle
;
2245 pci_regspec_t
*assigned
;
2249 ndi_ra_request_t request
;
2254 DEBUG1("%llx now under configuration\n", dip
);
2256 if (ddi_getlongprop(DDI_DEV_T_ANY
, dip
,
2257 DDI_PROP_DONTPASS
, "assigned-addresses", (caddr_t
)&assigned
,
2258 &length
) != DDI_PROP_SUCCESS
) {
2259 DEBUG0("Failed to read assigned-addresses property\n");
2260 return (PCICFG_FAILURE
);
2263 if (pcicfg_config_setup(dip
, &handle
) != DDI_SUCCESS
) {
2264 DEBUG0("Failed to map config space!\n");
2266 * Don't forget to free up memory from ddi_getlongprop
2268 kmem_free((caddr_t
)assigned
, length
);
2270 return (PCICFG_FAILURE
);
2274 * For each "assigned-addresses" property entry with a length,
2275 * call the memory allocation routines to return the
2279 * If there is an interrupt pin set program
2280 * interrupt line with default values.
2282 if (pci_config_get8(handle
, PCI_CONF_IPIN
)) {
2283 pci_config_put8(handle
, PCI_CONF_ILINE
, 0xf);
2286 bzero((caddr_t
)&request
, sizeof (ndi_ra_request_t
));
2288 request
.ra_flags
= NDI_RA_ALLOC_SPECIFIED
; /* specified addr */
2289 request
.ra_boundbase
= 0;
2290 request
.ra_boundlen
= PCICFG_4GIG_LIMIT
;
2292 acount
= length
/ sizeof (pci_regspec_t
);
2293 for (i
= 0; i
< acount
; i
++) {
2294 if ((assigned
[i
].pci_size_low
!= 0)||
2295 (assigned
[i
].pci_size_hi
!= 0)) {
2297 request
.ra_len
= assigned
[i
].pci_size_low
;
2299 switch (PCI_REG_ADDR_G(assigned
[i
].pci_phys_hi
)) {
2300 case PCI_REG_ADDR_G(PCI_ADDR_MEM64
):
2301 request
.ra_addr
= (uint64_t)PCICFG_LADDR(
2302 assigned
[i
].pci_phys_low
,
2303 assigned
[i
].pci_phys_mid
);
2305 /* allocate memory space from the allocator */
2306 if (ndi_ra_alloc(ddi_get_parent(dip
),
2307 &request
, &answer
, &alen
,
2308 NDI_RA_TYPE_MEM
, NDI_RA_PASS
)
2310 DEBUG0("Failed to allocate 64b mem\n");
2311 kmem_free(assigned
, length
);
2312 return (PCICFG_FAILURE
);
2316 case PCI_REG_ADDR_G(PCI_ADDR_MEM32
):
2317 request
.ra_addr
= (uint64_t)
2318 assigned
[i
].pci_phys_low
;
2320 /* allocate memory space from the allocator */
2321 if (ndi_ra_alloc(ddi_get_parent(dip
),
2322 &request
, &answer
, &alen
,
2323 NDI_RA_TYPE_MEM
, NDI_RA_PASS
)
2325 DEBUG0("Failed to allocate 32b mem\n");
2326 kmem_free(assigned
, length
);
2327 return (PCICFG_FAILURE
);
2331 case PCI_REG_ADDR_G(PCI_ADDR_IO
):
2332 request
.ra_addr
= (uint64_t)
2333 assigned
[i
].pci_phys_low
;
2335 /* allocate I/O space from the allocator */
2336 if (ndi_ra_alloc(ddi_get_parent(dip
),
2337 &request
, &answer
, &alen
,
2338 NDI_RA_TYPE_IO
, NDI_RA_PASS
)
2340 DEBUG0("Failed to allocate I/O\n");
2341 kmem_free(assigned
, length
);
2342 return (PCICFG_FAILURE
);
2347 DEBUG0("Unknown register type\n");
2348 kmem_free(assigned
, length
);
2349 return (PCICFG_FAILURE
);
2354 (void) pcicfg_device_on(handle
);
2355 kmem_free(assigned
, length
);
2357 PCICFG_DUMP_DEVICE_CONFIG(handle
);
2359 (void) pcicfg_config_teardown(&handle
);
2360 return (PCICFG_SUCCESS
);
2364 * The "dip" passed to this routine is assumed to be
2365 * the device at the Hotplug Connection (CN). Currently it is
2366 * assumed to be a bridge.
2369 pcicfg_allocate_chunk(dev_info_t
*dip
)
2371 pcicfg_phdl_t
*phdl
;
2372 ndi_ra_request_t
*mem_request
;
2373 ndi_ra_request_t
*io_request
;
2374 uint64_t mem_answer
;
2380 * This should not find an existing entry - so
2381 * it will create a new one.
2383 phdl
= pcicfg_find_phdl(dip
);
2386 mem_request
= &phdl
->mem_req
;
2387 io_request
= &phdl
->io_req
;
2390 * From this point in the tree - walk the devices,
2391 * The function passed in will read and "sum" up
2392 * the memory and I/O requirements and put them in
2395 ndi_devi_enter(ddi_get_parent(dip
), &count
);
2396 ddi_walk_devs(dip
, pcicfg_sum_resources
, (void *)phdl
);
2397 ndi_devi_exit(ddi_get_parent(dip
), count
);
2399 if (phdl
->error
!= PCICFG_SUCCESS
) {
2400 DEBUG0("Failure summing resources\n");
2401 return (phdl
->error
);
2405 * Call into the memory allocator with the request.
2406 * Record the addresses returned in the phdl
2408 DEBUG1("Connector requires [0x%x] bytes of memory space\n",
2409 mem_request
->ra_len
);
2410 DEBUG1("Connector requires [0x%x] bytes of I/O space\n",
2411 io_request
->ra_len
);
2413 mem_request
->ra_align_mask
=
2414 PCICFG_MEMGRAN
- 1; /* 1M alignment on memory space */
2415 io_request
->ra_align_mask
=
2416 PCICFG_IOGRAN
- 1; /* 4K alignment on I/O space */
2417 io_request
->ra_boundbase
= 0;
2418 io_request
->ra_boundlen
= PCICFG_4GIG_LIMIT
;
2419 io_request
->ra_flags
|= NDI_RA_ALLOC_BOUNDED
;
2421 mem_request
->ra_len
=
2422 PCICFG_ROUND_UP(mem_request
->ra_len
, PCICFG_MEMGRAN
);
2424 io_request
->ra_len
=
2425 PCICFG_ROUND_UP(io_request
->ra_len
, PCICFG_IOGRAN
);
2427 if (ndi_ra_alloc(ddi_get_parent(dip
),
2428 mem_request
, &mem_answer
, &alen
,
2429 NDI_RA_TYPE_MEM
, NDI_RA_PASS
) != NDI_SUCCESS
) {
2430 DEBUG0("Failed to allocate memory\n");
2431 return (PCICFG_FAILURE
);
2434 phdl
->memory_base
= phdl
->memory_last
= mem_answer
;
2435 phdl
->memory_len
= alen
;
2437 phdl
->mem_hole
.start
= phdl
->memory_base
;
2438 phdl
->mem_hole
.len
= phdl
->memory_len
;
2439 phdl
->mem_hole
.next
= (hole_t
*)NULL
;
2441 if (ndi_ra_alloc(ddi_get_parent(dip
), io_request
, &io_answer
,
2442 &alen
, NDI_RA_TYPE_IO
, NDI_RA_PASS
) != NDI_SUCCESS
) {
2444 DEBUG0("Failed to allocate I/O space\n");
2445 (void) ndi_ra_free(ddi_get_parent(dip
), mem_answer
,
2446 alen
, NDI_RA_TYPE_MEM
, NDI_RA_PASS
);
2447 phdl
->memory_len
= phdl
->io_len
= 0;
2448 return (PCICFG_FAILURE
);
2451 phdl
->io_base
= phdl
->io_last
= (uint32_t)io_answer
;
2452 phdl
->io_len
= (uint32_t)alen
;
2454 phdl
->io_hole
.start
= phdl
->io_base
;
2455 phdl
->io_hole
.len
= phdl
->io_len
;
2456 phdl
->io_hole
.next
= (hole_t
*)NULL
;
2458 DEBUG2("MEMORY BASE = [0x%x] length [0x%x]\n",
2459 phdl
->memory_base
, phdl
->memory_len
);
2460 DEBUG2("IO BASE = [0x%x] length [0x%x]\n",
2461 phdl
->io_base
, phdl
->io_len
);
2463 return (PCICFG_SUCCESS
);
2468 * This function is useful in debug mode, where we can measure how
2469 * much memory was wasted/unallocated in bridge device's domain.
2472 pcicfg_unused_space(hole_t
*hole
, uint32_t *hole_count
)
2482 *hole_count
= count
;
2488 * This function frees data structures that hold the hole information
2489 * which are allocated in pcicfg_alloc_hole(). This is not freeing
2490 * any memory allocated through NDI calls.
2493 pcicfg_free_hole(hole_t
*addr_hole
)
2495 hole_t
*nhole
, *hole
= addr_hole
->next
;
2499 kmem_free(hole
, sizeof (hole_t
));
2505 pcicfg_alloc_hole(hole_t
*addr_hole
, uint64_t *alast
, uint32_t length
)
2507 uint64_t actual_hole_start
, ostart
, olen
;
2508 hole_t
*hole
= addr_hole
, *thole
, *nhole
;
2511 actual_hole_start
= PCICFG_ROUND_UP(hole
->start
, length
);
2512 if (((actual_hole_start
- hole
->start
) + length
) <= hole
->len
) {
2513 DEBUG3("hole found. start %llx, len %llx, req=%x\n",
2514 hole
->start
, hole
->len
, length
);
2515 ostart
= hole
->start
;
2517 /* current hole parameters adjust */
2518 if ((actual_hole_start
- hole
->start
) == 0) {
2519 hole
->start
+= length
;
2520 hole
->len
-= length
;
2521 if (hole
->start
> *alast
)
2522 *alast
= hole
->start
;
2524 hole
->len
= actual_hole_start
- hole
->start
;
2525 nhole
= (hole_t
*)kmem_zalloc(sizeof (hole_t
),
2527 nhole
->start
= actual_hole_start
+ length
;
2528 nhole
->len
= (ostart
+ olen
) - nhole
->start
;
2532 nhole
->next
= thole
;
2533 if (nhole
->start
> *alast
)
2534 *alast
= nhole
->start
;
2535 DEBUG2("put new hole to %llx, %llx\n",
2536 nhole
->start
, nhole
->len
);
2538 DEBUG2("adjust current hole to %llx, %llx\n",
2539 hole
->start
, hole
->len
);
2542 actual_hole_start
= 0;
2546 DEBUG1("return hole at %llx\n", actual_hole_start
);
2547 return (actual_hole_start
);
2551 pcicfg_get_mem(pcicfg_phdl_t
*entry
,
2552 uint32_t length
, uint64_t *ans
)
2556 /* See if there is a hole, that can hold this request. */
2557 new_mem
= pcicfg_alloc_hole(&entry
->mem_hole
, &entry
->memory_last
,
2559 if (new_mem
) { /* if non-zero, found a hole. */
2563 cmn_err(CE_WARN
, "No %u bytes memory window for %s\n",
2564 length
, ddi_get_name(entry
->dip
));
2568 pcicfg_get_io(pcicfg_phdl_t
*entry
,
2569 uint32_t length
, uint32_t *ans
)
2575 * See if there is a hole, that can hold this request.
2576 * Pass 64 bit parameters and then truncate to 32 bit.
2578 io_last
= entry
->io_last
;
2579 new_io
= (uint32_t)pcicfg_alloc_hole(&entry
->io_hole
, &io_last
, length
);
2580 if (new_io
) { /* if non-zero, found a hole. */
2581 entry
->io_last
= (uint32_t)io_last
;
2585 cmn_err(CE_WARN
, "No %u bytes IO space window for %s\n",
2586 length
, ddi_get_name(entry
->dip
));
2590 pcicfg_sum_resources(dev_info_t
*dip
, void *hdl
)
2592 pcicfg_phdl_t
*entry
= (pcicfg_phdl_t
*)hdl
;
2593 pci_regspec_t
*pci_rp
;
2597 ndi_ra_request_t
*mem_request
;
2598 ndi_ra_request_t
*io_request
;
2599 uint8_t header_type
;
2600 ddi_acc_handle_t handle
;
2602 entry
->error
= PCICFG_SUCCESS
;
2604 mem_request
= &entry
->mem_req
;
2605 io_request
= &entry
->io_req
;
2607 if (pcicfg_config_setup(dip
, &handle
) != DDI_SUCCESS
) {
2608 DEBUG0("Failed to map config space!\n");
2609 entry
->error
= PCICFG_FAILURE
;
2610 return (DDI_WALK_TERMINATE
);
2613 header_type
= pci_config_get8(handle
, PCI_CONF_HEADER
);
2616 * If its a bridge - just record the highest bus seen
2618 if ((header_type
& PCI_HEADER_TYPE_M
) == PCI_HEADER_PPB
) {
2620 if (entry
->highest_bus
< pci_config_get8(handle
,
2622 entry
->highest_bus
=
2623 pci_config_get8(handle
, PCI_BCNF_SECBUS
);
2626 (void) pcicfg_config_teardown(&handle
);
2627 entry
->error
= PCICFG_FAILURE
;
2628 return (DDI_WALK_CONTINUE
);
2630 if (ddi_getlongprop(DDI_DEV_T_ANY
, dip
,
2631 DDI_PROP_DONTPASS
, "reg", (caddr_t
)&pci_rp
,
2632 &length
) != DDI_PROP_SUCCESS
) {
2634 * If one node in (the subtree of nodes)
2635 * does'nt have a "reg" property fail the
2638 entry
->memory_len
= 0;
2640 entry
->error
= PCICFG_FAILURE
;
2641 return (DDI_WALK_TERMINATE
);
2644 * For each "reg" property with a length, add that to the
2645 * total memory (or I/O) to allocate.
2647 rcount
= length
/ sizeof (pci_regspec_t
);
2649 for (i
= 0; i
< rcount
; i
++) {
2651 switch (PCI_REG_ADDR_G(pci_rp
[i
].pci_phys_hi
)) {
2653 case PCI_REG_ADDR_G(PCI_ADDR_MEM32
):
2654 mem_request
->ra_len
=
2655 pci_rp
[i
].pci_size_low
+
2656 PCICFG_ROUND_UP(mem_request
->ra_len
,
2657 pci_rp
[i
].pci_size_low
);
2658 DEBUG1("ADDING 32 --->0x%x\n",
2659 pci_rp
[i
].pci_size_low
);
2662 case PCI_REG_ADDR_G(PCI_ADDR_MEM64
):
2663 mem_request
->ra_len
=
2664 pci_rp
[i
].pci_size_low
+
2665 PCICFG_ROUND_UP(mem_request
->ra_len
,
2666 pci_rp
[i
].pci_size_low
);
2667 DEBUG1("ADDING 64 --->0x%x\n",
2668 pci_rp
[i
].pci_size_low
);
2671 case PCI_REG_ADDR_G(PCI_ADDR_IO
):
2672 io_request
->ra_len
=
2673 pci_rp
[i
].pci_size_low
+
2674 PCICFG_ROUND_UP(io_request
->ra_len
,
2675 pci_rp
[i
].pci_size_low
);
2676 DEBUG1("ADDING I/O --->0x%x\n",
2677 pci_rp
[i
].pci_size_low
);
2680 /* Config space register - not included */
2686 * free the memory allocated by ddi_getlongprop
2688 kmem_free(pci_rp
, length
);
2691 * continue the walk to the next sibling to sum memory
2694 (void) pcicfg_config_teardown(&handle
);
2696 return (DDI_WALK_CONTINUE
);
2701 pcicfg_find_resource_end(dev_info_t
*dip
, void *hdl
)
2703 pcicfg_phdl_t
*entry_p
= (pcicfg_phdl_t
*)hdl
;
2704 pci_regspec_t
*pci_ap
;
2705 pcicfg_range_t
*ranges
;
2710 entry_p
->error
= PCICFG_SUCCESS
;
2712 if (dip
== entry_p
->dip
) {
2713 DEBUG0("Don't include parent bridge node\n");
2714 return (DDI_WALK_CONTINUE
);
2717 if (ddi_getlongprop(DDI_DEV_T_ANY
, dip
,
2718 DDI_PROP_DONTPASS
, "ranges",
2719 (caddr_t
)&ranges
, &length
) != DDI_PROP_SUCCESS
) {
2720 DEBUG0("Node doesn't have ranges\n");
2724 rcount
= length
/ sizeof (pcicfg_range_t
);
2726 for (i
= 0; i
< rcount
; i
++) {
2728 uint64_t mid
= ranges
[i
].child_mid
;
2729 uint64_t lo
= ranges
[i
].child_lo
;
2730 uint64_t size
= ranges
[i
].size_lo
;
2732 switch (PCI_REG_ADDR_G(ranges
[i
].child_hi
)) {
2734 case PCI_REG_ADDR_G(PCI_ADDR_MEM32
):
2735 base
= entry_p
->memory_base
;
2736 entry_p
->memory_base
= MAX(base
, lo
+ size
);
2738 case PCI_REG_ADDR_G(PCI_ADDR_MEM64
):
2739 base
= entry_p
->memory_base
;
2740 entry_p
->memory_base
= MAX(base
,
2741 PCICFG_LADDR(lo
, mid
) + size
);
2743 case PCI_REG_ADDR_G(PCI_ADDR_IO
):
2744 base
= entry_p
->io_base
;
2745 entry_p
->io_base
= MAX(base
, lo
+ size
);
2750 kmem_free(ranges
, length
);
2751 return (DDI_WALK_CONTINUE
);
2753 ap
: if (ddi_getlongprop(DDI_DEV_T_ANY
, dip
,
2754 DDI_PROP_DONTPASS
, "assigned-addresses",
2755 (caddr_t
)&pci_ap
, &length
) != DDI_PROP_SUCCESS
) {
2756 DEBUG0("Node doesn't have assigned-addresses\n");
2757 return (DDI_WALK_CONTINUE
);
2760 rcount
= length
/ sizeof (pci_regspec_t
);
2762 for (i
= 0; i
< rcount
; i
++) {
2764 switch (PCI_REG_ADDR_G(pci_ap
[i
].pci_phys_hi
)) {
2766 case PCI_REG_ADDR_G(PCI_ADDR_MEM32
):
2767 if ((pci_ap
[i
].pci_phys_low
+
2768 pci_ap
[i
].pci_size_low
) >
2769 entry_p
->memory_base
) {
2770 entry_p
->memory_base
=
2771 pci_ap
[i
].pci_phys_low
+
2772 pci_ap
[i
].pci_size_low
;
2775 case PCI_REG_ADDR_G(PCI_ADDR_MEM64
):
2776 if ((PCICFG_LADDR(pci_ap
[i
].pci_phys_low
,
2777 pci_ap
[i
].pci_phys_mid
) +
2778 pci_ap
[i
].pci_size_low
) >
2779 entry_p
->memory_base
) {
2780 entry_p
->memory_base
= PCICFG_LADDR(
2781 pci_ap
[i
].pci_phys_low
,
2782 pci_ap
[i
].pci_phys_mid
) +
2783 pci_ap
[i
].pci_size_low
;
2786 case PCI_REG_ADDR_G(PCI_ADDR_IO
):
2787 if ((pci_ap
[i
].pci_phys_low
+
2788 pci_ap
[i
].pci_size_low
) >
2791 pci_ap
[i
].pci_phys_low
+
2792 pci_ap
[i
].pci_size_low
;
2799 * free the memory allocated by ddi_getlongprop
2801 kmem_free(pci_ap
, length
);
2804 * continue the walk to the next sibling to sum memory
2806 return (DDI_WALK_CONTINUE
);
2810 pcicfg_free_bridge_resources(dev_info_t
*dip
)
2812 pcicfg_range_t
*ranges
;
2819 if (ddi_getlongprop(DDI_DEV_T_ANY
, dip
,
2820 DDI_PROP_DONTPASS
, "ranges", (caddr_t
)&ranges
,
2821 &length
) != DDI_PROP_SUCCESS
) {
2822 DEBUG0("Failed to read ranges property\n");
2823 if (ddi_get_child(dip
)) {
2824 cmn_err(CE_WARN
, "No ranges property found for %s",
2827 * strictly speaking, we can check for children with
2828 * assigned-addresses but for now it is better to
2829 * be conservative and assume that if there are child
2830 * nodes, then they do consume PCI memory or IO
2831 * resources, Hence return failure.
2833 return (PCICFG_FAILURE
);
2839 for (i
= 0; i
< length
/ sizeof (pcicfg_range_t
); i
++) {
2840 if (ranges
[i
].size_lo
!= 0 ||
2841 ranges
[i
].size_hi
!= 0) {
2842 switch (ranges
[i
].parent_hi
& PCI_REG_ADDR_M
) {
2845 "base/length = [0x%x]/[0x%x]\n",
2848 if (ndi_ra_free(ddi_get_parent(dip
),
2849 (uint64_t)ranges
[i
].child_lo
,
2850 (uint64_t)ranges
[i
].size_lo
,
2851 NDI_RA_TYPE_IO
, NDI_RA_PASS
)
2853 DEBUG0("Trouble freeing "
2855 kmem_free(ranges
, length
);
2856 return (PCICFG_FAILURE
);
2859 case PCI_ADDR_MEM32
:
2860 case PCI_ADDR_MEM64
:
2861 DEBUG3("Free Memory base/length = "
2862 "[0x%x.%x]/[0x%x]\n",
2863 ranges
[i
].child_mid
,
2866 if (ndi_ra_free(ddi_get_parent(dip
),
2867 PCICFG_LADDR(ranges
[i
].child_lo
,
2868 ranges
[i
].child_mid
),
2869 (uint64_t)ranges
[i
].size_lo
,
2870 NDI_RA_TYPE_MEM
, NDI_RA_PASS
)
2872 DEBUG0("Trouble freeing "
2873 "PCI memory space\n");
2874 kmem_free(ranges
, length
);
2875 return (PCICFG_FAILURE
);
2879 DEBUG0("Unknown memory space\n");
2886 kmem_free(ranges
, length
);
2888 if (ddi_getlongprop(DDI_DEV_T_ANY
, dip
,
2889 DDI_PROP_DONTPASS
, "bus-range", (caddr_t
)&bus
,
2890 &k
) != DDI_PROP_SUCCESS
) {
2891 DEBUG0("Failed to read bus-range property\n");
2892 return (PCICFG_FAILURE
);
2895 DEBUG2("Need to free bus [%d] range [%d]\n",
2896 bus
[0], bus
[1] - bus
[0] + 1);
2898 if (ndi_ra_free(ddi_get_parent(dip
),
2899 (uint64_t)bus
[0], (uint64_t)(bus
[1] - bus
[0] + 1),
2900 NDI_RA_TYPE_PCI_BUSNUM
, NDI_RA_PASS
) != NDI_SUCCESS
) {
2902 DEBUG0("Failed to free a bus number\n");
2905 * Don't forget to free up memory from ddi_getlongprop
2907 kmem_free((caddr_t
)bus
, k
);
2909 return (PCICFG_SUCCESS
);
2913 pcicfg_free_device_resources(dev_info_t
*dip
, pcicfg_flags_t flags
)
2915 pci_regspec_t
*assigned
;
2921 if (ddi_getlongprop(DDI_DEV_T_ANY
, dip
,
2922 DDI_PROP_DONTPASS
, "assigned-addresses", (caddr_t
)&assigned
,
2923 &length
) != DDI_PROP_SUCCESS
) {
2924 DEBUG0("Failed to read assigned-addresses property\n");
2925 return (PCICFG_FAILURE
);
2929 * For each "assigned-addresses" property entry with a length,
2930 * call the memory allocation routines to return the
2933 acount
= length
/ sizeof (pci_regspec_t
);
2934 for (i
= 0; i
< acount
; i
++) {
2936 * Workaround for Devconf (x86) bug to skip extra entries
2937 * beyond the PCI_CONF_BASE5 offset. But we want to free up
2938 * any memory for expansion roms if allocated.
2940 if ((PCI_REG_REG_G(assigned
[i
].pci_phys_hi
) > PCI_CONF_BASE5
) &&
2941 (PCI_REG_REG_G(assigned
[i
].pci_phys_hi
) != PCI_CONF_ROM
))
2944 if (pcicfg_free_resource(dip
, assigned
[i
], flags
)) {
2945 DEBUG1("pcicfg_free_device_resources - Trouble freeing "
2946 "%x\n", assigned
[i
].pci_phys_hi
);
2948 * Don't forget to free up memory from ddi_getlongprop
2950 kmem_free((caddr_t
)assigned
, length
);
2952 return (PCICFG_FAILURE
);
2955 kmem_free(assigned
, length
);
2956 return (PCICFG_SUCCESS
);
2960 pcicfg_free_resources(dev_info_t
*dip
, pcicfg_flags_t flags
)
2962 ddi_acc_handle_t handle
;
2963 uint8_t header_type
;
2965 if (pcicfg_config_setup(dip
, &handle
) != DDI_SUCCESS
) {
2966 DEBUG0("Failed to map config space!\n");
2967 return (PCICFG_FAILURE
);
2970 header_type
= pci_config_get8(handle
, PCI_CONF_HEADER
);
2972 (void) pci_config_teardown(&handle
);
2975 * A different algorithm is used for bridges and leaf devices.
2977 if ((header_type
& PCI_HEADER_TYPE_M
) == PCI_HEADER_PPB
) {
2979 * We only support readonly probing for leaf devices.
2981 if (flags
& PCICFG_FLAG_READ_ONLY
)
2982 return (PCICFG_FAILURE
);
2984 if (pcicfg_free_bridge_resources(dip
) != PCICFG_SUCCESS
) {
2985 DEBUG0("Failed freeing up bridge resources\n");
2986 return (PCICFG_FAILURE
);
2989 if (pcicfg_free_device_resources(dip
, flags
)
2990 != PCICFG_SUCCESS
) {
2991 DEBUG0("Failed freeing up device resources\n");
2992 return (PCICFG_FAILURE
);
2995 return (PCICFG_SUCCESS
);
2998 #ifndef _DONT_USE_1275_GENERIC_NAMES
3000 pcicfg_get_class_name(uint32_t classcode
)
3002 struct pcicfg_name_entry
*ptr
;
3004 for (ptr
= &pcicfg_class_lookup
[0]; ptr
->name
!= NULL
; ptr
++) {
3005 if (ptr
->class_code
== classcode
) {
3011 #endif /* _DONT_USE_1275_GENERIC_NAMES */
3014 pcicfg_devi_find(dev_info_t
*dip
, uint_t device
, uint_t function
)
3016 struct pcicfg_find_ctrl ctrl
;
3019 ctrl
.device
= device
;
3020 ctrl
.function
= function
;
3023 ndi_devi_enter(dip
, &count
);
3024 ddi_walk_devs(ddi_get_child(dip
), pcicfg_match_dev
, (void *)&ctrl
);
3025 ndi_devi_exit(dip
, count
);
3031 pcicfg_match_dev(dev_info_t
*dip
, void *hdl
)
3033 struct pcicfg_find_ctrl
*ctrl
= (struct pcicfg_find_ctrl
*)hdl
;
3034 pci_regspec_t
*pci_rp
;
3039 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY
, dip
,
3040 DDI_PROP_DONTPASS
, "reg", (int **)&pci_rp
,
3041 (uint_t
*)&length
) != DDI_PROP_SUCCESS
) {
3043 return (DDI_WALK_TERMINATE
);
3046 /* get the PCI device address info */
3047 pci_dev
= PCI_REG_DEV_G(pci_rp
->pci_phys_hi
);
3048 pci_func
= PCI_REG_FUNC_G(pci_rp
->pci_phys_hi
);
3051 * free the memory allocated by ddi_prop_lookup_int_array
3053 ddi_prop_free(pci_rp
);
3056 if ((pci_dev
== ctrl
->device
) && (pci_func
== ctrl
->function
)) {
3057 /* found the match for the specified device address */
3059 return (DDI_WALK_TERMINATE
);
3063 * continue the walk to the next sibling to look for a match.
3065 return (DDI_WALK_PRUNECHILD
);
3069 pcicfg_update_assigned_prop(dev_info_t
*dip
, pci_regspec_t
*newone
)
3072 pci_regspec_t
*assigned
;
3076 DEBUG0("pcicfg_update_assigned_prop()\n");
3077 status
= ddi_getlongprop(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
3078 "assigned-addresses", (caddr_t
)&assigned
, &alen
);
3080 case DDI_PROP_SUCCESS
:
3082 case DDI_PROP_NO_MEMORY
:
3083 DEBUG0("no memory for assigned-addresses property\n");
3084 return (PCICFG_FAILURE
);
3086 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE
, dip
,
3087 "assigned-addresses", (int *)newone
,
3088 sizeof (*newone
)/sizeof (int));
3090 (void) pcicfg_dump_assigned(dip
);
3092 return (PCICFG_SUCCESS
);
3096 * Allocate memory for the existing
3097 * assigned-addresses(s) plus one and then
3101 newreg
= kmem_zalloc(alen
+sizeof (*newone
), KM_SLEEP
);
3103 bcopy(assigned
, newreg
, alen
);
3104 bcopy(newone
, newreg
+ alen
, sizeof (*newone
));
3107 * Write out the new "assigned-addresses" spec
3109 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE
, dip
,
3110 "assigned-addresses", (int *)newreg
,
3111 (alen
+ sizeof (*newone
))/sizeof (int));
3113 kmem_free((caddr_t
)newreg
, alen
+sizeof (*newone
));
3116 * Don't forget to free up memory from ddi_getlongprop
3118 kmem_free((caddr_t
)assigned
, alen
);
3120 (void) pcicfg_dump_assigned(dip
);
3122 return (PCICFG_SUCCESS
);
3125 pcicfg_update_ranges_prop(dev_info_t
*dip
, pcicfg_range_t
*addition
)
3128 pcicfg_range_t
*ranges
;
3132 status
= ddi_getlongprop(DDI_DEV_T_ANY
,
3133 dip
, DDI_PROP_DONTPASS
, "ranges", (caddr_t
)&ranges
, &rlen
);
3137 case DDI_PROP_SUCCESS
:
3139 case DDI_PROP_NO_MEMORY
:
3140 DEBUG0("ranges present, but unable to get memory\n");
3141 return (PCICFG_FAILURE
);
3143 DEBUG0("no ranges property - creating one\n");
3144 if (ndi_prop_update_int_array(DDI_DEV_T_NONE
,
3145 dip
, "ranges", (int *)addition
,
3146 sizeof (pcicfg_range_t
)/sizeof (int))
3148 DEBUG0("Did'nt create ranges property\n");
3149 return (PCICFG_FAILURE
);
3151 return (PCICFG_SUCCESS
);
3155 * Allocate memory for the existing reg(s) plus one and then
3158 newreg
= kmem_zalloc(rlen
+ sizeof (pcicfg_range_t
), KM_SLEEP
);
3160 bcopy(ranges
, newreg
, rlen
);
3161 bcopy(addition
, newreg
+ rlen
, sizeof (pcicfg_range_t
));
3164 * Write out the new "ranges" property
3166 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE
,
3167 dip
, "ranges", (int *)newreg
,
3168 (rlen
+ sizeof (pcicfg_range_t
))/sizeof (int));
3170 kmem_free((caddr_t
)newreg
, rlen
+sizeof (pcicfg_range_t
));
3172 kmem_free((caddr_t
)ranges
, rlen
);
3174 return (PCICFG_SUCCESS
);
3178 pcicfg_update_reg_prop(dev_info_t
*dip
, uint32_t regvalue
, uint_t reg_offset
)
3184 pci_regspec_t addition
;
3188 status
= ddi_getlongprop(DDI_DEV_T_ANY
,
3189 dip
, DDI_PROP_DONTPASS
, "reg", (caddr_t
)®
, &rlen
);
3192 case DDI_PROP_SUCCESS
:
3194 case DDI_PROP_NO_MEMORY
:
3195 DEBUG0("reg present, but unable to get memory\n");
3196 return (PCICFG_FAILURE
);
3198 DEBUG0("no reg property\n");
3199 return (PCICFG_FAILURE
);
3203 * Allocate memory for the existing reg(s) plus one and then
3206 newreg
= kmem_zalloc(rlen
+sizeof (pci_regspec_t
), KM_SLEEP
);
3209 * Build the regspec, then add it to the existing one(s)
3212 hiword
= PCICFG_MAKE_REG_HIGH(PCI_REG_BUS_G(reg
->pci_phys_hi
),
3213 PCI_REG_DEV_G(reg
->pci_phys_hi
),
3214 PCI_REG_FUNC_G(reg
->pci_phys_hi
), reg_offset
);
3216 if (reg_offset
== PCI_CONF_ROM
) {
3217 size
= (~(PCI_BASE_ROM_ADDR_M
& regvalue
))+1;
3218 hiword
|= PCI_ADDR_MEM32
;
3220 size
= (~(PCI_BASE_M_ADDR_M
& regvalue
))+1;
3222 if ((PCI_BASE_SPACE_M
& regvalue
) == PCI_BASE_SPACE_MEM
) {
3223 if ((PCI_BASE_TYPE_M
& regvalue
) == PCI_BASE_TYPE_MEM
) {
3224 hiword
|= PCI_ADDR_MEM32
;
3225 } else if ((PCI_BASE_TYPE_M
& regvalue
)
3226 == PCI_BASE_TYPE_ALL
) {
3227 hiword
|= PCI_ADDR_MEM64
;
3230 hiword
|= PCI_ADDR_IO
;
3234 addition
.pci_phys_hi
= hiword
;
3235 addition
.pci_phys_mid
= 0;
3236 addition
.pci_phys_low
= 0;
3237 addition
.pci_size_hi
= 0;
3238 addition
.pci_size_low
= size
;
3240 bcopy(reg
, newreg
, rlen
);
3241 bcopy(&addition
, newreg
+ rlen
, sizeof (pci_regspec_t
));
3244 * Write out the new "reg" property
3246 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE
,
3247 dip
, "reg", (int *)newreg
,
3248 (rlen
+ sizeof (pci_regspec_t
))/sizeof (int));
3250 kmem_free((caddr_t
)newreg
, rlen
+sizeof (pci_regspec_t
));
3251 kmem_free((caddr_t
)reg
, rlen
);
3253 return (PCICFG_SUCCESS
);
3256 pcicfg_update_available_prop(dev_info_t
*dip
, pci_regspec_t
*newone
)
3259 pci_regspec_t
*avail_p
;
3263 DEBUG2("pcicfg_update_available_prop() - Address %lx Size %x\n",
3264 newone
->pci_phys_low
, newone
->pci_size_low
);
3265 status
= ddi_getlongprop(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
3266 "available", (caddr_t
)&avail_p
, &alen
);
3268 case DDI_PROP_SUCCESS
:
3270 case DDI_PROP_NO_MEMORY
:
3271 DEBUG0("no memory for available property\n");
3272 return (PCICFG_FAILURE
);
3274 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE
, dip
,
3275 "available", (int *)newone
,
3276 sizeof (*newone
)/sizeof (int));
3278 return (PCICFG_SUCCESS
);
3282 * Allocate memory for the existing available plus one and then
3285 new_avail
= kmem_zalloc(alen
+sizeof (*newone
), KM_SLEEP
);
3287 bcopy(avail_p
, new_avail
, alen
);
3288 bcopy(newone
, new_avail
+ alen
, sizeof (*newone
));
3290 /* Write out the new "available" spec */
3291 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE
, dip
,
3292 "available", (int *)new_avail
,
3293 (alen
+ sizeof (*newone
))/sizeof (int));
3295 kmem_free((caddr_t
)new_avail
, alen
+sizeof (*newone
));
3297 /* Don't forget to free up memory from ddi_getlongprop */
3298 kmem_free((caddr_t
)avail_p
, alen
);
3300 return (PCICFG_SUCCESS
);
3304 pcicfg_update_assigned_prop_value(dev_info_t
*dip
, uint32_t size
,
3305 uint32_t base
, uint32_t base_hi
, uint_t reg_offset
)
3310 pci_regspec_t addition
;
3313 status
= ddi_getlongprop(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
3314 "reg", (caddr_t
)®
, &rlen
);
3317 case DDI_PROP_SUCCESS
:
3319 case DDI_PROP_NO_MEMORY
:
3320 DEBUG0("reg present, but unable to get memory\n");
3321 return (PCICFG_FAILURE
);
3324 * Since the config space "reg" entry should have been
3325 * created, we expect a "reg" property already
3328 DEBUG0("no reg property\n");
3329 return (PCICFG_FAILURE
);
3333 * Build the regspec, then add it to the existing one(s)
3336 hiword
= PCICFG_MAKE_REG_HIGH(PCI_REG_BUS_G(reg
->pci_phys_hi
),
3337 PCI_REG_DEV_G(reg
->pci_phys_hi
),
3338 PCI_REG_FUNC_G(reg
->pci_phys_hi
), reg_offset
);
3340 hiword
|= PCI_REG_REL_M
;
3342 if (reg_offset
== PCI_CONF_ROM
) {
3343 hiword
|= PCI_ADDR_MEM32
;
3345 base
= PCI_BASE_ROM_ADDR_M
& base
;
3347 if ((PCI_BASE_SPACE_M
& base
) == PCI_BASE_SPACE_MEM
) {
3348 if ((PCI_BASE_TYPE_M
& base
) == PCI_BASE_TYPE_MEM
) {
3349 hiword
|= PCI_ADDR_MEM32
;
3350 } else if ((PCI_BASE_TYPE_M
& base
)
3351 == PCI_BASE_TYPE_ALL
) {
3352 hiword
|= PCI_ADDR_MEM64
;
3355 if (base
& PCI_BASE_PREF_M
)
3356 hiword
|= PCI_REG_PF_M
;
3358 base
= PCI_BASE_M_ADDR_M
& base
;
3360 hiword
|= PCI_ADDR_IO
;
3362 base
= PCI_BASE_IO_ADDR_M
& base
;
3367 addition
.pci_phys_hi
= hiword
;
3368 addition
.pci_phys_mid
= base_hi
;
3369 addition
.pci_phys_low
= base
;
3370 addition
.pci_size_hi
= 0;
3371 addition
.pci_size_low
= size
;
3373 DEBUG3("updating BAR@off %x with %x,%x\n", reg_offset
, hiword
, size
);
3375 kmem_free((caddr_t
)reg
, rlen
);
3377 return (pcicfg_update_assigned_prop(dip
, &addition
));
3381 pcicfg_device_on(ddi_acc_handle_t config_handle
)
3384 * Enable memory, IO, and bus mastership
3385 * XXX should we enable parity, SERR#,
3386 * fast back-to-back, and addr. stepping?
3388 pci_config_put16(config_handle
, PCI_CONF_COMM
,
3389 pci_config_get16(config_handle
, PCI_CONF_COMM
) | 0x7);
3393 pcicfg_device_off(ddi_acc_handle_t config_handle
)
3396 * Disable I/O and memory traffic through the bridge
3398 pci_config_put16(config_handle
, PCI_CONF_COMM
, 0x0);
3402 * Setup the basic 1275 properties based on information found in the config
3403 * header of the PCI device
3406 pcicfg_set_standard_props(dev_info_t
*dip
, ddi_acc_handle_t config_handle
,
3410 uint16_t val
, cap_ptr
;
3414 /* These two exists only for non-bridges */
3415 if (((pci_config_get8(config_handle
, PCI_CONF_HEADER
)
3416 & PCI_HEADER_TYPE_M
) == PCI_HEADER_ZERO
) && !pcie_dev
) {
3417 byteval
= pci_config_get8(config_handle
, PCI_CONF_MIN_G
);
3418 if ((ret
= ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
3419 "min-grant", byteval
)) != DDI_SUCCESS
) {
3423 byteval
= pci_config_get8(config_handle
, PCI_CONF_MAX_L
);
3424 if ((ret
= ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
3425 "max-latency", byteval
)) != DDI_SUCCESS
) {
3431 * These should always exist and have the value of the
3432 * corresponding register value
3434 val
= pci_config_get16(config_handle
, PCI_CONF_VENID
);
3436 if ((ret
= ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
3437 "vendor-id", val
)) != DDI_SUCCESS
) {
3440 val
= pci_config_get16(config_handle
, PCI_CONF_DEVID
);
3441 if ((ret
= ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
3442 "device-id", val
)) != DDI_SUCCESS
) {
3445 byteval
= pci_config_get8(config_handle
, PCI_CONF_REVID
);
3446 if ((ret
= ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
3447 "revision-id", byteval
)) != DDI_SUCCESS
) {
3451 wordval
= (pci_config_get16(config_handle
, PCI_CONF_SUBCLASS
)<< 8) |
3452 (pci_config_get8(config_handle
, PCI_CONF_PROGCLASS
));
3454 if ((ret
= ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
3455 "class-code", wordval
)) != DDI_SUCCESS
) {
3458 /* devsel-speed starts at the 9th bit */
3459 val
= (pci_config_get16(config_handle
,
3460 PCI_CONF_STAT
) & PCI_STAT_DEVSELT
) >> 9;
3461 if ((ret
= ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
3462 "devsel-speed", val
)) != DDI_SUCCESS
) {
3467 * The next three are bits set in the status register. The property is
3468 * present (but with no value other than its own existence) if the bit
3469 * is set, non-existent otherwise
3472 (pci_config_get16(config_handle
, PCI_CONF_STAT
) &
3474 if ((ret
= ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
3475 "fast-back-to-back", 0)) != DDI_SUCCESS
) {
3480 (pci_config_get16(config_handle
, PCI_CONF_STAT
) &
3482 if ((ret
= ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
3483 "66mhz-capable", 0)) != DDI_SUCCESS
) {
3487 if (pci_config_get16(config_handle
, PCI_CONF_STAT
) & PCI_STAT_UDF
) {
3488 if ((ret
= ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
3489 "udf-supported", 0)) != DDI_SUCCESS
) {
3495 * These next three are optional and are not present
3496 * if the corresponding register is zero. If the value
3497 * is non-zero then the property exists with the value
3500 if ((val
= pci_config_get16(config_handle
,
3501 PCI_CONF_SUBVENID
)) != 0) {
3502 if ((ret
= ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
3503 "subsystem-vendor-id", val
)) != DDI_SUCCESS
) {
3507 if ((val
= pci_config_get16(config_handle
,
3508 PCI_CONF_SUBSYSID
)) != 0) {
3509 if ((ret
= ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
3510 "subsystem-id", val
)) != DDI_SUCCESS
) {
3514 if ((val
= pci_config_get16(config_handle
,
3515 PCI_CONF_CACHE_LINESZ
)) != 0) {
3516 if ((ret
= ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
3517 "cache-line-size", val
)) != DDI_SUCCESS
) {
3523 * If the Interrupt Pin register is non-zero then the
3524 * interrupts property exists
3526 if ((byteval
= pci_config_get8(config_handle
, PCI_CONF_IPIN
)) != 0) {
3528 * If interrupt pin is non-zero,
3529 * record the interrupt line used
3531 if ((ret
= ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
3532 "interrupts", byteval
)) != DDI_SUCCESS
) {
3537 ret
= PCI_CAP_LOCATE(config_handle
, PCI_CAP_ID_PCI_E
, &cap_ptr
);
3539 if (pcie_dev
&& (ret
== DDI_SUCCESS
)) {
3540 val
= PCI_CAP_GET16(config_handle
, NULL
, cap_ptr
,
3541 PCIE_PCIECAP
) & PCIE_PCIECAP_SLOT_IMPL
;
3542 /* if slot implemented, get physical slot number */
3544 wordval
= (PCI_CAP_GET32(config_handle
, NULL
,
3545 cap_ptr
, PCIE_SLOTCAP
) >>
3546 PCIE_SLOTCAP_PHY_SLOT_NUM_SHIFT
) &
3547 PCIE_SLOTCAP_PHY_SLOT_NUM_MASK
;
3548 if ((ret
= ndi_prop_update_int(DDI_DEV_T_NONE
,
3549 dip
, "physical-slot#", wordval
))
3555 return (PCICFG_SUCCESS
);
3558 pcicfg_set_busnode_props(dev_info_t
*dip
, uint8_t pcie_device_type
,
3562 char device_type
[8];
3564 if (pcie_device_type
)
3565 (void) strcpy(device_type
, "pciex");
3567 (void) strcpy(device_type
, "pci");
3569 if ((ret
= ndi_prop_update_string(DDI_DEV_T_NONE
, dip
,
3570 "device_type", device_type
)) != DDI_SUCCESS
) {
3573 if ((ret
= ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
3574 "#address-cells", 3)) != DDI_SUCCESS
) {
3577 if ((ret
= ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
3578 "#size-cells", 2)) != DDI_SUCCESS
) {
3583 * Create primary-bus and secondary-bus properties to be used
3584 * to restore bus numbers in the pcicfg_setup_bridge() routine.
3586 if (pbus
!= -1 && sbus
!= -1) {
3587 if ((ret
= ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
3588 "primary-bus", pbus
)) != DDI_SUCCESS
) {
3591 if ((ret
= ndi_prop_update_int(DDI_DEV_T_NONE
, dip
,
3592 "secondary-bus", sbus
)) != DDI_SUCCESS
) {
3596 return (PCICFG_SUCCESS
);
3600 pcicfg_set_childnode_props(dev_info_t
*dip
, ddi_acc_handle_t config_handle
,
3606 char buffer
[64], pprefix
[8];
3608 uint8_t revid
, pif
, pclass
, psubclass
;
3612 uint16_t sub_vid
, sub_sid
, vid
, did
;
3614 /* set the property prefix based on the device type */
3616 (void) sprintf(pprefix
, "pciex");
3618 (void) sprintf(pprefix
, "pci");
3619 sub_vid
= pci_config_get16(config_handle
, PCI_CONF_SUBVENID
);
3620 sub_sid
= pci_config_get16(config_handle
, PCI_CONF_SUBSYSID
);
3621 vid
= pci_config_get16(config_handle
, PCI_CONF_VENID
);
3622 did
= pci_config_get16(config_handle
, PCI_CONF_DEVID
);
3623 revid
= pci_config_get8(config_handle
, PCI_CONF_REVID
);
3624 pif
= pci_config_get8(config_handle
, PCI_CONF_PROGCLASS
);
3625 classcode
= pci_config_get16(config_handle
, PCI_CONF_SUBCLASS
);
3626 pclass
= pci_config_get8(config_handle
, PCI_CONF_BASCLASS
);
3627 psubclass
= pci_config_get8(config_handle
, PCI_CONF_SUBCLASS
);
3630 * NOTE: These are for both a child and PCI-PCI bridge node
3634 * "name" property rule
3635 * --------------------
3641 * | ssid \ | =0 | != 0 |
3642 * |------------|-----------------------|-----------------------|
3644 * | =0 | vid,did | svid,ssid |
3646 * |------------|-----------------------|-----------------------|
3648 * | !=0 | svid,ssid | svid,ssid |
3650 * |------------|-----------------------|-----------------------|
3655 * svid = subsystem vendor id
3656 * ssid = subsystem id
3659 if ((sub_sid
!= 0) || (sub_vid
!= 0)) {
3660 (void) sprintf(buffer
, "%s%x,%x", pprefix
, sub_vid
, sub_sid
);
3662 (void) sprintf(buffer
, "%s%x,%x", pprefix
, vid
, did
);
3666 * In some environments, trying to use "generic" 1275 names is
3667 * not the convention. In those cases use the name as created
3668 * above. In all the rest of the cases, check to see if there
3669 * is a generic name first.
3671 #ifdef _DONT_USE_1275_GENERIC_NAMES
3674 if ((name
= pcicfg_get_class_name(classcode
)) == NULL
) {
3676 * Set name to the above fabricated name
3683 * The node name field needs to be filled in with the name
3685 if (ndi_devi_set_nodename(dip
, name
, 0) != NDI_SUCCESS
) {
3686 DEBUG0("Failed to set nodename for node\n");
3687 return (PCICFG_FAILURE
);
3691 * Create the compatible property as an array of pointers
3692 * to strings. Start with the buffer created above.
3695 compat
[n
] = kmem_alloc(strlen(buffer
) + 1, KM_SLEEP
);
3696 (void) strcpy(compat
[n
++], buffer
);
3699 * Setup 'compatible' as per the PCI2.1 bindings document.
3700 * pci[ex]VVVV,DDDD.SSSS.ssss.RR
3701 * pci[ex]VVVV,DDDD.SSSS.ssss
3702 * pciSSSS.ssss -> not created for PCIe as per PCIe bindings
3703 * pci[ex]VVVV,DDDD.RR
3705 * pci[ex]class,CCSSPP
3709 /* pci[ex]VVVV,DDDD.SSSS.ssss.RR */
3710 (void) sprintf(buffer
, "%s%x,%x.%x.%x.%x", pprefix
, vid
, did
,
3711 sub_vid
, sub_sid
, revid
);
3712 compat
[n
] = kmem_alloc(strlen(buffer
) + 1, KM_SLEEP
);
3713 (void) strcpy(compat
[n
++], buffer
);
3715 /* pci[ex]VVVV,DDDD.SSSS.ssss */
3716 (void) sprintf(buffer
, "%s%x,%x.%x.%x", pprefix
, vid
, did
,
3718 compat
[n
] = kmem_alloc(strlen(buffer
) + 1, KM_SLEEP
);
3719 (void) strcpy(compat
[n
++], buffer
);
3721 /* pciSSSS.ssss -> not created for PCIe as per PCIe bindings */
3723 (void) sprintf(buffer
, "pci%x,%x", sub_vid
, sub_sid
);
3724 compat
[n
] = kmem_alloc(strlen(buffer
) + 1, KM_SLEEP
);
3725 (void) strcpy(compat
[n
++], buffer
);
3728 /* pci[ex]VVVV,DDDD.RR */
3729 (void) sprintf(buffer
, "%s%x,%x.%x", pprefix
, vid
, did
, revid
);
3730 compat
[n
] = kmem_alloc(strlen(buffer
) + 1, KM_SLEEP
);
3731 (void) strcpy(compat
[n
++], buffer
);
3733 /* pci[ex]VVVV,DDDD */
3734 (void) sprintf(buffer
, "%s%x,%x", pprefix
, vid
, did
);
3735 compat
[n
] = kmem_alloc(strlen(buffer
) + 1, KM_SLEEP
);
3736 (void) strcpy(compat
[n
++], buffer
);
3738 /* pci[ex]class,CCSSPP */
3739 (void) sprintf(buffer
, "%sclass,%02x%02x%02x", pprefix
,
3740 pclass
, psubclass
, pif
);
3741 compat
[n
] = kmem_alloc(strlen(buffer
) + 1, KM_SLEEP
);
3742 (void) strcpy(compat
[n
++], buffer
);
3744 /* pci[ex]class,CCSS */
3745 (void) sprintf(buffer
, "%sclass,%04x", pprefix
, classcode
);
3746 compat
[n
] = kmem_alloc(strlen(buffer
) + 1, KM_SLEEP
);
3747 (void) strcpy(compat
[n
++], buffer
);
3749 if ((ret
= ndi_prop_update_string_array(DDI_DEV_T_NONE
, dip
,
3750 "compatible", (char **)compat
, n
)) != DDI_SUCCESS
) {
3754 for (i
= 0; i
< n
; i
++) {
3755 kmem_free(compat
[i
], strlen(compat
[i
]) + 1);
3758 DEBUG1("pcicfg_set_childnode_props - creating name=%s\n", name
);
3759 if ((ret
= ndi_prop_update_string(DDI_DEV_T_NONE
, dip
,
3760 "name", name
)) != DDI_SUCCESS
) {
3762 DEBUG0("pcicfg_set_childnode_props - Unable to create name "
3768 return (PCICFG_SUCCESS
);
3772 * Program the bus numbers into the bridge
3776 pcicfg_set_bus_numbers(ddi_acc_handle_t config_handle
,
3777 uint_t primary
, uint_t secondary
, uint_t subordinate
)
3779 DEBUG3("Setting bridge bus-range %d,%d,%d\n", primary
, secondary
,
3784 pci_config_put8(config_handle
, PCI_BCNF_PRIBUS
, primary
);
3789 pci_config_put8(config_handle
, PCI_BCNF_SECBUS
, secondary
);
3794 pci_config_put8(config_handle
, PCI_BCNF_SUBBUS
, subordinate
);
3798 * Put bridge registers into initial state
3801 pcicfg_setup_bridge(pcicfg_phdl_t
*entry
,
3802 ddi_acc_handle_t handle
, dev_info_t
*dip
)
3807 * The highest bus seen during probing is the max-subordinate bus
3809 pci_config_put8(handle
, PCI_BCNF_SUBBUS
, entry
->highest_bus
);
3813 * If there exists more than 1 downstream bridge, it
3814 * will be reset by the below secondary bus reset which
3815 * will clear the bus numbers assumed to be programmed in
3816 * the pcicfg_probe_children() routine. We therefore restore
3819 if (pci_config_get8(handle
, PCI_BCNF_SECBUS
) == 0) {
3820 pbus
= ddi_prop_get_int(DDI_DEV_T_ANY
, dip
,
3821 DDI_PROP_DONTPASS
, "primary-bus", -1);
3822 sbus
= ddi_prop_get_int(DDI_DEV_T_ANY
, dip
,
3823 DDI_PROP_DONTPASS
, "secondary-bus", -1);
3824 if (pbus
!= -1 && sbus
!= -1) {
3825 pci_config_put8(handle
, PCI_BCNF_PRIBUS
, (uint_t
)pbus
);
3826 pci_config_put8(handle
, PCI_BCNF_SECBUS
, (uint_t
)sbus
);
3828 cmn_err(CE_WARN
, "Invalid Bridge number detected: \
3829 %s%d: pbus = 0x%x, sbus = 0x%x",
3830 ddi_get_name(dip
), ddi_get_instance(dip
), pbus
,
3836 * Reset the secondary bus
3838 pci_config_put16(handle
, PCI_BCNF_BCNTRL
,
3839 pci_config_get16(handle
, PCI_BCNF_BCNTRL
) | 0x40);
3843 pci_config_put16(handle
, PCI_BCNF_BCNTRL
,
3844 pci_config_get16(handle
, PCI_BCNF_BCNTRL
) & ~0x40);
3847 * Program the memory base register with the
3848 * start of the memory range
3850 pci_config_put16(handle
, PCI_BCNF_MEM_BASE
,
3851 PCICFG_HIWORD(PCICFG_LOADDR(entry
->memory_last
)));
3854 * Program the I/O base register with the start of the I/O range
3856 pci_config_put8(handle
, PCI_BCNF_IO_BASE_LOW
,
3857 PCICFG_HIBYTE(PCICFG_LOWORD(PCICFG_LOADDR(entry
->io_last
))));
3858 pci_config_put16(handle
, PCI_BCNF_IO_BASE_HI
,
3859 PCICFG_HIWORD(PCICFG_LOADDR(entry
->io_last
)));
3864 pci_config_put16(handle
, PCI_BCNF_SEC_STATUS
, 0xffff);
3867 * Turn off prefetchable range
3869 pci_config_put32(handle
, PCI_BCNF_PF_BASE_LOW
, 0x0000ffff);
3870 pci_config_put32(handle
, PCI_BCNF_PF_BASE_HIGH
, 0xffffffff);
3871 pci_config_put32(handle
, PCI_BCNF_PF_LIMIT_HIGH
, 0x0);
3874 * Needs to be set to this value
3876 pci_config_put8(handle
, PCI_CONF_ILINE
, 0xf);
3879 * After a Reset, we need to wait 2^25 clock cycles before the
3880 * first Configuration access. The worst case is 33MHz, which
3881 * is a 1 second wait.
3883 drv_usecwait(pcicfg_sec_reset_delay
);
3888 pcicfg_update_bridge(pcicfg_phdl_t
*entry
,
3889 ddi_acc_handle_t handle
)
3894 * Program the memory limit register with the end of the memory range
3897 DEBUG1("DOWN ROUNDED ===>[0x%x]\n",
3898 PCICFG_ROUND_DOWN(entry
->memory_last
,
3901 pci_config_put16(handle
, PCI_BCNF_MEM_LIMIT
,
3902 PCICFG_HIWORD(PCICFG_LOADDR(
3903 PCICFG_ROUND_DOWN(entry
->memory_last
,
3906 * Since this is a bridge, the rest of this range will
3907 * be responded to by the bridge. We have to round up
3908 * so no other device claims it.
3910 if ((length
= (PCICFG_ROUND_UP(entry
->memory_last
,
3911 PCICFG_MEMGRAN
) - entry
->memory_last
)) > 0) {
3912 (void) pcicfg_get_mem(entry
, length
, NULL
);
3913 DEBUG1("Added [0x%x]at the top of "
3914 "the bridge (mem)\n", length
);
3918 * Program the I/O limit register with the end of the I/O range
3920 pci_config_put8(handle
, PCI_BCNF_IO_LIMIT_LOW
,
3921 PCICFG_HIBYTE(PCICFG_LOWORD(
3922 PCICFG_LOADDR(PCICFG_ROUND_DOWN(entry
->io_last
,
3925 pci_config_put16(handle
, PCI_BCNF_IO_LIMIT_HI
,
3926 PCICFG_HIWORD(PCICFG_LOADDR(PCICFG_ROUND_DOWN(entry
->io_last
,
3930 * Same as above for I/O space. Since this is a
3931 * bridge, the rest of this range will be responded
3932 * to by the bridge. We have to round up so no
3933 * other device claims it.
3935 if ((length
= (PCICFG_ROUND_UP(entry
->io_last
,
3936 PCICFG_IOGRAN
) - entry
->io_last
)) > 0) {
3937 (void) pcicfg_get_io(entry
, length
, NULL
);
3938 DEBUG1("Added [0x%x]at the top of "
3939 "the bridge (I/O)\n", length
);
3945 pcicfg_disable_bridge_probe_err(dev_info_t
*dip
, ddi_acc_handle_t h
,
3946 pcicfg_err_regs_t
*regs
)
3950 /* disable SERR generated in the context of Master Aborts. */
3951 regs
->cmd
= val
= pci_config_get16(h
, PCI_CONF_COMM
);
3952 val
&= ~PCI_COMM_SERR_ENABLE
;
3953 pci_config_put16(h
, PCI_CONF_COMM
, val
);
3954 regs
->bcntl
= val
= pci_config_get16(h
, PCI_BCNF_BCNTRL
);
3955 val
&= ~PCI_BCNF_BCNTRL_SERR_ENABLE
;
3956 pci_config_put16(h
, PCI_BCNF_BCNTRL
, val
);
3957 /* clear any current pending errors */
3958 pci_config_put16(h
, PCI_CONF_STAT
, PCI_STAT_S_TARG_AB
|
3959 PCI_STAT_R_TARG_AB
| PCI_STAT_R_MAST_AB
| PCI_STAT_S_SYSERR
);
3960 pci_config_put16(h
, PCI_BCNF_SEC_STATUS
, PCI_STAT_S_TARG_AB
|
3961 PCI_STAT_R_TARG_AB
| PCI_STAT_R_MAST_AB
| PCI_STAT_S_SYSERR
);
3962 /* if we are a PCIe device, disable the generation of UR, CE and NFE */
3963 if (regs
->pcie_dev
) {
3967 if ((PCI_CAP_LOCATE(h
, PCI_CAP_ID_PCI_E
, &cap_ptr
)) ==
3971 regs
->pcie_cap_off
= cap_ptr
;
3972 regs
->devctl
= devctl
= PCI_CAP_GET16(h
, NULL
, cap_ptr
,
3974 devctl
&= ~(PCIE_DEVCTL_UR_REPORTING_EN
|
3975 PCIE_DEVCTL_CE_REPORTING_EN
|
3976 PCIE_DEVCTL_NFE_REPORTING_EN
|
3977 PCIE_DEVCTL_FE_REPORTING_EN
);
3978 PCI_CAP_PUT16(h
, NULL
, cap_ptr
, PCIE_DEVCTL
, devctl
);
3984 pcicfg_enable_bridge_probe_err(dev_info_t
*dip
, ddi_acc_handle_t h
,
3985 pcicfg_err_regs_t
*regs
)
3987 /* clear any pending errors */
3988 pci_config_put16(h
, PCI_CONF_STAT
, PCI_STAT_S_TARG_AB
|
3989 PCI_STAT_R_TARG_AB
| PCI_STAT_R_MAST_AB
| PCI_STAT_S_SYSERR
);
3990 pci_config_put16(h
, PCI_BCNF_SEC_STATUS
, PCI_STAT_S_TARG_AB
|
3991 PCI_STAT_R_TARG_AB
| PCI_STAT_R_MAST_AB
| PCI_STAT_S_SYSERR
);
3993 /* restore original settings */
3994 if (regs
->pcie_dev
) {
3995 pcie_clear_errors(dip
);
3996 pci_config_put16(h
, regs
->pcie_cap_off
+ PCIE_DEVCTL
,
4000 pci_config_put16(h
, PCI_BCNF_BCNTRL
, regs
->bcntl
);
4001 pci_config_put16(h
, PCI_CONF_COMM
, regs
->cmd
);
4006 pcicfg_probe_children(dev_info_t
*parent
, uint_t bus
, uint_t device
,
4007 uint_t func
, uint_t
*highest_bus
, pcicfg_flags_t flags
, boolean_t is_pcie
)
4009 dev_info_t
*new_child
;
4010 ddi_acc_handle_t config_handle
;
4011 uint8_t header_type
, pcie_dev
= 0;
4013 pcicfg_err_regs_t regs
;
4016 * This node will be put immediately below
4017 * "parent". Allocate a blank device node. It will either
4018 * be filled in or freed up based on further probing.
4021 * Note: in usr/src/uts/common/io/hotplug/pcicfg/pcicfg.c
4022 * ndi_devi_alloc() is called as ndi_devi_alloc_sleep()
4024 if (ndi_devi_alloc(parent
, DEVI_PSEUDO_NEXNAME
,
4025 (pnode_t
)DEVI_SID_NODEID
, &new_child
)
4027 DEBUG0("pcicfg_probe_children(): Failed to alloc child node\n");
4028 return (PCICFG_FAILURE
);
4031 if (pcicfg_add_config_reg(new_child
, bus
,
4032 device
, func
) != DDI_SUCCESS
) {
4033 DEBUG0("pcicfg_probe_children():"
4034 "Failed to add candidate REG\n");
4038 if ((ret
= pcicfg_config_setup(new_child
, &config_handle
))
4039 != PCICFG_SUCCESS
) {
4040 if (ret
== PCICFG_NODEVICE
) {
4041 (void) ndi_devi_free(new_child
);
4044 DEBUG0("pcicfg_probe_children():"
4045 "Failed to setup config space\n");
4050 (void) pcie_init_bus(new_child
, PCI_GETBDF(bus
, device
, func
),
4054 * As soon as we have access to config space,
4055 * turn off device. It will get turned on
4056 * later (after memory is assigned).
4058 (void) pcicfg_device_off(config_handle
);
4060 /* check if we are PCIe device */
4061 if (pcicfg_pcie_dev(new_child
, PCICFG_DEVICE_TYPE_PCIE
, ®s
)
4063 DEBUG0("PCIe device detected\n");
4068 * Set 1275 properties common to all devices
4070 if (pcicfg_set_standard_props(new_child
, config_handle
,
4071 pcie_dev
) != PCICFG_SUCCESS
) {
4072 DEBUG0("Failed to set standard properties\n");
4077 * Child node properties NOTE: Both for PCI-PCI bridge and child node
4079 if (pcicfg_set_childnode_props(new_child
, config_handle
,
4080 pcie_dev
) != PCICFG_SUCCESS
) {
4084 header_type
= pci_config_get8(config_handle
, PCI_CONF_HEADER
);
4087 * If this is not a multi-function card only probe function zero.
4089 if ((!(header_type
& PCI_HEADER_MULTI
)) && (func
!= 0)) {
4091 (void) pcicfg_config_teardown(&config_handle
);
4092 (void) ndi_devi_free(new_child
);
4093 return (PCICFG_NODEVICE
);
4096 DEBUG1("---Vendor ID = [0x%x]\n",
4097 pci_config_get16(config_handle
, PCI_CONF_VENID
));
4098 DEBUG1("---Device ID = [0x%x]\n",
4099 pci_config_get16(config_handle
, PCI_CONF_DEVID
));
4102 * Attach the child to its parent
4104 (void) i_ndi_config_node(new_child
, DS_LINKED
, 0);
4106 if ((header_type
& PCI_HEADER_TYPE_M
) == PCI_HEADER_PPB
) {
4108 DEBUG3("--Bridge found bus [0x%x] device"
4109 "[0x%x] func [0x%x]\n", bus
, device
, func
);
4111 /* Only support read-only probe for leaf device */
4112 if (flags
& PCICFG_FLAG_READ_ONLY
)
4115 if (pcicfg_probe_bridge(new_child
, config_handle
,
4116 bus
, highest_bus
, is_pcie
) != PCICFG_SUCCESS
) {
4117 (void) pcicfg_free_bridge_resources(new_child
);
4123 DEBUG3("--Leaf device found bus [0x%x] device"
4124 "[0x%x] func [0x%x]\n",
4127 if (flags
& PCICFG_FLAG_READ_ONLY
) {
4129 * with read-only probe, don't do any resource
4130 * allocation, just read the BARs and update props.
4132 ret
= pcicfg_populate_props_from_bar(new_child
,
4134 if (ret
!= PCICFG_SUCCESS
)
4138 * for readonly probe "assigned-addresses" property
4139 * has already been setup by reading the BAR, here
4140 * just substract the resource from its parent here.
4142 ret
= pcicfg_device_assign_readonly(new_child
);
4143 if (ret
!= PCICFG_SUCCESS
) {
4144 (void) pcicfg_free_device_resources(new_child
,
4150 * update "reg" property by sizing the BARs.
4152 ret
= pcicfg_populate_reg_props(new_child
,
4154 if (ret
!= PCICFG_SUCCESS
)
4157 /* now allocate & program the resources */
4158 ret
= pcicfg_device_assign(new_child
);
4159 if (ret
!= PCICFG_SUCCESS
) {
4160 (void) pcicfg_free_device_resources(new_child
,
4166 (void) ndi_devi_bind_driver(new_child
, 0);
4169 (void) pcicfg_config_teardown(&config_handle
);
4172 * Properties have been setted up, so initilize the rest fields
4176 (void) pcie_init_bus(new_child
, 0, PCIE_BUS_FINAL
);
4178 return (PCICFG_SUCCESS
);
4182 (void) pcicfg_config_teardown(&config_handle
);
4184 pcie_fini_bus(new_child
, PCIE_BUS_FINAL
);
4188 (void) ndi_devi_free(new_child
);
4189 return (PCICFG_FAILURE
);
4193 * Sizing the BARs and update "reg" property
4196 pcicfg_populate_reg_props(dev_info_t
*new_child
,
4197 ddi_acc_handle_t config_handle
)
4204 while (i
<= PCI_CONF_BASE5
) {
4206 pci_config_put32(config_handle
, i
, 0xffffffff);
4208 request
= pci_config_get32(config_handle
, i
);
4210 * If its a zero length, don't do
4215 * Add to the "reg" property
4217 if (pcicfg_update_reg_prop(new_child
,
4218 request
, i
) != PCICFG_SUCCESS
) {
4222 DEBUG1("BASE register [0x%x] asks for "
4223 "[0x0]=[0x0](32)\n", i
);
4229 * Increment by eight if it is 64 bit address space
4231 if ((PCI_BASE_TYPE_M
& request
) == PCI_BASE_TYPE_ALL
) {
4232 DEBUG3("BASE register [0x%x] asks for "
4233 "[0x%x]=[0x%x] (64)\n",
4235 (~(PCI_BASE_M_ADDR_M
& request
))+1)
4238 DEBUG3("BASE register [0x%x] asks for "
4239 "[0x%x]=[0x%x](32)\n",
4241 (~(PCI_BASE_M_ADDR_M
& request
))+1)
4247 * Get the ROM size and create register for it
4249 pci_config_put32(config_handle
, PCI_CONF_ROM
, 0xfffffffe);
4251 request
= pci_config_get32(config_handle
, PCI_CONF_ROM
);
4253 * If its a zero length, don't do
4258 DEBUG3("BASE register [0x%x] asks for [0x%x]=[0x%x]\n",
4259 PCI_CONF_ROM
, request
,
4260 (~(PCI_BASE_ROM_ADDR_M
& request
))+1);
4262 * Add to the "reg" property
4264 if (pcicfg_update_reg_prop(new_child
,
4265 request
, PCI_CONF_ROM
) != PCICFG_SUCCESS
) {
4270 return (PCICFG_SUCCESS
);
4273 return (PCICFG_FAILURE
);
4277 pcicfg_fcode_probe(dev_info_t
*parent
, uint_t bus
, uint_t device
,
4278 uint_t func
, uint_t
*highest_bus
, pcicfg_flags_t flags
, boolean_t is_pcie
)
4280 dev_info_t
*new_child
;
4283 ddi_acc_handle_t h
, ph
;
4285 extern int pcicfg_dont_interpret
;
4286 pcicfg_err_regs_t parent_regs
, regs
;
4287 char *status_prop
= NULL
;
4288 #ifdef PCICFG_INTERPRET_FCODE
4289 struct pci_ops_bus_args po
;
4291 char unit_address
[64];
4293 uchar_t
*fcode_addr
;
4294 uint64_t mem_answer
, mem_alen
;
4297 ndi_ra_request_t req
;
4298 int16_t vendor_id
, device_id
;
4302 * check if our parent is of type pciex.
4303 * if so, program config space to disable error msgs during probe.
4305 if (pcicfg_pcie_dev(parent
, PCICFG_DEVICE_TYPE_PCIE
, &parent_regs
)
4307 DEBUG0("PCI/PCIe parent detected. Disable errors.\n");
4309 * disable parent generating URs or SERR#s during probing
4312 if (pci_config_setup(parent
, &ph
) != DDI_SUCCESS
)
4313 return (DDI_FAILURE
);
4315 if ((flags
& PCICFG_FLAG_READ_ONLY
) == 0) {
4316 pcicfg_disable_bridge_probe_err(parent
,
4322 * This node will be put immediately below
4323 * "parent". Allocate a blank device node. It will either
4324 * be filled in or freed up based on further probing.
4327 if (ndi_devi_alloc(parent
, DEVI_PSEUDO_NEXNAME
,
4328 (pnode_t
)DEVI_SID_NODEID
, &new_child
)
4330 DEBUG0("pcicfg_fcode_probe(): Failed to alloc child node\n");
4331 /* return (PCICFG_FAILURE); */
4332 ret
= PCICFG_FAILURE
;
4337 * Create a dummy reg property. This will be replaced with
4338 * a real reg property when fcode completes or if we need to
4339 * produce one by hand.
4341 if (pcicfg_add_config_reg(new_child
, bus
,
4342 device
, func
) != DDI_SUCCESS
) {
4343 ret
= PCICFG_FAILURE
;
4347 if ((ret
= pcicfg_config_setup(new_child
, &h
))
4348 != PCICFG_SUCCESS
) {
4349 DEBUG0("pcicfg_fcode_probe():"
4350 "Failed to setup config space\n");
4351 ret
= PCICFG_NODEVICE
;
4356 p
.pci_phys_hi
= PCICFG_MAKE_REG_HIGH(bus
, device
, func
, 0);
4357 p
.pci_phys_mid
= p
.pci_phys_low
= 0;
4358 p
.pci_size_hi
= p
.pci_size_low
= 0;
4361 * Map in configuration space (temporarily)
4363 acc
.devacc_attr_version
= DDI_DEVICE_ATTR_V0
;
4364 acc
.devacc_attr_endian_flags
= DDI_STRUCTURE_LE_ACC
;
4365 acc
.devacc_attr_dataorder
= DDI_STRICTORDER_ACC
;
4367 if (pcicfg_map_phys(new_child
, &p
, &virt
, &acc
, &h
)) {
4368 DEBUG0("pcicfg_fcode_probe():"
4369 "Failed to setup config space\n");
4370 ret
= PCICFG_NODEVICE
;
4375 * First use ddi_peek16 so that if there is not a device there,
4376 * a bus error will not cause a panic.
4378 v
= virt
+ PCI_CONF_VENID
;
4379 if (ddi_peek16(new_child
, (int16_t *)v
, &vendor_id
)) {
4380 DEBUG0("Can not read Vendor ID");
4381 pcicfg_unmap_phys(&h
, &p
);
4382 ret
= PCICFG_NODEVICE
;
4388 (void) pcie_init_bus(new_child
, PCI_GETBDF(bus
, device
, func
),
4391 DEBUG0("fcode_probe: conf space mapped.\n");
4393 * As soon as we have access to config space,
4394 * turn off device. It will get turned on
4395 * later (after memory is assigned).
4397 (void) pcicfg_device_off(h
);
4399 /* check if we are PCIe device */
4400 if (pcicfg_pcie_dev(new_child
, PCICFG_DEVICE_TYPE_PCIE
, ®s
)
4403 DEBUG0("PCI/PCIe device detected\n");
4407 * Set 1275 properties common to all devices
4409 if (pcicfg_set_standard_props(new_child
,
4410 h
, regs
.pcie_dev
) != PCICFG_SUCCESS
) {
4411 DEBUG0("Failed to set standard properties\n");
4416 * Child node properties NOTE: Both for PCI-PCI bridge and child node
4418 if (pcicfg_set_childnode_props(new_child
,
4419 h
, regs
.pcie_dev
) != PCICFG_SUCCESS
) {
4420 ret
= PCICFG_FAILURE
;
4424 header_type
= pci_config_get8(h
, PCI_CONF_HEADER
);
4427 * If this is not a multi-function card only probe function zero.
4429 if (!(header_type
& PCI_HEADER_MULTI
) && (func
> 0)) {
4431 ret
= PCICFG_NODEVICE
;
4435 if ((header_type
& PCI_HEADER_TYPE_M
) == PCI_HEADER_PPB
) {
4438 * XXX - Transparent bridges are handled differently
4439 * than other devices with regards to fcode. Since
4440 * no transparent bridge currently ships with fcode,
4441 * there is no reason to try to extract it from its rom
4442 * or call the fcode interpreter to try to load a drop-in.
4443 * If fcode is developed to handle transparent bridges,
4444 * this code will have to change.
4447 DEBUG3("--Bridge found bus [0x%x] device"
4448 "[0x%x] func [0x%x]\n", bus
, device
, func
);
4450 /* Only support read-only probe for leaf device */
4451 if (flags
& PCICFG_FLAG_READ_ONLY
)
4454 if ((ret
= pcicfg_probe_bridge(new_child
, h
,
4455 bus
, highest_bus
, is_pcie
)) != PCICFG_SUCCESS
)
4456 (void) pcicfg_free_bridge_resources(new_child
);
4460 DEBUG3("--Leaf device found bus [0x%x] device"
4461 "[0x%x] func [0x%x]\n",
4465 * link in tree, but don't bind driver
4466 * We don't have compatible property yet
4468 (void) i_ndi_config_node(new_child
, DS_LINKED
, 0);
4470 /* XXX for now, don't run Fcode in read-only probe. */
4471 if (flags
& PCICFG_FLAG_READ_ONLY
)
4474 if (pci_config_get8(h
, PCI_CONF_IPIN
)) {
4475 pci_config_put8(h
, PCI_CONF_ILINE
, 0xf);
4478 #ifdef PCICFG_INTERPRET_FCODE
4480 * Some platforms (x86) don't run fcode, so don't interpret
4481 * fcode that might be in the ROM.
4483 if (pcicfg_dont_interpret
== 0) {
4485 /* This platform supports fcode */
4487 vendor_id
= pci_config_get16(h
, PCI_CONF_VENID
);
4488 device_id
= pci_config_get16(h
, PCI_CONF_DEVID
);
4491 * Get the ROM size and create register for it
4493 pci_config_put32(h
, PCI_CONF_ROM
, 0xfffffffe);
4495 request
= pci_config_get32(h
, PCI_CONF_ROM
);
4498 * If its a zero length, don't do
4504 * Add resource to assigned-addresses.
4506 if (pcicfg_fcode_assign_bars(h
, new_child
,
4507 bus
, device
, func
, request
, &p
)
4508 != PCICFG_SUCCESS
) {
4509 DEBUG0("Failed to assign addresses to "
4510 "implemented BARs");
4511 ret
= PCICFG_FAILURE
;
4515 /* Turn device on */
4516 (void) pcicfg_device_on(h
);
4519 * Attempt to load fcode.
4521 (void) pcicfg_load_fcode(new_child
, bus
, device
,
4522 func
, vendor_id
, device_id
, &fcode_addr
,
4523 &fcode_size
, PCICFG_LOADDR(mem_answer
),
4524 (~(PCI_BASE_ROM_ADDR_M
& request
)) + 1);
4526 /* Turn device off */
4527 (void) pcicfg_device_off(h
);
4530 * Free the ROM resources.
4532 (void) pcicfg_free_resource(new_child
, p
, 0);
4534 DEBUG2("configure: fcode addr %lx size %x\n",
4535 fcode_addr
, fcode_size
);
4538 * Create the fcode-rom-offset property. The
4539 * buffer containing the fcode always starts
4540 * with 0xF1, so the fcode offset is zero.
4542 if (ndi_prop_update_int(DDI_DEV_T_NONE
,
4543 new_child
, "fcode-rom-offset", 0)
4545 DEBUG0("Failed to create "
4546 "fcode-rom-offset property\n");
4547 ret
= PCICFG_FAILURE
;
4551 DEBUG0("There is no Expansion ROM\n");
4557 * Fill in the bus specific arguments. For
4558 * PCI, it is the config address.
4561 PCICFG_MAKE_REG_HIGH(bus
, device
, func
, 0);
4563 DEBUG1("config_address=%x\n", po
.config_address
);
4566 * Build unit address.
4568 (void) sprintf(unit_address
, "%x,%x", device
, func
);
4570 DEBUG3("pci_fc_ops_alloc_handle ap=%lx "
4571 "new device=%lx unit address=%s\n",
4572 parent
, new_child
, unit_address
);
4574 c
= pci_fc_ops_alloc_handle(parent
, new_child
,
4575 fcode_addr
, fcode_size
, unit_address
, &po
);
4577 DEBUG0("calling fcode_interpreter()\n");
4579 DEBUG3("Before int DIP=%lx binding name %s major %d\n",
4580 new_child
, ddi_binding_name(new_child
),
4581 ddi_driver_major(new_child
));
4583 error
= fcode_interpreter(parent
, &pci_fc_ops
, c
);
4585 DEBUG1("returned from fcode_interpreter() - "
4586 "returned %x\n", error
);
4588 pci_fc_ops_free_handle(c
);
4590 DEBUG1("fcode size = %x\n", fcode_size
);
4592 * We don't need the fcode anymore. While allocating
4593 * we had rounded up to a page size.
4596 kmem_free(fcode_addr
, ptob(btopr(fcode_size
)));
4599 /* This platform does not support fcode */
4601 DEBUG0("NOT calling fcode_interpreter()\n");
4604 #endif /* PCICFG_INTERPRET_FCODE */
4606 if ((error
== 0) && (pcicfg_dont_interpret
== 0)) {
4608 * The interpreter completed successfully.
4609 * We need to redo the resources based on the new reg
4612 DEBUG3("DIP=%lx binding name %s major %d\n", new_child
,
4613 ddi_binding_name(new_child
),
4614 ddi_driver_major(new_child
));
4617 * Readjust resources specified by reg property.
4619 if (pcicfg_alloc_new_resources(new_child
) ==
4621 ret
= PCICFG_FAILURE
;
4626 * At this stage, there should be enough info to pull
4627 * the status property if it exists.
4629 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
,
4630 new_child
, NULL
, "status", &status_prop
) ==
4632 if ((strncmp("disabled", status_prop
, 8) ==
4633 0) || (strncmp("fail", status_prop
, 4) ==
4635 ret
= PCICFG_FAILURE
;
4636 ddi_prop_free(status_prop
);
4639 ddi_prop_free(status_prop
);
4643 ret
= PCICFG_SUCCESS
;
4644 /* no fcode, bind driver now */
4645 (void) ndi_devi_bind_driver(new_child
, 0);
4648 } else if ((error
!= FC_NO_FCODE
) &&
4649 (pcicfg_dont_interpret
== 0)) {
4651 * The interpreter located fcode, but had an error in
4652 * processing. Cleanup and fail the operation.
4654 DEBUG0("Interpreter detected fcode failure\n");
4655 (void) pcicfg_free_resources(new_child
, flags
);
4656 ret
= PCICFG_FAILURE
;
4661 * Either the interpreter failed with FC_NO_FCODE or we
4662 * chose not to run the interpreter
4663 * (pcicfg_dont_interpret).
4665 * If the interpreter failed because there was no
4666 * dropin, then we need to probe the device ourself.
4670 * Free any resources that may have been assigned
4671 * during fcode loading/execution since we need
4674 (void) pcicfg_free_resources(new_child
, flags
);
4677 pcicfg_config_teardown(&h
);
4679 pcicfg_unmap_phys(&h
, &p
);
4681 /* destroy the bus_t before the dev node is gone */
4683 pcie_fini_bus(new_child
, PCIE_BUS_FINAL
);
4685 (void) ndi_devi_free(new_child
);
4687 DEBUG0("No Drop-in Probe device ourself\n");
4689 ret
= pcicfg_probe_children(parent
, bus
, device
, func
,
4690 highest_bus
, flags
, is_pcie
);
4692 if (ret
!= PCICFG_SUCCESS
) {
4693 DEBUG0("Could not self probe child\n");
4698 * We successfully self probed the device.
4700 if ((new_child
= pcicfg_devi_find(
4701 parent
, device
, func
)) == NULL
) {
4702 DEBUG0("Did'nt find device node "
4704 ret
= PCICFG_FAILURE
;
4709 * Till now, we have detected a non transparent bridge
4710 * (ntbridge) as a part of the generic probe code and
4711 * configured only one configuration
4712 * header which is the side facing the host bus.
4713 * Now, configure the other side and create children.
4715 * To make the process simpler, lets load the device
4716 * driver for the non transparent bridge as this is a
4717 * Solaris bundled driver, and use its configuration map
4718 * services rather than programming it here.
4719 * If the driver is not bundled into Solaris, it must be
4720 * first loaded and configured before performing any
4721 * hotplug operations.
4723 * This not only makes the code simpler but also more
4728 if (pcicfg_is_ntbridge(new_child
) != DDI_FAILURE
) {
4730 DEBUG0("Found nontransparent bridge.\n");
4732 ret
= pcicfg_configure_ntbridge(new_child
,
4735 if (ret
!= PCICFG_SUCCESS
) {
4737 * Bridge configure failed. Free up the self
4738 * probed entry. The bus resource allocation
4739 * maps need to be cleaned up to prevent
4740 * warnings on retries of the failed configure.
4742 (void) pcicfg_ntbridge_unconfigure(new_child
);
4743 (void) pcicfg_teardown_device(new_child
,
4753 if (ret
== PCICFG_SUCCESS
)
4754 (void) pcie_init_bus(new_child
, 0, PCIE_BUS_FINAL
);
4756 pcie_fini_bus(new_child
, PCIE_BUS_FINAL
);
4760 pcicfg_config_teardown(&h
);
4762 pcicfg_unmap_phys(&h
, &p
);
4765 if (ret
!= PCICFG_SUCCESS
)
4766 (void) ndi_devi_free(new_child
);
4769 if (parent_regs
.pcie_dev
) {
4770 if ((flags
& PCICFG_FLAG_READ_ONLY
) == 0) {
4771 pcicfg_enable_bridge_probe_err(parent
,
4774 pci_config_teardown(&ph
);
4781 * Read the BARs and update properties. Used in virtual hotplug.
4784 pcicfg_populate_props_from_bar(dev_info_t
*new_child
,
4785 ddi_acc_handle_t config_handle
)
4787 uint32_t request
, base
, base_hi
, size
;
4792 while (i
<= PCI_CONF_BASE5
) {
4794 * determine the size of the address space
4796 base
= pci_config_get32(config_handle
, i
);
4797 pci_config_put32(config_handle
, i
, 0xffffffff);
4798 request
= pci_config_get32(config_handle
, i
);
4799 pci_config_put32(config_handle
, i
, base
);
4802 * If its a zero length, don't do any programming.
4806 * Add to the "reg" property
4808 if (pcicfg_update_reg_prop(new_child
,
4809 request
, i
) != PCICFG_SUCCESS
) {
4813 if ((PCI_BASE_SPACE_IO
& request
) == 0 &&
4814 (PCI_BASE_TYPE_M
& request
) == PCI_BASE_TYPE_ALL
) {
4815 base_hi
= pci_config_get32(config_handle
, i
+4);
4820 * Add to "assigned-addresses" property
4822 size
= (~(PCI_BASE_M_ADDR_M
& request
))+1;
4823 if (pcicfg_update_assigned_prop_value(new_child
,
4824 size
, base
, base_hi
, i
) != PCICFG_SUCCESS
) {
4828 DEBUG1("BASE register [0x%x] asks for "
4829 "[0x0]=[0x0](32)\n", i
);
4835 * Increment by eight if it is 64 bit address space
4837 if ((PCI_BASE_TYPE_M
& request
) == PCI_BASE_TYPE_ALL
) {
4838 DEBUG3("BASE register [0x%x] asks for "
4839 "[0x%x]=[0x%x] (64)\n",
4841 (~(PCI_BASE_M_ADDR_M
& request
))+1)
4844 DEBUG3("BASE register [0x%x] asks for "
4845 "[0x%x]=[0x%x](32)\n",
4847 (~(PCI_BASE_M_ADDR_M
& request
))+1)
4853 * Get the ROM size and create register for it
4855 base
= pci_config_get32(config_handle
, PCI_CONF_ROM
);
4856 pci_config_put32(config_handle
, PCI_CONF_ROM
, 0xfffffffe);
4857 request
= pci_config_get32(config_handle
, PCI_CONF_ROM
);
4858 pci_config_put32(config_handle
, PCI_CONF_ROM
, base
);
4861 * If its a zero length, don't do
4865 DEBUG3("BASE register [0x%x] asks for [0x%x]=[0x%x]\n",
4866 PCI_CONF_ROM
, request
,
4867 (~(PCI_BASE_ROM_ADDR_M
& request
))+1);
4869 * Add to the "reg" property
4871 if (pcicfg_update_reg_prop(new_child
,
4872 request
, PCI_CONF_ROM
) != PCICFG_SUCCESS
) {
4876 * Add to "assigned-addresses" property
4878 size
= (~(PCI_BASE_ROM_ADDR_M
& request
))+1;
4879 if (pcicfg_update_assigned_prop_value(new_child
, size
,
4880 base
, 0, PCI_CONF_ROM
) != PCICFG_SUCCESS
) {
4885 return (PCICFG_SUCCESS
);
4888 return (PCICFG_FAILURE
);
4892 pcicfg_probe_bridge(dev_info_t
*new_child
, ddi_acc_handle_t h
, uint_t bus
,
4893 uint_t
*highest_bus
, boolean_t is_pcie
)
4896 uint_t new_bus
, num_slots
;
4897 ndi_ra_request_t req
;
4899 uint64_t mem_answer
, mem_base
, mem_alen
, mem_size
, mem_end
;
4900 uint64_t io_answer
, io_base
, io_alen
, io_size
, io_end
;
4901 uint64_t round_answer
, round_len
;
4902 pcicfg_range_t range
[PCICFG_RANGE_LEN
];
4906 uint64_t pcibus_base
, pcibus_alen
;
4908 uint8_t pcie_device_type
= 0;
4909 dev_info_t
*new_device
;
4911 int ari_mode
= B_FALSE
;
4912 int max_function
= PCICFG_MAX_FUNCTION
;
4915 * Set "device_type" to "pci", the actual type will be set later
4916 * by pcicfg_set_busnode_props() below. This is needed as the
4917 * pcicfg_ra_free() below would update "available" property based
4920 * This code can be removed later after PCI configurator is changed
4921 * to use PCIRM, which automatically update properties upon allocation
4922 * and free, at that time we'll be able to remove the code inside
4923 * ndi_ra_alloc/free() which currently updates "available" property
4924 * for pci/pcie devices in pcie fabric.
4926 if (ndi_prop_update_string(DDI_DEV_T_NONE
, new_child
,
4927 "device_type", "pci") != DDI_SUCCESS
) {
4928 DEBUG0("Failed to set \"device_type\" props\n");
4929 return (PCICFG_FAILURE
);
4932 bzero((caddr_t
)&req
, sizeof (ndi_ra_request_t
));
4933 req
.ra_flags
= (NDI_RA_ALLOC_BOUNDED
| NDI_RA_ALLOC_PARTIAL_OK
);
4934 req
.ra_boundbase
= 0;
4935 req
.ra_boundlen
= PCICFG_MAX_BUS_DEPTH
;
4936 req
.ra_len
= PCICFG_MAX_BUS_DEPTH
;
4937 req
.ra_align_mask
= 0; /* no alignment needed */
4939 rval
= ndi_ra_alloc(ddi_get_parent(new_child
), &req
,
4940 &pcibus_base
, &pcibus_alen
, NDI_RA_TYPE_PCI_BUSNUM
, NDI_RA_PASS
);
4942 if (rval
!= NDI_SUCCESS
) {
4943 if (rval
== NDI_RA_PARTIAL_REQ
) {
4945 DEBUG0("NDI_RA_PARTIAL_REQ returned for bus range\n");
4948 "Failed to allocate bus range for bridge\n");
4949 return (PCICFG_FAILURE
);
4953 DEBUG2("Bus Range Allocated [base=%d] [len=%d]\n",
4954 pcibus_base
, pcibus_alen
);
4956 if (ndi_ra_map_setup(new_child
, NDI_RA_TYPE_PCI_BUSNUM
)
4958 DEBUG0("Can not setup resource map - NDI_RA_TYPE_PCI_BUSNUM\n");
4959 return (PCICFG_FAILURE
);
4963 * Put available bus range into the pool.
4964 * Take the first one for this bridge to use and don't give
4967 (void) ndi_ra_free(new_child
, pcibus_base
+1, pcibus_alen
-1,
4968 NDI_RA_TYPE_PCI_BUSNUM
, NDI_RA_PASS
);
4970 next_bus
= pcibus_base
;
4971 max_bus
= pcibus_base
+ pcibus_alen
- 1;
4975 DEBUG1("NEW bus found ->[%d]\n", new_bus
);
4977 /* Keep track of highest bus for subordinate bus programming */
4978 *highest_bus
= new_bus
;
4981 * Allocate Memory Space for Bridge
4983 bzero((caddr_t
)&req
, sizeof (ndi_ra_request_t
));
4984 req
.ra_flags
= (NDI_RA_ALLOC_BOUNDED
| NDI_RA_ALLOC_PARTIAL_OK
);
4985 req
.ra_boundbase
= 0;
4987 * Note: To support a 32b system, boundlen and len need to be
4990 req
.ra_boundlen
= PCICFG_4GIG_LIMIT
+ 1;
4991 req
.ra_len
= PCICFG_4GIG_LIMIT
+ 1; /* Get as big as possible */
4993 PCICFG_MEMGRAN
- 1; /* 1M alignment on memory space */
4995 rval
= ndi_ra_alloc(ddi_get_parent(new_child
), &req
,
4996 &mem_answer
, &mem_alen
, NDI_RA_TYPE_MEM
, NDI_RA_PASS
);
4998 if (rval
!= NDI_SUCCESS
) {
4999 if (rval
== NDI_RA_PARTIAL_REQ
) {
5001 DEBUG0("NDI_RA_PARTIAL_REQ returned\n");
5004 "Failed to allocate memory for bridge\n");
5005 return (PCICFG_FAILURE
);
5009 DEBUG3("Bridge Memory Allocated [0x%x.%x] len [0x%x]\n",
5010 PCICFG_HIADDR(mem_answer
),
5011 PCICFG_LOADDR(mem_answer
),
5014 if (ndi_ra_map_setup(new_child
, NDI_RA_TYPE_MEM
) == NDI_FAILURE
) {
5015 DEBUG0("Can not setup resource map - NDI_RA_TYPE_MEM\n");
5016 return (PCICFG_FAILURE
);
5020 * Put available memory into the pool.
5022 (void) ndi_ra_free(new_child
, mem_answer
, mem_alen
, NDI_RA_TYPE_MEM
,
5025 mem_base
= mem_answer
;
5028 * Allocate I/O Space for Bridge
5030 bzero((caddr_t
)&req
, sizeof (ndi_ra_request_t
));
5031 req
.ra_align_mask
= PCICFG_IOGRAN
- 1; /* 4k alignment */
5032 req
.ra_boundbase
= 0;
5033 req
.ra_boundlen
= PCICFG_4GIG_LIMIT
;
5034 req
.ra_flags
= (NDI_RA_ALLOC_BOUNDED
| NDI_RA_ALLOC_PARTIAL_OK
);
5035 req
.ra_len
= PCICFG_4GIG_LIMIT
; /* Get as big as possible */
5037 rval
= ndi_ra_alloc(ddi_get_parent(new_child
), &req
, &io_answer
,
5038 &io_alen
, NDI_RA_TYPE_IO
, NDI_RA_PASS
);
5040 if (rval
!= NDI_SUCCESS
) {
5041 if (rval
== NDI_RA_PARTIAL_REQ
) {
5043 DEBUG0("NDI_RA_PARTIAL_REQ returned\n");
5045 DEBUG0("Failed to allocate io space for bridge\n");
5046 io_base
= io_answer
= io_alen
= 0;
5047 /* return (PCICFG_FAILURE); */
5052 DEBUG3("Bridge IO Space Allocated [0x%x.%x] len [0x%x]\n",
5053 PCICFG_HIADDR(io_answer
), PCICFG_LOADDR(io_answer
),
5056 if (ndi_ra_map_setup(new_child
, NDI_RA_TYPE_IO
) ==
5058 DEBUG0("Can not setup resource map - NDI_RA_TYPE_IO\n");
5059 return (PCICFG_FAILURE
);
5063 * Put available I/O into the pool.
5065 (void) ndi_ra_free(new_child
, io_answer
, io_alen
,
5066 NDI_RA_TYPE_IO
, NDI_RA_PASS
);
5067 io_base
= io_answer
;
5070 pcicfg_set_bus_numbers(h
, bus
, new_bus
, max_bus
);
5073 * Setup "bus-range" property before onlining the bridge.
5075 bus_range
[0] = new_bus
;
5076 bus_range
[1] = max_bus
;
5078 if (ndi_prop_update_int_array(DDI_DEV_T_NONE
, new_child
,
5079 "bus-range", bus_range
, 2) != DDI_SUCCESS
) {
5080 DEBUG0("Failed to set bus-range property");
5081 return (PCICFG_FAILURE
);
5085 * Reset the secondary bus
5087 pci_config_put16(h
, PCI_BCNF_BCNTRL
,
5088 pci_config_get16(h
, PCI_BCNF_BCNTRL
) | 0x40);
5092 pci_config_put16(h
, PCI_BCNF_BCNTRL
,
5093 pci_config_get16(h
, PCI_BCNF_BCNTRL
) & ~0x40);
5096 * Program the memory base register with the
5097 * start of the memory range
5099 pci_config_put16(h
, PCI_BCNF_MEM_BASE
,
5100 PCICFG_HIWORD(PCICFG_LOADDR(mem_answer
)));
5103 * Program the memory limit register with the
5104 * end of the memory range.
5107 pci_config_put16(h
, PCI_BCNF_MEM_LIMIT
,
5108 PCICFG_HIWORD(PCICFG_LOADDR(
5109 PCICFG_ROUND_DOWN((mem_answer
+ mem_alen
), PCICFG_MEMGRAN
) - 1)));
5112 * Allocate the chunk of memory (if any) not programmed into the
5113 * bridge because of the round down.
5115 if (PCICFG_ROUND_DOWN((mem_answer
+ mem_alen
), PCICFG_MEMGRAN
)
5116 != (mem_answer
+ mem_alen
)) {
5117 DEBUG0("Need to allocate Memory round off chunk\n");
5118 bzero((caddr_t
)&req
, sizeof (ndi_ra_request_t
));
5119 req
.ra_flags
= NDI_RA_ALLOC_SPECIFIED
;
5120 req
.ra_addr
= PCICFG_ROUND_DOWN((mem_answer
+ mem_alen
),
5122 req
.ra_len
= (mem_answer
+ mem_alen
) -
5123 (PCICFG_ROUND_DOWN((mem_answer
+ mem_alen
),
5126 (void) ndi_ra_alloc(new_child
, &req
,
5127 &round_answer
, &round_len
, NDI_RA_TYPE_MEM
, NDI_RA_PASS
);
5131 * Program the I/O Space Base
5133 pci_config_put8(h
, PCI_BCNF_IO_BASE_LOW
,
5134 PCICFG_HIBYTE(PCICFG_LOWORD(
5135 PCICFG_LOADDR(io_answer
))));
5137 pci_config_put16(h
, PCI_BCNF_IO_BASE_HI
,
5138 PCICFG_HIWORD(PCICFG_LOADDR(io_answer
)));
5141 * Program the I/O Space Limit
5143 pci_config_put8(h
, PCI_BCNF_IO_LIMIT_LOW
,
5144 PCICFG_HIBYTE(PCICFG_LOWORD(
5145 PCICFG_LOADDR(PCICFG_ROUND_DOWN(io_answer
+ io_alen
,
5146 PCICFG_IOGRAN
)))) - 1);
5148 pci_config_put16(h
, PCI_BCNF_IO_LIMIT_HI
,
5149 PCICFG_HIWORD(PCICFG_LOADDR(
5150 PCICFG_ROUND_DOWN(io_answer
+ io_alen
, PCICFG_IOGRAN
)))
5154 * Allocate the chunk of I/O (if any) not programmed into the
5155 * bridge because of the round down.
5157 if (PCICFG_ROUND_DOWN((io_answer
+ io_alen
), PCICFG_IOGRAN
)
5158 != (io_answer
+ io_alen
)) {
5159 DEBUG0("Need to allocate I/O round off chunk\n");
5160 bzero((caddr_t
)&req
, sizeof (ndi_ra_request_t
));
5161 req
.ra_flags
= NDI_RA_ALLOC_SPECIFIED
;
5162 req
.ra_addr
= PCICFG_ROUND_DOWN((io_answer
+ io_alen
),
5164 req
.ra_len
= (io_answer
+ io_alen
) -
5165 (PCICFG_ROUND_DOWN((io_answer
+ io_alen
),
5168 (void) ndi_ra_alloc(new_child
, &req
,
5169 &round_answer
, &round_len
, NDI_RA_TYPE_IO
, NDI_RA_PASS
);
5173 * Setup "ranges" property before onlining the bridge.
5175 bzero((caddr_t
)range
, sizeof (pcicfg_range_t
) * PCICFG_RANGE_LEN
);
5177 range
[0].child_hi
= range
[0].parent_hi
|= (PCI_REG_REL_M
| PCI_ADDR_IO
);
5178 range
[0].child_lo
= range
[0].parent_lo
= io_base
;
5179 range
[1].child_hi
= range
[1].parent_hi
|=
5180 (PCI_REG_REL_M
| PCI_ADDR_MEM32
);
5181 range
[1].child_lo
= range
[1].parent_lo
= mem_base
;
5183 range
[0].size_lo
= io_alen
;
5184 if (pcicfg_update_ranges_prop(new_child
, &range
[0])) {
5185 DEBUG0("Failed to update ranges (io)\n");
5186 return (PCICFG_FAILURE
);
5188 range
[1].size_lo
= mem_alen
;
5189 if (pcicfg_update_ranges_prop(new_child
, &range
[1])) {
5190 DEBUG0("Failed to update ranges (memory)\n");
5191 return (PCICFG_FAILURE
);
5197 pci_config_put16(h
, PCI_BCNF_SEC_STATUS
, 0xffff);
5200 * Turn off prefetchable range
5202 pci_config_put32(h
, PCI_BCNF_PF_BASE_LOW
, 0x0000ffff);
5203 pci_config_put32(h
, PCI_BCNF_PF_BASE_HIGH
, 0xffffffff);
5204 pci_config_put32(h
, PCI_BCNF_PF_LIMIT_HIGH
, 0x0);
5207 * Needs to be set to this value
5209 pci_config_put8(h
, PCI_CONF_ILINE
, 0xf);
5211 /* check our device_type as defined by Open Firmware */
5212 if (pcicfg_pcie_device_type(new_child
, h
) == DDI_SUCCESS
)
5213 pcie_device_type
= 1;
5216 * Set bus properties
5218 if (pcicfg_set_busnode_props(new_child
, pcie_device_type
,
5219 (int)bus
, (int)new_bus
) != PCICFG_SUCCESS
) {
5220 DEBUG0("Failed to set busnode props\n");
5221 return (PCICFG_FAILURE
);
5224 (void) pcicfg_device_on(h
);
5227 (void) pcie_init_bus(new_child
, 0, PCIE_BUS_FINAL
);
5228 if (ndi_devi_online(new_child
, NDI_NO_EVENT
|NDI_CONFIG
)
5230 DEBUG0("Unable to online bridge\n");
5231 return (PCICFG_FAILURE
);
5234 DEBUG0("Bridge is ONLINE\n");
5237 * After a Reset, we need to wait 2^25 clock cycles before the
5238 * first Configuration access. The worst case is 33MHz, which
5239 * is a 1 second wait.
5241 drv_usecwait(pcicfg_sec_reset_delay
);
5244 * Probe all children devices
5246 DEBUG0("Bridge Programming Complete - probe children\n");
5247 ndi_devi_enter(new_child
, &count
);
5248 for (i
= 0; ((i
< PCICFG_MAX_DEVICE
) && (ari_mode
== B_FALSE
));
5250 for (j
= 0; j
< max_function
; ) {
5252 trans_device
= j
>> 3;
5256 if ((rval
= pcicfg_fcode_probe(new_child
,
5257 new_bus
, trans_device
, (j
& 7), highest_bus
,
5259 != PCICFG_SUCCESS
) {
5260 if (rval
== PCICFG_NODEVICE
) {
5261 DEBUG3("No Device at bus [0x%x]"
5263 "func [0x%x]\n", new_bus
,
5264 trans_device
, j
& 7);
5269 DEBUG3("Failed to configure bus "
5270 "[0x%x] device [0x%x] "
5271 "func [0x%x]\n", new_bus
,
5272 trans_device
, j
& 7);
5274 rval
= PCICFG_FAILURE
;
5279 new_device
= pcicfg_devi_find(new_child
,
5280 trans_device
, (j
& 7));
5283 * Determine if ARI Forwarding should be enabled.
5286 if (new_device
== NULL
)
5289 if ((pcie_ari_supported(new_child
) ==
5290 PCIE_ARI_FORW_ENABLED
) &&
5291 (pcie_ari_device(new_device
) ==
5293 if (pcie_ari_enable(new_child
) ==
5295 (void) ddi_prop_create(
5299 "ari-enabled", NULL
, 0);
5302 PCICFG_MAX_ARI_FUNCTION
;
5307 if (ari_mode
== B_TRUE
) {
5310 if (new_device
== NULL
)
5313 if (pcie_ari_get_next_function(new_device
,
5314 &next_function
) != DDI_SUCCESS
)
5319 if (next_function
== 0)
5326 ndi_devi_exit(new_child
, count
);
5328 /* if empty topology underneath, it is still a success. */
5329 if (rval
!= PCICFG_FAILURE
)
5330 rval
= PCICFG_SUCCESS
;
5333 * Offline the bridge to allow reprogramming of resources.
5335 * This should always succeed since nobody else has started to
5336 * use it yet, failing to detach the driver would indicate a bug.
5337 * Also in that case it's better just panic than allowing the
5338 * configurator to proceed with BAR reprogramming without bridge
5341 VERIFY(ndi_devi_offline(new_child
, NDI_NO_EVENT
|NDI_UNCONFIG
)
5344 pcie_fini_bus(new_child
, PCIE_BUS_INITIAL
);
5346 phdl
.dip
= new_child
;
5347 phdl
.memory_base
= mem_answer
;
5348 phdl
.io_base
= (uint32_t)io_answer
;
5349 phdl
.error
= PCICFG_SUCCESS
; /* in case of empty child tree */
5351 ndi_devi_enter(ddi_get_parent(new_child
), &count
);
5352 ddi_walk_devs(new_child
, pcicfg_find_resource_end
, (void *)&phdl
);
5353 ndi_devi_exit(ddi_get_parent(new_child
), count
);
5355 if (phdl
.error
!= PCICFG_SUCCESS
) {
5356 DEBUG0("Failure summing resources\n");
5357 return (PCICFG_FAILURE
);
5360 num_slots
= pcicfg_get_nslots(new_child
, h
);
5361 mem_end
= PCICFG_ROUND_UP(phdl
.memory_base
, PCICFG_MEMGRAN
);
5362 io_end
= PCICFG_ROUND_UP(phdl
.io_base
, PCICFG_IOGRAN
);
5364 DEBUG3("Start of Unallocated Bridge(%d slots) Resources "
5365 "Mem=0x%lx I/O=0x%lx\n", num_slots
, mem_end
, io_end
);
5368 * Before probing the children we've allocated maximum MEM/IO
5369 * resources from parent, and updated "available" property
5370 * accordingly. Later we'll be giving up unused resources to
5371 * the parent, thus we need to destroy "available" property
5372 * here otherwise it will be out-of-sync with the actual free
5373 * resources this bridge has. This property will be rebuilt below
5374 * with the actual free resources reserved for hotplug slots
5377 (void) ndi_prop_remove(DDI_DEV_T_NONE
, new_child
, "available");
5379 * if the bridge a slots, then preallocate. If not, assume static
5380 * configuration. Also check for preallocation limits and spit
5381 * warning messages appropriately (perhaps some can be in debug mode).
5385 uint64_t mem_assigned
= mem_end
;
5386 uint64_t io_assigned
= io_end
;
5387 uint64_t mem_reqd
= mem_answer
+ (num_slots
*
5388 pcicfg_slot_memsize
);
5389 uint64_t io_reqd
= io_answer
+ (num_slots
*
5390 pcicfg_slot_iosize
);
5391 uint8_t highest_bus_reqd
= new_bus
+ (num_slots
*
5392 pcicfg_slot_busnums
);
5394 if (mem_end
> mem_reqd
)
5395 DEBUG3("Memory space consumed by bridge"
5396 " more than planned for %d slot(s)(%lx, %lx)",
5397 num_slots
, mem_answer
, mem_end
);
5398 if (io_end
> io_reqd
)
5399 DEBUG3("IO space consumed by bridge"
5400 " more than planned for %d slot(s)(%lx, %lx)",
5401 num_slots
, io_answer
, io_end
);
5402 if (*highest_bus
> highest_bus_reqd
)
5403 DEBUG3("Buses consumed by bridge"
5404 " more than planned for %d slot(s)(%x, %x)",
5405 num_slots
, new_bus
, *highest_bus
);
5407 if (mem_reqd
> (mem_answer
+ mem_alen
))
5408 DEBUG3("Memory space required by bridge"
5409 " more than available for %d slot(s)(%lx, %lx)",
5410 num_slots
, mem_answer
, mem_end
);
5412 if (io_reqd
> (io_answer
+ io_alen
))
5413 DEBUG3("IO space required by bridge"
5414 " more than available for %d slot(s)(%lx, %lx)",
5415 num_slots
, io_answer
, io_end
);
5416 if (highest_bus_reqd
> max_bus
)
5417 DEBUG3("Bus numbers required by bridge"
5418 " more than available for %d slot(s)(%x, %x)",
5419 num_slots
, new_bus
, *highest_bus
);
5421 mem_end
= MAX((MIN(mem_reqd
, (mem_answer
+ mem_alen
))),
5423 io_end
= MAX((MIN(io_reqd
, (io_answer
+ io_alen
))), io_end
);
5424 *highest_bus
= MAX((MIN(highest_bus_reqd
, max_bus
)),
5426 DEBUG3("mem_end %lx, io_end %lx, highest_bus %x\n",
5427 mem_end
, io_end
, *highest_bus
);
5429 mem_size
= mem_end
- mem_assigned
;
5430 io_size
= io_end
- io_assigned
;
5432 reg
.pci_phys_mid
= reg
.pci_size_hi
= 0;
5434 reg
.pci_phys_hi
= (PCI_REG_REL_M
| PCI_ADDR_IO
);
5435 reg
.pci_phys_low
= io_assigned
;
5436 reg
.pci_size_low
= io_size
;
5437 if (pcicfg_update_available_prop(new_child
, ®
)) {
5438 DEBUG0("Failed to update available prop "
5440 return (PCICFG_FAILURE
);
5444 reg
.pci_phys_hi
= (PCI_REG_REL_M
| PCI_ADDR_MEM32
);
5445 reg
.pci_phys_low
= mem_assigned
;
5446 reg
.pci_size_low
= mem_size
;
5447 if (pcicfg_update_available_prop(new_child
, ®
)) {
5448 DEBUG0("Failed to update available prop "
5450 return (PCICFG_FAILURE
);
5456 * Give back unused memory space to parent.
5458 (void) ndi_ra_free(ddi_get_parent(new_child
),
5459 mem_end
, (mem_answer
+ mem_alen
) - mem_end
, NDI_RA_TYPE_MEM
,
5462 if (mem_end
== mem_answer
) {
5463 DEBUG0("No memory resources used\n");
5465 * To prevent the bridge from forwarding any Memory
5466 * transactions, the Memory Limit will be programmed
5467 * with a smaller value than the Memory Base.
5469 pci_config_put16(h
, PCI_BCNF_MEM_BASE
, 0xffff);
5470 pci_config_put16(h
, PCI_BCNF_MEM_LIMIT
, 0);
5475 * Reprogram the end of the memory.
5477 pci_config_put16(h
, PCI_BCNF_MEM_LIMIT
,
5478 PCICFG_HIWORD(mem_end
) - 1);
5479 mem_size
= mem_end
- mem_base
;
5483 * Give back unused io space to parent.
5485 (void) ndi_ra_free(ddi_get_parent(new_child
),
5486 io_end
, (io_answer
+ io_alen
) - io_end
,
5487 NDI_RA_TYPE_IO
, NDI_RA_PASS
);
5489 if (io_end
== io_answer
) {
5490 DEBUG0("No IO Space resources used\n");
5493 * To prevent the bridge from forwarding any I/O
5494 * transactions, the I/O Limit will be programmed
5495 * with a smaller value than the I/O Base.
5497 pci_config_put8(h
, PCI_BCNF_IO_LIMIT_LOW
, 0);
5498 pci_config_put16(h
, PCI_BCNF_IO_LIMIT_HI
, 0);
5499 pci_config_put8(h
, PCI_BCNF_IO_BASE_LOW
, 0xff);
5500 pci_config_put16(h
, PCI_BCNF_IO_BASE_HI
, 0);
5505 * Reprogram the end of the io space.
5507 pci_config_put8(h
, PCI_BCNF_IO_LIMIT_LOW
,
5508 PCICFG_HIBYTE(PCICFG_LOWORD(
5509 PCICFG_LOADDR(io_end
) - 1)));
5511 pci_config_put16(h
, PCI_BCNF_IO_LIMIT_HI
,
5512 PCICFG_HIWORD(PCICFG_LOADDR(io_end
- 1)));
5514 io_size
= io_end
- io_base
;
5517 if ((max_bus
- *highest_bus
) > 0) {
5519 * Give back unused bus numbers
5521 (void) ndi_ra_free(ddi_get_parent(new_child
),
5522 *highest_bus
+1, max_bus
- *highest_bus
,
5523 NDI_RA_TYPE_PCI_BUSNUM
, NDI_RA_PASS
);
5527 * Set bus numbers to ranges encountered during scan
5529 pcicfg_set_bus_numbers(h
, bus
, new_bus
, *highest_bus
);
5531 bus_range
[0] = pci_config_get8(h
, PCI_BCNF_SECBUS
);
5532 bus_range
[1] = pci_config_get8(h
, PCI_BCNF_SUBBUS
);
5533 DEBUG1("End of bridge probe: bus_range[0] = %d\n", bus_range
[0]);
5534 DEBUG1("End of bridge probe: bus_range[1] = %d\n", bus_range
[1]);
5536 if (ndi_prop_update_int_array(DDI_DEV_T_NONE
, new_child
,
5537 "bus-range", bus_range
, 2) != DDI_SUCCESS
) {
5538 DEBUG0("Failed to set bus-range property");
5539 return (PCICFG_FAILURE
);
5543 * Remove the ranges property if it exists since we will create
5546 (void) ndi_prop_remove(DDI_DEV_T_NONE
, new_child
, "ranges");
5548 DEBUG2("Creating Ranges property - Mem Address %lx Mem Size %x\n",
5549 mem_base
, mem_size
);
5550 DEBUG2(" - I/O Address %lx I/O Size %x\n",
5553 bzero((caddr_t
)range
, sizeof (pcicfg_range_t
) * PCICFG_RANGE_LEN
);
5555 range
[0].child_hi
= range
[0].parent_hi
|= (PCI_REG_REL_M
| PCI_ADDR_IO
);
5556 range
[0].child_lo
= range
[0].parent_lo
= io_base
;
5557 range
[1].child_hi
= range
[1].parent_hi
|=
5558 (PCI_REG_REL_M
| PCI_ADDR_MEM32
);
5559 range
[1].child_lo
= range
[1].parent_lo
= mem_base
;
5562 range
[0].size_lo
= io_size
;
5563 if (pcicfg_update_ranges_prop(new_child
, &range
[0])) {
5564 DEBUG0("Failed to update ranges (io)\n");
5565 return (PCICFG_FAILURE
);
5569 range
[1].size_lo
= mem_size
;
5570 if (pcicfg_update_ranges_prop(new_child
, &range
[1])) {
5571 DEBUG0("Failed to update ranges (memory)\n");
5572 return (PCICFG_FAILURE
);
5577 * Remove the resource maps for the bridge since we no longer
5578 * need them. Note that the failure is ignored since the
5579 * ndi_devi_offline above may have already taken care of it via
5581 * It has been checked that there are no other reasons for
5582 * failure other than map itself being non-existent. So we are Ok.
5584 if (ndi_ra_map_destroy(new_child
, NDI_RA_TYPE_MEM
) == NDI_FAILURE
) {
5586 DEBUG0("Can not destroy resource map - NDI_RA_TYPE_MEM\n");
5589 if (ndi_ra_map_destroy(new_child
, NDI_RA_TYPE_IO
) == NDI_FAILURE
) {
5591 DEBUG0("Can not destroy resource map - NDI_RA_TYPE_IO\n");
5594 if (ndi_ra_map_destroy(new_child
, NDI_RA_TYPE_PCI_BUSNUM
)
5597 DEBUG0("Can't destroy resource map - NDI_RA_TYPE_PCI_BUSNUM\n");
5604 * Return PCICFG_SUCCESS if device exists at the specified address.
5605 * Return PCICFG_NODEVICE is no device exists at the specified address.
5609 pcicfg_config_setup(dev_info_t
*dip
, ddi_acc_handle_t
*handle
)
5612 ddi_device_acc_attr_t attr
;
5616 int ret
= DDI_SUCCESS
;
5619 * flags = PCICFG_CONF_INDIRECT_MAP if configuration space is indirectly
5620 * mapped, otherwise it is 0. "flags" is introduced in support of any
5621 * non transparent bridges, where configuration space is indirectly
5623 * Indirect mapping is always true on sun4v systems.
5629 * Get the pci register spec from the node
5631 status
= ddi_getlongprop(DDI_DEV_T_ANY
,
5632 dip
, DDI_PROP_DONTPASS
, "reg", (caddr_t
)®
, &rlen
);
5635 case DDI_PROP_SUCCESS
:
5637 case DDI_PROP_NO_MEMORY
:
5638 DEBUG0("reg present, but unable to get memory\n");
5639 return (PCICFG_FAILURE
);
5641 DEBUG0("no reg property\n");
5642 return (PCICFG_FAILURE
);
5645 if (pcicfg_indirect_map(dip
) == DDI_SUCCESS
)
5646 flags
|= PCICFG_CONF_INDIRECT_MAP
;
5649 * Map in configuration space (temporarily)
5651 attr
.devacc_attr_version
= DDI_DEVICE_ATTR_V0
;
5652 attr
.devacc_attr_endian_flags
= DDI_STRUCTURE_LE_ACC
;
5653 attr
.devacc_attr_dataorder
= DDI_STRICTORDER_ACC
;
5654 attr
.devacc_attr_access
= DDI_CAUTIOUS_ACC
;
5657 if (ddi_regs_map_setup(dip
, 0, &virt
,
5658 0, 0, &attr
, handle
) != DDI_SUCCESS
)
5660 if (pcicfg_map_phys(dip
, reg
, &virt
, &attr
, handle
)
5664 DEBUG0("pcicfg_config_setup():"
5665 "Failed to setup config space\n");
5667 kmem_free((caddr_t
)reg
, rlen
);
5668 return (PCICFG_FAILURE
);
5671 if (flags
& PCICFG_CONF_INDIRECT_MAP
) {
5673 * need to use DDI interfaces as the conf space is
5674 * cannot be directly accessed by the host.
5676 tmp
= (int16_t)ddi_get16(*handle
, (uint16_t *)virt
);
5678 ret
= ddi_peek16(dip
, (int16_t *)virt
, &tmp
);
5681 if (ret
== DDI_SUCCESS
) {
5683 DEBUG1("NO DEVICEFOUND, read %x\n", tmp
);
5684 ret
= PCICFG_NODEVICE
;
5686 /* XXX - Need to check why HV is returning 0 */
5688 DEBUG0("Device Not Ready yet ?");
5689 ret
= PCICFG_NODEVICE
;
5691 DEBUG1("DEVICEFOUND, read %x\n", tmp
);
5692 ret
= PCICFG_SUCCESS
;
5696 DEBUG0("ddi_peek failed, must be NODEVICE\n");
5697 ret
= PCICFG_NODEVICE
;
5701 * A bug in XMITS 3.0 causes us to miss the Master Abort Split
5702 * Completion message. The result is the error message being
5703 * sent back as part of the config data. If the first two words
5704 * of the config space happen to be the same as the Master Abort
5705 * message, then report back that there is no device there.
5707 if ((ret
== PCICFG_SUCCESS
) && !(flags
& PCICFG_CONF_INDIRECT_MAP
)) {
5710 #define PCICFG_PCIX_SCM 0x10000004
5713 (void) ddi_peek32(dip
, (int32_t *)virt
, &pcix_scm
);
5714 if (pcix_scm
== PCICFG_PCIX_SCM
) {
5716 (void) ddi_peek32(dip
,
5717 (int32_t *)(virt
+ 4), &pcix_scm
);
5718 if (pcix_scm
== PCICFG_PCIX_SCM
)
5719 ret
= PCICFG_NODEVICE
;
5723 if (ret
== PCICFG_NODEVICE
)
5725 ddi_regs_map_free(handle
);
5727 pcicfg_unmap_phys(handle
, reg
);
5730 kmem_free((caddr_t
)reg
, rlen
);
5737 pcicfg_config_teardown(ddi_acc_handle_t
*handle
)
5739 (void) ddi_regs_map_free(handle
);
5743 pcicfg_add_config_reg(dev_info_t
*dip
,
5744 uint_t bus
, uint_t device
, uint_t func
)
5746 int reg
[10] = { PCI_ADDR_CONFIG
, 0, 0, 0, 0};
5748 reg
[0] = PCICFG_MAKE_REG_HIGH(bus
, device
, func
, 0);
5750 return (ndi_prop_update_int_array(DDI_DEV_T_NONE
, dip
,
5755 pcicfg_dump_assigned(dev_info_t
*dip
)
5762 if (ddi_getlongprop(DDI_DEV_T_ANY
, dip
,
5763 DDI_PROP_DONTPASS
, "assigned-addresses", (caddr_t
)®
,
5764 &length
) != DDI_PROP_SUCCESS
) {
5765 DEBUG0("Failed to read assigned-addresses property\n");
5766 return (PCICFG_FAILURE
);
5769 rcount
= length
/ sizeof (pci_regspec_t
);
5770 for (i
= 0; i
< rcount
; i
++) {
5771 DEBUG4("pcicfg_dump_assigned - size=%x low=%x mid=%x high=%x\n",
5772 reg
[i
].pci_size_low
, reg
[i
].pci_phys_low
,
5773 reg
[i
].pci_phys_mid
, reg
[i
].pci_phys_hi
);
5776 * Don't forget to free up memory from ddi_getlongprop
5778 kmem_free((caddr_t
)reg
, length
);
5780 return (PCICFG_SUCCESS
);
5783 #ifdef PCICFG_INTERPRET_FCODE
5785 pcicfg_load_fcode(dev_info_t
*dip
, uint_t bus
, uint_t device
, uint_t func
,
5786 uint16_t vendor_id
, uint16_t device_id
, uchar_t
**fcode_addr
,
5787 int *fcode_size
, int rom_paddr
, int rom_size
)
5795 ddi_device_acc_attr_t acc
;
5797 int8_t image_not_found
, indicator
;
5798 uint16_t vendor_id_img
, device_id_img
;
5804 DEBUG4("pcicfg_load_fcode() - "
5805 "bus %x device =%x func=%x rom_paddr=%lx\n",
5806 bus
, device
, func
, rom_paddr
);
5807 DEBUG2("pcicfg_load_fcode() - vendor_id=%x device_id=%x\n",
5808 vendor_id
, device_id
);
5813 acc
.devacc_attr_version
= DDI_DEVICE_ATTR_V0
;
5814 acc
.devacc_attr_endian_flags
= DDI_STRUCTURE_LE_ACC
;
5815 acc
.devacc_attr_dataorder
= DDI_STRICTORDER_ACC
;
5817 p
.pci_phys_hi
= PCI_ADDR_MEM32
| PCICFG_MAKE_REG_HIGH(bus
, device
,
5818 func
, PCI_CONF_ROM
);
5823 p
.pci_size_low
= rom_size
;
5826 if (pcicfg_map_phys(dip
, &p
, (caddr_t
*)&addr
, &acc
, &h
)) {
5827 DEBUG1("Can Not map in ROM %x\n", p
.pci_phys_low
);
5828 return (PCICFG_FAILURE
);
5832 * Walk the ROM to find the proper image for this device.
5834 image_not_found
= 1;
5835 while (image_not_found
) {
5836 DEBUG1("Expansion ROM maps to %lx\n", addr
);
5839 if (pcicfg_dump_fcode
) {
5840 for (i
= 0; i
< 100; i
++)
5841 DEBUG2("ROM 0x%x --> 0x%x\n", i
,
5842 ddi_get8(h
, (uint8_t *)(addr
+ i
)));
5847 * Some device say they have an Expansion ROM, but do not, so
5848 * for non-21554 devices use peek so we don't panic due to
5849 * accessing non existent memory.
5851 if (pcicfg_indirect_map(dip
) == DDI_SUCCESS
) {
5852 rom_sig
= ddi_get16(h
,
5853 (uint16_t *)(addr
+ PCI_ROM_SIGNATURE
));
5856 (int16_t *)(addr
+ PCI_ROM_SIGNATURE
), &rom_sig
)) {
5858 "PCI Expansion ROM is not accessible");
5859 pcicfg_unmap_phys(&h
, &p
);
5860 return (PCICFG_FAILURE
);
5865 * Validate the ROM Signature.
5867 if ((uint16_t)rom_sig
!= 0xaa55) {
5868 DEBUG1("Invalid ROM Signature %x\n", (uint16_t)rom_sig
);
5869 pcicfg_unmap_phys(&h
, &p
);
5870 return (PCICFG_FAILURE
);
5873 DEBUG0("Valid ROM Signature Found\n");
5875 start_of_fcode
= ddi_get16(h
, (uint16_t *)(addr
+ 2));
5877 pci_data
= ddi_get16(h
,
5878 (uint16_t *)(addr
+ PCI_ROM_PCI_DATA_STRUCT_PTR
));
5880 DEBUG2("Pointer To PCI Data Structure %x %x\n", pci_data
,
5884 * Validate the PCI Data Structure Signature.
5885 * 0x52494350 = "PCIR"
5888 if (ddi_get8(h
, (uint8_t *)(addr
+ pci_data
)) != 0x50) {
5889 DEBUG0("Invalid PCI Data Structure Signature\n");
5890 pcicfg_unmap_phys(&h
, &p
);
5891 return (PCICFG_FAILURE
);
5894 if (ddi_get8(h
, (uint8_t *)(addr
+ pci_data
+ 1)) != 0x43) {
5895 DEBUG0("Invalid PCI Data Structure Signature\n");
5896 pcicfg_unmap_phys(&h
, &p
);
5897 return (PCICFG_FAILURE
);
5899 if (ddi_get8(h
, (uint8_t *)(addr
+ pci_data
+ 2)) != 0x49) {
5900 DEBUG0("Invalid PCI Data Structure Signature\n");
5901 pcicfg_unmap_phys(&h
, &p
);
5902 return (PCICFG_FAILURE
);
5904 if (ddi_get8(h
, (uint8_t *)(addr
+ pci_data
+ 3)) != 0x52) {
5905 DEBUG0("Invalid PCI Data Structure Signature\n");
5906 pcicfg_unmap_phys(&h
, &p
);
5907 return (PCICFG_FAILURE
);
5911 * Is this image for this device?
5913 vendor_id_img
= ddi_get16(h
,
5914 (uint16_t *)(addr
+ pci_data
+ PCI_PDS_VENDOR_ID
));
5915 device_id_img
= ddi_get16(h
,
5916 (uint16_t *)(addr
+ pci_data
+ PCI_PDS_DEVICE_ID
));
5918 DEBUG2("This image is for vendor_id=%x device_id=%x\n",
5919 vendor_id_img
, device_id_img
);
5921 code_type
= ddi_get8(h
, addr
+ pci_data
+ PCI_PDS_CODE_TYPE
);
5923 switch (code_type
) {
5924 case PCI_PDS_CODE_TYPE_PCAT
:
5925 DEBUG0("ROM is of x86/PC-AT Type\n");
5927 case PCI_PDS_CODE_TYPE_OPEN_FW
:
5928 DEBUG0("ROM is of Open Firmware Type\n");
5931 DEBUG1("ROM is of Unknown Type 0x%x\n", code_type
);
5935 if ((vendor_id_img
!= vendor_id
) ||
5936 (device_id_img
!= device_id
) ||
5937 (code_type
!= PCI_PDS_CODE_TYPE_OPEN_FW
)) {
5938 DEBUG0("Firmware Image is not for this device..."
5939 "goto next image\n");
5941 * Read indicator byte to see if there is another
5944 indicator
= ddi_get8(h
,
5945 (uint8_t *)(addr
+ pci_data
+ PCI_PDS_INDICATOR
));
5947 if (indicator
!= 1) {
5949 * There is another image in the ROM.
5951 image_length
= ddi_get16(h
, (uint16_t *)(addr
+
5952 pci_data
+ PCI_PDS_IMAGE_LENGTH
)) * 512;
5954 addr
+= image_length
;
5957 * There are no more images.
5959 DEBUG0("There are no more images in the ROM\n");
5960 pcicfg_unmap_phys(&h
, &p
);
5962 return (PCICFG_FAILURE
);
5965 DEBUG0("Correct image was found\n");
5966 image_not_found
= 0; /* Image was found */
5970 *fcode_size
= (ddi_get8(h
, addr
+ start_of_fcode
+ 4) << 24) |
5971 (ddi_get8(h
, addr
+ start_of_fcode
+ 5) << 16) |
5972 (ddi_get8(h
, addr
+ start_of_fcode
+ 6) << 8) |
5973 (ddi_get8(h
, addr
+ start_of_fcode
+ 7));
5975 DEBUG1("Fcode Size %x\n", *fcode_size
);
5978 * Allocate page aligned buffer space
5980 *fcode_addr
= kmem_zalloc(ptob(btopr(*fcode_size
)), KM_SLEEP
);
5982 if (*fcode_addr
== NULL
) {
5983 DEBUG0("kmem_zalloc returned NULL\n");
5984 pcicfg_unmap_phys(&h
, &p
);
5985 return (PCICFG_FAILURE
);
5988 DEBUG1("Fcode Addr %lx\n", *fcode_addr
);
5990 ddi_rep_get8(h
, *fcode_addr
, addr
+ start_of_fcode
, *fcode_size
,
5993 pcicfg_unmap_phys(&h
, &p
);
5995 return (PCICFG_SUCCESS
);
5999 pcicfg_fcode_assign_bars(ddi_acc_handle_t h
, dev_info_t
*dip
, uint_t bus
,
6000 uint_t device
, uint_t func
, int32_t fc_request
, pci_regspec_t
*rom_regspec
)
6003 * Assign values to all BARs so that it is safe to turn on the
6004 * device for accessing the fcode on the PROM. On successful
6005 * exit from this function, "assigned-addresses" are created
6006 * for all BARs and ROM BAR is enabled. Also, rom_regspec is
6007 * filled with the values that can be used to free up this
6010 uint32_t request
, hiword
, size
;
6011 pci_regspec_t phys_spec
;
6012 ndi_ra_request_t req
;
6013 uint64_t mem_answer
, mem_alen
;
6016 DEBUG1("pcicfg_fcode_assign_bars :%s\n", DEVI(dip
)->devi_name
);
6021 for (i
= PCI_CONF_BASE0
; i
<= PCI_CONF_BASE5
; ) {
6022 pci_config_put32(h
, i
, 0xffffffff);
6023 request
= pci_config_get32(h
, i
);
6025 * Check if implemented
6028 DEBUG1("pcicfg_fcode_assign_bars :"
6029 "BASE register [0x%x] asks for 0(32)\n", i
);
6034 * Build the phys_spec for this BAR
6036 hiword
= PCICFG_MAKE_REG_HIGH(bus
, device
, func
, i
);
6037 size
= (~(PCI_BASE_M_ADDR_M
& request
)) + 1;
6039 DEBUG3("pcicfg_fcode_assign_bars :"
6040 "BASE register [0x%x] asks for [0x%x]=[0x%x]\n",
6043 if ((PCI_BASE_SPACE_M
& request
) == PCI_BASE_SPACE_MEM
) {
6044 if ((PCI_BASE_TYPE_M
& request
) == PCI_BASE_TYPE_MEM
) {
6045 hiword
|= PCI_ADDR_MEM32
;
6046 } else if ((PCI_BASE_TYPE_M
& request
)
6047 == PCI_BASE_TYPE_ALL
) {
6048 hiword
|= PCI_ADDR_MEM64
;
6050 if (request
& PCI_BASE_PREF_M
)
6051 hiword
|= PCI_REG_PF_M
;
6053 hiword
|= PCI_ADDR_IO
;
6055 phys_spec
.pci_phys_hi
= hiword
;
6056 phys_spec
.pci_phys_mid
= 0;
6057 phys_spec
.pci_phys_low
= 0;
6058 phys_spec
.pci_size_hi
= 0;
6059 phys_spec
.pci_size_low
= size
;
6062 * The following function
6063 * - allocates address space
6064 * - programs the BAR
6065 * - adds an "assigned-addresses" property
6067 if (pcicfg_alloc_resource(dip
, phys_spec
)) {
6068 cmn_err(CE_WARN
, "failed to allocate %d bytes"
6069 " for dev %s BASE register [0x%x]\n",
6070 size
, DEVI(dip
)->devi_name
, i
);
6073 if ((PCI_BASE_TYPE_M
& request
) == PCI_BASE_TYPE_ALL
) {
6075 * 64 bit, should be in memory space.
6080 * 32 bit, either memory or I/O space.
6087 * Handle ROM BAR. We do not use the common
6088 * resource allocator function because we need to
6089 * return reg spec to the caller.
6091 size
= (~(PCI_BASE_ROM_ADDR_M
& fc_request
)) + 1;
6093 DEBUG3("BASE register [0x%x] asks for "
6094 "[0x%x]=[0x%x]\n", PCI_CONF_ROM
, fc_request
, size
);
6096 bzero((caddr_t
)&req
, sizeof (ndi_ra_request_t
));
6098 req
.ra_boundbase
= 0;
6099 req
.ra_boundlen
= PCICFG_4GIG_LIMIT
;
6101 req
.ra_flags
= (NDI_RA_ALIGN_SIZE
| NDI_RA_ALLOC_BOUNDED
);
6103 if (ndi_ra_alloc(ddi_get_parent(dip
),
6104 &req
, &mem_answer
, &mem_alen
,
6105 NDI_RA_TYPE_MEM
, NDI_RA_PASS
)) {
6106 cmn_err(CE_WARN
, "failed to allocate %d bytes"
6107 " for dev %s ROM BASE register\n",
6108 size
, DEVI(dip
)->devi_name
);
6112 DEBUG3("ROM addr = [0x%x.%x] len [0x%x]\n",
6113 PCICFG_HIADDR(mem_answer
),
6114 PCICFG_LOADDR(mem_answer
), mem_alen
);
6117 * Assign address space and enable ROM.
6119 pci_config_put32(h
, PCI_CONF_ROM
,
6120 PCICFG_LOADDR(mem_answer
) | PCI_BASE_ROM_ENABLE
);
6123 * Add resource to assigned-addresses.
6125 phys_spec
.pci_phys_hi
= PCICFG_MAKE_REG_HIGH(bus
, device
, func
, \
6126 PCI_CONF_ROM
) | PCI_ADDR_MEM32
;
6127 if (fc_request
& PCI_BASE_PREF_M
)
6128 phys_spec
.pci_phys_hi
|= PCI_REG_PF_M
;
6129 phys_spec
.pci_phys_mid
= 0;
6130 phys_spec
.pci_phys_low
= PCICFG_LOADDR(mem_answer
);
6131 phys_spec
.pci_size_hi
= 0;
6132 phys_spec
.pci_size_low
= size
;
6134 if (pcicfg_update_assigned_prop(dip
, &phys_spec
)
6135 != PCICFG_SUCCESS
) {
6136 cmn_err(CE_WARN
, "failed to update"
6137 " assigned-address property for dev %s\n",
6138 DEVI(dip
)->devi_name
);
6142 * Copy out the reg spec.
6144 *rom_regspec
= phys_spec
;
6146 return (PCICFG_SUCCESS
);
6150 * We came in with no "assigned-addresses".
6151 * Free up the resources we may have allocated.
6153 (void) pcicfg_free_device_resources(dip
, 0);
6155 return (PCICFG_FAILURE
);
6158 #endif /* PCICFG_INTERPRET_FCODE */
6161 pcicfg_free_all_resources(dev_info_t
*dip
)
6163 pci_regspec_t
*assigned
;
6168 if (ddi_getlongprop(DDI_DEV_T_ANY
, dip
,
6169 DDI_PROP_DONTPASS
, "assigned-addresses", (caddr_t
)&assigned
,
6170 &assigned_len
) != DDI_PROP_SUCCESS
) {
6171 DEBUG0("Failed to read assigned-addresses property\n");
6172 return (PCICFG_FAILURE
);
6175 acount
= assigned_len
/ sizeof (pci_regspec_t
);
6177 for (i
= 0; i
< acount
; i
++) {
6178 if (pcicfg_free_resource(dip
, assigned
[i
], 0)) {
6180 * Dont forget to free mem from ddi_getlongprop
6182 kmem_free((caddr_t
)assigned
, assigned_len
);
6183 return (PCICFG_FAILURE
);
6188 * Don't forget to free up memory from ddi_getlongprop
6191 kmem_free((caddr_t
)assigned
, assigned_len
);
6193 return (PCICFG_SUCCESS
);
6196 pcicfg_alloc_new_resources(dev_info_t
*dip
)
6198 pci_regspec_t
*assigned
, *reg
;
6199 int assigned_len
, reg_len
;
6201 int i
, j
, alloc_size
;
6204 if (ddi_getlongprop(DDI_DEV_T_ANY
, dip
,
6205 DDI_PROP_DONTPASS
, "reg", (caddr_t
)®
,
6206 ®_len
) != DDI_PROP_SUCCESS
) {
6207 DEBUG0("Failed to read reg property\n");
6208 return (PCICFG_FAILURE
);
6210 rcount
= reg_len
/ sizeof (pci_regspec_t
);
6212 DEBUG2("pcicfg_alloc_new_resources() reg size=%x entries=%x\n",
6215 if (ddi_getlongprop(DDI_DEV_T_ANY
, dip
,
6216 DDI_PROP_DONTPASS
, "assigned-addresses", (caddr_t
)&assigned
,
6217 &assigned_len
) != DDI_PROP_SUCCESS
) {
6220 acount
= assigned_len
/ sizeof (pci_regspec_t
);
6223 DEBUG1("assigned-addresses property len=%x\n", acount
);
6226 * For each address described by reg, search for it in the
6227 * assigned-addresses property. If it does not exist, allocate
6228 * resources for it. If it does exist, check the size in both.
6229 * The size needs to be bigger of the two.
6231 for (i
= 1; i
< rcount
; i
++) {
6233 alloc_size
= reg
[i
].pci_size_low
;
6234 for (j
= 0; j
< acount
; j
++) {
6235 if (assigned
[j
].pci_phys_hi
== reg
[i
].pci_phys_hi
) {
6237 * There is an exact match. Check size.
6239 DEBUG1("pcicfg_alloc_new_resources "
6241 reg
[i
].pci_phys_hi
);
6243 if (reg
[i
].pci_size_low
>
6244 assigned
[j
].pci_size_low
) {
6248 DEBUG3("pcicfg_alloc_new_resources"
6250 " assigned 0x%x reg 0x%x\n",
6251 assigned
[j
].pci_phys_hi
,
6252 assigned
[j
].pci_size_low
,
6253 reg
[i
].pci_size_low
);
6256 * Free the old resource.
6258 (void) pcicfg_free_resource(dip
,
6261 DEBUG3("pcicfg_alloc_new_resources"
6263 " assigned 0x%x reg 0x%x\n",
6264 assigned
[j
].pci_phys_hi
,
6265 assigned
[j
].pci_size_low
,
6266 reg
[i
].pci_size_low
);
6273 * Fcode may have set one or more of the
6274 * NPT bits in phys.hi.
6276 if (PCI_REG_BDFR_G(assigned
[j
].pci_phys_hi
) ==
6277 PCI_REG_BDFR_G(reg
[i
].pci_phys_hi
)) {
6279 DEBUG2("pcicfg_alloc_new_resources "
6280 "- PARTIAL MATCH assigned 0x%x "
6281 "reg 0x%x\n", assigned
[j
].pci_phys_hi
,
6282 reg
[i
].pci_phys_hi
);
6284 * Changing the SS bits is an error
6287 assigned
[j
].pci_phys_hi
) !=
6288 PCI_REG_ADDR_G(reg
[i
].pci_phys_hi
)) {
6290 DEBUG2("Fcode changing"
6291 " SS bits of - 0x%x -"
6292 " on %s\n", reg
[i
].pci_phys_hi
,
6293 DEVI(dip
)->devi_name
);
6299 * We are going to allocate new resource.
6300 * Free the old resource. Again, adjust
6301 * the size to be safe.
6303 (void) pcicfg_free_resource(dip
,
6306 alloc_size
= MAX(reg
[i
].pci_size_low
,
6307 assigned
[j
].pci_size_low
);
6313 * We are allocating resources for one of three reasons -
6314 * - Fcode wants a larger address space
6315 * - Fcode has set changed/set n, p, t bits.
6316 * - It is a new "reg", it should be only ROM bar, but
6317 * we don't do the checking.
6319 if (alloc
== B_TRUE
) {
6320 DEBUG1("pcicfg_alloc_new_resources : creating 0x%x\n",
6321 reg
[i
].pci_phys_hi
);
6323 reg
[i
].pci_size_low
= alloc_size
;
6324 if (pcicfg_alloc_resource(dip
, reg
[i
])) {
6326 * Dont forget to free mem from
6330 kmem_free((caddr_t
)assigned
,
6332 kmem_free((caddr_t
)reg
, reg_len
);
6333 return (PCICFG_FAILURE
);
6339 * Don't forget to free up memory from ddi_getlongprop
6342 kmem_free((caddr_t
)assigned
, assigned_len
);
6343 kmem_free((caddr_t
)reg
, reg_len
);
6345 return (PCICFG_SUCCESS
);
6349 pcicfg_alloc_resource(dev_info_t
*dip
, pci_regspec_t phys_spec
)
6354 pci_regspec_t config
;
6356 ddi_device_acc_attr_t acc
;
6358 ndi_ra_request_t request
;
6359 pci_regspec_t
*assigned
;
6360 int assigned_len
, entries
, i
;
6362 if (ddi_getlongprop(DDI_DEV_T_ANY
, dip
,
6363 DDI_PROP_DONTPASS
, "assigned-addresses", (caddr_t
)&assigned
,
6364 &assigned_len
) == DDI_PROP_SUCCESS
) {
6365 DEBUG0("pcicfg_alloc_resource - "
6366 "searching assigned-addresses\n");
6368 entries
= assigned_len
/ (sizeof (pci_regspec_t
));
6371 * Walk through the assigned-addresses entries. If there is
6372 * a match, there is no need to allocate the resource.
6374 for (i
= 0; i
< entries
; i
++) {
6375 if (assigned
[i
].pci_phys_hi
== phys_spec
.pci_phys_hi
) {
6376 DEBUG1("pcicfg_alloc_resource - MATCH %x\n",
6377 assigned
[i
].pci_phys_hi
);
6378 kmem_free(assigned
, assigned_len
);
6382 kmem_free(assigned
, assigned_len
);
6385 bzero((caddr_t
)&request
, sizeof (ndi_ra_request_t
));
6387 config
.pci_phys_hi
= PCI_CONF_ADDR_MASK
& phys_spec
.pci_phys_hi
;
6388 config
.pci_phys_hi
&= ~PCI_REG_REG_M
;
6389 config
.pci_phys_mid
= config
.pci_phys_low
= 0;
6390 config
.pci_size_hi
= config
.pci_size_low
= 0;
6393 * Map in configuration space (temporarily)
6395 acc
.devacc_attr_version
= DDI_DEVICE_ATTR_V0
;
6396 acc
.devacc_attr_endian_flags
= DDI_STRUCTURE_LE_ACC
;
6397 acc
.devacc_attr_dataorder
= DDI_STRICTORDER_ACC
;
6399 if (pcicfg_map_phys(dip
, &config
, &virt
, &acc
, &h
)) {
6400 DEBUG0("Can not map in config space\n");
6404 request
.ra_flags
= NDI_RA_ALIGN_SIZE
;
6405 request
.ra_boundbase
= 0;
6406 request
.ra_boundlen
= PCICFG_4GIG_LIMIT
;
6408 * Use size stored in phys_spec parameter.
6410 request
.ra_len
= phys_spec
.pci_size_low
;
6412 offset
= PCI_REG_REG_G(phys_spec
.pci_phys_hi
);
6416 if (PCI_REG_REG_G(phys_spec
.pci_phys_hi
) == PCI_CONF_ROM
) {
6418 request
.ra_flags
|= NDI_RA_ALLOC_BOUNDED
;
6420 /* allocate memory space from the allocator */
6422 if (ndi_ra_alloc(ddi_get_parent(dip
),
6423 &request
, &answer
, &alen
,
6424 NDI_RA_TYPE_MEM
, NDI_RA_PASS
)
6426 DEBUG0("(ROM)Failed to allocate 32b mem");
6427 pcicfg_unmap_phys(&h
, &config
);
6430 DEBUG3("ROM addr = [0x%x.%x] len [0x%x]\n",
6431 PCICFG_HIADDR(answer
),
6432 PCICFG_LOADDR(answer
),
6435 /* program the low word */
6437 ddi_put32(h
, (uint32_t *)v
, (uint32_t)PCICFG_LOADDR(answer
));
6439 phys_spec
.pci_phys_low
= PCICFG_LOADDR(answer
);
6440 phys_spec
.pci_phys_mid
= PCICFG_HIADDR(answer
);
6443 switch (PCI_REG_ADDR_G(phys_spec
.pci_phys_hi
)) {
6444 case PCI_REG_ADDR_G(PCI_ADDR_MEM64
):
6445 request
.ra_flags
&= ~NDI_RA_ALLOC_BOUNDED
;
6446 /* allocate memory space from the allocator */
6447 if (ndi_ra_alloc(ddi_get_parent(dip
),
6448 &request
, &answer
, &alen
,
6449 NDI_RA_TYPE_MEM
, NDI_RA_PASS
)
6451 DEBUG0("Failed to allocate 64b mem\n");
6452 pcicfg_unmap_phys(&h
, &config
);
6455 DEBUG3("64 addr = [0x%x.%x] len [0x%x]\n",
6456 PCICFG_HIADDR(answer
),
6457 PCICFG_LOADDR(answer
),
6460 /* program the low word */
6462 ddi_put32(h
, (uint32_t *)v
,
6463 (uint32_t)PCICFG_LOADDR(answer
));
6465 /* program the high word with value zero */
6467 ddi_put32(h
, (uint32_t *)v
,
6468 (uint32_t)PCICFG_HIADDR(answer
));
6470 phys_spec
.pci_phys_low
= PCICFG_LOADDR(answer
);
6471 phys_spec
.pci_phys_mid
= PCICFG_HIADDR(answer
);
6473 * currently support 32b address space
6476 phys_spec
.pci_phys_hi
^= PCI_ADDR_MEM64
^
6481 case PCI_REG_ADDR_G(PCI_ADDR_MEM32
):
6482 request
.ra_flags
|= NDI_RA_ALLOC_BOUNDED
;
6483 /* allocate memory space from the allocator */
6484 if (ndi_ra_alloc(ddi_get_parent(dip
),
6485 &request
, &answer
, &alen
,
6486 NDI_RA_TYPE_MEM
, NDI_RA_PASS
)
6488 DEBUG0("Failed to allocate 32b mem\n");
6489 pcicfg_unmap_phys(&h
, &config
);
6493 DEBUG3("32 addr = [0x%x.%x] len [0x%x]\n",
6494 PCICFG_HIADDR(answer
),
6495 PCICFG_LOADDR(answer
),
6498 /* program the low word */
6500 ddi_put32(h
, (uint32_t *)v
,
6501 (uint32_t)PCICFG_LOADDR(answer
));
6503 phys_spec
.pci_phys_low
= PCICFG_LOADDR(answer
);
6506 case PCI_REG_ADDR_G(PCI_ADDR_IO
):
6507 /* allocate I/O space from the allocator */
6508 request
.ra_flags
|= NDI_RA_ALLOC_BOUNDED
;
6509 if (ndi_ra_alloc(ddi_get_parent(dip
),
6510 &request
, &answer
, &alen
,
6511 NDI_RA_TYPE_IO
, NDI_RA_PASS
)
6513 DEBUG0("Failed to allocate I/O\n");
6514 pcicfg_unmap_phys(&h
, &config
);
6517 DEBUG3("I/O addr = [0x%x.%x] len [0x%x]\n",
6518 PCICFG_HIADDR(answer
),
6519 PCICFG_LOADDR(answer
),
6522 ddi_put32(h
, (uint32_t *)v
,
6523 (uint32_t)PCICFG_LOADDR(answer
));
6525 phys_spec
.pci_phys_low
= PCICFG_LOADDR(answer
);
6529 DEBUG0("Unknown register type\n");
6530 pcicfg_unmap_phys(&h
, &config
);
6536 * Now that memory locations are assigned,
6537 * update the assigned address property.
6540 DEBUG1("updating assigned-addresss for %x\n", phys_spec
.pci_phys_hi
);
6542 if (pcicfg_update_assigned_prop(dip
, &phys_spec
)) {
6543 pcicfg_unmap_phys(&h
, &config
);
6547 pcicfg_unmap_phys(&h
, &config
);
6553 pcicfg_free_resource(dev_info_t
*dip
, pci_regspec_t phys_spec
,
6554 pcicfg_flags_t flags
)
6557 pci_regspec_t config
;
6559 ddi_device_acc_attr_t acc
;
6561 ndi_ra_request_t request
;
6564 bzero((caddr_t
)&request
, sizeof (ndi_ra_request_t
));
6566 config
.pci_phys_hi
= PCI_CONF_ADDR_MASK
& phys_spec
.pci_phys_hi
;
6567 config
.pci_phys_hi
&= ~PCI_REG_REG_M
;
6568 config
.pci_phys_mid
= config
.pci_phys_low
= 0;
6569 config
.pci_size_hi
= config
.pci_size_low
= 0;
6572 * Map in configuration space (temporarily)
6574 acc
.devacc_attr_version
= DDI_DEVICE_ATTR_V0
;
6575 acc
.devacc_attr_endian_flags
= DDI_STRUCTURE_LE_ACC
;
6576 acc
.devacc_attr_dataorder
= DDI_STRICTORDER_ACC
;
6578 if (pcicfg_map_phys(dip
, &config
, &virt
, &acc
, &h
)) {
6579 DEBUG0("Can not map in config space\n");
6583 offset
= PCI_REG_REG_G(phys_spec
.pci_phys_hi
);
6588 * Use size stored in phys_spec parameter.
6590 l
= phys_spec
.pci_size_low
;
6592 if (PCI_REG_REG_G(phys_spec
.pci_phys_hi
) == PCI_CONF_ROM
) {
6594 /* free memory back to the allocator */
6595 if (ndi_ra_free(ddi_get_parent(dip
), phys_spec
.pci_phys_low
,
6596 l
, NDI_RA_TYPE_MEM
, NDI_RA_PASS
) != NDI_SUCCESS
) {
6597 DEBUG0("(ROM)Can not free 32b mem");
6598 pcicfg_unmap_phys(&h
, &config
);
6602 /* Unmap the BAR by writing a zero */
6604 if ((flags
& PCICFG_FLAG_READ_ONLY
) == 0)
6605 ddi_put32(h
, (uint32_t *)v
, (uint32_t)0);
6608 switch (PCI_REG_ADDR_G(phys_spec
.pci_phys_hi
)) {
6610 case PCI_REG_ADDR_G(PCI_ADDR_MEM64
):
6611 case PCI_REG_ADDR_G(PCI_ADDR_MEM32
):
6612 /* free memory back to the allocator */
6613 if (ndi_ra_free(ddi_get_parent(dip
),
6614 PCICFG_LADDR(phys_spec
.pci_phys_low
,
6615 phys_spec
.pci_phys_mid
),
6617 NDI_RA_PASS
) != NDI_SUCCESS
) {
6618 DEBUG0("Cannot free mem");
6619 pcicfg_unmap_phys(&h
, &config
);
6624 case PCI_REG_ADDR_G(PCI_ADDR_IO
):
6625 /* free I/O space back to the allocator */
6626 if (ndi_ra_free(ddi_get_parent(dip
),
6627 phys_spec
.pci_phys_low
,
6629 NDI_RA_PASS
) != NDI_SUCCESS
) {
6630 DEBUG0("Can not free I/O space");
6631 pcicfg_unmap_phys(&h
, &config
);
6637 DEBUG0("Unknown register type\n");
6638 pcicfg_unmap_phys(&h
, &config
);
6644 * Now that memory locations are assigned,
6645 * update the assigned address property.
6648 DEBUG1("updating assigned-addresss for %x\n", phys_spec
.pci_phys_hi
);
6650 if (pcicfg_remove_assigned_prop(dip
, &phys_spec
)) {
6651 pcicfg_unmap_phys(&h
, &config
);
6655 pcicfg_unmap_phys(&h
, &config
);
6661 pcicfg_remove_assigned_prop(dev_info_t
*dip
, pci_regspec_t
*oldone
)
6663 int alen
, num_entries
, i
;
6664 pci_regspec_t
*assigned
, *assigned_copy
;
6667 status
= ddi_getlongprop(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
6668 "assigned-addresses", (caddr_t
)&assigned
, &alen
);
6670 case DDI_PROP_SUCCESS
:
6672 case DDI_PROP_NO_MEMORY
:
6673 DEBUG0("no memory for assigned-addresses property\n");
6676 DEBUG0("assigned-addresses property does not exist\n");
6681 * Make a copy of old assigned-addresses property.
6683 assigned_copy
= kmem_alloc(alen
, KM_SLEEP
);
6684 bcopy(assigned
, assigned_copy
, alen
);
6686 status
= ndi_prop_remove(DDI_DEV_T_NONE
, dip
, "assigned-addresses");
6688 if (status
!= DDI_PROP_SUCCESS
) {
6690 * If "assigned-addresses" is retrieved from PROM, the
6691 * ndi_prop_remove() will fail.
6693 DEBUG1("pcicfg_remove_assigned_prop: 0x%x not removed\n",
6694 oldone
->pci_phys_hi
);
6697 * Free up allocated memory
6699 kmem_free(assigned_copy
, alen
);
6700 kmem_free((caddr_t
)assigned
, alen
);
6705 num_entries
= alen
/ sizeof (pci_regspec_t
);
6708 * Rebuild the assigned-addresses property.
6710 for (i
= 0; i
< num_entries
; i
++) {
6711 if (assigned_copy
[i
].pci_phys_hi
!= oldone
->pci_phys_hi
) {
6712 (void) pcicfg_update_assigned_prop(dip
,
6718 * Free the copy of the original assigned-addresses.
6720 kmem_free(assigned_copy
, alen
);
6723 * Don't forget to free up memory from ddi_getlongprop
6725 kmem_free((caddr_t
)assigned
, alen
);
6731 pcicfg_map_phys(dev_info_t
*dip
, pci_regspec_t
*phys_spec
,
6732 caddr_t
*addrp
, ddi_device_acc_attr_t
*accattrp
,
6733 ddi_acc_handle_t
*handlep
)
6739 *handlep
= impl_acc_hdl_alloc(KM_SLEEP
, NULL
);
6740 hp
= impl_acc_hdl_get(*handlep
);
6741 hp
->ah_vers
= VERS_ACCHDL
;
6746 hp
->ah_acc
= *accattrp
;
6748 mr
.map_op
= DDI_MO_MAP_LOCKED
;
6749 mr
.map_type
= DDI_MT_REGSPEC
;
6750 mr
.map_obj
.rp
= (struct regspec
*)phys_spec
;
6751 mr
.map_prot
= PROT_READ
| PROT_WRITE
;
6752 mr
.map_flags
= DDI_MF_KERNEL_MAPPING
;
6753 mr
.map_handlep
= hp
;
6754 mr
.map_vers
= DDI_MAP_VERSION
;
6756 result
= ddi_map(dip
, &mr
, 0, 0, addrp
);
6758 if (result
!= DDI_SUCCESS
) {
6759 impl_acc_hdl_free(*handlep
);
6760 *handlep
= (ddi_acc_handle_t
)NULL
;
6762 hp
->ah_addr
= *addrp
;
6769 pcicfg_unmap_phys(ddi_acc_handle_t
*handlep
, pci_regspec_t
*ph
)
6774 hp
= impl_acc_hdl_get(*handlep
);
6777 mr
.map_op
= DDI_MO_UNMAP
;
6778 mr
.map_type
= DDI_MT_REGSPEC
;
6779 mr
.map_obj
.rp
= (struct regspec
*)ph
;
6780 mr
.map_prot
= PROT_READ
| PROT_WRITE
;
6781 mr
.map_flags
= DDI_MF_KERNEL_MAPPING
;
6782 mr
.map_handlep
= hp
;
6783 mr
.map_vers
= DDI_MAP_VERSION
;
6785 (void) ddi_map(hp
->ah_dip
, &mr
, hp
->ah_offset
,
6786 hp
->ah_len
, &hp
->ah_addr
);
6788 impl_acc_hdl_free(*handlep
);
6789 *handlep
= (ddi_acc_handle_t
)NULL
;
6793 pcicfg_ari_configure(dev_info_t
*dip
)
6795 if (pcie_ari_supported(dip
) == PCIE_ARI_FORW_NOT_SUPPORTED
)
6796 return (DDI_FAILURE
);
6799 * Until we have resource balancing, dynamically configure
6800 * ARI functions without firmware assistamce.
6802 return (DDI_FAILURE
);
6807 debug(char *fmt
, uintptr_t a1
, uintptr_t a2
, uintptr_t a3
,
6808 uintptr_t a4
, uintptr_t a5
)
6810 if (pcicfg_debug
== 1) {
6811 prom_printf("pcicfg: ");
6812 prom_printf(fmt
, a1
, a2
, a3
, a4
, a5
);
6815 cmn_err(CE_CONT
, fmt
, a1
, a2
, a3
, a4
, a5
);
6820 * Return true if the devinfo node is in a PCI Express hierarchy.
6823 is_pcie_fabric(dev_info_t
*dip
)
6825 dev_info_t
*root
= ddi_root_node();
6827 boolean_t found
= B_FALSE
;
6831 * Does this device reside in a pcie fabric ?
6833 for (pdip
= dip
; pdip
&& (pdip
!= root
) && !found
;
6834 pdip
= ddi_get_parent(pdip
)) {
6835 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, pdip
,
6836 DDI_PROP_DONTPASS
, "device_type", &bus
) !=
6840 if (strcmp(bus
, "pciex") == 0)