Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/intel/io/hotplug/pcicfg/pcicfg.c
+++ new/usr/src/uts/intel/io/hotplug/pcicfg/pcicfg.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 */
24 24
25 25 /*
26 26 * PCI configurator (pcicfg)
27 27 */
28 28
29 29 #include <sys/sysmacros.h>
30 30 #include <sys/conf.h>
31 31 #include <sys/kmem.h>
32 32 #include <sys/debug.h>
33 33 #include <sys/modctl.h>
34 34 #include <sys/autoconf.h>
35 35 #include <sys/hwconf.h>
36 36 #include <sys/pcie.h>
37 37 #include <sys/pcie_impl.h>
38 38 #include <sys/pci_cap.h>
39 39 #include <sys/ddi.h>
40 40 #include <sys/sunndi.h>
41 41 #include <sys/hotplug/pci/pcicfg.h>
42 42 #include <sys/ndi_impldefs.h>
43 43 #include <sys/pci_cfgacc.h>
44 44 #include <sys/pcie_impl.h>
45 45
46 46 /*
47 47 * ************************************************************************
48 48 * *** Implementation specific local data structures/definitions. ***
49 49 * ************************************************************************
50 50 */
51 51
52 52 static int pcicfg_start_devno = 0; /* for Debug only */
53 53
54 54 #define PCICFG_MAX_ARI_FUNCTION 256
55 55
56 56 #define PCICFG_NODEVICE 42
57 57 #define PCICFG_NOMEMORY 43
58 58 #define PCICFG_NOMULTI 44
59 59 #define PCICFG_NORESRC 45
60 60
61 61 #define PCICFG_HIADDR(n) ((uint32_t)(((uint64_t)(n) & \
62 62 0xFFFFFFFF00000000ULL)>> 32))
63 63 #define PCICFG_LOADDR(n) ((uint32_t)((uint64_t)(n) & 0x00000000FFFFFFFF))
64 64 #define PCICFG_LADDR(lo, hi) (((uint64_t)(hi) << 32) | (uint32_t)(lo))
65 65
66 66 #define PCICFG_HIWORD(n) ((uint16_t)(((uint32_t)(n) & 0xFFFF0000)>> 16))
67 67 #define PCICFG_LOWORD(n) ((uint16_t)((uint32_t)(n) & 0x0000FFFF))
68 68 #define PCICFG_HIBYTE(n) ((uint8_t)(((uint16_t)(n) & 0xFF00)>> 8))
69 69 #define PCICFG_LOBYTE(n) ((uint8_t)((uint16_t)(n) & 0x00FF))
70 70
71 71 #define PCICFG_ROUND_UP(addr, gran) ((uintptr_t)((gran+addr-1)&(~(gran-1))))
72 72 #define PCICFG_ROUND_DOWN(addr, gran) ((uintptr_t)((addr) & ~(gran-1)))
73 73
74 74 #define PCICFG_MEMGRAN 0x100000
75 75 #define PCICFG_IOGRAN 0x1000
76 76 #define PCICFG_4GIG_LIMIT 0xFFFFFFFFUL
77 77
78 78 #define PCICFG_MEM_MULT 4
79 79 #define PCICFG_IO_MULT 4
80 80 #define PCICFG_RANGE_LEN 3 /* Number of range entries */
81 81
82 82 static int pcicfg_slot_busnums = 8;
83 83 static int pcicfg_slot_memsize = 32 * PCICFG_MEMGRAN; /* 32MB per slot */
84 84 static int pcicfg_slot_pf_memsize = 32 * PCICFG_MEMGRAN; /* 32MB per slot */
85 85 static int pcicfg_slot_iosize = 64 * PCICFG_IOGRAN; /* 64K per slot */
86 86 static int pcicfg_sec_reset_delay = 3000000;
87 87 static int pcicfg_do_legacy_props = 1; /* create legacy compatible prop */
88 88
89 89 typedef struct hole hole_t;
90 90
91 91 struct hole {
92 92 uint64_t start;
93 93 uint64_t len;
94 94 hole_t *next;
95 95 };
96 96
97 97 typedef struct pcicfg_phdl pcicfg_phdl_t;
98 98
99 99 struct pcicfg_phdl {
100 100
101 101 dev_info_t *dip; /* Associated with the bridge */
102 102 dev_info_t *top_dip; /* top node of the attach point */
103 103 pcicfg_phdl_t *next;
104 104
105 105 /* non-prefetchable memory space */
106 106 uint64_t memory_base; /* Memory base for this attach point */
107 107 uint64_t memory_last;
108 108 uint64_t memory_len;
109 109
110 110 /* prefetchable memory space */
111 111 uint64_t pf_memory_base; /* PF Memory base for this Connection */
112 112 uint64_t pf_memory_last;
113 113 uint64_t pf_memory_len;
114 114
115 115 /* io space */
116 116 uint32_t io_base; /* I/O base for this attach point */
117 117 uint32_t io_last;
118 118 uint32_t io_len;
119 119
120 120 int error;
121 121 uint_t highest_bus; /* Highest bus seen on the probe */
122 122
123 123 hole_t mem_hole; /* Memory hole linked list. */
124 124 hole_t pf_mem_hole; /* PF Memory hole linked list. */
125 125 hole_t io_hole; /* IO hole linked list */
126 126
127 127 ndi_ra_request_t mem_req; /* allocator request for memory */
128 128 ndi_ra_request_t pf_mem_req; /* allocator request for PF memory */
129 129 ndi_ra_request_t io_req; /* allocator request for I/O */
130 130 };
131 131
132 132 struct pcicfg_standard_prop_entry {
133 133 uchar_t *name;
134 134 uint_t config_offset;
135 135 uint_t size;
136 136 };
137 137
138 138
139 139 struct pcicfg_name_entry {
140 140 uint32_t class_code;
141 141 char *name;
142 142 };
143 143
144 144 struct pcicfg_find_ctrl {
145 145 uint_t device;
146 146 uint_t function;
147 147 dev_info_t *dip;
148 148 };
149 149
150 150 /*
151 151 * List of Indirect Config Map Devices. At least the intent of the
152 152 * design is to look for a device in this list during the configure
↓ open down ↓ |
152 lines elided |
↑ open up ↑ |
153 153 * operation, and if the device is listed here, then it is a nontransparent
154 154 * bridge, hence load the driver and avail the config map services from
155 155 * the driver. Class and Subclass should be as defined in the PCI specs
156 156 * ie. class is 0x6, and subclass is 0x9.
157 157 */
158 158 static struct {
159 159 uint8_t mem_range_bar_offset;
160 160 uint8_t io_range_bar_offset;
161 161 uint8_t prefetch_mem_range_bar_offset;
162 162 } pcicfg_indirect_map_devs[] = {
163 - PCI_CONF_BASE3, PCI_CONF_BASE2, PCI_CONF_BASE3,
164 - 0, 0, 0,
163 + { PCI_CONF_BASE3, PCI_CONF_BASE2, PCI_CONF_BASE3 },
164 + { 0, 0, 0 },
165 165 };
166 166
167 167 #define PCICFG_MAKE_REG_HIGH(busnum, devnum, funcnum, register)\
168 168 (\
169 169 ((ulong_t)(busnum & 0xff) << 16) |\
170 170 ((ulong_t)(devnum & 0x1f) << 11) |\
171 171 ((ulong_t)(funcnum & 0x7) << 8) |\
172 172 ((ulong_t)(register & 0x3f)))
173 173
174 174 /*
175 175 * debug macros:
176 176 */
177 177 #if defined(DEBUG)
178 178 extern void prom_printf(const char *, ...);
179 179
180 180 /*
181 181 * Following values are defined for this debug flag.
182 182 *
183 183 * 1 = dump configuration header only.
184 184 * 2 = dump generic debug data only (no config header dumped)
185 185 * 3 = dump everything (both 1 and 2)
186 186 */
187 187 int pcicfg_debug = 0;
188 188
189 189 static void debug(char *, uintptr_t, uintptr_t,
190 190 uintptr_t, uintptr_t, uintptr_t);
191 191
192 192 #define DEBUG0(fmt)\
193 193 debug(fmt, 0, 0, 0, 0, 0);
194 194 #define DEBUG1(fmt, a1)\
195 195 debug(fmt, (uintptr_t)(a1), 0, 0, 0, 0);
196 196 #define DEBUG2(fmt, a1, a2)\
197 197 debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2), 0, 0, 0);
198 198 #define DEBUG3(fmt, a1, a2, a3)\
199 199 debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2),\
200 200 (uintptr_t)(a3), 0, 0);
201 201 #define DEBUG4(fmt, a1, a2, a3, a4)\
202 202 debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2),\
203 203 (uintptr_t)(a3), (uintptr_t)(a4), 0);
204 204 #define DEBUG5(fmt, a1, a2, a3, a4, a5)\
205 205 debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2),\
206 206 (uintptr_t)(a3), (uintptr_t)(a4), (uintptr_t)(a5));
207 207 #else
208 208 #define DEBUG0(fmt)
209 209 #define DEBUG1(fmt, a1)
210 210 #define DEBUG2(fmt, a1, a2)
211 211 #define DEBUG3(fmt, a1, a2, a3)
212 212 #define DEBUG4(fmt, a1, a2, a3, a4)
213 213 #define DEBUG5(fmt, a1, a2, a3, a4, a5)
214 214 #endif
215 215
216 216 /*
217 217 * forward declarations for routines defined in this module (called here)
218 218 */
219 219
220 220 static int pcicfg_add_config_reg(dev_info_t *,
221 221 uint_t, uint_t, uint_t);
222 222 static int pcicfg_probe_children(dev_info_t *, uint_t, uint_t, uint_t,
223 223 uint_t *, pcicfg_flags_t, boolean_t);
224 224 static int pcicfg_match_dev(dev_info_t *, void *);
225 225 static dev_info_t *pcicfg_devi_find(dev_info_t *, uint_t, uint_t);
226 226 static pcicfg_phdl_t *pcicfg_find_phdl(dev_info_t *);
227 227 static pcicfg_phdl_t *pcicfg_create_phdl(dev_info_t *);
228 228 static int pcicfg_destroy_phdl(dev_info_t *);
229 229 static int pcicfg_sum_resources(dev_info_t *, void *);
230 230 static int pcicfg_device_assign(dev_info_t *);
231 231 static int pcicfg_bridge_assign(dev_info_t *, void *);
232 232 static int pcicfg_device_assign_readonly(dev_info_t *);
233 233 static int pcicfg_free_resources(dev_info_t *, pcicfg_flags_t);
234 234 static void pcicfg_setup_bridge(pcicfg_phdl_t *, ddi_acc_handle_t);
235 235 static void pcicfg_update_bridge(pcicfg_phdl_t *, ddi_acc_handle_t);
236 236 static int pcicfg_update_assigned_prop(dev_info_t *, pci_regspec_t *);
237 237 static void pcicfg_device_on(ddi_acc_handle_t);
238 238 static void pcicfg_device_off(ddi_acc_handle_t);
239 239 static int pcicfg_set_busnode_props(dev_info_t *, uint8_t);
240 240 static int pcicfg_free_bridge_resources(dev_info_t *);
241 241 static int pcicfg_free_device_resources(dev_info_t *);
242 242 static int pcicfg_teardown_device(dev_info_t *, pcicfg_flags_t, boolean_t);
243 243 static void pcicfg_reparent_node(dev_info_t *, dev_info_t *);
244 244 static int pcicfg_config_setup(dev_info_t *, ddi_acc_handle_t *);
245 245 static void pcicfg_config_teardown(ddi_acc_handle_t *);
246 246 static void pcicfg_get_mem(pcicfg_phdl_t *, uint32_t, uint64_t *);
247 247 static void pcicfg_get_pf_mem(pcicfg_phdl_t *, uint32_t, uint64_t *);
248 248 static void pcicfg_get_io(pcicfg_phdl_t *, uint32_t, uint32_t *);
249 249 static int pcicfg_update_ranges_prop(dev_info_t *, ppb_ranges_t *);
250 250 static int pcicfg_configure_ntbridge(dev_info_t *, uint_t, uint_t);
251 251 static uint_t pcicfg_ntbridge_child(dev_info_t *);
252 252 static uint_t pcicfg_get_ntbridge_child_range(dev_info_t *, uint64_t *,
253 253 uint64_t *, uint_t);
254 254 static int pcicfg_is_ntbridge(dev_info_t *);
255 255 static int pcicfg_ntbridge_allocate_resources(dev_info_t *);
256 256 static int pcicfg_ntbridge_configure_done(dev_info_t *);
257 257 static int pcicfg_ntbridge_program_child(dev_info_t *);
258 258 static uint_t pcicfg_ntbridge_unconfigure(dev_info_t *);
259 259 static int pcicfg_ntbridge_unconfigure_child(dev_info_t *, uint_t);
260 260 static void pcicfg_free_hole(hole_t *);
261 261 static uint64_t pcicfg_alloc_hole(hole_t *, uint64_t *, uint32_t);
262 262 static int pcicfg_device_type(dev_info_t *, ddi_acc_handle_t *);
263 263 static void pcicfg_update_phdl(dev_info_t *, uint8_t, uint8_t);
264 264 static int pcicfg_get_cap(ddi_acc_handle_t, uint8_t);
265 265 static uint8_t pcicfg_get_nslots(dev_info_t *, ddi_acc_handle_t);
266 266 static int pcicfg_pcie_dev(dev_info_t *, ddi_acc_handle_t);
267 267 static int pcicfg_pcie_device_type(dev_info_t *, ddi_acc_handle_t);
268 268 static int pcicfg_pcie_port_type(dev_info_t *, ddi_acc_handle_t);
269 269 static int pcicfg_probe_bridge(dev_info_t *, ddi_acc_handle_t, uint_t,
270 270 uint_t *, boolean_t);
271 271 static int pcicfg_find_resource_end(dev_info_t *, void *);
272 272 static boolean_t is_pcie_fabric(dev_info_t *);
273 273
274 274 static int pcicfg_populate_reg_props(dev_info_t *, ddi_acc_handle_t);
275 275 static int pcicfg_populate_props_from_bar(dev_info_t *, ddi_acc_handle_t);
276 276 static int pcicfg_update_assigned_prop_value(dev_info_t *, uint32_t,
277 277 uint32_t, uint32_t, uint_t);
278 278 static int pcicfg_ari_configure(dev_info_t *);
279 279
280 280 #ifdef DEBUG
281 281 static void pcicfg_dump_common_config(ddi_acc_handle_t config_handle);
282 282 static void pcicfg_dump_device_config(ddi_acc_handle_t);
283 283 static void pcicfg_dump_bridge_config(ddi_acc_handle_t config_handle);
284 284 static uint64_t pcicfg_unused_space(hole_t *, uint32_t *);
285 285
286 286 #define PCICFG_DUMP_COMMON_CONFIG(hdl) (void)pcicfg_dump_common_config(hdl)
287 287 #define PCICFG_DUMP_DEVICE_CONFIG(hdl) (void)pcicfg_dump_device_config(hdl)
288 288 #define PCICFG_DUMP_BRIDGE_CONFIG(hdl) (void)pcicfg_dump_bridge_config(hdl)
289 289 #else
290 290 #define PCICFG_DUMP_COMMON_CONFIG(handle)
291 291 #define PCICFG_DUMP_DEVICE_CONFIG(handle)
292 292 #define PCICFG_DUMP_BRIDGE_CONFIG(handle)
293 293 #endif
294 294
295 295 static kmutex_t pcicfg_list_mutex; /* Protects the probe handle list */
296 296 static pcicfg_phdl_t *pcicfg_phdl_list = NULL;
297 297
298 298 #ifndef _DONT_USE_1275_GENERIC_NAMES
299 299 /*
300 300 * Class code table
301 301 */
302 302 static struct pcicfg_name_entry pcicfg_class_lookup [] = {
303 303
304 304 { 0x001, "display" },
305 305 { 0x100, "scsi" },
306 306 { 0x101, "ide" },
307 307 { 0x102, "fdc" },
308 308 { 0x103, "ipi" },
309 309 { 0x104, "raid" },
310 310 { 0x105, "ata" },
311 311 { 0x106, "sata" },
312 312 { 0x200, "ethernet" },
313 313 { 0x201, "token-ring" },
314 314 { 0x202, "fddi" },
315 315 { 0x203, "atm" },
316 316 { 0x204, "isdn" },
317 317 { 0x206, "mcd" },
318 318 { 0x300, "display" },
319 319 { 0x400, "video" },
320 320 { 0x401, "sound" },
321 321 { 0x500, "memory" },
322 322 { 0x501, "flash" },
323 323 { 0x600, "host" },
324 324 { 0x601, "isa" },
325 325 { 0x602, "eisa" },
326 326 { 0x603, "mca" },
327 327 { 0x604, "pci" },
328 328 { 0x605, "pcmcia" },
329 329 { 0x606, "nubus" },
330 330 { 0x607, "cardbus" },
331 331 { 0x609, "pci" },
332 332 { 0x60a, "ib-pci" },
333 333 { 0x700, "serial" },
334 334 { 0x701, "parallel" },
335 335 { 0x800, "interrupt-controller" },
336 336 { 0x801, "dma-controller" },
337 337 { 0x802, "timer" },
338 338 { 0x803, "rtc" },
339 339 { 0x900, "keyboard" },
340 340 { 0x901, "pen" },
341 341 { 0x902, "mouse" },
342 342 { 0xa00, "dock" },
343 343 { 0xb00, "cpu" },
344 344 { 0xb01, "cpu" },
345 345 { 0xb02, "cpu" },
346 346 { 0xb10, "cpu" },
347 347 { 0xb20, "cpu" },
348 348 { 0xb30, "cpu" },
349 349 { 0xb40, "coproc" },
350 350 { 0xc00, "firewire" },
351 351 { 0xc01, "access-bus" },
352 352 { 0xc02, "ssa" },
353 353 { 0xc03, "usb" },
354 354 { 0xc04, "fibre-channel" },
355 355 { 0xc05, "smbus" },
356 356 { 0xc06, "ib" },
357 357 { 0xd00, "irda" },
358 358 { 0xd01, "ir" },
359 359 { 0xd10, "rf" },
360 360 { 0xd11, "btooth" },
361 361 { 0xd12, "brdband" },
362 362 { 0xd20, "802.11a" },
363 363 { 0xd21, "802.11b" },
364 364 { 0xe00, "i2o" },
365 365 { 0xf01, "tv" },
366 366 { 0xf02, "audio" },
367 367 { 0xf03, "voice" },
368 368 { 0xf04, "data" },
369 369 { 0, 0 }
370 370 };
371 371 #endif /* _DONT_USE_1275_GENERIC_NAMES */
372 372
373 373 /*
374 374 * Module control operations
↓ open down ↓ |
200 lines elided |
↑ open up ↑ |
375 375 */
376 376
377 377 extern struct mod_ops mod_miscops;
378 378
379 379 static struct modlmisc modlmisc = {
380 380 &mod_miscops, /* Type of module */
381 381 "PCI configurator"
382 382 };
383 383
384 384 static struct modlinkage modlinkage = {
385 - MODREV_1, (void *)&modlmisc, NULL
385 + MODREV_1, { (void *)&modlmisc, NULL }
386 386 };
387 387
388 388
389 389 #ifdef DEBUG
390 390
391 391 static void
392 392 pcicfg_dump_common_config(ddi_acc_handle_t config_handle)
393 393 {
394 394 if ((pcicfg_debug & 1) == 0)
395 395 return;
396 396 prom_printf(" Vendor ID = [0x%x]\n",
397 397 pci_config_get16(config_handle, PCI_CONF_VENID));
398 398 prom_printf(" Device ID = [0x%x]\n",
399 399 pci_config_get16(config_handle, PCI_CONF_DEVID));
400 400 prom_printf(" Command REG = [0x%x]\n",
401 401 pci_config_get16(config_handle, PCI_CONF_COMM));
402 402 prom_printf(" Status REG = [0x%x]\n",
403 403 pci_config_get16(config_handle, PCI_CONF_STAT));
404 404 prom_printf(" Revision ID = [0x%x]\n",
405 405 pci_config_get8(config_handle, PCI_CONF_REVID));
406 406 prom_printf(" Prog Class = [0x%x]\n",
407 407 pci_config_get8(config_handle, PCI_CONF_PROGCLASS));
408 408 prom_printf(" Dev Class = [0x%x]\n",
409 409 pci_config_get8(config_handle, PCI_CONF_SUBCLASS));
410 410 prom_printf(" Base Class = [0x%x]\n",
411 411 pci_config_get8(config_handle, PCI_CONF_BASCLASS));
412 412 prom_printf(" Device ID = [0x%x]\n",
413 413 pci_config_get8(config_handle, PCI_CONF_CACHE_LINESZ));
414 414 prom_printf(" Header Type = [0x%x]\n",
415 415 pci_config_get8(config_handle, PCI_CONF_HEADER));
416 416 prom_printf(" BIST = [0x%x]\n",
417 417 pci_config_get8(config_handle, PCI_CONF_BIST));
418 418 prom_printf(" BASE 0 = [0x%x]\n",
419 419 pci_config_get32(config_handle, PCI_CONF_BASE0));
420 420 prom_printf(" BASE 1 = [0x%x]\n",
421 421 pci_config_get32(config_handle, PCI_CONF_BASE1));
422 422
423 423 }
424 424
425 425 static void
426 426 pcicfg_dump_device_config(ddi_acc_handle_t config_handle)
427 427 {
428 428 if ((pcicfg_debug & 1) == 0)
429 429 return;
430 430 pcicfg_dump_common_config(config_handle);
431 431
432 432 prom_printf(" BASE 2 = [0x%x]\n",
433 433 pci_config_get32(config_handle, PCI_CONF_BASE2));
434 434 prom_printf(" BASE 3 = [0x%x]\n",
435 435 pci_config_get32(config_handle, PCI_CONF_BASE3));
436 436 prom_printf(" BASE 4 = [0x%x]\n",
437 437 pci_config_get32(config_handle, PCI_CONF_BASE4));
438 438 prom_printf(" BASE 5 = [0x%x]\n",
439 439 pci_config_get32(config_handle, PCI_CONF_BASE5));
440 440 prom_printf(" Cardbus CIS = [0x%x]\n",
441 441 pci_config_get32(config_handle, PCI_CONF_CIS));
442 442 prom_printf(" Sub VID = [0x%x]\n",
443 443 pci_config_get16(config_handle, PCI_CONF_SUBVENID));
444 444 prom_printf(" Sub SID = [0x%x]\n",
445 445 pci_config_get16(config_handle, PCI_CONF_SUBSYSID));
446 446 prom_printf(" ROM = [0x%x]\n",
447 447 pci_config_get32(config_handle, PCI_CONF_ROM));
448 448 prom_printf(" I Line = [0x%x]\n",
449 449 pci_config_get8(config_handle, PCI_CONF_ILINE));
450 450 prom_printf(" I Pin = [0x%x]\n",
451 451 pci_config_get8(config_handle, PCI_CONF_IPIN));
452 452 prom_printf(" Max Grant = [0x%x]\n",
453 453 pci_config_get8(config_handle, PCI_CONF_MIN_G));
454 454 prom_printf(" Max Latent = [0x%x]\n",
455 455 pci_config_get8(config_handle, PCI_CONF_MAX_L));
456 456 }
457 457
458 458 static void
459 459 pcicfg_dump_bridge_config(ddi_acc_handle_t config_handle)
460 460 {
461 461 if ((pcicfg_debug & 1) == 0)
462 462 return;
463 463 pcicfg_dump_common_config(config_handle);
464 464
465 465 prom_printf("........................................\n");
466 466
467 467 prom_printf(" Pri Bus = [0x%x]\n",
468 468 pci_config_get8(config_handle, PCI_BCNF_PRIBUS));
469 469 prom_printf(" Sec Bus = [0x%x]\n",
470 470 pci_config_get8(config_handle, PCI_BCNF_SECBUS));
471 471 prom_printf(" Sub Bus = [0x%x]\n",
472 472 pci_config_get8(config_handle, PCI_BCNF_SUBBUS));
473 473 prom_printf(" Latency = [0x%x]\n",
474 474 pci_config_get8(config_handle, PCI_BCNF_LATENCY_TIMER));
475 475 prom_printf(" I/O Base LO = [0x%x]\n",
476 476 pci_config_get8(config_handle, PCI_BCNF_IO_BASE_LOW));
477 477 prom_printf(" I/O Lim LO = [0x%x]\n",
478 478 pci_config_get8(config_handle, PCI_BCNF_IO_LIMIT_LOW));
479 479 prom_printf(" Sec. Status = [0x%x]\n",
480 480 pci_config_get16(config_handle, PCI_BCNF_SEC_STATUS));
481 481 prom_printf(" Mem Base = [0x%x]\n",
482 482 pci_config_get16(config_handle, PCI_BCNF_MEM_BASE));
483 483 prom_printf(" Mem Limit = [0x%x]\n",
484 484 pci_config_get16(config_handle, PCI_BCNF_MEM_LIMIT));
485 485 prom_printf(" PF Mem Base = [0x%x]\n",
486 486 pci_config_get16(config_handle, PCI_BCNF_PF_BASE_LOW));
487 487 prom_printf(" PF Mem Lim = [0x%x]\n",
488 488 pci_config_get16(config_handle, PCI_BCNF_PF_LIMIT_LOW));
489 489 prom_printf(" PF Base HI = [0x%x]\n",
490 490 pci_config_get32(config_handle, PCI_BCNF_PF_BASE_HIGH));
491 491 prom_printf(" PF Lim HI = [0x%x]\n",
492 492 pci_config_get32(config_handle, PCI_BCNF_PF_LIMIT_HIGH));
493 493 prom_printf(" I/O Base HI = [0x%x]\n",
494 494 pci_config_get16(config_handle, PCI_BCNF_IO_BASE_HI));
495 495 prom_printf(" I/O Lim HI = [0x%x]\n",
496 496 pci_config_get16(config_handle, PCI_BCNF_IO_LIMIT_HI));
497 497 prom_printf(" ROM addr = [0x%x]\n",
498 498 pci_config_get32(config_handle, PCI_BCNF_ROM));
499 499 prom_printf(" Intr Line = [0x%x]\n",
500 500 pci_config_get8(config_handle, PCI_BCNF_ILINE));
501 501 prom_printf(" Intr Pin = [0x%x]\n",
502 502 pci_config_get8(config_handle, PCI_BCNF_IPIN));
503 503 prom_printf(" Bridge Ctrl = [0x%x]\n",
504 504 pci_config_get16(config_handle, PCI_BCNF_BCNTRL));
505 505 }
506 506 #endif
507 507
508 508 int
509 509 _init()
510 510 {
511 511 DEBUG0(" PCI configurator installed\n");
512 512 mutex_init(&pcicfg_list_mutex, NULL, MUTEX_DRIVER, NULL);
513 513 return (mod_install(&modlinkage));
514 514 }
515 515
516 516 int
517 517 _fini(void)
518 518 {
519 519 int error;
520 520
521 521 error = mod_remove(&modlinkage);
522 522 if (error != 0) {
523 523 return (error);
524 524 }
525 525 mutex_destroy(&pcicfg_list_mutex);
526 526 return (0);
527 527 }
528 528
529 529 int
530 530 _info(struct modinfo *modinfop)
531 531 {
532 532 return (mod_info(&modlinkage, modinfop));
533 533 }
534 534
535 535 /*
536 536 * In the following functions ndi_devi_enter() without holding the
537 537 * parent dip is sufficient. This is because pci dr is driven through
538 538 * opens on the nexus which is in the device tree path above the node
539 539 * being operated on, and implicitly held due to the open.
540 540 */
541 541
542 542 /*
543 543 * This entry point is called to configure a device (and
544 544 * all its children) on the given bus. It is called when
545 545 * a new device is added to the PCI domain. This routine
546 546 * will create the device tree and program the devices
547 547 * registers.
548 548 */
549 549 int
550 550 pcicfg_configure(dev_info_t *devi, uint_t device, uint_t function,
551 551 pcicfg_flags_t flags)
552 552 {
553 553 uint_t bus;
554 554 int len;
555 555 int func;
556 556 dev_info_t *attach_point;
557 557 pci_bus_range_t pci_bus_range;
558 558 int rv;
559 559 int circ;
560 560 uint_t highest_bus;
561 561 int ari_mode = B_FALSE;
562 562 int max_function = PCI_MAX_FUNCTIONS;
563 563 int trans_device;
564 564 dev_info_t *new_device;
565 565 boolean_t is_pcie;
566 566
567 567 if (flags == PCICFG_FLAG_ENABLE_ARI)
568 568 return (pcicfg_ari_configure(devi));
569 569
570 570 /*
571 571 * Start probing at the device specified in "device" on the
572 572 * "bus" specified.
573 573 */
574 574 len = sizeof (pci_bus_range_t);
575 575 if (ddi_getlongprop_buf(DDI_DEV_T_ANY, devi, 0, "bus-range",
576 576 (caddr_t)&pci_bus_range, &len) != DDI_SUCCESS) {
577 577 DEBUG0("no bus-range property\n");
578 578 return (PCICFG_FAILURE);
579 579 }
580 580
581 581 bus = pci_bus_range.lo; /* primary bus number of this bus node */
582 582
583 583 attach_point = devi;
584 584
585 585 is_pcie = is_pcie_fabric(devi);
586 586
587 587 ndi_devi_enter(devi, &circ);
588 588 for (func = 0; func < max_function; ) {
589 589
590 590 if ((function != PCICFG_ALL_FUNC) && (function != func))
591 591 goto next;
592 592
593 593 if (ari_mode)
594 594 trans_device = func >> 3;
595 595 else
596 596 trans_device = device;
597 597
598 598 switch (rv = pcicfg_probe_children(attach_point,
599 599 bus, trans_device, func & 7, &highest_bus,
600 600 flags, is_pcie)) {
601 601 case PCICFG_NORESRC:
602 602 case PCICFG_FAILURE:
603 603 DEBUG2("configure failed: bus [0x%x] device "
604 604 "[0x%x]\n", bus, trans_device);
605 605 goto cleanup;
606 606 case PCICFG_NODEVICE:
607 607 DEBUG3("no device : bus "
608 608 "[0x%x] slot [0x%x] func [0x%x]\n",
609 609 bus, trans_device, func &7);
610 610
611 611 /*
612 612 * When walking the list of ARI functions
613 613 * we don't expect to see a non-present
614 614 * function, so we will stop walking
615 615 * the function list.
616 616 */
617 617 if (ari_mode == B_TRUE)
618 618 break;
619 619
620 620 if (func)
621 621 goto next;
622 622 break;
623 623 default:
624 624 DEBUG3("configure: bus => [%d] "
625 625 "slot => [%d] func => [%d]\n",
626 626 bus, trans_device, func & 7);
627 627 break;
628 628 }
629 629
630 630 if (rv != PCICFG_SUCCESS)
631 631 break;
632 632
633 633 if ((new_device = pcicfg_devi_find(attach_point,
634 634 trans_device, func & 7)) == NULL) {
635 635 DEBUG0("Did'nt find device node just created\n");
636 636 goto cleanup;
637 637 }
638 638
639 639 /*
640 640 * Up until now, we have detected a non transparent bridge
641 641 * (ntbridge) as a part of the generic probe code and
642 642 * configured only one configuration
643 643 * header which is the side facing the host bus.
644 644 * Now, configure the other side and create children.
645 645 *
646 646 * In order to make the process simpler, lets load the device
647 647 * driver for the non transparent bridge as this is a
648 648 * Solaris bundled driver, and use its configuration map
649 649 * services rather than programming it here.
650 650 * If the driver is not bundled into Solaris, it must be
651 651 * first loaded and configured before performing any
652 652 * hotplug operations.
653 653 *
654 654 * This not only makes the code here simpler but also more
655 655 * generic.
656 656 *
657 657 * So here we go.
658 658 */
659 659
660 660 /*
661 661 * check if this is a bridge in nontransparent mode
662 662 */
663 663 if (pcicfg_is_ntbridge(new_device) != DDI_FAILURE) {
664 664 DEBUG0("pcicfg: Found nontransparent bridge.\n");
665 665
666 666 rv = pcicfg_configure_ntbridge(new_device, bus,
667 667 trans_device);
668 668 if (rv != PCICFG_SUCCESS)
669 669 goto cleanup;
670 670 }
671 671
672 672 next:
673 673 /*
674 674 * Determine if ARI Forwarding should be enabled.
675 675 */
676 676 if (func == 0) {
677 677 if ((pcie_ari_supported(devi)
678 678 == PCIE_ARI_FORW_SUPPORTED) &&
679 679 (pcie_ari_device(new_device) == PCIE_ARI_DEVICE)) {
680 680 if (pcie_ari_enable(devi) == DDI_SUCCESS) {
681 681 (void) ddi_prop_create(DDI_DEV_T_NONE,
682 682 devi, DDI_PROP_CANSLEEP,
683 683 "ari-enabled", NULL, 0);
684 684
685 685 ari_mode = B_TRUE;
686 686 max_function = PCICFG_MAX_ARI_FUNCTION;
687 687 }
688 688 }
689 689 }
690 690 if (ari_mode == B_TRUE) {
691 691 int next_function;
692 692
693 693 DEBUG0("Next Function - ARI Device\n");
694 694 if (pcie_ari_get_next_function(new_device,
695 695 &next_function) != DDI_SUCCESS)
696 696 goto cleanup;
697 697
698 698 /*
699 699 * Check if there are more fucntions to probe.
700 700 */
701 701 if (next_function == 0) {
702 702 DEBUG0("Next Function - "
703 703 "No more ARI Functions\n");
704 704 break;
705 705 }
706 706 func = next_function;
707 707 } else {
708 708 func++;
709 709 }
710 710 DEBUG1("Next Function - %x\n", func);
711 711 }
712 712
713 713 ndi_devi_exit(devi, circ);
714 714
715 715 if (func == 0)
716 716 return (PCICFG_FAILURE); /* probe failed */
717 717 else
718 718 return (PCICFG_SUCCESS);
719 719
720 720 cleanup:
721 721 /*
722 722 * Clean up a partially created "probe state" tree.
723 723 * There are no resources allocated to the in the
724 724 * probe state.
725 725 */
726 726
727 727 for (func = 0; func < PCI_MAX_FUNCTIONS; func++) {
728 728 if ((function != PCICFG_ALL_FUNC) && (function != func))
729 729 continue;
730 730
731 731 if ((new_device = pcicfg_devi_find(devi, device, func))
732 732 == NULL) {
733 733 continue;
734 734 }
735 735
736 736 DEBUG2("Cleaning up device [0x%x] function [0x%x]\n",
737 737 device, func);
738 738 /*
739 739 * If this was a bridge device it will have a
740 740 * probe handle - if not, no harm in calling this.
741 741 */
742 742 (void) pcicfg_destroy_phdl(new_device);
743 743 if (is_pcie) {
744 744 /*
745 745 * free pcie_bus_t for the sub-tree
746 746 */
747 747 if (ddi_get_child(new_device) != NULL)
748 748 pcie_fab_fini_bus(new_device, PCIE_BUS_ALL);
749 749
750 750 pcie_fini_bus(new_device, PCIE_BUS_ALL);
751 751 }
752 752 /*
753 753 * This will free up the node
754 754 */
755 755 (void) ndi_devi_offline(new_device, NDI_DEVI_REMOVE);
756 756 }
757 757 ndi_devi_exit(devi, circ);
758 758
759 759 /*
760 760 * Use private return codes to help identify issues without debugging
761 761 * enabled. Resource limitations and mis-configurations are
762 762 * probably the most likely caue of configuration failures on x86.
763 763 * Convert return code back to values expected by the external
764 764 * consumer before returning so we will warn only once on the first
765 765 * encountered failure.
766 766 */
767 767 if (rv == PCICFG_NORESRC) {
768 768 char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
769 769
770 770 (void) ddi_pathname(devi, path);
771 771 cmn_err(CE_CONT, "?Not enough PCI resources to "
772 772 "configure: %s\n", path);
773 773
774 774 kmem_free(path, MAXPATHLEN);
775 775 rv = PCICFG_FAILURE;
776 776 }
777 777
778 778 return (rv);
779 779 }
780 780
781 781 /*
782 782 * configure the child nodes of ntbridge. new_device points to ntbridge itself
783 783 */
784 784 /*ARGSUSED*/
785 785 static int
786 786 pcicfg_configure_ntbridge(dev_info_t *new_device, uint_t bus, uint_t device)
787 787 {
788 788 int bus_range[2], rc = PCICFG_FAILURE, rc1, max_devs = 0;
789 789 int devno;
790 790 dev_info_t *new_ntbridgechild;
791 791 ddi_acc_handle_t config_handle;
792 792 uint16_t vid;
793 793 uint64_t next_bus;
794 794 uint64_t blen;
795 795 ndi_ra_request_t req;
796 796 uint8_t pcie_device_type = 0;
797 797
798 798 /*
799 799 * If we need to do indirect config, lets create a property here
800 800 * to let the child conf map routine know that it has to
801 801 * go through the DDI calls, and not assume the devices are
802 802 * mapped directly under the host.
803 803 */
804 804 if ((rc = ndi_prop_update_int(DDI_DEV_T_NONE, new_device,
805 805 PCI_DEV_CONF_MAP_PROP, (int)DDI_SUCCESS)) != DDI_SUCCESS) {
806 806 DEBUG0("Cannot create indirect conf map property.\n");
807 807 return ((int)PCICFG_FAILURE);
808 808 }
809 809
810 810 if (pci_config_setup(new_device, &config_handle) != DDI_SUCCESS)
811 811 return (PCICFG_FAILURE);
812 812 /* check if we are PCIe device */
813 813 if (pcicfg_pcie_device_type(new_device, config_handle) == DDI_SUCCESS) {
814 814 DEBUG0("PCIe device detected\n");
815 815 pcie_device_type = 1;
816 816 }
817 817 pci_config_teardown(&config_handle);
818 818 /* create Bus node properties for ntbridge. */
819 819 if (pcicfg_set_busnode_props(new_device, pcie_device_type)
820 820 != PCICFG_SUCCESS) {
821 821 DEBUG0("Failed to set busnode props\n");
822 822 return (rc);
823 823 }
824 824
825 825 /* For now: Lets only support one layer of child */
826 826 bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
827 827 req.ra_len = 1;
828 828 if (ndi_ra_alloc(ddi_get_parent(new_device), &req, &next_bus, &blen,
829 829 NDI_RA_TYPE_PCI_BUSNUM, NDI_RA_PASS) != NDI_SUCCESS) {
830 830 DEBUG0("ntbridge: Failed to get a bus number\n");
831 831 return (PCICFG_NORESRC);
832 832 }
833 833
834 834 DEBUG1("ntbridge bus range start ->[%d]\n", next_bus);
835 835
836 836 /*
837 837 * Following will change, as we detect more bridges
838 838 * on the way.
839 839 */
840 840 bus_range[0] = (int)next_bus;
841 841 bus_range[1] = (int)next_bus;
842 842
843 843 if (ndi_prop_update_int_array(DDI_DEV_T_NONE, new_device, "bus-range",
844 844 bus_range, 2) != DDI_SUCCESS) {
845 845 DEBUG0("Cannot set ntbridge bus-range property");
846 846 return (rc);
847 847 }
848 848
849 849 /*
850 850 * The other interface (away from the host) will be
851 851 * initialized by the nexus driver when it loads.
852 852 * We just have to set the registers and the nexus driver
853 853 * figures out the rest.
854 854 */
855 855
856 856 /*
857 857 * finally, lets load and attach the driver
858 858 * before configuring children of ntbridge.
859 859 */
860 860 rc = ndi_devi_online(new_device, NDI_ONLINE_ATTACH|NDI_CONFIG);
861 861 if (rc != NDI_SUCCESS) {
862 862 cmn_err(CE_WARN,
863 863 "pcicfg: Fail:cant load nontransparent bridgd driver..\n");
864 864 rc = PCICFG_FAILURE;
865 865 return (rc);
866 866 }
867 867 DEBUG0("pcicfg: Success loading nontransparent bridge nexus driver..");
868 868
869 869 /* Now set aside pci resource allocation requests for our children */
870 870 if (pcicfg_ntbridge_allocate_resources(new_device) != PCICFG_SUCCESS) {
871 871 max_devs = 0;
872 872 rc = PCICFG_FAILURE;
873 873 } else
874 874 max_devs = PCI_MAX_DEVICES;
875 875
876 876 /* Probe devices on 2nd bus */
877 877 rc = PCICFG_SUCCESS;
878 878 for (devno = pcicfg_start_devno; devno < max_devs; devno++) {
879 879
880 880 ndi_devi_alloc_sleep(new_device, DEVI_PSEUDO_NEXNAME,
881 881 (pnode_t)DEVI_SID_NODEID, &new_ntbridgechild);
882 882
883 883 if (pcicfg_add_config_reg(new_ntbridgechild, next_bus, devno, 0)
884 884 != DDI_PROP_SUCCESS) {
885 885 cmn_err(CE_WARN,
886 886 "Failed to add conf reg for ntbridge child.\n");
887 887 (void) ndi_devi_free(new_ntbridgechild);
888 888 rc = PCICFG_FAILURE;
889 889 break;
890 890 }
891 891
892 892 if (pci_config_setup(new_ntbridgechild, &config_handle)
893 893 != DDI_SUCCESS) {
894 894 cmn_err(CE_WARN,
895 895 "Cannot map ntbridge child %x\n", devno);
896 896 (void) ndi_devi_free(new_ntbridgechild);
897 897 rc = PCICFG_FAILURE;
898 898 break;
899 899 }
900 900
901 901 /*
902 902 * See if there is any PCI HW at this location
903 903 * by reading the Vendor ID. If it returns with 0xffff
904 904 * then there is no hardware at this location.
905 905 */
906 906 vid = pci_config_get16(config_handle, PCI_CONF_VENID);
907 907
908 908 pci_config_teardown(&config_handle);
909 909 (void) ndi_devi_free(new_ntbridgechild);
910 910 if (vid == 0xffff)
911 911 continue;
912 912
913 913 /* Lets fake attachments points for each child, */
914 914 rc = pcicfg_configure(new_device, devno, PCICFG_ALL_FUNC, 0);
915 915 if (rc != PCICFG_SUCCESS) {
916 916 int old_dev = pcicfg_start_devno;
917 917
918 918 cmn_err(CE_WARN,
919 919 "Error configuring ntbridge child dev=%d\n", devno);
920 920
921 921 while (old_dev != devno) {
922 922 if (pcicfg_ntbridge_unconfigure_child(
923 923 new_device, old_dev) == PCICFG_FAILURE)
924 924 cmn_err(CE_WARN, "Unconfig Error "
925 925 "ntbridge child dev=%d\n", old_dev);
926 926 old_dev++;
927 927 }
928 928 break;
929 929 }
930 930 } /* devno loop */
931 931 DEBUG1("ntbridge: finish probing 2nd bus, rc=%d\n", rc);
932 932
933 933 if (rc == PCICFG_SUCCESS)
934 934 rc = pcicfg_ntbridge_configure_done(new_device);
935 935 else {
936 936 pcicfg_phdl_t *entry = pcicfg_find_phdl(new_device);
937 937 uint_t *bus;
938 938 int k;
939 939
940 940 if (ddi_getlongprop(DDI_DEV_T_ANY, new_device,
941 941 DDI_PROP_DONTPASS, "bus-range", (caddr_t)&bus, &k)
942 942 != DDI_PROP_SUCCESS) {
943 943 DEBUG0("Failed to read bus-range property\n");
944 944 rc = PCICFG_FAILURE;
945 945 return (rc);
946 946 }
947 947
948 948 DEBUG2("Need to free bus [%d] range [%d]\n",
949 949 bus[0], bus[1] - bus[0] + 1);
950 950
951 951 if (ndi_ra_free(ddi_get_parent(new_device), (uint64_t)bus[0],
952 952 (uint64_t)(bus[1] - bus[0] + 1), NDI_RA_TYPE_PCI_BUSNUM,
953 953 NDI_RA_PASS) != NDI_SUCCESS) {
954 954 DEBUG0("Failed to free a bus number\n");
955 955 rc = PCICFG_FAILURE;
956 956 kmem_free(bus, k);
957 957 return (rc);
958 958 }
959 959
960 960 /*
961 961 * Since no memory allocations are done for non transparent
962 962 * bridges (but instead we just set the handle with the
963 963 * already allocated memory, we just need to reset the
964 964 * following values before calling the destroy_phdl()
965 965 * function next, otherwise the it will try to free
966 966 * memory allocated as in case of a transparent bridge.
967 967 */
968 968 entry->memory_len = 0;
969 969 entry->pf_memory_len = 0;
970 970 entry->io_len = 0;
971 971 kmem_free(bus, k);
972 972 /* the following will free hole data. */
973 973 (void) pcicfg_destroy_phdl(new_device);
974 974 }
975 975
976 976 /*
977 977 * Unload driver just in case child configure failed!
978 978 */
979 979 rc1 = ndi_devi_offline(new_device, 0);
980 980 DEBUG1("pcicfg: now unloading the ntbridge driver. rc1=%d\n", rc1);
981 981 if (rc1 != NDI_SUCCESS) {
982 982 cmn_err(CE_WARN,
983 983 "pcicfg: cant unload ntbridge driver..children.\n");
984 984 rc = PCICFG_FAILURE;
985 985 }
986 986
987 987 return (rc);
988 988 }
989 989
990 990 static int
991 991 pcicfg_ntbridge_allocate_resources(dev_info_t *dip)
992 992 {
993 993 pcicfg_phdl_t *phdl;
994 994 ndi_ra_request_t *mem_request;
995 995 ndi_ra_request_t *pf_mem_request;
996 996 ndi_ra_request_t *io_request;
997 997 uint64_t boundbase, boundlen;
998 998
999 999 phdl = pcicfg_find_phdl(dip);
1000 1000 ASSERT(phdl);
1001 1001
1002 1002 mem_request = &phdl->mem_req;
1003 1003 pf_mem_request = &phdl->pf_mem_req;
1004 1004 io_request = &phdl->io_req;
1005 1005
1006 1006 phdl->error = PCICFG_SUCCESS;
1007 1007
1008 1008 /* Set Memory space handle for ntbridge */
1009 1009 if (pcicfg_get_ntbridge_child_range(dip, &boundbase, &boundlen,
1010 1010 PCI_BASE_SPACE_MEM) != DDI_SUCCESS) {
1011 1011 cmn_err(CE_WARN,
1012 1012 "ntbridge: Mem resource information failure\n");
1013 1013 phdl->memory_len = 0;
1014 1014 return (PCICFG_FAILURE);
1015 1015 }
1016 1016 mem_request->ra_boundbase = boundbase;
1017 1017 mem_request->ra_boundlen = boundbase + boundlen;
1018 1018 mem_request->ra_len = boundlen;
1019 1019 mem_request->ra_align_mask =
1020 1020 PCICFG_MEMGRAN - 1; /* 1M alignment on memory space */
1021 1021 mem_request->ra_flags |= NDI_RA_ALLOC_BOUNDED;
1022 1022
1023 1023 /*
1024 1024 * mem_request->ra_len =
1025 1025 * PCICFG_ROUND_UP(mem_request->ra_len, PCICFG_MEMGRAN);
1026 1026 */
1027 1027
1028 1028 phdl->memory_base = phdl->memory_last = boundbase;
1029 1029 phdl->memory_len = boundlen;
1030 1030 phdl->mem_hole.start = phdl->memory_base;
1031 1031 phdl->mem_hole.len = mem_request->ra_len;
1032 1032 phdl->mem_hole.next = (hole_t *)NULL;
1033 1033
1034 1034 DEBUG2("Connector requested [0x%llx], needs [0x%llx] bytes of memory\n",
1035 1035 boundlen, mem_request->ra_len);
1036 1036
1037 1037 /* Set IO space handle for ntbridge */
1038 1038 if (pcicfg_get_ntbridge_child_range(dip, &boundbase, &boundlen,
1039 1039 PCI_BASE_SPACE_IO) != DDI_SUCCESS) {
1040 1040 cmn_err(CE_WARN, "ntbridge: IO resource information failure\n");
1041 1041 phdl->io_len = 0;
1042 1042 return (PCICFG_FAILURE);
1043 1043 }
1044 1044 io_request->ra_len = boundlen;
1045 1045 io_request->ra_align_mask =
1046 1046 PCICFG_IOGRAN - 1; /* 4K alignment on I/O space */
1047 1047 io_request->ra_boundbase = boundbase;
1048 1048 io_request->ra_boundlen = boundbase + boundlen;
1049 1049 io_request->ra_flags |= NDI_RA_ALLOC_BOUNDED;
1050 1050
1051 1051 /*
1052 1052 * io_request->ra_len =
1053 1053 * PCICFG_ROUND_UP(io_request->ra_len, PCICFG_IOGRAN);
1054 1054 */
1055 1055
1056 1056 phdl->io_base = phdl->io_last = (uint32_t)boundbase;
1057 1057 phdl->io_len = (uint32_t)boundlen;
1058 1058 phdl->io_hole.start = phdl->io_base;
1059 1059 phdl->io_hole.len = io_request->ra_len;
1060 1060 phdl->io_hole.next = (hole_t *)NULL;
1061 1061
1062 1062 DEBUG2("Connector requested [0x%llx], needs [0x%llx] bytes of IO\n",
1063 1063 boundlen, io_request->ra_len);
1064 1064
1065 1065 /* Set Prefetchable Memory space handle for ntbridge */
1066 1066 if (pcicfg_get_ntbridge_child_range(dip, &boundbase, &boundlen,
1067 1067 PCI_BASE_SPACE_MEM | PCI_BASE_PREF_M) != DDI_SUCCESS) {
1068 1068 cmn_err(CE_WARN,
1069 1069 "ntbridge: PF Mem resource information failure\n");
1070 1070 phdl->pf_memory_len = 0;
1071 1071 return (PCICFG_FAILURE);
1072 1072 }
1073 1073 pf_mem_request->ra_boundbase = boundbase;
1074 1074 pf_mem_request->ra_boundlen = boundbase + boundlen;
1075 1075 pf_mem_request->ra_len = boundlen;
1076 1076 pf_mem_request->ra_align_mask =
1077 1077 PCICFG_MEMGRAN - 1; /* 1M alignment on memory space */
1078 1078 pf_mem_request->ra_flags |= NDI_RA_ALLOC_BOUNDED;
1079 1079
1080 1080 /*
1081 1081 * pf_mem_request->ra_len =
1082 1082 * PCICFG_ROUND_UP(pf_mem_request->ra_len, PCICFG_MEMGRAN);
1083 1083 */
1084 1084
1085 1085 phdl->pf_memory_base = phdl->pf_memory_last = boundbase;
1086 1086 phdl->pf_memory_len = boundlen;
1087 1087 phdl->pf_mem_hole.start = phdl->pf_memory_base;
1088 1088 phdl->pf_mem_hole.len = pf_mem_request->ra_len;
1089 1089 phdl->pf_mem_hole.next = (hole_t *)NULL;
1090 1090
1091 1091 DEBUG2("Connector requested [0x%llx], needs [0x%llx] bytes of PF "
1092 1092 "memory\n", boundlen, pf_mem_request->ra_len);
1093 1093
1094 1094 DEBUG2("MEMORY BASE = [0x%lx] length [0x%lx]\n",
1095 1095 phdl->memory_base, phdl->memory_len);
1096 1096 DEBUG2("IO BASE = [0x%x] length [0x%x]\n",
1097 1097 phdl->io_base, phdl->io_len);
1098 1098 DEBUG2("PF MEMORY BASE = [0x%lx] length [0x%lx]\n",
1099 1099 phdl->pf_memory_base, phdl->pf_memory_len);
1100 1100
1101 1101 return (PCICFG_SUCCESS);
1102 1102 }
1103 1103
1104 1104 static int
1105 1105 pcicfg_ntbridge_configure_done(dev_info_t *dip)
1106 1106 {
1107 1107 ppb_ranges_t range[PCICFG_RANGE_LEN];
1108 1108 pcicfg_phdl_t *entry;
1109 1109 uint_t len;
1110 1110 pci_bus_range_t bus_range;
1111 1111 int new_bus_range[2];
1112 1112
1113 1113 DEBUG1("Configuring children for %p\n", dip);
1114 1114
1115 1115 entry = pcicfg_find_phdl(dip);
1116 1116 ASSERT(entry);
1117 1117
1118 1118 bzero((caddr_t)range, sizeof (ppb_ranges_t) * PCICFG_RANGE_LEN);
1119 1119 range[1].child_high = range[1].parent_high |=
1120 1120 (PCI_REG_REL_M | PCI_ADDR_MEM32);
1121 1121 range[1].child_low = range[1].parent_low = (uint32_t)entry->memory_base;
1122 1122
1123 1123 range[0].child_high = range[0].parent_high |=
1124 1124 (PCI_REG_REL_M | PCI_ADDR_IO);
1125 1125 range[0].child_low = range[0].parent_low = (uint32_t)entry->io_base;
1126 1126
1127 1127 range[2].child_high = range[2].parent_high |=
1128 1128 (PCI_REG_REL_M | PCI_ADDR_MEM32 | PCI_REG_PF_M);
1129 1129 range[2].child_low = range[2].parent_low =
1130 1130 (uint32_t)entry->pf_memory_base;
1131 1131
1132 1132 len = sizeof (pci_bus_range_t);
1133 1133 if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1134 1134 "bus-range", (caddr_t)&bus_range, (int *)&len) != DDI_SUCCESS) {
1135 1135 DEBUG0("no bus-range property\n");
1136 1136 return (PCICFG_FAILURE);
1137 1137 }
1138 1138
1139 1139 new_bus_range[0] = bus_range.lo; /* primary bus number */
1140 1140 if (entry->highest_bus) { /* secondary bus number */
1141 1141 if (entry->highest_bus < bus_range.lo) {
1142 1142 cmn_err(CE_WARN,
1143 1143 "ntbridge bus range invalid !(%d,%d)\n",
1144 1144 bus_range.lo, entry->highest_bus);
1145 1145 new_bus_range[1] = bus_range.lo + entry->highest_bus;
1146 1146 }
1147 1147 else
1148 1148 new_bus_range[1] = entry->highest_bus;
1149 1149 }
1150 1150 else
1151 1151 new_bus_range[1] = bus_range.hi;
1152 1152
1153 1153 DEBUG2("ntbridge: bus range lo=%x, hi=%x\n", new_bus_range[0],
1154 1154 new_bus_range[1]);
1155 1155
1156 1156 if (ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, "bus-range",
1157 1157 new_bus_range, 2) != DDI_SUCCESS) {
1158 1158 DEBUG0("Failed to set bus-range property");
1159 1159 entry->error = PCICFG_FAILURE;
1160 1160 return (PCICFG_FAILURE);
1161 1161 }
1162 1162
1163 1163 #ifdef DEBUG
1164 1164 {
1165 1165 uint64_t unused;
1166 1166 unused = pcicfg_unused_space(&entry->io_hole, &len);
1167 1167 DEBUG2("ntbridge: Unused IO space %llx bytes over %d holes\n",
1168 1168 unused, len);
1169 1169 }
1170 1170 #endif
1171 1171
1172 1172 range[0].size_low = entry->io_len;
1173 1173 if (pcicfg_update_ranges_prop(dip, &range[0])) {
1174 1174 DEBUG0("Failed to update ranges (i/o)\n");
1175 1175 entry->error = PCICFG_FAILURE;
1176 1176 return (PCICFG_FAILURE);
1177 1177 }
1178 1178
1179 1179 #ifdef DEBUG
1180 1180 {
1181 1181 uint64_t unused;
1182 1182 unused = pcicfg_unused_space(&entry->mem_hole, &len);
1183 1183 DEBUG2("ntbridge: Unused Mem space %llx bytes over %d holes\n",
1184 1184 unused, len);
1185 1185 }
1186 1186 #endif
1187 1187
1188 1188 range[1].size_low = entry->memory_len;
1189 1189 if (pcicfg_update_ranges_prop(dip, &range[1])) {
1190 1190 DEBUG0("Failed to update ranges (memory)\n");
1191 1191 entry->error = PCICFG_FAILURE;
1192 1192 return (PCICFG_FAILURE);
1193 1193 }
1194 1194
1195 1195 #ifdef DEBUG
1196 1196 {
1197 1197 uint64_t unused;
1198 1198 unused = pcicfg_unused_space(&entry->pf_mem_hole, &len);
1199 1199 DEBUG2("ntbridge: Unused PF Mem space %llx bytes over"
1200 1200 " %d holes\n", unused, len);
1201 1201 }
1202 1202 #endif
1203 1203
1204 1204 range[2].size_low = entry->pf_memory_len;
1205 1205 if (pcicfg_update_ranges_prop(dip, &range[2])) {
1206 1206 DEBUG0("Failed to update ranges (PF memory)\n");
1207 1207 entry->error = PCICFG_FAILURE;
1208 1208 return (PCICFG_FAILURE);
1209 1209 }
1210 1210
1211 1211 return (PCICFG_SUCCESS);
1212 1212 }
1213 1213
1214 1214 static int
1215 1215 pcicfg_ntbridge_program_child(dev_info_t *dip)
1216 1216 {
1217 1217 pcicfg_phdl_t *entry;
1218 1218 int rc = PCICFG_SUCCESS;
1219 1219 dev_info_t *anode = dip;
1220 1220
1221 1221 /* Find the Hotplug Connection (CN) node */
1222 1222 while ((anode != NULL) &&
1223 1223 (strcmp(ddi_binding_name(anode), "hp_attachment") != 0)) {
1224 1224 anode = ddi_get_parent(anode);
1225 1225 }
1226 1226
1227 1227 if (anode == NULL) {
1228 1228 DEBUG0("ntbridge child tree not in PROBE state\n");
1229 1229 return (PCICFG_FAILURE);
1230 1230 }
1231 1231 entry = pcicfg_find_phdl(ddi_get_parent(anode));
1232 1232 ASSERT(entry);
1233 1233
1234 1234 if (pcicfg_bridge_assign(dip, entry) == DDI_WALK_TERMINATE) {
1235 1235 cmn_err(CE_WARN,
1236 1236 "ntbridge: Error assigning range for child %s\n",
1237 1237 ddi_get_name(dip));
1238 1238 rc = PCICFG_FAILURE;
1239 1239 }
1240 1240 return (rc);
1241 1241 }
1242 1242
1243 1243 static int
1244 1244 pcicfg_ntbridge_unconfigure_child(dev_info_t *new_device, uint_t devno)
1245 1245 {
1246 1246
1247 1247 dev_info_t *new_ntbridgechild;
1248 1248 int len, bus;
1249 1249 uint16_t vid;
1250 1250 ddi_acc_handle_t config_handle;
1251 1251 pci_bus_range_t pci_bus_range;
1252 1252
1253 1253 len = sizeof (pci_bus_range_t);
1254 1254 if (ddi_getlongprop_buf(DDI_DEV_T_ANY, new_device, DDI_PROP_DONTPASS,
1255 1255 "bus-range", (caddr_t)&pci_bus_range, &len) != DDI_SUCCESS) {
1256 1256 DEBUG0("no bus-range property\n");
1257 1257 return (PCICFG_FAILURE);
1258 1258 }
1259 1259
1260 1260 bus = pci_bus_range.lo; /* primary bus number of this bus node */
1261 1261
1262 1262 ndi_devi_alloc_sleep(new_device, DEVI_PSEUDO_NEXNAME,
1263 1263 (pnode_t)DEVI_SID_NODEID, &new_ntbridgechild);
1264 1264
1265 1265 if (pcicfg_add_config_reg(new_ntbridgechild, bus, devno, 0)
1266 1266 != DDI_PROP_SUCCESS) {
1267 1267 cmn_err(CE_WARN, "Unconfigure: Failed to add conf reg prop for "
1268 1268 "ntbridge child.\n");
1269 1269 (void) ndi_devi_free(new_ntbridgechild);
1270 1270 return (PCICFG_FAILURE);
1271 1271 }
1272 1272
1273 1273 if (pci_config_setup(new_ntbridgechild, &config_handle)
1274 1274 != DDI_SUCCESS) {
1275 1275 cmn_err(CE_WARN, "pcicfg: Cannot map ntbridge child %x\n",
1276 1276 devno);
1277 1277 (void) ndi_devi_free(new_ntbridgechild);
1278 1278 return (PCICFG_FAILURE);
1279 1279 }
1280 1280
1281 1281 /*
1282 1282 * See if there is any PCI HW at this location
1283 1283 * by reading the Vendor ID. If it returns with 0xffff
1284 1284 * then there is no hardware at this location.
1285 1285 */
1286 1286 vid = pci_config_get16(config_handle, PCI_CONF_VENID);
1287 1287
1288 1288 pci_config_teardown(&config_handle);
1289 1289 (void) ndi_devi_free(new_ntbridgechild);
1290 1290 if (vid == 0xffff)
1291 1291 return (PCICFG_NODEVICE);
1292 1292
1293 1293 return (pcicfg_unconfigure(new_device, devno, PCICFG_ALL_FUNC, 0));
1294 1294 }
1295 1295
1296 1296 static uint_t
1297 1297 pcicfg_ntbridge_unconfigure(dev_info_t *dip)
1298 1298 {
1299 1299 pcicfg_phdl_t *entry = pcicfg_find_phdl(dip);
1300 1300 uint_t *bus;
1301 1301 int k, rc = DDI_FAILURE;
1302 1302
1303 1303 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "bus-range",
1304 1304 (caddr_t)&bus, &k) != DDI_PROP_SUCCESS) {
1305 1305 DEBUG0("ntbridge: Failed to read bus-range property\n");
1306 1306 return (rc);
1307 1307 }
1308 1308
1309 1309 DEBUG2("ntbridge: Need to free bus [%d] range [%d]\n",
1310 1310 bus[0], bus[1] - bus[0] + 1);
1311 1311
1312 1312 if (ndi_ra_free(ddi_get_parent(dip), (uint64_t)bus[0],
1313 1313 (uint64_t)(bus[1] - bus[0] + 1),
1314 1314 NDI_RA_TYPE_PCI_BUSNUM, NDI_RA_PASS) != NDI_SUCCESS) {
1315 1315 DEBUG0("ntbridge: Failed to free a bus number\n");
1316 1316 kmem_free(bus, k);
1317 1317 return (rc);
1318 1318 }
1319 1319
1320 1320 /*
1321 1321 * Since our resources will be freed at the parent level,
1322 1322 * just reset these values.
1323 1323 */
1324 1324 entry->memory_len = 0;
1325 1325 entry->io_len = 0;
1326 1326 entry->pf_memory_len = 0;
1327 1327
1328 1328 kmem_free(bus, k);
1329 1329
1330 1330 /* the following will also free hole data. */
1331 1331 return (pcicfg_destroy_phdl(dip));
1332 1332
1333 1333 }
1334 1334
1335 1335 static int
1336 1336 pcicfg_is_ntbridge(dev_info_t *dip)
1337 1337 {
1338 1338 ddi_acc_handle_t config_handle;
1339 1339 uint8_t class, subclass;
1340 1340 int rc = DDI_SUCCESS;
1341 1341
1342 1342 if (pci_config_setup(dip, &config_handle) != DDI_SUCCESS) {
1343 1343 cmn_err(CE_WARN,
1344 1344 "pcicfg: cannot map config space, to get map type\n");
1345 1345 return (DDI_FAILURE);
1346 1346 }
1347 1347 class = pci_config_get8(config_handle, PCI_CONF_BASCLASS);
1348 1348 subclass = pci_config_get8(config_handle, PCI_CONF_SUBCLASS);
1349 1349
1350 1350 /* check for class=6, subclass=9, for non transparent bridges. */
1351 1351 if ((class != PCI_CLASS_BRIDGE) || (subclass != PCI_BRIDGE_STBRIDGE))
1352 1352 rc = DDI_FAILURE;
1353 1353
1354 1354 DEBUG3("pcicfg: checking device %x,%x for indirect map. rc=%d\n",
1355 1355 pci_config_get16(config_handle, PCI_CONF_VENID),
1356 1356 pci_config_get16(config_handle, PCI_CONF_DEVID),
1357 1357 rc);
1358 1358 pci_config_teardown(&config_handle);
1359 1359 return (rc);
1360 1360 }
1361 1361
1362 1362 static uint_t
1363 1363 pcicfg_ntbridge_child(dev_info_t *dip)
1364 1364 {
1365 1365 int len, val, rc = DDI_FAILURE;
1366 1366 dev_info_t *anode = dip;
1367 1367
1368 1368 /*
1369 1369 * Find the Hotplug Connection (CN) node
1370 1370 */
1371 1371 while ((anode != NULL) && (strcmp(ddi_binding_name(anode),
1372 1372 "hp_attachment") != 0)) {
1373 1373 anode = ddi_get_parent(anode);
1374 1374 }
1375 1375
1376 1376 if (anode == NULL) {
1377 1377 DEBUG0("ntbridge child tree not in PROBE state\n");
1378 1378 return (rc);
1379 1379 }
1380 1380 len = sizeof (int);
1381 1381 if (ddi_getlongprop_buf(DDI_DEV_T_ANY, ddi_get_parent(anode),
1382 1382 DDI_PROP_DONTPASS, PCI_DEV_CONF_MAP_PROP, (caddr_t)&val, &len)
1383 1383 != DDI_SUCCESS) {
1384 1384
1385 1385 DEBUG1("ntbridge child: no \"%s\" property\n",
1386 1386 PCI_DEV_CONF_MAP_PROP);
1387 1387 return (rc);
1388 1388 }
1389 1389 DEBUG0("ntbridge child: success\n");
1390 1390 return (DDI_SUCCESS);
1391 1391 }
1392 1392
1393 1393 static uint_t
1394 1394 pcicfg_get_ntbridge_child_range(dev_info_t *dip, uint64_t *boundbase,
1395 1395 uint64_t *boundlen, uint_t space_type)
1396 1396 {
1397 1397 int length, found = DDI_FAILURE, acount, i, ibridge;
1398 1398 pci_regspec_t *assigned;
1399 1399
1400 1400 if ((ibridge = pcicfg_is_ntbridge(dip)) == DDI_FAILURE)
1401 1401 return (found);
1402 1402
1403 1403 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1404 1404 "assigned-addresses", (caddr_t)&assigned, &length)
1405 1405 != DDI_PROP_SUCCESS) {
1406 1406 DEBUG1("Failed to get assigned-addresses property %llx\n", dip);
1407 1407 return (found);
1408 1408 }
1409 1409 DEBUG1("pcicfg: ntbridge child range: dip = %s\n",
1410 1410 ddi_driver_name(dip));
1411 1411
1412 1412 acount = length / sizeof (pci_regspec_t);
1413 1413
1414 1414 for (i = 0; i < acount; i++) {
1415 1415 if ((PCI_REG_REG_G(assigned[i].pci_phys_hi) ==
1416 1416 pcicfg_indirect_map_devs[ibridge].mem_range_bar_offset) &&
1417 1417 (space_type == PCI_BASE_SPACE_MEM)) {
1418 1418 found = DDI_SUCCESS;
1419 1419 break;
1420 1420 } else if ((PCI_REG_REG_G(assigned[i].pci_phys_hi) ==
1421 1421 pcicfg_indirect_map_devs[ibridge].io_range_bar_offset) &&
1422 1422 (space_type == PCI_BASE_SPACE_IO)) {
1423 1423 found = DDI_SUCCESS;
1424 1424 break;
1425 1425 } else if ((PCI_REG_REG_G(assigned[i].pci_phys_hi) ==
1426 1426 pcicfg_indirect_map_devs[ibridge].
1427 1427 prefetch_mem_range_bar_offset) &&
1428 1428 (space_type == (PCI_BASE_SPACE_MEM |
1429 1429 PCI_BASE_PREF_M))) {
1430 1430 found = DDI_SUCCESS;
1431 1431 break;
1432 1432 }
1433 1433 }
1434 1434 DEBUG3("pcicfg: ntbridge child range: space=%x, base=%lx, len=%lx\n",
1435 1435 space_type, assigned[i].pci_phys_low, assigned[i].pci_size_low);
1436 1436
1437 1437 if (found == DDI_SUCCESS) {
1438 1438 *boundbase = assigned[i].pci_phys_low;
1439 1439 *boundlen = assigned[i].pci_size_low;
1440 1440 }
1441 1441
1442 1442 kmem_free(assigned, length);
1443 1443 return (found);
1444 1444 }
1445 1445
1446 1446 /*
1447 1447 * This will turn resources allocated by pcicfg_configure()
1448 1448 * and remove the device tree from the Hotplug Connection (CN)
1449 1449 * and below. The routine assumes the devices have their
1450 1450 * drivers detached.
1451 1451 */
1452 1452 int
1453 1453 pcicfg_unconfigure(dev_info_t *devi, uint_t device, uint_t function,
1454 1454 pcicfg_flags_t flags)
1455 1455 {
1456 1456 dev_info_t *child_dip;
1457 1457 int func;
1458 1458 int i;
1459 1459 int max_function, trans_device;
1460 1460 int circ;
1461 1461 boolean_t is_pcie;
1462 1462
1463 1463 if (pcie_ari_is_enabled(devi) == PCIE_ARI_FORW_ENABLED)
1464 1464 max_function = PCICFG_MAX_ARI_FUNCTION;
1465 1465 else
1466 1466 max_function = PCI_MAX_FUNCTIONS;
1467 1467
1468 1468 /*
1469 1469 * Cycle through devices to make sure none are busy.
1470 1470 * If a single device is busy fail the whole unconfigure.
1471 1471 */
1472 1472 is_pcie = is_pcie_fabric(devi);
1473 1473
1474 1474 ndi_devi_enter(devi, &circ);
1475 1475 for (func = 0; func < max_function; func++) {
1476 1476 if ((function != PCICFG_ALL_FUNC) && (function != func))
1477 1477 continue;
1478 1478
1479 1479 if (max_function == PCICFG_MAX_ARI_FUNCTION)
1480 1480 trans_device = func >> 3; /* ARI Device */
1481 1481 else
1482 1482 trans_device = device;
1483 1483
1484 1484 if ((child_dip = pcicfg_devi_find(devi, trans_device,
1485 1485 func & 7)) == NULL)
1486 1486 continue;
1487 1487
1488 1488 if (ndi_devi_offline(child_dip, NDI_UNCONFIG) == NDI_SUCCESS)
1489 1489 continue;
1490 1490
1491 1491 /*
1492 1492 * Device function is busy. Before returning we have to
1493 1493 * put all functions back online which were taken
1494 1494 * offline during the process.
1495 1495 */
1496 1496 DEBUG2("Device [0x%x] function [0x%x] is busy\n",
1497 1497 trans_device, func & 7);
1498 1498 /*
1499 1499 * If we are only asked to offline one specific function,
1500 1500 * and that fails, we just simply return.
1501 1501 */
1502 1502 if (function != PCICFG_ALL_FUNC)
1503 1503 return (PCICFG_FAILURE);
1504 1504
1505 1505 for (i = 0; i < func; i++) {
1506 1506 if (max_function == PCICFG_MAX_ARI_FUNCTION)
1507 1507 trans_device = i >> 3;
1508 1508
1509 1509 if ((child_dip = pcicfg_devi_find(devi, trans_device,
1510 1510 i & 7)) == NULL) {
1511 1511 DEBUG0("No more devices to put back "
1512 1512 "on line!!\n");
1513 1513 /*
1514 1514 * Made it through all functions
1515 1515 */
1516 1516 continue;
1517 1517 }
1518 1518 if (ndi_devi_online(child_dip, NDI_CONFIG)
1519 1519 != NDI_SUCCESS) {
1520 1520 DEBUG0("Failed to put back devices state\n");
1521 1521 goto fail;
1522 1522 }
1523 1523 }
1524 1524 goto fail;
1525 1525 }
1526 1526
1527 1527 /*
1528 1528 * Now, tear down all devinfo nodes for this Connector.
1529 1529 */
1530 1530 for (func = 0; func < max_function; func++) {
1531 1531 if ((function != PCICFG_ALL_FUNC) && (function != func))
1532 1532 continue;
1533 1533
1534 1534 if (max_function == PCICFG_MAX_ARI_FUNCTION)
1535 1535 trans_device = func >> 3; /* ARI Device */
1536 1536 else
1537 1537 trans_device = device;
1538 1538
1539 1539 if ((child_dip = pcicfg_devi_find(devi, trans_device, func & 7))
1540 1540 == NULL) {
1541 1541 DEBUG2("No device at %x,%x\n", trans_device, func & 7);
1542 1542 continue;
1543 1543 }
1544 1544
1545 1545 DEBUG2("Tearing down device [0x%x] function [0x%x]\n",
1546 1546 trans_device, func & 7);
1547 1547
1548 1548 if (pcicfg_is_ntbridge(child_dip) != DDI_FAILURE)
1549 1549 if (pcicfg_ntbridge_unconfigure(child_dip) !=
1550 1550 PCICFG_SUCCESS) {
1551 1551 cmn_err(CE_WARN,
1552 1552 "ntbridge: unconfigure failed\n");
1553 1553 goto fail;
1554 1554 }
1555 1555
1556 1556 if (pcicfg_teardown_device(child_dip, flags, is_pcie)
1557 1557 != PCICFG_SUCCESS) {
1558 1558 DEBUG2("Failed to tear down device [0x%x]"
1559 1559 "function [0x%x]\n", trans_device, func & 7);
1560 1560 goto fail;
1561 1561 }
1562 1562 }
1563 1563
1564 1564 if (pcie_ari_is_enabled(devi) == PCIE_ARI_FORW_ENABLED) {
1565 1565 (void) ddi_prop_remove(DDI_DEV_T_NONE, devi, "ari-enabled");
1566 1566 (void) pcie_ari_disable(devi);
1567 1567 }
1568 1568
1569 1569 ndi_devi_exit(devi, circ);
1570 1570 return (PCICFG_SUCCESS);
1571 1571
1572 1572 fail:
1573 1573 ndi_devi_exit(devi, circ);
1574 1574 return (PCICFG_FAILURE);
1575 1575 }
1576 1576
1577 1577 static int
1578 1578 pcicfg_teardown_device(dev_info_t *dip, pcicfg_flags_t flags, boolean_t is_pcie)
1579 1579 {
1580 1580 ddi_acc_handle_t handle;
1581 1581
1582 1582 /*
1583 1583 * Free up resources associated with 'dip'
1584 1584 */
1585 1585 if (pcicfg_free_resources(dip, flags) != PCICFG_SUCCESS) {
1586 1586 DEBUG0("Failed to free resources\n");
1587 1587 return (PCICFG_FAILURE);
1588 1588 }
1589 1589
1590 1590 /*
1591 1591 * disable the device
1592 1592 */
1593 1593 if (pcicfg_config_setup(dip, &handle) != PCICFG_SUCCESS)
1594 1594 return (PCICFG_FAILURE);
1595 1595 pcicfg_device_off(handle);
1596 1596 pcicfg_config_teardown(&handle);
1597 1597
1598 1598 if (is_pcie) {
1599 1599 /*
1600 1600 * free pcie_bus_t for the sub-tree
1601 1601 */
1602 1602 if (ddi_get_child(dip) != NULL)
1603 1603 pcie_fab_fini_bus(dip, PCIE_BUS_ALL);
1604 1604
1605 1605 pcie_fini_bus(dip, PCIE_BUS_ALL);
1606 1606 }
1607 1607
1608 1608 /*
1609 1609 * The framework provides this routine which can
1610 1610 * tear down a sub-tree.
1611 1611 */
1612 1612 if (ndi_devi_offline(dip, NDI_DEVI_REMOVE) != NDI_SUCCESS) {
1613 1613 DEBUG0("Failed to offline and remove node\n");
1614 1614 return (PCICFG_FAILURE);
1615 1615 }
1616 1616
1617 1617 return (PCICFG_SUCCESS);
1618 1618 }
1619 1619
1620 1620 /*
1621 1621 * BEGIN GENERIC SUPPORT ROUTINES
1622 1622 */
1623 1623 static pcicfg_phdl_t *
1624 1624 pcicfg_find_phdl(dev_info_t *dip)
1625 1625 {
1626 1626 pcicfg_phdl_t *entry;
1627 1627 mutex_enter(&pcicfg_list_mutex);
1628 1628 for (entry = pcicfg_phdl_list; entry != NULL; entry = entry->next) {
1629 1629 if (entry->dip == dip) {
1630 1630 mutex_exit(&pcicfg_list_mutex);
1631 1631 return (entry);
1632 1632 }
1633 1633 }
1634 1634 mutex_exit(&pcicfg_list_mutex);
1635 1635
1636 1636 /*
1637 1637 * Did'nt find entry - create one
1638 1638 */
1639 1639 return (pcicfg_create_phdl(dip));
1640 1640 }
1641 1641
1642 1642 static pcicfg_phdl_t *
1643 1643 pcicfg_create_phdl(dev_info_t *dip)
1644 1644 {
1645 1645 pcicfg_phdl_t *new;
1646 1646
1647 1647 new = (pcicfg_phdl_t *)kmem_zalloc(sizeof (pcicfg_phdl_t), KM_SLEEP);
1648 1648
1649 1649 new->dip = dip;
1650 1650 mutex_enter(&pcicfg_list_mutex);
1651 1651 new->next = pcicfg_phdl_list;
1652 1652 pcicfg_phdl_list = new;
1653 1653 mutex_exit(&pcicfg_list_mutex);
1654 1654
1655 1655 return (new);
1656 1656 }
1657 1657
1658 1658 static int
1659 1659 pcicfg_destroy_phdl(dev_info_t *dip)
1660 1660 {
1661 1661 pcicfg_phdl_t *entry;
1662 1662 pcicfg_phdl_t *follow = NULL;
1663 1663
1664 1664 mutex_enter(&pcicfg_list_mutex);
1665 1665 for (entry = pcicfg_phdl_list; entry != NULL; follow = entry,
1666 1666 entry = entry->next) {
1667 1667 if (entry->dip == dip) {
1668 1668 if (entry == pcicfg_phdl_list) {
1669 1669 pcicfg_phdl_list = entry->next;
1670 1670 } else {
1671 1671 follow->next = entry->next;
1672 1672 }
1673 1673 /*
1674 1674 * If this entry has any allocated memory
1675 1675 * or IO space associated with it, that
1676 1676 * must be freed up.
1677 1677 */
1678 1678 if (entry->memory_len > 0) {
1679 1679 (void) ndi_ra_free(ddi_get_parent(dip),
1680 1680 entry->memory_base, entry->memory_len,
1681 1681 NDI_RA_TYPE_MEM, NDI_RA_PASS);
1682 1682 }
1683 1683 pcicfg_free_hole(&entry->mem_hole);
1684 1684
1685 1685 if (entry->io_len > 0) {
1686 1686 (void) ndi_ra_free(ddi_get_parent(dip),
1687 1687 entry->io_base, entry->io_len,
1688 1688 NDI_RA_TYPE_IO, NDI_RA_PASS);
1689 1689 }
1690 1690 pcicfg_free_hole(&entry->io_hole);
1691 1691
1692 1692 if (entry->pf_memory_len > 0) {
1693 1693 (void) ndi_ra_free(ddi_get_parent(dip),
1694 1694 entry->pf_memory_base, entry->pf_memory_len,
1695 1695 NDI_RA_TYPE_PCI_PREFETCH_MEM, NDI_RA_PASS);
1696 1696 }
1697 1697 pcicfg_free_hole(&entry->pf_mem_hole);
1698 1698
1699 1699 /*
1700 1700 * Destroy this entry
1701 1701 */
1702 1702 kmem_free((caddr_t)entry, sizeof (pcicfg_phdl_t));
1703 1703 mutex_exit(&pcicfg_list_mutex);
1704 1704 return (PCICFG_SUCCESS);
1705 1705 }
1706 1706 }
1707 1707 mutex_exit(&pcicfg_list_mutex);
1708 1708 /*
1709 1709 * Did'nt find the entry
1710 1710 */
1711 1711 return (PCICFG_FAILURE);
1712 1712 }
1713 1713
1714 1714 static int
1715 1715 pcicfg_bridge_assign(dev_info_t *dip, void *hdl)
1716 1716 {
1717 1717 ddi_acc_handle_t handle;
1718 1718 pci_regspec_t *reg;
1719 1719 int length;
1720 1720 int rcount;
1721 1721 int i;
1722 1722 int offset;
1723 1723 uint64_t mem_answer;
1724 1724 uint32_t io_answer;
1725 1725 int count;
1726 1726 uint8_t header_type;
1727 1727 ppb_ranges_t range[PCICFG_RANGE_LEN];
1728 1728 int bus_range[2];
1729 1729 uint64_t mem_residual;
1730 1730 uint64_t pf_mem_residual;
1731 1731 uint64_t io_residual;
1732 1732
1733 1733 pcicfg_phdl_t *entry = (pcicfg_phdl_t *)hdl;
1734 1734
1735 1735 DEBUG1("bridge assign: assigning addresses to %s\n", ddi_get_name(dip));
1736 1736
1737 1737 entry->error = PCICFG_SUCCESS;
1738 1738
1739 1739 if (entry == NULL) {
1740 1740 DEBUG0("Failed to get entry\n");
1741 1741 entry->error = PCICFG_FAILURE;
1742 1742 return (DDI_WALK_TERMINATE);
1743 1743 }
1744 1744
1745 1745 if (pcicfg_config_setup(dip, &handle) != DDI_SUCCESS) {
1746 1746 DEBUG0("Failed to map config space!\n");
1747 1747 entry->error = PCICFG_FAILURE;
1748 1748 return (DDI_WALK_TERMINATE);
1749 1749 }
1750 1750
1751 1751 header_type = pci_config_get8(handle, PCI_CONF_HEADER);
1752 1752
1753 1753 if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
1754 1754
1755 1755 bzero((caddr_t)range, sizeof (ppb_ranges_t) * PCICFG_RANGE_LEN);
1756 1756
1757 1757 (void) pcicfg_setup_bridge(entry, handle);
1758 1758
1759 1759 range[0].child_high = range[0].parent_high |=
1760 1760 (PCI_REG_REL_M | PCI_ADDR_IO);
1761 1761 range[0].child_low = range[0].parent_low = entry->io_last;
1762 1762 range[1].child_high = range[1].parent_high |=
1763 1763 (PCI_REG_REL_M | PCI_ADDR_MEM32);
1764 1764 range[1].child_low = range[1].parent_low =
1765 1765 entry->memory_last;
1766 1766 range[2].child_high = range[2].parent_high |=
1767 1767 (PCI_REG_REL_M | PCI_ADDR_MEM32 | PCI_REG_PF_M);
1768 1768 range[2].child_low = range[2].parent_low =
1769 1769 entry->pf_memory_last;
1770 1770
1771 1771 ndi_devi_enter(dip, &count);
1772 1772 ddi_walk_devs(ddi_get_child(dip),
1773 1773 pcicfg_bridge_assign, (void *)entry);
1774 1774 ndi_devi_exit(dip, count);
1775 1775
1776 1776 (void) pcicfg_update_bridge(entry, handle);
1777 1777
1778 1778 bus_range[0] = pci_config_get8(handle, PCI_BCNF_SECBUS);
1779 1779 bus_range[1] = pci_config_get8(handle, PCI_BCNF_SUBBUS);
1780 1780
1781 1781 if (ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
1782 1782 "bus-range", bus_range, 2) != DDI_SUCCESS) {
1783 1783 DEBUG0("Failed to set bus-range property");
1784 1784 entry->error = PCICFG_FAILURE;
1785 1785 (void) pcicfg_config_teardown(&handle);
1786 1786 return (DDI_WALK_TERMINATE);
1787 1787 }
1788 1788
1789 1789 /*
1790 1790 * Put back memory and I/O space not allocated
1791 1791 * under the bridge.
1792 1792 */
1793 1793 mem_residual = entry->memory_len -
1794 1794 (entry->memory_last - entry->memory_base);
1795 1795 if (mem_residual > 0) {
1796 1796 (void) ndi_ra_free(ddi_get_parent(dip),
1797 1797 entry->memory_last, mem_residual,
1798 1798 NDI_RA_TYPE_MEM, NDI_RA_PASS);
1799 1799 }
1800 1800
1801 1801 io_residual = entry->io_len - (entry->io_last - entry->io_base);
1802 1802 if (io_residual > 0) {
1803 1803 (void) ndi_ra_free(ddi_get_parent(dip), entry->io_last,
1804 1804 io_residual, NDI_RA_TYPE_IO, NDI_RA_PASS);
1805 1805 }
1806 1806
1807 1807 pf_mem_residual = entry->pf_memory_len -
1808 1808 (entry->pf_memory_last - entry->pf_memory_base);
1809 1809 if (pf_mem_residual > 0) {
1810 1810 (void) ndi_ra_free(ddi_get_parent(dip),
1811 1811 entry->pf_memory_last, pf_mem_residual,
1812 1812 NDI_RA_TYPE_PCI_PREFETCH_MEM, NDI_RA_PASS);
1813 1813 }
1814 1814
1815 1815 if (entry->io_len > 0) {
1816 1816 range[0].size_low = entry->io_last - entry->io_base;
1817 1817 if (pcicfg_update_ranges_prop(dip, &range[0])) {
1818 1818 DEBUG0("Failed to update ranges (i/o)\n");
1819 1819 entry->error = PCICFG_FAILURE;
1820 1820 (void) pcicfg_config_teardown(&handle);
1821 1821 return (DDI_WALK_TERMINATE);
1822 1822 }
1823 1823 }
1824 1824 if (entry->memory_len > 0) {
1825 1825 range[1].size_low =
1826 1826 entry->memory_last - entry->memory_base;
1827 1827 if (pcicfg_update_ranges_prop(dip, &range[1])) {
1828 1828 DEBUG0("Failed to update ranges (memory)\n");
1829 1829 entry->error = PCICFG_FAILURE;
1830 1830 (void) pcicfg_config_teardown(&handle);
1831 1831 return (DDI_WALK_TERMINATE);
1832 1832 }
1833 1833 }
1834 1834 if (entry->pf_memory_len > 0) {
1835 1835 range[2].size_low =
1836 1836 entry->pf_memory_last - entry->pf_memory_base;
1837 1837 if (pcicfg_update_ranges_prop(dip, &range[2])) {
1838 1838 DEBUG0("Failed to update ranges (PF memory)\n");
1839 1839 entry->error = PCICFG_FAILURE;
1840 1840 (void) pcicfg_config_teardown(&handle);
1841 1841 return (DDI_WALK_TERMINATE);
1842 1842 }
1843 1843 }
1844 1844
1845 1845 (void) pcicfg_device_on(handle);
1846 1846
1847 1847 PCICFG_DUMP_BRIDGE_CONFIG(handle);
1848 1848
1849 1849 (void) pcicfg_config_teardown(&handle);
1850 1850
1851 1851 return (DDI_WALK_PRUNECHILD);
1852 1852 }
1853 1853
1854 1854 /*
1855 1855 * If there is an interrupt pin set program
1856 1856 * interrupt line with default values.
1857 1857 */
1858 1858 if (pci_config_get8(handle, PCI_CONF_IPIN)) {
1859 1859 pci_config_put8(handle, PCI_CONF_ILINE, 0xf);
1860 1860 }
1861 1861
1862 1862 /*
1863 1863 * A single device (under a bridge).
1864 1864 * For each "reg" property with a length, allocate memory
1865 1865 * and program the base registers.
1866 1866 */
1867 1867 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg",
1868 1868 (caddr_t)®, &length) != DDI_PROP_SUCCESS) {
1869 1869 DEBUG0("Failed to read reg property\n");
1870 1870 entry->error = PCICFG_FAILURE;
1871 1871 (void) pcicfg_config_teardown(&handle);
1872 1872 return (DDI_WALK_TERMINATE);
1873 1873 }
1874 1874
1875 1875 rcount = length / sizeof (pci_regspec_t);
1876 1876 offset = PCI_CONF_BASE0;
1877 1877 for (i = 0; i < rcount; i++) {
1878 1878 if ((reg[i].pci_size_low != 0) || (reg[i].pci_size_hi != 0)) {
1879 1879
1880 1880 offset = PCI_REG_REG_G(reg[i].pci_phys_hi);
1881 1881
1882 1882 switch (PCI_REG_ADDR_G(reg[i].pci_phys_hi)) {
1883 1883 case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
1884 1884
1885 1885 if (reg[i].pci_phys_hi & PCI_REG_PF_M) {
1886 1886 /* allocate prefetchable memory */
1887 1887 pcicfg_get_pf_mem(entry,
1888 1888 reg[i].pci_size_low, &mem_answer);
1889 1889 } else { /* get non prefetchable memory */
1890 1890 pcicfg_get_mem(entry,
1891 1891 reg[i].pci_size_low, &mem_answer);
1892 1892 }
1893 1893 pci_config_put64(handle, offset, mem_answer);
1894 1894 DEBUG2("REGISTER off %x (64)LO ----> [0x%x]\n",
1895 1895 offset, pci_config_get32(handle, offset));
1896 1896 DEBUG2("REGISTER off %x (64)HI ----> [0x%x]\n",
1897 1897 offset + 4,
1898 1898 pci_config_get32(handle, offset + 4));
1899 1899
1900 1900 reg[i].pci_phys_hi |= PCI_REG_REL_M;
1901 1901 reg[i].pci_phys_low = PCICFG_LOADDR(mem_answer);
1902 1902 reg[i].pci_phys_mid = PCICFG_HIADDR(mem_answer);
1903 1903 break;
1904 1904
1905 1905 case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
1906 1906 if (reg[i].pci_phys_hi & PCI_REG_PF_M) {
1907 1907 /* allocate prefetchable memory */
1908 1908 pcicfg_get_pf_mem(entry,
1909 1909 reg[i].pci_size_low, &mem_answer);
1910 1910 } else {
1911 1911 /* get non prefetchable memory */
1912 1912 pcicfg_get_mem(entry,
1913 1913 reg[i].pci_size_low, &mem_answer);
1914 1914 }
1915 1915
1916 1916 pci_config_put32(handle, offset,
1917 1917 (uint32_t)mem_answer);
1918 1918
1919 1919 DEBUG2("REGISTER off %x(32)LO ----> [0x%x]\n",
1920 1920 offset, pci_config_get32(handle, offset));
1921 1921
1922 1922 reg[i].pci_phys_hi |= PCI_REG_REL_M;
1923 1923 reg[i].pci_phys_low = (uint32_t)mem_answer;
1924 1924
1925 1925 break;
1926 1926 case PCI_REG_ADDR_G(PCI_ADDR_IO):
1927 1927 /* allocate I/O space from the allocator */
1928 1928
1929 1929 (void) pcicfg_get_io(entry, reg[i].pci_size_low,
1930 1930 &io_answer);
1931 1931 pci_config_put32(handle, offset, io_answer);
1932 1932
1933 1933 DEBUG2("REGISTER off %x (I/O)LO ----> [0x%x]\n",
1934 1934 offset, pci_config_get32(handle, offset));
1935 1935
1936 1936 reg[i].pci_phys_hi |= PCI_REG_REL_M;
1937 1937 reg[i].pci_phys_low = io_answer;
1938 1938
1939 1939 break;
1940 1940 default:
1941 1941 DEBUG0("Unknown register type\n");
1942 1942 kmem_free(reg, length);
1943 1943 (void) pcicfg_config_teardown(&handle);
1944 1944 entry->error = PCICFG_FAILURE;
1945 1945 return (DDI_WALK_TERMINATE);
1946 1946 } /* switch */
1947 1947
1948 1948 /*
1949 1949 * Now that memory locations are assigned,
1950 1950 * update the assigned address property.
1951 1951 */
1952 1952 if (pcicfg_update_assigned_prop(dip, ®[i])
1953 1953 != PCICFG_SUCCESS) {
1954 1954 kmem_free(reg, length);
1955 1955 (void) pcicfg_config_teardown(&handle);
1956 1956 entry->error = PCICFG_FAILURE;
1957 1957 return (DDI_WALK_TERMINATE);
1958 1958 }
1959 1959 }
1960 1960 }
1961 1961 (void) pcicfg_device_on(handle);
1962 1962
1963 1963 PCICFG_DUMP_DEVICE_CONFIG(handle);
1964 1964
1965 1965 (void) pcicfg_config_teardown(&handle);
1966 1966 kmem_free((caddr_t)reg, length);
1967 1967 return (DDI_WALK_CONTINUE);
1968 1968 }
1969 1969
1970 1970 static int
1971 1971 pcicfg_device_assign(dev_info_t *dip)
1972 1972 {
1973 1973 ddi_acc_handle_t handle;
1974 1974 pci_regspec_t *reg;
1975 1975 int length;
1976 1976 int rcount;
1977 1977 int i;
1978 1978 int offset;
1979 1979 ndi_ra_request_t request;
1980 1980 uint64_t answer;
1981 1981 uint64_t alen;
1982 1982
1983 1983 DEBUG1("%llx now under configuration\n", dip);
1984 1984
1985 1985 /* request.ra_len = PCICFG_ROUND_UP(request.ra_len, PCICFG_IOGRAN); */
1986 1986 if (pcicfg_ntbridge_child(dip) == DDI_SUCCESS) {
1987 1987
1988 1988 return (pcicfg_ntbridge_program_child(dip));
1989 1989 }
1990 1990 /*
1991 1991 * XXX Failure here should be noted
1992 1992 */
1993 1993 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg",
1994 1994 (caddr_t)®, &length) != DDI_PROP_SUCCESS) {
1995 1995 DEBUG0("Failed to read reg property\n");
1996 1996 return (PCICFG_FAILURE);
1997 1997 }
1998 1998
1999 1999 if (pcicfg_config_setup(dip, &handle) != DDI_SUCCESS) {
2000 2000 DEBUG0("Failed to map config space!\n");
2001 2001 kmem_free(reg, length);
2002 2002 return (PCICFG_FAILURE);
2003 2003 }
2004 2004
2005 2005 /*
2006 2006 * A single device
2007 2007 *
2008 2008 * For each "reg" property with a length, allocate memory
2009 2009 * and program the base registers.
2010 2010 */
2011 2011
2012 2012 /*
2013 2013 * If there is an interrupt pin set program
2014 2014 * interrupt line with default values.
2015 2015 */
2016 2016 if (pci_config_get8(handle, PCI_CONF_IPIN)) {
2017 2017 pci_config_put8(handle, PCI_CONF_ILINE, 0xf);
2018 2018 }
2019 2019
2020 2020 bzero((caddr_t)&request, sizeof (ndi_ra_request_t));
2021 2021
2022 2022 /*
2023 2023 * Note: Both non-prefetchable and prefetchable memory space
2024 2024 * allocations are made within 32bit space. Currently, BIOSs
2025 2025 * allocate device memory for PCI devices within the 32bit space
2026 2026 * so this will not be a problem.
2027 2027 */
2028 2028 request.ra_flags |= NDI_RA_ALIGN_SIZE | NDI_RA_ALLOC_BOUNDED;
2029 2029 request.ra_boundbase = 0;
2030 2030 request.ra_boundlen = PCICFG_4GIG_LIMIT;
2031 2031
2032 2032 rcount = length / sizeof (pci_regspec_t);
2033 2033 offset = PCI_CONF_BASE0;
2034 2034 for (i = 0; i < rcount; i++) {
2035 2035 char *mem_type;
2036 2036
2037 2037 if ((reg[i].pci_size_low != 0)|| (reg[i].pci_size_hi != 0)) {
2038 2038
2039 2039 offset = PCI_REG_REG_G(reg[i].pci_phys_hi);
2040 2040 request.ra_len = reg[i].pci_size_low;
2041 2041
2042 2042 switch (PCI_REG_ADDR_G(reg[i].pci_phys_hi)) {
2043 2043 case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
2044 2044 if (reg[i].pci_phys_hi & PCI_REG_PF_M) {
2045 2045 mem_type = NDI_RA_TYPE_PCI_PREFETCH_MEM;
2046 2046 } else {
2047 2047 mem_type = NDI_RA_TYPE_MEM;
2048 2048 }
2049 2049 /* allocate memory space from the allocator */
2050 2050 if (ndi_ra_alloc(ddi_get_parent(dip), &request,
2051 2051 &answer, &alen, mem_type, NDI_RA_PASS)
2052 2052 != NDI_SUCCESS) {
2053 2053 DEBUG0("Failed to allocate 64b mem\n");
2054 2054 kmem_free(reg, length);
2055 2055 (void) pcicfg_config_teardown(&handle);
2056 2056 return (PCICFG_NORESRC);
2057 2057 }
2058 2058 DEBUG3("64 addr = [0x%x.0x%x] len [0x%x]\n",
2059 2059 PCICFG_HIADDR(answer),
2060 2060 PCICFG_LOADDR(answer), alen);
2061 2061 /* program the low word */
2062 2062 pci_config_put32(handle, offset,
2063 2063 PCICFG_LOADDR(answer));
2064 2064 /* program the high word */
2065 2065 pci_config_put32(handle, offset + 4,
2066 2066 PCICFG_HIADDR(answer));
2067 2067
2068 2068 reg[i].pci_phys_hi |= PCI_REG_REL_M;
2069 2069 reg[i].pci_phys_low = PCICFG_LOADDR(answer);
2070 2070 reg[i].pci_phys_mid = PCICFG_HIADDR(answer);
2071 2071 /*
2072 2072 * currently support 32b address space
2073 2073 * assignments only.
2074 2074 */
2075 2075 reg[i].pci_phys_hi ^=
2076 2076 PCI_ADDR_MEM64 ^ PCI_ADDR_MEM32;
2077 2077
2078 2078 offset += 8;
2079 2079 break;
2080 2080
2081 2081 case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
2082 2082 if (reg[i].pci_phys_hi & PCI_REG_PF_M)
2083 2083 mem_type = NDI_RA_TYPE_PCI_PREFETCH_MEM;
2084 2084 else
2085 2085 mem_type = NDI_RA_TYPE_MEM;
2086 2086 /* allocate memory space from the allocator */
2087 2087 if (ndi_ra_alloc(ddi_get_parent(dip), &request,
2088 2088 &answer, &alen, mem_type, NDI_RA_PASS)
2089 2089 != NDI_SUCCESS) {
2090 2090 DEBUG0("Failed to allocate 32b mem\n");
2091 2091 kmem_free(reg, length);
2092 2092 (void) pcicfg_config_teardown(&handle);
2093 2093 return (PCICFG_NORESRC);
2094 2094 }
2095 2095 DEBUG3("32 addr = [0x%x.0x%x] len [0x%x]\n",
2096 2096 PCICFG_HIADDR(answer),
2097 2097 PCICFG_LOADDR(answer),
2098 2098 alen);
2099 2099 /* program the low word */
2100 2100 pci_config_put32(handle, offset,
2101 2101 PCICFG_LOADDR(answer));
2102 2102
2103 2103 reg[i].pci_phys_hi |= PCI_REG_REL_M;
2104 2104 reg[i].pci_phys_low = PCICFG_LOADDR(answer);
2105 2105 reg[i].pci_phys_mid = 0;
2106 2106
2107 2107 offset += 4;
2108 2108 break;
2109 2109 case PCI_REG_ADDR_G(PCI_ADDR_IO):
2110 2110 /*
2111 2111 * Try to allocate I/O space. If it fails,
2112 2112 * continue here instead of returning failure
2113 2113 * so that the hotplug for drivers that don't
2114 2114 * use I/O space can succeed, For drivers
2115 2115 * that need to use I/O space, the hotplug
2116 2116 * will still fail later during driver attach.
2117 2117 */
2118 2118 if (ndi_ra_alloc(ddi_get_parent(dip), &request,
2119 2119 &answer, &alen, NDI_RA_TYPE_IO, NDI_RA_PASS)
2120 2120 != NDI_SUCCESS) {
2121 2121 DEBUG0("Failed to allocate I/O\n");
2122 2122 continue;
2123 2123 }
2124 2124 DEBUG3("I/O addr = [0x%x.0x%x] len [0x%x]\n",
2125 2125 PCICFG_HIADDR(answer),
2126 2126 PCICFG_LOADDR(answer), alen);
2127 2127 pci_config_put32(handle, offset,
2128 2128 PCICFG_LOADDR(answer));
2129 2129
2130 2130 reg[i].pci_phys_hi |= PCI_REG_REL_M;
2131 2131 reg[i].pci_phys_low = PCICFG_LOADDR(answer);
2132 2132
2133 2133 offset += 4;
2134 2134 break;
2135 2135 default:
2136 2136 DEBUG0("Unknown register type\n");
2137 2137 kmem_free(reg, length);
2138 2138 (void) pcicfg_config_teardown(&handle);
2139 2139 return (PCICFG_FAILURE);
2140 2140 } /* switch */
2141 2141
2142 2142 /*
2143 2143 * Now that memory locations are assigned,
2144 2144 * update the assigned address property.
2145 2145 */
2146 2146
2147 2147 if (pcicfg_update_assigned_prop(dip, ®[i])
2148 2148 != PCICFG_SUCCESS) {
2149 2149 kmem_free(reg, length);
2150 2150 (void) pcicfg_config_teardown(&handle);
2151 2151 return (PCICFG_FAILURE);
2152 2152 }
2153 2153 }
2154 2154 }
2155 2155
2156 2156 (void) pcicfg_device_on(handle);
2157 2157 kmem_free(reg, length);
2158 2158
2159 2159 PCICFG_DUMP_DEVICE_CONFIG(handle);
2160 2160
2161 2161 (void) pcicfg_config_teardown(&handle);
2162 2162 return (PCICFG_SUCCESS);
2163 2163 }
2164 2164
2165 2165 static int
2166 2166 pcicfg_device_assign_readonly(dev_info_t *dip)
2167 2167 {
2168 2168 ddi_acc_handle_t handle;
2169 2169 pci_regspec_t *assigned;
2170 2170 int length;
2171 2171 int acount;
2172 2172 int i;
2173 2173 ndi_ra_request_t request;
2174 2174 uint64_t answer;
2175 2175 uint64_t alen;
2176 2176
2177 2177 DEBUG1("%llx now under configuration\n", dip);
2178 2178
2179 2179 /*
2180 2180 * we don't support ntbridges for readonly probe.
2181 2181 */
2182 2182 if (pcicfg_ntbridge_child(dip) == DDI_SUCCESS) {
2183 2183 return (PCICFG_FAILURE);
2184 2184 }
2185 2185
2186 2186 if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
2187 2187 DDI_PROP_DONTPASS, "assigned-addresses", (caddr_t)&assigned,
2188 2188 &length) != DDI_PROP_SUCCESS) {
2189 2189 DEBUG0("Failed to read assigned-addresses property\n");
2190 2190 return (PCICFG_FAILURE);
2191 2191 }
2192 2192
2193 2193 if (pcicfg_config_setup(dip, &handle) != DDI_SUCCESS) {
2194 2194 DEBUG0("Failed to map config space!\n");
2195 2195 kmem_free(assigned, length);
2196 2196 return (PCICFG_FAILURE);
2197 2197 }
2198 2198
2199 2199 /*
2200 2200 * If there is an interrupt pin set program
2201 2201 * interrupt line with default values.
2202 2202 */
2203 2203 if (pci_config_get8(handle, PCI_CONF_IPIN)) {
2204 2204 pci_config_put8(handle, PCI_CONF_ILINE, 0xf);
2205 2205 }
2206 2206 /*
2207 2207 * Note: Both non-prefetchable and prefetchable memory space
2208 2208 * allocations are made within 32bit space. Currently, BIOSs
2209 2209 * allocate device memory for PCI devices within the 32bit space
2210 2210 * so this will not be a problem.
2211 2211 */
2212 2212 bzero((caddr_t)&request, sizeof (ndi_ra_request_t));
2213 2213
2214 2214 request.ra_flags = NDI_RA_ALLOC_SPECIFIED; /* specified addr */
2215 2215 request.ra_boundbase = 0;
2216 2216 request.ra_boundlen = PCICFG_4GIG_LIMIT;
2217 2217
2218 2218 acount = length / sizeof (pci_regspec_t);
2219 2219 for (i = 0; i < acount; i++) {
2220 2220 char *mem_type;
2221 2221
2222 2222 if ((assigned[i].pci_size_low != 0)||
2223 2223 (assigned[i].pci_size_hi != 0)) {
2224 2224
2225 2225 request.ra_len = assigned[i].pci_size_low;
2226 2226
2227 2227 switch (PCI_REG_ADDR_G(assigned[i].pci_phys_hi)) {
2228 2228 case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
2229 2229 request.ra_addr = (uint64_t)PCICFG_LADDR(
2230 2230 assigned[i].pci_phys_low,
2231 2231 assigned[i].pci_phys_mid);
2232 2232
2233 2233 if (assigned[i].pci_phys_hi & PCI_REG_PF_M) {
2234 2234 mem_type = NDI_RA_TYPE_PCI_PREFETCH_MEM;
2235 2235 } else {
2236 2236 mem_type = NDI_RA_TYPE_MEM;
2237 2237 }
2238 2238 /* allocate memory space from the allocator */
2239 2239 if (ndi_ra_alloc(ddi_get_parent(dip), &request,
2240 2240 &answer, &alen, mem_type, NDI_RA_PASS)
2241 2241 != NDI_SUCCESS) {
2242 2242 DEBUG0("Failed to allocate 64b mem\n");
2243 2243 kmem_free(assigned, length);
2244 2244 return (PCICFG_NORESRC);
2245 2245 }
2246 2246
2247 2247 break;
2248 2248 case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
2249 2249 request.ra_addr = (uint64_t)
2250 2250 assigned[i].pci_phys_low;
2251 2251
2252 2252 if (assigned[i].pci_phys_hi & PCI_REG_PF_M)
2253 2253 mem_type = NDI_RA_TYPE_PCI_PREFETCH_MEM;
2254 2254 else
2255 2255 mem_type = NDI_RA_TYPE_MEM;
2256 2256 /* allocate memory space from the allocator */
2257 2257 if (ndi_ra_alloc(ddi_get_parent(dip), &request,
2258 2258 &answer, &alen, mem_type, NDI_RA_PASS)
2259 2259 != NDI_SUCCESS) {
2260 2260 DEBUG0("Failed to allocate 32b mem\n");
2261 2261 kmem_free(assigned, length);
2262 2262 return (PCICFG_NORESRC);
2263 2263 }
2264 2264
2265 2265 break;
2266 2266 case PCI_REG_ADDR_G(PCI_ADDR_IO):
2267 2267 request.ra_addr = (uint64_t)
2268 2268 assigned[i].pci_phys_low;
2269 2269
2270 2270 /* allocate I/O space from the allocator */
2271 2271 if (ndi_ra_alloc(ddi_get_parent(dip), &request,
2272 2272 &answer, &alen, NDI_RA_TYPE_IO, NDI_RA_PASS)
2273 2273 != NDI_SUCCESS) {
2274 2274 DEBUG0("Failed to allocate I/O\n");
2275 2275 kmem_free(assigned, length);
2276 2276 return (PCICFG_NORESRC);
2277 2277 }
2278 2278
2279 2279 break;
2280 2280 default:
2281 2281 DEBUG0("Unknown register type\n");
2282 2282 kmem_free(assigned, length);
2283 2283 return (PCICFG_FAILURE);
2284 2284 } /* switch */
2285 2285 }
2286 2286 }
2287 2287
2288 2288 (void) pcicfg_device_on(handle);
2289 2289 kmem_free(assigned, length);
2290 2290
2291 2291 PCICFG_DUMP_DEVICE_CONFIG(handle);
2292 2292
2293 2293 (void) pcicfg_config_teardown(&handle);
2294 2294 return (PCICFG_SUCCESS);
2295 2295 }
2296 2296
2297 2297 #ifdef DEBUG
2298 2298 /*
2299 2299 * This function is useful in debug mode, where we can measure how
2300 2300 * much memory was wasted/unallocated in bridge device's domain.
2301 2301 */
2302 2302 static uint64_t
2303 2303 pcicfg_unused_space(hole_t *hole, uint32_t *hole_count)
2304 2304 {
2305 2305 uint64_t len = 0;
2306 2306 uint32_t count = 0;
2307 2307
2308 2308 do {
2309 2309 len += hole->len;
2310 2310 hole = hole->next;
2311 2311 count++;
2312 2312 } while (hole);
2313 2313 *hole_count = count;
2314 2314 return (len);
2315 2315 }
2316 2316 #endif
2317 2317
2318 2318 /*
2319 2319 * This function frees data structures that hold the hole information
2320 2320 * which are allocated in pcicfg_alloc_hole(). This is not freeing
2321 2321 * any memory allocated through NDI calls.
2322 2322 */
2323 2323 static void
2324 2324 pcicfg_free_hole(hole_t *addr_hole)
2325 2325 {
2326 2326 hole_t *nhole, *hole = addr_hole->next;
2327 2327
2328 2328 while (hole) {
2329 2329 nhole = hole->next;
2330 2330 kmem_free(hole, sizeof (hole_t));
2331 2331 hole = nhole;
2332 2332 }
2333 2333 }
2334 2334
2335 2335 static uint64_t
2336 2336 pcicfg_alloc_hole(hole_t *addr_hole, uint64_t *alast, uint32_t length)
2337 2337 {
2338 2338 uint64_t actual_hole_start, ostart, olen;
2339 2339 hole_t *hole = addr_hole, *thole, *nhole;
2340 2340
2341 2341 do {
2342 2342 actual_hole_start = PCICFG_ROUND_UP(hole->start, length);
2343 2343 if (((actual_hole_start - hole->start) + length) <= hole->len) {
2344 2344 DEBUG3("hole found. start %llx, len %llx, req=0x%x\n",
2345 2345 hole->start, hole->len, length);
2346 2346 ostart = hole->start;
2347 2347 olen = hole->len;
2348 2348 /* current hole parameters adjust */
2349 2349 if ((actual_hole_start - hole->start) == 0) {
2350 2350 hole->start += length;
2351 2351 hole->len -= length;
2352 2352 if (hole->start > *alast)
2353 2353 *alast = hole->start;
2354 2354 } else {
2355 2355 hole->len = actual_hole_start - hole->start;
2356 2356 nhole = (hole_t *)kmem_zalloc(sizeof (hole_t),
2357 2357 KM_SLEEP);
2358 2358 nhole->start = actual_hole_start + length;
2359 2359 nhole->len = (ostart + olen) - nhole->start;
2360 2360 nhole->next = NULL;
2361 2361 thole = hole->next;
2362 2362 hole->next = nhole;
2363 2363 nhole->next = thole;
2364 2364 if (nhole->start > *alast)
2365 2365 *alast = nhole->start;
2366 2366 DEBUG2("put new hole to %llx, %llx\n",
2367 2367 nhole->start, nhole->len);
2368 2368 }
2369 2369 DEBUG2("adjust current hole to %llx, %llx\n",
2370 2370 hole->start, hole->len);
2371 2371 break;
2372 2372 }
2373 2373 actual_hole_start = 0;
2374 2374 hole = hole->next;
2375 2375 } while (hole);
2376 2376
2377 2377 DEBUG1("return hole at %llx\n", actual_hole_start);
2378 2378 return (actual_hole_start);
2379 2379 }
2380 2380
2381 2381 static void
2382 2382 pcicfg_get_mem(pcicfg_phdl_t *entry, uint32_t length, uint64_t *ans)
2383 2383 {
2384 2384 uint64_t new_mem;
2385 2385
2386 2386 /* See if there is a hole, that can hold this request. */
2387 2387 new_mem = pcicfg_alloc_hole(&entry->mem_hole, &entry->memory_last,
2388 2388 length);
2389 2389 if (new_mem) { /* if non-zero, found a hole. */
2390 2390 if (ans != NULL)
2391 2391 *ans = new_mem;
2392 2392 } else
2393 2393 cmn_err(CE_WARN, "No %u bytes memory window for %s\n",
2394 2394 length, ddi_get_name(entry->dip));
2395 2395 }
2396 2396
2397 2397 static void
2398 2398 pcicfg_get_io(pcicfg_phdl_t *entry,
2399 2399 uint32_t length, uint32_t *ans)
2400 2400 {
2401 2401 uint32_t new_io;
2402 2402 uint64_t io_last;
2403 2403
2404 2404 /*
2405 2405 * See if there is a hole, that can hold this request.
2406 2406 * Pass 64 bit parameters and then truncate to 32 bit.
2407 2407 */
2408 2408 io_last = entry->io_last;
2409 2409 new_io = (uint32_t)pcicfg_alloc_hole(&entry->io_hole, &io_last, length);
2410 2410 if (new_io) { /* if non-zero, found a hole. */
2411 2411 entry->io_last = (uint32_t)io_last;
2412 2412 if (ans != NULL)
2413 2413 *ans = new_io;
2414 2414 } else
2415 2415 cmn_err(CE_WARN, "No %u bytes IO space window for %s\n",
2416 2416 length, ddi_get_name(entry->dip));
2417 2417 }
2418 2418
2419 2419 static void
2420 2420 pcicfg_get_pf_mem(pcicfg_phdl_t *entry, uint32_t length, uint64_t *ans)
2421 2421 {
2422 2422 uint64_t new_mem;
2423 2423
2424 2424 /* See if there is a hole, that can hold this request. */
2425 2425 new_mem = pcicfg_alloc_hole(&entry->pf_mem_hole, &entry->pf_memory_last,
2426 2426 length);
2427 2427 if (new_mem) { /* if non-zero, found a hole. */
2428 2428 if (ans != NULL)
2429 2429 *ans = new_mem;
2430 2430 } else
2431 2431 cmn_err(CE_WARN, "No %u bytes PF memory window for %s\n",
2432 2432 length, ddi_get_name(entry->dip));
2433 2433 }
2434 2434
2435 2435 static int
2436 2436 pcicfg_sum_resources(dev_info_t *dip, void *hdl)
2437 2437 {
2438 2438 pcicfg_phdl_t *entry = (pcicfg_phdl_t *)hdl;
2439 2439 pci_regspec_t *pci_rp;
2440 2440 int length;
2441 2441 int rcount;
2442 2442 int i;
2443 2443 ndi_ra_request_t *pf_mem_request;
2444 2444 ndi_ra_request_t *mem_request;
2445 2445 ndi_ra_request_t *io_request;
2446 2446 uint8_t header_type;
2447 2447 ddi_acc_handle_t handle;
2448 2448
2449 2449 entry->error = PCICFG_SUCCESS;
2450 2450
2451 2451 pf_mem_request = &entry->pf_mem_req;
2452 2452 mem_request = &entry->mem_req;
2453 2453 io_request = &entry->io_req;
2454 2454
2455 2455 if (pcicfg_config_setup(dip, &handle) != DDI_SUCCESS) {
2456 2456 DEBUG0("Failed to map config space!\n");
2457 2457 entry->error = PCICFG_FAILURE;
2458 2458 return (DDI_WALK_TERMINATE);
2459 2459 }
2460 2460
2461 2461 header_type = pci_config_get8(handle, PCI_CONF_HEADER);
2462 2462
2463 2463 /*
2464 2464 * If its a bridge - just record the highest bus seen
2465 2465 */
2466 2466 if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
2467 2467
2468 2468 if (entry->highest_bus < pci_config_get8(handle,
2469 2469 PCI_BCNF_SECBUS)) {
2470 2470 entry->highest_bus =
2471 2471 pci_config_get8(handle, PCI_BCNF_SECBUS);
2472 2472 }
2473 2473 (void) pcicfg_config_teardown(&handle);
2474 2474 entry->error = PCICFG_FAILURE;
2475 2475 return (DDI_WALK_CONTINUE);
2476 2476 } else {
2477 2477 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
2478 2478 "reg", (caddr_t)&pci_rp, &length) != DDI_PROP_SUCCESS) {
2479 2479 /*
2480 2480 * If one node in (the subtree of nodes)
2481 2481 * doesn't have a "reg" property fail the
2482 2482 * allocation.
2483 2483 */
2484 2484 entry->memory_len = 0;
2485 2485 entry->io_len = 0;
2486 2486 entry->pf_memory_len = 0;
2487 2487 entry->error = PCICFG_FAILURE;
2488 2488 (void) pcicfg_config_teardown(&handle);
2489 2489 return (DDI_WALK_TERMINATE);
2490 2490 }
2491 2491 /*
2492 2492 * For each "reg" property with a length, add that to the
2493 2493 * total memory (or I/O) to allocate.
2494 2494 */
2495 2495 rcount = length / sizeof (pci_regspec_t);
2496 2496
2497 2497 for (i = 0; i < rcount; i++) {
2498 2498
2499 2499 switch (PCI_REG_ADDR_G(pci_rp[i].pci_phys_hi)) {
2500 2500
2501 2501 case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
2502 2502 if (pci_rp[i].pci_phys_hi & PCI_REG_PF_M) {
2503 2503 pf_mem_request->ra_len =
2504 2504 pci_rp[i].pci_size_low +
2505 2505 PCICFG_ROUND_UP(
2506 2506 pf_mem_request->ra_len,
2507 2507 pci_rp[i].pci_size_low);
2508 2508 DEBUG1("ADDING 32 --->0x%x\n",
2509 2509 pci_rp[i].pci_size_low);
2510 2510 } else {
2511 2511 mem_request->ra_len =
2512 2512 pci_rp[i].pci_size_low +
2513 2513 PCICFG_ROUND_UP(mem_request->ra_len,
2514 2514 pci_rp[i].pci_size_low);
2515 2515 DEBUG1("ADDING 32 --->0x%x\n",
2516 2516 pci_rp[i].pci_size_low);
2517 2517 }
2518 2518
2519 2519 break;
2520 2520 case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
2521 2521 if (pci_rp[i].pci_phys_hi & PCI_REG_PF_M) {
2522 2522 pf_mem_request->ra_len =
2523 2523 pci_rp[i].pci_size_low +
2524 2524 PCICFG_ROUND_UP(
2525 2525 pf_mem_request->ra_len,
2526 2526 pci_rp[i].pci_size_low);
2527 2527 DEBUG1("ADDING 64 --->0x%x\n",
2528 2528 pci_rp[i].pci_size_low);
2529 2529 } else {
2530 2530 mem_request->ra_len =
2531 2531 pci_rp[i].pci_size_low +
2532 2532 PCICFG_ROUND_UP(mem_request->ra_len,
2533 2533 pci_rp[i].pci_size_low);
2534 2534 DEBUG1("ADDING 64 --->0x%x\n",
2535 2535 pci_rp[i].pci_size_low);
2536 2536 }
2537 2537
2538 2538 break;
2539 2539 case PCI_REG_ADDR_G(PCI_ADDR_IO):
2540 2540 io_request->ra_len =
2541 2541 pci_rp[i].pci_size_low +
2542 2542 PCICFG_ROUND_UP(io_request->ra_len,
2543 2543 pci_rp[i].pci_size_low);
2544 2544 DEBUG1("ADDING I/O --->0x%x\n",
2545 2545 pci_rp[i].pci_size_low);
2546 2546 break;
2547 2547 default:
2548 2548 /* Config space register - not included */
2549 2549 break;
2550 2550 }
2551 2551 }
2552 2552
2553 2553 /*
2554 2554 * free the memory allocated by ddi_getlongprop
2555 2555 */
2556 2556 kmem_free(pci_rp, length);
2557 2557
2558 2558 /*
2559 2559 * continue the walk to the next sibling to sum memory
2560 2560 */
2561 2561
2562 2562 (void) pcicfg_config_teardown(&handle);
2563 2563
2564 2564 return (DDI_WALK_CONTINUE);
2565 2565 }
2566 2566 }
2567 2567
2568 2568 static int
2569 2569 pcicfg_free_bridge_resources(dev_info_t *dip)
2570 2570 {
2571 2571 ppb_ranges_t *ranges;
2572 2572 uint_t *bus;
2573 2573 int k;
2574 2574 int length = 0;
2575 2575 int i;
2576 2576
2577 2577
2578 2578 if ((i = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
2579 2579 "ranges", (caddr_t)&ranges, &length)) != DDI_PROP_SUCCESS) {
2580 2580 DEBUG0("Failed to read ranges property\n");
2581 2581 if (ddi_get_child(dip)) {
2582 2582 cmn_err(CE_WARN, "No ranges property found for %s",
2583 2583 ddi_get_name(dip));
2584 2584 /*
2585 2585 * strictly speaking, we can check for children with
2586 2586 * assigned-addresses but for now it is better to
2587 2587 * be conservative and assume that if there are child
2588 2588 * nodes, then they do consume PCI memory or IO
2589 2589 * resources, Hence return failure.
2590 2590 */
2591 2591 return (PCICFG_FAILURE);
2592 2592 }
2593 2593 length = 0;
2594 2594 }
2595 2595
2596 2596 for (i = 0; i < length / sizeof (ppb_ranges_t); i++) {
2597 2597 char *mem_type;
2598 2598
2599 2599 if (ranges[i].size_low != 0 || ranges[i].size_high != 0) {
2600 2600 switch (ranges[i].parent_high & PCI_REG_ADDR_M) {
2601 2601 case PCI_ADDR_IO:
2602 2602 DEBUG2("Free I/O base/length = "
2603 2603 "[0x%x]/[0x%x]\n", ranges[i].child_low,
2604 2604 ranges[i].size_low);
2605 2605 if (ndi_ra_free(ddi_get_parent(dip),
2606 2606 (uint64_t)ranges[i].child_low,
2607 2607 (uint64_t)ranges[i].size_low,
2608 2608 NDI_RA_TYPE_IO, NDI_RA_PASS)
2609 2609 != NDI_SUCCESS) {
2610 2610 DEBUG0("Trouble freeing "
2611 2611 "PCI i/o space\n");
2612 2612 kmem_free(ranges, length);
2613 2613 return (PCICFG_FAILURE);
2614 2614 }
2615 2615 break;
2616 2616 case PCI_ADDR_MEM32:
2617 2617 case PCI_ADDR_MEM64:
2618 2618 if (ranges[i].parent_high & PCI_REG_PF_M) {
2619 2619 DEBUG3("Free PF Memory base/length = "
2620 2620 "[0x%x.0x%x]/[0x%x]\n",
2621 2621 ranges[i].child_mid,
2622 2622 ranges[i].child_low,
2623 2623 ranges[i].size_low);
2624 2624 mem_type = NDI_RA_TYPE_PCI_PREFETCH_MEM;
2625 2625 } else {
2626 2626 DEBUG3("Free Memory base/length"
2627 2627 " = [0x%x.0x%x]/[0x%x]\n",
2628 2628 ranges[i].child_mid,
2629 2629 ranges[i].child_low,
2630 2630 ranges[i].size_low)
2631 2631 mem_type = NDI_RA_TYPE_MEM;
2632 2632 }
2633 2633 if (ndi_ra_free(ddi_get_parent(dip),
2634 2634 PCICFG_LADDR(ranges[i].child_low,
2635 2635 ranges[i].child_mid),
2636 2636 (uint64_t)ranges[i].size_low,
2637 2637 mem_type, NDI_RA_PASS) != NDI_SUCCESS) {
2638 2638 DEBUG0("Trouble freeing "
2639 2639 "PCI memory space\n");
2640 2640 kmem_free(ranges, length);
2641 2641 return (PCICFG_FAILURE);
2642 2642 }
2643 2643 break;
2644 2644 default:
2645 2645 DEBUG0("Unknown memory space\n");
2646 2646 break;
2647 2647 }
2648 2648 }
2649 2649 }
2650 2650
2651 2651 if (length)
2652 2652 kmem_free(ranges, length);
2653 2653
2654 2654 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
2655 2655 "bus-range", (caddr_t)&bus, &k) != DDI_PROP_SUCCESS) {
2656 2656 DEBUG0("Failed to read bus-range property\n");
2657 2657 return (PCICFG_FAILURE);
2658 2658 }
2659 2659
2660 2660 DEBUG2("Need to free bus [%d] range [%d]\n",
2661 2661 bus[0], bus[1] - bus[0] + 1);
2662 2662
2663 2663 if (ndi_ra_free(ddi_get_parent(dip), (uint64_t)bus[0],
2664 2664 (uint64_t)(bus[1] - bus[0] + 1), NDI_RA_TYPE_PCI_BUSNUM,
2665 2665 NDI_RA_PASS) != NDI_SUCCESS) {
2666 2666 DEBUG0("Failed to free a bus number\n");
2667 2667 kmem_free(bus, k);
2668 2668 return (PCICFG_FAILURE);
2669 2669 }
2670 2670
2671 2671 kmem_free(bus, k);
2672 2672 return (PCICFG_SUCCESS);
2673 2673 }
2674 2674
2675 2675 static int
2676 2676 pcicfg_free_device_resources(dev_info_t *dip)
2677 2677 {
2678 2678 pci_regspec_t *assigned;
2679 2679
2680 2680 int length;
2681 2681 int acount;
2682 2682 int i;
2683 2683
2684 2684 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
2685 2685 "assigned-addresses", (caddr_t)&assigned, &length)
2686 2686 != DDI_PROP_SUCCESS) {
2687 2687 DEBUG0("Failed to read assigned-addresses property\n");
2688 2688 return (PCICFG_FAILURE);
2689 2689 }
2690 2690
2691 2691 /*
2692 2692 * For each "assigned-addresses" property entry with a length,
2693 2693 * call the memory allocation routines to return the
2694 2694 * resource.
2695 2695 */
2696 2696 acount = length / sizeof (pci_regspec_t);
2697 2697 for (i = 0; i < acount; i++) {
2698 2698 char *mem_type;
2699 2699
2700 2700 /*
2701 2701 * Free the resource if the size of it is not zero.
2702 2702 */
2703 2703 if ((assigned[i].pci_size_low != 0)||
2704 2704 (assigned[i].pci_size_hi != 0)) {
2705 2705 switch (PCI_REG_ADDR_G(assigned[i].pci_phys_hi)) {
2706 2706 case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
2707 2707 /*
2708 2708 * Check the assigned address for zero.
2709 2709 * (Workaround for Devconf (x86) bug to
2710 2710 * skip bogus entry for ROM base address
2711 2711 * register. If the assigned address is
2712 2712 * zero then ignore the entry
2713 2713 * (see bugid 4281306)).
2714 2714 */
2715 2715 if (assigned[i].pci_phys_low == 0)
2716 2716 break; /* ignore the entry */
2717 2717
2718 2718 if (assigned[i].pci_phys_hi & PCI_REG_PF_M)
2719 2719 mem_type = NDI_RA_TYPE_PCI_PREFETCH_MEM;
2720 2720 else
2721 2721 mem_type = NDI_RA_TYPE_MEM;
2722 2722
2723 2723 if (ndi_ra_free(ddi_get_parent(dip),
2724 2724 (uint64_t)assigned[i].pci_phys_low,
2725 2725 (uint64_t)assigned[i].pci_size_low,
2726 2726 mem_type, NDI_RA_PASS) != NDI_SUCCESS) {
2727 2727 DEBUG0("Trouble freeing "
2728 2728 "PCI memory space\n");
2729 2729 kmem_free(assigned, length);
2730 2730 return (PCICFG_FAILURE);
2731 2731 }
2732 2732
2733 2733 DEBUG4("Returned 0x%x of 32 bit %s space"
2734 2734 " @ 0x%x from register 0x%x\n",
2735 2735 assigned[i].pci_size_low, mem_type,
2736 2736 assigned[i].pci_phys_low,
2737 2737 PCI_REG_REG_G(assigned[i].pci_phys_hi));
2738 2738
2739 2739 break;
2740 2740 case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
2741 2741 if (assigned[i].pci_phys_hi & PCI_REG_PF_M)
2742 2742 mem_type = NDI_RA_TYPE_PCI_PREFETCH_MEM;
2743 2743 else
2744 2744 mem_type = NDI_RA_TYPE_MEM;
2745 2745
2746 2746 if (ndi_ra_free(ddi_get_parent(dip),
2747 2747 PCICFG_LADDR(assigned[i].pci_phys_low,
2748 2748 assigned[i].pci_phys_mid),
2749 2749 (uint64_t)assigned[i].pci_size_low,
2750 2750 mem_type, NDI_RA_PASS) != NDI_SUCCESS) {
2751 2751 DEBUG0("Trouble freeing "
2752 2752 "PCI memory space\n");
2753 2753 kmem_free(assigned, length);
2754 2754 return (PCICFG_FAILURE);
2755 2755 }
2756 2756
2757 2757 DEBUG5("Returned 0x%x of 64 bit %s space"
2758 2758 " @ 0x%x.0x%x from register 0x%x\n",
2759 2759 assigned[i].pci_size_low,
2760 2760 mem_type, assigned[i].pci_phys_mid,
2761 2761 assigned[i].pci_phys_low,
2762 2762 PCI_REG_REG_G(assigned[i].pci_phys_hi));
2763 2763
2764 2764 break;
2765 2765 case PCI_REG_ADDR_G(PCI_ADDR_IO):
2766 2766 if (ndi_ra_free(ddi_get_parent(dip),
2767 2767 (uint64_t)assigned[i].pci_phys_low,
2768 2768 (uint64_t)assigned[i].pci_size_low,
2769 2769 NDI_RA_TYPE_IO, NDI_RA_PASS) !=
2770 2770 NDI_SUCCESS) {
2771 2771 DEBUG0("Trouble freeing "
2772 2772 "PCI IO space\n");
2773 2773 kmem_free(assigned, length);
2774 2774 return (PCICFG_FAILURE);
2775 2775 }
2776 2776 DEBUG3("Returned 0x%x of IO space @ 0x%x from "
2777 2777 "register 0x%x\n", assigned[i].pci_size_low,
2778 2778 assigned[i].pci_phys_low,
2779 2779 PCI_REG_REG_G(assigned[i].pci_phys_hi));
2780 2780 break;
2781 2781 default:
2782 2782 DEBUG0("Unknown register type\n");
2783 2783 kmem_free(assigned, length);
2784 2784 return (PCICFG_FAILURE);
2785 2785 } /* switch */
2786 2786 }
2787 2787 }
2788 2788 kmem_free(assigned, length);
2789 2789 return (PCICFG_SUCCESS);
2790 2790 }
2791 2791
2792 2792 static int
2793 2793 pcicfg_free_resources(dev_info_t *dip, pcicfg_flags_t flags)
2794 2794 {
2795 2795 ddi_acc_handle_t handle;
2796 2796 uint8_t header_type;
2797 2797
2798 2798 if (pci_config_setup(dip, &handle) != DDI_SUCCESS) {
2799 2799 DEBUG0("Failed to map config space!\n");
2800 2800 return (PCICFG_FAILURE);
2801 2801 }
2802 2802
2803 2803 header_type = pci_config_get8(handle, PCI_CONF_HEADER);
2804 2804
2805 2805 (void) pci_config_teardown(&handle);
2806 2806
2807 2807 /*
2808 2808 * A different algorithm is used for bridges and leaf devices.
2809 2809 */
2810 2810 if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
2811 2811 /*
2812 2812 * We only support readonly probing for leaf devices.
2813 2813 */
2814 2814 if (flags & PCICFG_FLAG_READ_ONLY)
2815 2815 return (PCICFG_FAILURE);
2816 2816
2817 2817 if (pcicfg_free_bridge_resources(dip) != PCICFG_SUCCESS) {
2818 2818 DEBUG0("Failed freeing up bridge resources\n");
2819 2819 return (PCICFG_FAILURE);
2820 2820 }
2821 2821 } else {
2822 2822 if (pcicfg_free_device_resources(dip) != PCICFG_SUCCESS) {
2823 2823 DEBUG0("Failed freeing up device resources\n");
2824 2824 return (PCICFG_FAILURE);
2825 2825 }
2826 2826 }
2827 2827
2828 2828 return (PCICFG_SUCCESS);
2829 2829 }
2830 2830
2831 2831 #ifndef _DONT_USE_1275_GENERIC_NAMES
2832 2832 static char *
2833 2833 pcicfg_get_class_name(uint32_t classcode)
2834 2834 {
2835 2835 struct pcicfg_name_entry *ptr;
2836 2836
2837 2837 for (ptr = &pcicfg_class_lookup[0]; ptr->name != NULL; ptr++) {
2838 2838 if (ptr->class_code == classcode) {
2839 2839 return (ptr->name);
2840 2840 }
2841 2841 }
2842 2842 return (NULL);
2843 2843 }
2844 2844 #endif /* _DONT_USE_1275_GENERIC_NAMES */
2845 2845
2846 2846 static dev_info_t *
2847 2847 pcicfg_devi_find(dev_info_t *dip, uint_t device, uint_t function)
2848 2848 {
2849 2849 struct pcicfg_find_ctrl ctrl;
2850 2850 int count;
2851 2851
2852 2852 ctrl.device = device;
2853 2853 ctrl.function = function;
2854 2854 ctrl.dip = NULL;
2855 2855
2856 2856 ndi_devi_enter(dip, &count);
2857 2857 ddi_walk_devs(ddi_get_child(dip), pcicfg_match_dev, (void *)&ctrl);
2858 2858 ndi_devi_exit(dip, count);
2859 2859
2860 2860 return (ctrl.dip);
2861 2861 }
2862 2862
2863 2863 static int
2864 2864 pcicfg_match_dev(dev_info_t *dip, void *hdl)
2865 2865 {
2866 2866 struct pcicfg_find_ctrl *ctrl = (struct pcicfg_find_ctrl *)hdl;
2867 2867 pci_regspec_t *pci_rp;
2868 2868 int length;
2869 2869 int pci_dev;
2870 2870 int pci_func;
2871 2871
2872 2872 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
2873 2873 "reg", (int **)&pci_rp, (uint_t *)&length) != DDI_PROP_SUCCESS) {
2874 2874 ctrl->dip = NULL;
2875 2875 return (DDI_WALK_TERMINATE);
2876 2876 }
2877 2877
2878 2878 /* get the PCI device address info */
2879 2879 pci_dev = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
2880 2880 pci_func = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
2881 2881
2882 2882 /*
2883 2883 * free the memory allocated by ddi_prop_lookup_int_array
2884 2884 */
2885 2885 ddi_prop_free(pci_rp);
2886 2886
2887 2887
2888 2888 if ((pci_dev == ctrl->device) && (pci_func == ctrl->function)) {
2889 2889 /* found the match for the specified device address */
2890 2890 ctrl->dip = dip;
2891 2891 return (DDI_WALK_TERMINATE);
2892 2892 }
2893 2893
2894 2894 /*
2895 2895 * continue the walk to the next sibling to look for a match.
2896 2896 */
2897 2897 return (DDI_WALK_PRUNECHILD);
2898 2898 }
2899 2899
2900 2900 static int
2901 2901 pcicfg_update_assigned_prop(dev_info_t *dip, pci_regspec_t *newone)
2902 2902 {
2903 2903 int alen;
2904 2904 pci_regspec_t *assigned;
2905 2905 caddr_t newreg;
2906 2906 uint_t status;
2907 2907
2908 2908 status = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
2909 2909 "assigned-addresses", (caddr_t)&assigned, &alen);
2910 2910 switch (status) {
2911 2911 case DDI_PROP_SUCCESS:
2912 2912 break;
2913 2913 case DDI_PROP_NO_MEMORY:
2914 2914 DEBUG0("no memory for assigned-addresses property\n");
2915 2915 return (PCICFG_FAILURE);
2916 2916 default:
2917 2917 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
2918 2918 "assigned-addresses", (int *)newone,
2919 2919 sizeof (*newone)/sizeof (int));
2920 2920 return (PCICFG_SUCCESS);
2921 2921 }
2922 2922
2923 2923 /*
2924 2924 * Allocate memory for the existing
2925 2925 * assigned-addresses(s) plus one and then
2926 2926 * build it.
2927 2927 */
2928 2928
2929 2929 newreg = kmem_zalloc(alen+sizeof (*newone), KM_SLEEP);
2930 2930
2931 2931 bcopy(assigned, newreg, alen);
2932 2932 bcopy(newone, newreg + alen, sizeof (*newone));
2933 2933
2934 2934 /*
2935 2935 * Write out the new "assigned-addresses" spec
2936 2936 */
2937 2937 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
2938 2938 "assigned-addresses", (int *)newreg,
2939 2939 (alen + sizeof (*newone))/sizeof (int));
2940 2940
2941 2941 kmem_free((caddr_t)newreg, alen+sizeof (*newone));
2942 2942 kmem_free(assigned, alen);
2943 2943
2944 2944 return (PCICFG_SUCCESS);
2945 2945 }
2946 2946
2947 2947 static int
2948 2948 pcicfg_update_ranges_prop(dev_info_t *dip, ppb_ranges_t *addition)
2949 2949 {
2950 2950 int rlen;
2951 2951 ppb_ranges_t *ranges;
2952 2952 caddr_t newreg;
2953 2953 uint_t status;
2954 2954
2955 2955 status = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
2956 2956 "ranges", (caddr_t)&ranges, &rlen);
2957 2957
2958 2958
2959 2959 switch (status) {
2960 2960 case DDI_PROP_SUCCESS:
2961 2961 break;
2962 2962 case DDI_PROP_NO_MEMORY:
2963 2963 DEBUG0("ranges present, but unable to get memory\n");
2964 2964 return (PCICFG_FAILURE);
2965 2965 default:
2966 2966 DEBUG0("no ranges property - creating one\n");
2967 2967 if (ndi_prop_update_int_array(DDI_DEV_T_NONE,
2968 2968 dip, "ranges", (int *)addition,
2969 2969 sizeof (ppb_ranges_t)/sizeof (int))
2970 2970 != DDI_SUCCESS) {
2971 2971 DEBUG0("Did'nt create ranges property\n");
2972 2972 return (PCICFG_FAILURE);
2973 2973 }
2974 2974 return (PCICFG_SUCCESS);
2975 2975 }
2976 2976
2977 2977 /*
2978 2978 * Allocate memory for the existing ranges plus one and then
2979 2979 * build it.
2980 2980 */
2981 2981 newreg = kmem_zalloc(rlen+sizeof (ppb_ranges_t), KM_SLEEP);
2982 2982
2983 2983 bcopy(ranges, newreg, rlen);
2984 2984 bcopy(addition, newreg + rlen, sizeof (ppb_ranges_t));
2985 2985
2986 2986 /*
2987 2987 * Write out the new "ranges" property
2988 2988 */
2989 2989 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, "ranges",
2990 2990 (int *)newreg, (rlen + sizeof (ppb_ranges_t))/sizeof (int));
2991 2991
2992 2992 DEBUG1("Updating ranges property for %d entries",
2993 2993 rlen / sizeof (ppb_ranges_t) + 1);
2994 2994
2995 2995 kmem_free((caddr_t)newreg, rlen+sizeof (ppb_ranges_t));
2996 2996
2997 2997 kmem_free((caddr_t)ranges, rlen);
2998 2998
2999 2999 return (PCICFG_SUCCESS);
3000 3000 }
3001 3001
3002 3002 static int
3003 3003 pcicfg_update_reg_prop(dev_info_t *dip, uint32_t regvalue, uint_t reg_offset)
3004 3004 {
3005 3005 int rlen;
3006 3006 pci_regspec_t *reg;
3007 3007 caddr_t newreg;
3008 3008 uint32_t hiword;
3009 3009 pci_regspec_t addition;
3010 3010 uint32_t size;
3011 3011 uint_t status;
3012 3012
3013 3013 status = ddi_getlongprop(DDI_DEV_T_ANY,
3014 3014 dip, DDI_PROP_DONTPASS, "reg", (caddr_t)®, &rlen);
3015 3015
3016 3016 switch (status) {
3017 3017 case DDI_PROP_SUCCESS:
3018 3018 break;
3019 3019 case DDI_PROP_NO_MEMORY:
3020 3020 DEBUG0("reg present, but unable to get memory\n");
3021 3021 return (PCICFG_FAILURE);
3022 3022 default:
3023 3023 DEBUG0("no reg property\n");
3024 3024 return (PCICFG_FAILURE);
3025 3025 }
3026 3026
3027 3027 /*
3028 3028 * Allocate memory for the existing reg(s) plus one and then
3029 3029 * build it.
3030 3030 */
3031 3031 newreg = kmem_zalloc(rlen+sizeof (pci_regspec_t), KM_SLEEP);
3032 3032
3033 3033 /*
3034 3034 * Build the regspec, then add it to the existing one(s)
3035 3035 */
3036 3036
3037 3037 hiword = PCICFG_MAKE_REG_HIGH(PCI_REG_BUS_G(reg->pci_phys_hi),
3038 3038 PCI_REG_DEV_G(reg->pci_phys_hi),
3039 3039 PCI_REG_FUNC_G(reg->pci_phys_hi), reg_offset);
3040 3040
3041 3041 if (reg_offset == PCI_CONF_ROM) {
3042 3042 size = (~(PCI_BASE_ROM_ADDR_M & regvalue))+1;
3043 3043 hiword |= PCI_ADDR_MEM32;
3044 3044 } else {
3045 3045 size = (~(PCI_BASE_M_ADDR_M & regvalue))+1;
3046 3046
3047 3047 if ((PCI_BASE_SPACE_M & regvalue) == PCI_BASE_SPACE_MEM) {
3048 3048 if ((PCI_BASE_TYPE_M & regvalue) == PCI_BASE_TYPE_MEM) {
3049 3049 hiword |= PCI_ADDR_MEM32;
3050 3050 } else if ((PCI_BASE_TYPE_M & regvalue)
3051 3051 == PCI_BASE_TYPE_ALL) {
3052 3052 hiword |= PCI_ADDR_MEM64;
3053 3053 }
3054 3054 if (regvalue & PCI_BASE_PREF_M)
3055 3055 hiword |= PCI_REG_PF_M;
3056 3056 } else {
3057 3057 hiword |= PCI_ADDR_IO;
3058 3058 }
3059 3059 }
3060 3060
3061 3061 addition.pci_phys_hi = hiword;
3062 3062 addition.pci_phys_mid = 0;
3063 3063 addition.pci_phys_low = 0;
3064 3064 addition.pci_size_hi = 0;
3065 3065 addition.pci_size_low = size;
3066 3066
3067 3067 bcopy(reg, newreg, rlen);
3068 3068 bcopy(&addition, newreg + rlen, sizeof (pci_regspec_t));
3069 3069
3070 3070 DEBUG3("updating BAR@off %x with %x,%x\n", reg_offset, hiword, size);
3071 3071 /*
3072 3072 * Write out the new "reg" property
3073 3073 */
3074 3074 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, "reg",
3075 3075 (int *)newreg, (rlen + sizeof (pci_regspec_t))/sizeof (int));
3076 3076
3077 3077 kmem_free((caddr_t)newreg, rlen+sizeof (pci_regspec_t));
3078 3078 kmem_free((caddr_t)reg, rlen);
3079 3079
3080 3080 return (PCICFG_SUCCESS);
3081 3081 }
3082 3082
3083 3083 static int
3084 3084 pcicfg_update_assigned_prop_value(dev_info_t *dip, uint32_t size,
3085 3085 uint32_t base, uint32_t base_hi, uint_t reg_offset)
3086 3086 {
3087 3087 int rlen;
3088 3088 pci_regspec_t *reg;
3089 3089 uint32_t hiword;
3090 3090 pci_regspec_t addition;
3091 3091 uint_t status;
3092 3092
3093 3093 status = ddi_getlongprop(DDI_DEV_T_ANY,
3094 3094 dip, DDI_PROP_DONTPASS, "reg", (caddr_t)®, &rlen);
3095 3095
3096 3096 switch (status) {
3097 3097 case DDI_PROP_SUCCESS:
3098 3098 break;
3099 3099 case DDI_PROP_NO_MEMORY:
3100 3100 DEBUG0("reg present, but unable to get memory\n");
3101 3101 return (PCICFG_FAILURE);
3102 3102 default:
3103 3103 /*
3104 3104 * Since the config space "reg" entry should have been
3105 3105 * created, we expect a "reg" property already
3106 3106 * present here.
3107 3107 */
3108 3108 DEBUG0("no reg property\n");
3109 3109 return (PCICFG_FAILURE);
3110 3110 }
3111 3111
3112 3112 /*
3113 3113 * Build the regspec, then add it to the existing one(s)
3114 3114 */
3115 3115
3116 3116 hiword = PCICFG_MAKE_REG_HIGH(PCI_REG_BUS_G(reg->pci_phys_hi),
3117 3117 PCI_REG_DEV_G(reg->pci_phys_hi),
3118 3118 PCI_REG_FUNC_G(reg->pci_phys_hi), reg_offset);
3119 3119
3120 3120 hiword |= PCI_REG_REL_M;
3121 3121
3122 3122 if (reg_offset == PCI_CONF_ROM) {
3123 3123 hiword |= PCI_ADDR_MEM32;
3124 3124
3125 3125 base = PCI_BASE_ROM_ADDR_M & base;
3126 3126 } else {
3127 3127 if ((PCI_BASE_SPACE_M & base) == PCI_BASE_SPACE_MEM) {
3128 3128 if ((PCI_BASE_TYPE_M & base) == PCI_BASE_TYPE_MEM) {
3129 3129 hiword |= PCI_ADDR_MEM32;
3130 3130 } else if ((PCI_BASE_TYPE_M & base)
3131 3131 == PCI_BASE_TYPE_ALL) {
3132 3132 hiword |= PCI_ADDR_MEM64;
3133 3133 }
3134 3134 if (base & PCI_BASE_PREF_M)
3135 3135 hiword |= PCI_REG_PF_M;
3136 3136
3137 3137 base = PCI_BASE_M_ADDR_M & base;
3138 3138 } else {
3139 3139 hiword |= PCI_ADDR_IO;
3140 3140
3141 3141 base = PCI_BASE_IO_ADDR_M & base;
3142 3142 base_hi = 0;
3143 3143 }
3144 3144 }
3145 3145
3146 3146 addition.pci_phys_hi = hiword;
3147 3147 addition.pci_phys_mid = base_hi;
3148 3148 addition.pci_phys_low = base;
3149 3149 addition.pci_size_hi = 0;
3150 3150 addition.pci_size_low = size;
3151 3151
3152 3152 DEBUG3("updating BAR@off %x with %x,%x\n", reg_offset, hiword, size);
3153 3153
3154 3154 kmem_free((caddr_t)reg, rlen);
3155 3155
3156 3156 return (pcicfg_update_assigned_prop(dip, &addition));
3157 3157 }
3158 3158
3159 3159 static void
3160 3160 pcicfg_device_on(ddi_acc_handle_t config_handle)
3161 3161 {
3162 3162 /*
3163 3163 * Enable memory, IO, and bus mastership
3164 3164 * XXX should we enable parity, SERR#,
3165 3165 * fast back-to-back, and addr. stepping?
3166 3166 */
3167 3167 pci_config_put16(config_handle, PCI_CONF_COMM,
3168 3168 pci_config_get16(config_handle, PCI_CONF_COMM) | 0x7);
3169 3169 }
3170 3170
3171 3171 static void
3172 3172 pcicfg_device_off(ddi_acc_handle_t config_handle)
3173 3173 {
3174 3174 /*
3175 3175 * Disable I/O and memory traffic through the bridge
3176 3176 */
3177 3177 pci_config_put16(config_handle, PCI_CONF_COMM, 0x0);
3178 3178 }
3179 3179
3180 3180 /*
3181 3181 * Setup the basic 1275 properties based on information found in the config
3182 3182 * header of the PCI device
3183 3183 */
3184 3184 static int
3185 3185 pcicfg_set_standard_props(dev_info_t *dip, ddi_acc_handle_t config_handle,
3186 3186 uint8_t pcie_dev)
3187 3187 {
3188 3188 int ret;
3189 3189 uint16_t cap_id_loc, val;
3190 3190 uint32_t wordval;
3191 3191 uint8_t byteval;
3192 3192
3193 3193 /* These two exists only for non-bridges */
3194 3194 if (((pci_config_get8(config_handle, PCI_CONF_HEADER) &
3195 3195 PCI_HEADER_TYPE_M) == PCI_HEADER_ZERO) && !pcie_dev) {
3196 3196 byteval = pci_config_get8(config_handle, PCI_CONF_MIN_G);
3197 3197 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3198 3198 "min-grant", byteval)) != DDI_SUCCESS) {
3199 3199 return (ret);
3200 3200 }
3201 3201
3202 3202 byteval = pci_config_get8(config_handle, PCI_CONF_MAX_L);
3203 3203 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3204 3204 "max-latency", byteval)) != DDI_SUCCESS) {
3205 3205 return (ret);
3206 3206 }
3207 3207 }
3208 3208
3209 3209 /*
3210 3210 * These should always exist and have the value of the
3211 3211 * corresponding register value
3212 3212 */
3213 3213 val = pci_config_get16(config_handle, PCI_CONF_VENID);
3214 3214
3215 3215 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip, "vendor-id", val))
3216 3216 != DDI_SUCCESS) {
3217 3217 return (ret);
3218 3218 }
3219 3219 val = pci_config_get16(config_handle, PCI_CONF_DEVID);
3220 3220 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip, "device-id", val))
3221 3221 != DDI_SUCCESS) {
3222 3222 return (ret);
3223 3223 }
3224 3224 byteval = pci_config_get8(config_handle, PCI_CONF_REVID);
3225 3225 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3226 3226 "revision-id", byteval)) != DDI_SUCCESS) {
3227 3227 return (ret);
3228 3228 }
3229 3229
3230 3230 wordval = (pci_config_get16(config_handle, PCI_CONF_SUBCLASS)<< 8) |
3231 3231 (pci_config_get8(config_handle, PCI_CONF_PROGCLASS));
3232 3232
3233 3233 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3234 3234 "class-code", wordval)) != DDI_SUCCESS) {
3235 3235 return (ret);
3236 3236 }
3237 3237 val = (pci_config_get16(config_handle, PCI_CONF_STAT) &
3238 3238 PCI_STAT_DEVSELT);
3239 3239 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3240 3240 "devsel-speed", val)) != DDI_SUCCESS) {
3241 3241 return (ret);
3242 3242 }
3243 3243
3244 3244 /*
3245 3245 * The next three are bits set in the status register. The property is
3246 3246 * present (but with no value other than its own existence) if the bit
3247 3247 * is set, non-existent otherwise
3248 3248 */
3249 3249 if ((!pcie_dev) &&
3250 3250 (pci_config_get16(config_handle, PCI_CONF_STAT) & PCI_STAT_FBBC)) {
3251 3251 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3252 3252 "fast-back-to-back", 0)) != DDI_SUCCESS) {
3253 3253 return (ret);
3254 3254 }
3255 3255 }
3256 3256 if ((!pcie_dev) &&
3257 3257 (pci_config_get16(config_handle, PCI_CONF_STAT) & PCI_STAT_66MHZ)) {
3258 3258 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3259 3259 "66mhz-capable", 0)) != DDI_SUCCESS) {
3260 3260 return (ret);
3261 3261 }
3262 3262 }
3263 3263 if (pci_config_get16(config_handle, PCI_CONF_STAT) & PCI_STAT_UDF) {
3264 3264 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3265 3265 "udf-supported", 0)) != DDI_SUCCESS) {
3266 3266 return (ret);
3267 3267 }
3268 3268 }
3269 3269
3270 3270 /*
3271 3271 * These next three are optional and are not present
3272 3272 * if the corresponding register is zero. If the value
3273 3273 * is non-zero then the property exists with the value
3274 3274 * of the register.
3275 3275 */
3276 3276 if ((val = pci_config_get16(config_handle, PCI_CONF_SUBVENID)) != 0) {
3277 3277 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3278 3278 "subsystem-vendor-id", val)) != DDI_SUCCESS) {
3279 3279 return (ret);
3280 3280 }
3281 3281 }
3282 3282 if ((val = pci_config_get16(config_handle, PCI_CONF_SUBSYSID)) != 0) {
3283 3283 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3284 3284 "subsystem-id", val)) != DDI_SUCCESS) {
3285 3285 return (ret);
3286 3286 }
3287 3287 }
3288 3288 if ((val = pci_config_get16(config_handle, PCI_CONF_CACHE_LINESZ))
3289 3289 != 0) {
3290 3290 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3291 3291 "cache-line-size", val)) != DDI_SUCCESS) {
3292 3292 return (ret);
3293 3293 }
3294 3294 }
3295 3295
3296 3296 /*
3297 3297 * If the Interrupt Pin register is non-zero then the
3298 3298 * interrupts property exists
3299 3299 */
3300 3300 if ((byteval = pci_config_get8(config_handle, PCI_CONF_IPIN)) != 0) {
3301 3301 /*
3302 3302 * If interrupt pin is non-zero,
3303 3303 * record the interrupt line used
3304 3304 */
3305 3305 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3306 3306 "interrupts", byteval)) != DDI_SUCCESS) {
3307 3307 return (ret);
3308 3308 }
3309 3309 }
3310 3310 (void) PCI_CAP_LOCATE(config_handle, PCI_CAP_ID_PCI_E, &cap_id_loc);
3311 3311 if (pcie_dev && cap_id_loc != PCI_CAP_NEXT_PTR_NULL) {
3312 3312 val = pci_config_get16(config_handle, cap_id_loc + PCIE_PCIECAP)
3313 3313 & PCIE_PCIECAP_SLOT_IMPL;
3314 3314 /* if slot implemented, get physical slot number */
3315 3315 if (val) {
3316 3316 wordval = pci_config_get32(config_handle, cap_id_loc +
3317 3317 PCIE_SLOTCAP);
3318 3318 /* create the property only if slotnum set correctly? */
3319 3319 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3320 3320 "physical-slot#", PCIE_SLOTCAP_PHY_SLOT_NUM(
3321 3321 wordval))) != DDI_SUCCESS) {
3322 3322 return (ret);
3323 3323 }
3324 3324 }
3325 3325 }
3326 3326
3327 3327 return (PCICFG_SUCCESS);
3328 3328 }
3329 3329
3330 3330 static int
3331 3331 pcicfg_set_busnode_props(dev_info_t *dip, uint8_t pcie_device_type)
3332 3332 {
3333 3333 int ret;
3334 3334 char device_type[8];
3335 3335
3336 3336 if (pcie_device_type)
3337 3337 (void) strcpy(device_type, "pciex");
3338 3338 else
3339 3339 (void) strcpy(device_type, "pci");
3340 3340
3341 3341 if ((ret = ndi_prop_update_string(DDI_DEV_T_NONE, dip,
3342 3342 "device_type", device_type)) != DDI_SUCCESS) {
3343 3343 return (ret);
3344 3344 }
3345 3345 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3346 3346 "#address-cells", 3)) != DDI_SUCCESS) {
3347 3347 return (ret);
3348 3348 }
3349 3349 if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip, "#size-cells", 2))
3350 3350 != DDI_SUCCESS) {
3351 3351 return (ret);
3352 3352 }
3353 3353 return (PCICFG_SUCCESS);
3354 3354 }
3355 3355
3356 3356 static int
3357 3357 pcicfg_set_childnode_props(dev_info_t *dip, ddi_acc_handle_t config_handle,
3358 3358 uint8_t pcie_dev)
3359 3359 {
3360 3360
3361 3361 int ret;
3362 3362 char *name;
3363 3363 char buffer[64], pprefix[8], nprefix[8];
3364 3364 uint16_t classcode;
3365 3365 uint8_t revid, pif, pclass, psubclass;
3366 3366 char *compat[24];
3367 3367 int i;
3368 3368 int n;
3369 3369 uint16_t sub_vid, sub_sid, vid, did;
3370 3370 /* set the property prefix based on the device type */
3371 3371 if (pcie_dev) {
3372 3372 (void) sprintf(pprefix, "pciex");
3373 3373 } else
3374 3374 (void) sprintf(pprefix, "pci");
3375 3375
3376 3376 /* set the prefix right for name property */
3377 3377 /* x86 platforms need to go with pci for upgrade purposes */
3378 3378 (void) sprintf(nprefix, "pci");
3379 3379
3380 3380 /*
3381 3381 * NOTE: These are for both a child and PCI-PCI bridge node
3382 3382 */
3383 3383 sub_vid = pci_config_get16(config_handle, PCI_CONF_SUBVENID);
3384 3384 sub_sid = pci_config_get16(config_handle, PCI_CONF_SUBSYSID);
3385 3385 vid = pci_config_get16(config_handle, PCI_CONF_VENID);
3386 3386 did = pci_config_get16(config_handle, PCI_CONF_DEVID);
3387 3387 revid = pci_config_get8(config_handle, PCI_CONF_REVID);
3388 3388 pif = pci_config_get8(config_handle, PCI_CONF_PROGCLASS);
3389 3389 classcode = pci_config_get16(config_handle, PCI_CONF_SUBCLASS);
3390 3390 pclass = pci_config_get8(config_handle, PCI_CONF_BASCLASS);
3391 3391 psubclass = pci_config_get8(config_handle, PCI_CONF_SUBCLASS);
3392 3392
3393 3393 if (!sub_vid)
3394 3394 (void) sprintf(buffer, "%s%x,%x", nprefix, vid, did);
3395 3395 else
3396 3396 (void) sprintf(buffer, "%s%x,%x", nprefix, sub_vid, sub_sid);
3397 3397
3398 3398 /*
3399 3399 * In some environments, trying to use "generic" 1275 names is
3400 3400 * not the convention. In those cases use the name as created
3401 3401 * above. In all the rest of the cases, check to see if there
3402 3402 * is a generic name first.
3403 3403 */
3404 3404 #ifdef _DONT_USE_1275_GENERIC_NAMES
3405 3405 name = buffer;
3406 3406 #else
3407 3407 if ((name = pcicfg_get_class_name(classcode)) == NULL) {
3408 3408 /*
3409 3409 * Set name to the above fabricated name
3410 3410 */
3411 3411 name = buffer;
3412 3412 }
3413 3413 #endif
3414 3414
3415 3415 /*
3416 3416 * The node name field needs to be filled in with the name
3417 3417 */
3418 3418 if (ndi_devi_set_nodename(dip, name, 0) != NDI_SUCCESS) {
3419 3419 DEBUG0("Failed to set nodename for node\n");
3420 3420 return (PCICFG_FAILURE);
3421 3421 }
3422 3422
3423 3423 /*
3424 3424 * Create the compatible property as an array of pointers
3425 3425 * to strings. Start with the buffer created above.
3426 3426 */
3427 3427 n = 0;
3428 3428
3429 3429 /*
3430 3430 * Setup 'compatible' as per the PCI2.1 bindings document.
3431 3431 * pci[ex]VVVV,DDDD.SSSS.ssss.RR
3432 3432 * pci[ex]VVVV,DDDD.SSSS.ssss
3433 3433 * pciSSSS.ssss -> not created for PCIe as per PCIe bindings
3434 3434 * pci[ex]VVVV,DDDD.RR
3435 3435 * pci[ex]VVVV,DDDD
3436 3436 * pci[ex]class,CCSSPP
3437 3437 * pci[ex]class,CCSS
3438 3438 * Add legacy entries for compatibility with legacy devices and OS
3439 3439 * for x86.
3440 3440 * pciVVVV,DDDD.SSSS.ssss.RR
3441 3441 * pciVVVV,DDDD.SSSS.ssss
3442 3442 * pciSSSS.ssss
3443 3443 * pciVVVV,DDDD.RR
3444 3444 * pciVVVV,DDDD
3445 3445 * pciclass,CCSSPP
3446 3446 * pciclass,CCSS
3447 3447 */
3448 3448
3449 3449 do {
3450 3450 if (sub_vid) {
3451 3451 /* pci[ex]VVVV,DDDD.SSSS.ssss.RR */
3452 3452 (void) sprintf(buffer, "%s%x,%x.%x.%x.%x", pprefix, vid,
3453 3453 did, sub_vid, sub_sid, revid);
3454 3454 compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3455 3455 (void) strcpy(compat[n++], buffer);
3456 3456
3457 3457 /* pci[ex]VVVV,DDDD.SSSS.ssss */
3458 3458 (void) sprintf(buffer, "%s%x,%x.%x.%x", pprefix, vid,
3459 3459 did, sub_vid, sub_sid);
3460 3460 compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3461 3461 (void) strcpy(compat[n++], buffer);
3462 3462
3463 3463 /* pciSSSS.ssss -> not created for PCIe as per PCIe */
3464 3464 /* binding to IEEE 1275 spec. */
3465 3465 if (!pcie_dev && pcicfg_do_legacy_props) {
3466 3466 (void) sprintf(buffer, "pci%x,%x", sub_vid,
3467 3467 sub_sid);
3468 3468 compat[n] = kmem_alloc(strlen(buffer) + 1,
3469 3469 KM_SLEEP);
3470 3470 (void) strcpy(compat[n++], buffer);
3471 3471 }
3472 3472 }
3473 3473
3474 3474 /* pci[ex]VVVV,DDDD.RR */
3475 3475 (void) sprintf(buffer, "%s%x,%x.%x", pprefix, vid, did, revid);
3476 3476 compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3477 3477 (void) strcpy(compat[n++], buffer);
3478 3478
3479 3479 /* pci[ex]VVVV,DDDD */
3480 3480 (void) sprintf(buffer, "%s%x,%x", pprefix, vid, did);
3481 3481 compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3482 3482 (void) strcpy(compat[n++], buffer);
3483 3483
3484 3484 /* pci[ex]class,CCSSPP */
3485 3485 (void) sprintf(buffer, "%sclass,%02x%02x%02x", pprefix, pclass,
3486 3486 psubclass, pif);
3487 3487 compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3488 3488 (void) strcpy(compat[n++], buffer);
3489 3489
3490 3490 /* pci[ex]class,CCSS */
3491 3491 (void) sprintf(buffer, "%sclass,%04x", pprefix, classcode);
3492 3492 compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
3493 3493 (void) strcpy(compat[n++], buffer);
3494 3494
3495 3495 if (!pcie_dev)
3496 3496 break;
3497 3497
3498 3498 /* also add compatible names using "pci" prefix */
3499 3499 (void) sprintf(pprefix, "pci");
3500 3500 pcie_dev = 0;
3501 3501
3502 3502 } while (pcicfg_do_legacy_props);
3503 3503
3504 3504 ret = ndi_prop_update_string_array(DDI_DEV_T_NONE, dip, "compatible",
3505 3505 (char **)compat, n);
3506 3506
3507 3507 for (i = 0; i < n; i++) {
3508 3508 kmem_free(compat[i], strlen(compat[i]) + 1);
3509 3509 }
3510 3510
3511 3511 return (ret);
3512 3512 }
3513 3513
3514 3514 /*
3515 3515 * Program the bus numbers into the bridge
3516 3516 */
3517 3517 static void
3518 3518 pcicfg_set_bus_numbers(ddi_acc_handle_t config_handle,
3519 3519 uint_t primary, uint_t secondary, uint_t subordinate)
3520 3520 {
3521 3521 DEBUG3("Setting bridge bus-range %d,%d,%d\n", primary, secondary,
3522 3522 subordinate);
3523 3523 /*
3524 3524 * Primary bus#
3525 3525 */
3526 3526 pci_config_put8(config_handle, PCI_BCNF_PRIBUS, primary);
3527 3527
3528 3528 /*
3529 3529 * Secondary bus#
3530 3530 */
3531 3531 pci_config_put8(config_handle, PCI_BCNF_SECBUS, secondary);
3532 3532
3533 3533 /*
3534 3534 * Set the subordinate bus number to ff in order to pass through any
3535 3535 * type 1 cycle with a bus number higher than the secondary bus#
3536 3536 */
3537 3537 pci_config_put8(config_handle, PCI_BCNF_SUBBUS, subordinate);
3538 3538 }
3539 3539
3540 3540 /*
3541 3541 * Put bridge registers into initial state
3542 3542 */
3543 3543 static void
3544 3544 pcicfg_setup_bridge(pcicfg_phdl_t *entry,
3545 3545 ddi_acc_handle_t handle)
3546 3546 {
3547 3547 /*
3548 3548 * The highest bus seen during probing is the max-subordinate bus
3549 3549 */
3550 3550 pci_config_put8(handle, PCI_BCNF_SUBBUS, entry->highest_bus);
3551 3551
3552 3552 /*
3553 3553 * Reset the secondary bus
3554 3554 */
3555 3555 pci_config_put16(handle, PCI_BCNF_BCNTRL,
3556 3556 pci_config_get16(handle, PCI_BCNF_BCNTRL) | 0x40);
3557 3557 drv_usecwait(1000);
3558 3558 pci_config_put16(handle, PCI_BCNF_BCNTRL,
3559 3559 pci_config_get16(handle, PCI_BCNF_BCNTRL) & ~0x40);
3560 3560 drv_usecwait(1000);
3561 3561
3562 3562 /*
3563 3563 * Program the memory base register with the
3564 3564 * start of the memory range
3565 3565 */
3566 3566 pci_config_put16(handle, PCI_BCNF_MEM_BASE,
3567 3567 PCICFG_HIWORD(PCICFG_LOADDR(entry->memory_last)));
3568 3568
3569 3569 /*
3570 3570 * Program the I/O base register with the start of the I/O range
3571 3571 */
3572 3572 pci_config_put8(handle, PCI_BCNF_IO_BASE_LOW,
3573 3573 PCICFG_HIBYTE(PCICFG_LOWORD(PCICFG_LOADDR(entry->io_last))));
3574 3574 pci_config_put16(handle, PCI_BCNF_IO_BASE_HI,
3575 3575 PCICFG_HIWORD(PCICFG_LOADDR(entry->io_last)));
3576 3576
3577 3577 /*
3578 3578 * Program the PF memory base register with the start of
3579 3579 * PF memory range
3580 3580 */
3581 3581 pci_config_put16(handle, PCI_BCNF_PF_BASE_LOW,
3582 3582 PCICFG_HIWORD(PCICFG_LOADDR(entry->pf_memory_last)));
3583 3583 pci_config_put32(handle, PCI_BCNF_PF_BASE_HIGH,
3584 3584 PCICFG_HIADDR(entry->pf_memory_last));
3585 3585
3586 3586 /*
3587 3587 * Clear status bits
3588 3588 */
3589 3589 pci_config_put16(handle, PCI_BCNF_SEC_STATUS, 0xffff);
3590 3590
3591 3591 /*
3592 3592 * Needs to be set to this value
3593 3593 */
3594 3594 pci_config_put8(handle, PCI_CONF_ILINE, 0xf);
3595 3595
3596 3596 /*
3597 3597 * XXX - may be delay should be used since noone configures
3598 3598 * devices in the interrupt context
3599 3599 */
3600 3600 drv_usecwait(pcicfg_sec_reset_delay); /* 1 sec wait */
3601 3601 }
3602 3602
3603 3603 static void
3604 3604 pcicfg_update_bridge(pcicfg_phdl_t *entry,
3605 3605 ddi_acc_handle_t handle)
3606 3606 {
3607 3607 uint_t length;
3608 3608
3609 3609 /*
3610 3610 * Program the memory limit register with the end of the memory range
3611 3611 */
3612 3612
3613 3613 DEBUG1("DOWN ROUNDED ===>[0x%x]\n",
3614 3614 PCICFG_ROUND_DOWN(entry->memory_last, PCICFG_MEMGRAN));
3615 3615
3616 3616 pci_config_put16(handle, PCI_BCNF_MEM_LIMIT,
3617 3617 PCICFG_HIWORD(PCICFG_LOADDR(
3618 3618 PCICFG_ROUND_DOWN(entry->memory_last, PCICFG_MEMGRAN))));
3619 3619 /*
3620 3620 * Since this is a bridge, the rest of this range will
3621 3621 * be responded to by the bridge. We have to round up
3622 3622 * so no other device claims it.
3623 3623 */
3624 3624 if ((length = (PCICFG_ROUND_UP(entry->memory_last, PCICFG_MEMGRAN)
3625 3625 - entry->memory_last)) > 0) {
3626 3626 (void) pcicfg_get_mem(entry, length, NULL);
3627 3627 DEBUG1("Added [0x%x]at the top of the bridge (mem)\n", length);
3628 3628 }
3629 3629
3630 3630 /*
3631 3631 * Program the PF memory limit register with the end of the memory range
3632 3632 */
3633 3633
3634 3634 DEBUG1("DOWN ROUNDED ===>[0x%x]\n",
3635 3635 PCICFG_ROUND_DOWN(entry->pf_memory_last, PCICFG_MEMGRAN));
3636 3636
3637 3637 pci_config_put16(handle, PCI_BCNF_PF_LIMIT_LOW,
3638 3638 PCICFG_HIWORD(PCICFG_LOADDR(PCICFG_ROUND_DOWN(
3639 3639 entry->pf_memory_last, PCICFG_MEMGRAN))));
3640 3640 pci_config_put32(handle, PCI_BCNF_PF_LIMIT_HIGH, PCICFG_HIADDR(
3641 3641 PCICFG_ROUND_DOWN(entry->pf_memory_last, PCICFG_MEMGRAN)));
3642 3642 if ((length = (PCICFG_ROUND_UP(entry->pf_memory_last, PCICFG_MEMGRAN)
3643 3643 - entry->pf_memory_last)) > 0) {
3644 3644 (void) pcicfg_get_pf_mem(entry, length, NULL);
3645 3645 DEBUG1("Added [0x%x]at the top of the bridge (PF mem)\n",
3646 3646 length);
3647 3647 }
3648 3648
3649 3649 /*
3650 3650 * Program the I/O limit register with the end of the I/O range
3651 3651 */
3652 3652 pci_config_put8(handle, PCI_BCNF_IO_LIMIT_LOW,
3653 3653 PCICFG_HIBYTE(PCICFG_LOWORD(
3654 3654 PCICFG_LOADDR(PCICFG_ROUND_DOWN(entry->io_last, PCICFG_IOGRAN)))));
3655 3655
3656 3656 pci_config_put16(handle, PCI_BCNF_IO_LIMIT_HI, PCICFG_HIWORD(
3657 3657 PCICFG_LOADDR(PCICFG_ROUND_DOWN(entry->io_last, PCICFG_IOGRAN))));
3658 3658
3659 3659 /*
3660 3660 * Same as above for I/O space. Since this is a
3661 3661 * bridge, the rest of this range will be responded
3662 3662 * to by the bridge. We have to round up so no
3663 3663 * other device claims it.
3664 3664 */
3665 3665 if ((length = (PCICFG_ROUND_UP(entry->io_last, PCICFG_IOGRAN)
3666 3666 - entry->io_last)) > 0) {
3667 3667 (void) pcicfg_get_io(entry, length, NULL);
3668 3668 DEBUG1("Added [0x%x]at the top of the bridge (I/O)\n", length);
3669 3669 }
3670 3670 }
3671 3671
3672 3672 static int
3673 3673 pcicfg_probe_children(dev_info_t *parent, uint_t bus, uint_t device,
3674 3674 uint_t func, uint_t *highest_bus, pcicfg_flags_t flags, boolean_t is_pcie)
3675 3675 {
3676 3676 dev_info_t *new_child;
3677 3677 ddi_acc_handle_t config_handle;
3678 3678 uint8_t header_type, pcie_dev = 0;
3679 3679 int ret = PCICFG_FAILURE;
3680 3680
3681 3681 /*
3682 3682 * This node will be put immediately below
3683 3683 * "parent". Allocate a blank device node. It will either
3684 3684 * be filled in or freed up based on further probing.
3685 3685 */
3686 3686
3687 3687 ndi_devi_alloc_sleep(parent, DEVI_PSEUDO_NEXNAME,
3688 3688 (pnode_t)DEVI_SID_NODEID, &new_child);
3689 3689
3690 3690 if (pcicfg_add_config_reg(new_child, bus, device, func)
3691 3691 != DDI_SUCCESS) {
3692 3692 DEBUG0("pcicfg_probe_children():Failed to add candidate REG\n");
3693 3693 goto failedconfig;
3694 3694 }
3695 3695
3696 3696 if ((ret = pcicfg_config_setup(new_child, &config_handle))
3697 3697 != PCICFG_SUCCESS) {
3698 3698 if (ret == PCICFG_NODEVICE) {
3699 3699 (void) ndi_devi_free(new_child);
3700 3700 return (ret);
3701 3701 }
3702 3702 DEBUG0("pcicfg_probe_children():"
3703 3703 "Failed to setup config space\n");
3704 3704 goto failedconfig;
3705 3705 }
3706 3706
3707 3707 if (is_pcie)
3708 3708 (void) pcie_init_bus(new_child, PCI_GETBDF(bus, device, func),
3709 3709 PCIE_BUS_INITIAL);
3710 3710
3711 3711 /*
3712 3712 * As soon as we have access to config space,
3713 3713 * turn off device. It will get turned on
3714 3714 * later (after memory is assigned).
3715 3715 */
3716 3716 (void) pcicfg_device_off(config_handle);
3717 3717
3718 3718 /* check if we are PCIe device */
3719 3719 if (pcicfg_pcie_dev(new_child, config_handle) == DDI_SUCCESS) {
3720 3720 DEBUG0("PCIe device detected\n");
3721 3721 pcie_dev = 1;
3722 3722 }
3723 3723
3724 3724 /*
3725 3725 * Set 1275 properties common to all devices
3726 3726 */
3727 3727 if (pcicfg_set_standard_props(new_child, config_handle, pcie_dev)
3728 3728 != PCICFG_SUCCESS) {
3729 3729 DEBUG0("Failed to set standard properties\n");
3730 3730 goto failedchild;
3731 3731 }
3732 3732
3733 3733 /*
3734 3734 * Child node properties NOTE: Both for PCI-PCI bridge and child node
3735 3735 */
3736 3736 if (pcicfg_set_childnode_props(new_child, config_handle, pcie_dev)
3737 3737 != PCICFG_SUCCESS) {
3738 3738 goto failedchild;
3739 3739 }
3740 3740
3741 3741 header_type = pci_config_get8(config_handle, PCI_CONF_HEADER);
3742 3742
3743 3743 /*
3744 3744 * If this is not a multi-function card only probe function zero.
3745 3745 */
3746 3746 if ((!(header_type & PCI_HEADER_MULTI)) && (func != 0)) {
3747 3747
3748 3748 ret = PCICFG_NODEVICE;
3749 3749 goto failedchild;
3750 3750 }
3751 3751
3752 3752 /*
3753 3753 * Attach the child to its parent
3754 3754 */
3755 3755 (void) i_ndi_config_node(new_child, DS_LINKED, 0);
3756 3756
3757 3757 DEVI_SET_PCI(new_child);
3758 3758
3759 3759 if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
3760 3760
3761 3761 DEBUG3("--Bridge found bus [0x%x] device[0x%x] func [0x%x]\n",
3762 3762 bus, device, func);
3763 3763
3764 3764 /* Only support read-only probe for leaf device */
3765 3765 if (flags & PCICFG_FLAG_READ_ONLY)
3766 3766 goto failedchild;
3767 3767
3768 3768 ret = pcicfg_probe_bridge(new_child, config_handle, bus,
3769 3769 highest_bus, is_pcie);
3770 3770 if (ret != PCICFG_SUCCESS) {
3771 3771 (void) pcicfg_free_bridge_resources(new_child);
3772 3772 goto failedchild;
3773 3773 }
3774 3774
3775 3775 } else {
3776 3776
3777 3777 DEBUG3("--Leaf device found bus [0x%x] device"
3778 3778 "[0x%x] func [0x%x]\n", bus, device, func);
3779 3779
3780 3780 if (flags & PCICFG_FLAG_READ_ONLY) {
3781 3781 /*
3782 3782 * with read-only probe, don't do any resource
3783 3783 * allocation, just read the BARs and update props.
3784 3784 */
3785 3785 ret = pcicfg_populate_props_from_bar(new_child,
3786 3786 config_handle);
3787 3787 if (ret != PCICFG_SUCCESS)
3788 3788 goto failedchild;
3789 3789
3790 3790 /*
3791 3791 * now allocate the resources, just remove the
3792 3792 * resources from the parent busra pool.
3793 3793 */
3794 3794 ret = pcicfg_device_assign_readonly(new_child);
3795 3795 if (ret != PCICFG_SUCCESS) {
3796 3796 (void) pcicfg_free_device_resources(new_child);
3797 3797 goto failedchild;
3798 3798 }
3799 3799
3800 3800 } else {
3801 3801 /*
3802 3802 * update "reg" property by sizing the BARs.
3803 3803 */
3804 3804 ret = pcicfg_populate_reg_props(new_child,
3805 3805 config_handle);
3806 3806 if (ret != PCICFG_SUCCESS)
3807 3807 goto failedchild;
3808 3808
3809 3809 /* now allocate & program the resources */
3810 3810 ret = pcicfg_device_assign(new_child);
3811 3811 if (ret != PCICFG_SUCCESS) {
3812 3812 (void) pcicfg_free_device_resources(new_child);
3813 3813 goto failedchild;
3814 3814 }
3815 3815 }
3816 3816
3817 3817 (void) ndi_devi_bind_driver(new_child, 0);
3818 3818 }
3819 3819
3820 3820 (void) pcicfg_config_teardown(&config_handle);
3821 3821
3822 3822 /*
3823 3823 * Properties have been setted up, so initialize the remaining
3824 3824 * bus_t fields
3825 3825 */
3826 3826 if (is_pcie)
3827 3827 (void) pcie_init_bus(new_child, 0, PCIE_BUS_FINAL);
3828 3828
3829 3829 return (PCICFG_SUCCESS);
3830 3830
3831 3831 failedchild:
3832 3832 /*
3833 3833 * XXX check if it should be taken offline (if online)
3834 3834 */
3835 3835 (void) pcicfg_config_teardown(&config_handle);
3836 3836
3837 3837 if (is_pcie)
3838 3838 pcie_fini_bus(new_child, PCIE_BUS_FINAL);
3839 3839
3840 3840 failedconfig:
3841 3841
3842 3842 (void) ndi_devi_free(new_child);
3843 3843 return (ret);
3844 3844 }
3845 3845
3846 3846 /*
3847 3847 * Sizing the BARs and update "reg" property
3848 3848 */
3849 3849 static int
3850 3850 pcicfg_populate_reg_props(dev_info_t *new_child,
3851 3851 ddi_acc_handle_t config_handle)
3852 3852 {
3853 3853 int i;
3854 3854 uint32_t request;
3855 3855
3856 3856 i = PCI_CONF_BASE0;
3857 3857
3858 3858 while (i <= PCI_CONF_BASE5) {
3859 3859
3860 3860 pci_config_put32(config_handle, i, 0xffffffff);
3861 3861
3862 3862 request = pci_config_get32(config_handle, i);
3863 3863 /*
3864 3864 * If its a zero length, don't do
3865 3865 * any programming.
3866 3866 */
3867 3867 if (request != 0) {
3868 3868 /*
3869 3869 * Add to the "reg" property
3870 3870 */
3871 3871 if (pcicfg_update_reg_prop(new_child,
3872 3872 request, i) != PCICFG_SUCCESS) {
3873 3873 goto failedchild;
3874 3874 }
3875 3875 } else {
3876 3876 DEBUG1("BASE register [0x%x] asks for "
3877 3877 "[0x0]=[0x0](32)\n", i);
3878 3878 i += 4;
3879 3879 continue;
3880 3880 }
3881 3881
3882 3882 /*
3883 3883 * Increment by eight if it is 64 bit address space
3884 3884 */
3885 3885 if ((PCI_BASE_TYPE_M & request) == PCI_BASE_TYPE_ALL) {
3886 3886 DEBUG3("BASE register [0x%x] asks for "
3887 3887 "[0x%x]=[0x%x] (64)\n",
3888 3888 i, request, (~(PCI_BASE_M_ADDR_M & request))+1);
3889 3889 i += 8;
3890 3890 } else {
3891 3891 DEBUG3("BASE register [0x%x] asks for "
3892 3892 "[0x%x]=[0x%x](32)\n",
3893 3893 i, request, (~(PCI_BASE_M_ADDR_M & request))+1);
3894 3894 i += 4;
3895 3895 }
3896 3896 }
3897 3897
3898 3898 /*
3899 3899 * Get the ROM size and create register for it
3900 3900 */
3901 3901 pci_config_put32(config_handle, PCI_CONF_ROM, 0xfffffffe);
3902 3902
3903 3903 request = pci_config_get32(config_handle, PCI_CONF_ROM);
3904 3904 /*
3905 3905 * If its a zero length, don't do
3906 3906 * any programming.
3907 3907 */
3908 3908
3909 3909 if (request != 0) {
3910 3910 DEBUG3("BASE register [0x%x] asks for [0x%x]=[0x%x]\n",
3911 3911 PCI_CONF_ROM, request,
3912 3912 (~(PCI_BASE_ROM_ADDR_M & request)) + 1);
3913 3913 /*
3914 3914 * Add to the "reg" property
3915 3915 */
3916 3916 if (pcicfg_update_reg_prop(new_child, request, PCI_CONF_ROM)
3917 3917 != PCICFG_SUCCESS) {
3918 3918 goto failedchild;
3919 3919 }
3920 3920 }
3921 3921
3922 3922 return (PCICFG_SUCCESS);
3923 3923
3924 3924 failedchild:
3925 3925 return (PCICFG_FAILURE);
3926 3926 }
3927 3927
3928 3928 /*
3929 3929 * Read the BARs and update properties. Used in virtual hotplug.
3930 3930 */
3931 3931 static int
3932 3932 pcicfg_populate_props_from_bar(dev_info_t *new_child,
3933 3933 ddi_acc_handle_t config_handle)
3934 3934 {
3935 3935 uint32_t request, base, base_hi, size;
3936 3936 int i;
3937 3937
3938 3938 i = PCI_CONF_BASE0;
3939 3939
3940 3940 while (i <= PCI_CONF_BASE5) {
3941 3941 /*
3942 3942 * determine the size of the address space
3943 3943 */
3944 3944 base = pci_config_get32(config_handle, i);
3945 3945 pci_config_put32(config_handle, i, 0xffffffff);
3946 3946 request = pci_config_get32(config_handle, i);
3947 3947 pci_config_put32(config_handle, i, base);
3948 3948
3949 3949 /*
3950 3950 * If its a zero length, don't do any programming.
3951 3951 */
3952 3952 if (request != 0) {
3953 3953 /*
3954 3954 * Add to the "reg" property
3955 3955 */
3956 3956 if (pcicfg_update_reg_prop(new_child,
3957 3957 request, i) != PCICFG_SUCCESS) {
3958 3958 goto failedchild;
3959 3959 }
3960 3960
3961 3961 if ((PCI_BASE_SPACE_IO & request) == 0 &&
3962 3962 (PCI_BASE_TYPE_M & request) == PCI_BASE_TYPE_ALL) {
3963 3963 base_hi = pci_config_get32(config_handle, i+4);
3964 3964 } else {
3965 3965 base_hi = 0;
3966 3966 }
3967 3967 /*
3968 3968 * Add to "assigned-addresses" property
3969 3969 */
3970 3970 size = (~(PCI_BASE_M_ADDR_M & request))+1;
3971 3971 if (pcicfg_update_assigned_prop_value(new_child,
3972 3972 size, base, base_hi, i) != PCICFG_SUCCESS) {
3973 3973 goto failedchild;
3974 3974 }
3975 3975 } else {
3976 3976 DEBUG1("BASE register [0x%x] asks for [0x0]=[0x0]"
3977 3977 "(32)\n", i);
3978 3978 i += 4;
3979 3979 continue;
3980 3980 }
3981 3981
3982 3982 /*
3983 3983 * Increment by eight if it is 64 bit address space
3984 3984 */
3985 3985 if ((PCI_BASE_TYPE_M & request) == PCI_BASE_TYPE_ALL) {
3986 3986 DEBUG3("BASE register [0x%x] asks for [0x%x]=[0x%x]"
3987 3987 "(64)\n", i, request,
3988 3988 (~(PCI_BASE_M_ADDR_M & request)) + 1);
3989 3989 i += 8;
3990 3990 } else {
3991 3991 DEBUG3("BASE register [0x%x] asks for [0x%x]=[0x%x]"
3992 3992 "(32)\n", i, request,
3993 3993 (~(PCI_BASE_M_ADDR_M & request)) + 1);
3994 3994 i += 4;
3995 3995 }
3996 3996 }
3997 3997
3998 3998 /*
3999 3999 * Get the ROM size and create register for it
4000 4000 */
4001 4001 base = pci_config_get32(config_handle, PCI_CONF_ROM);
4002 4002 pci_config_put32(config_handle, PCI_CONF_ROM, 0xfffffffe);
4003 4003 request = pci_config_get32(config_handle, PCI_CONF_ROM);
4004 4004 pci_config_put32(config_handle, PCI_CONF_ROM, base);
4005 4005
4006 4006 /*
4007 4007 * If its a zero length, don't do
4008 4008 * any programming.
4009 4009 */
4010 4010 if (request != 0) {
4011 4011 DEBUG3("BASE register [0x%x] asks for [0x%x]=[0x%x]\n",
4012 4012 PCI_CONF_ROM, request,
4013 4013 (~(PCI_BASE_ROM_ADDR_M & request)) + 1);
4014 4014 /*
4015 4015 * Add to the "reg" property
4016 4016 */
4017 4017 if (pcicfg_update_reg_prop(new_child, request, PCI_CONF_ROM)
4018 4018 != PCICFG_SUCCESS) {
4019 4019 goto failedchild;
4020 4020 }
4021 4021 /*
4022 4022 * Add to "assigned-addresses" property
4023 4023 */
4024 4024 size = (~(PCI_BASE_ROM_ADDR_M & request))+1;
4025 4025 if (pcicfg_update_assigned_prop_value(new_child, size,
4026 4026 base, 0, PCI_CONF_ROM) != PCICFG_SUCCESS) {
4027 4027 goto failedchild;
4028 4028 }
4029 4029 }
4030 4030
4031 4031 return (PCICFG_SUCCESS);
4032 4032
4033 4033 failedchild:
4034 4034 return (PCICFG_FAILURE);
4035 4035 }
4036 4036
4037 4037 static int
4038 4038 pcicfg_probe_bridge(dev_info_t *new_child, ddi_acc_handle_t h, uint_t bus,
4039 4039 uint_t *highest_bus, boolean_t is_pcie)
4040 4040 {
4041 4041 uint64_t next_bus;
4042 4042 uint_t new_bus, num_slots;
4043 4043 ndi_ra_request_t req;
4044 4044 int rval, i, j;
4045 4045 uint64_t mem_answer, io_answer, mem_base, io_base, mem_alen, io_alen;
4046 4046 uint64_t pf_mem_answer, pf_mem_base, pf_mem_alen;
4047 4047 uint64_t mem_size, io_size, pf_mem_size;
4048 4048 uint64_t mem_end, pf_mem_end, io_end;
4049 4049 uint64_t round_answer, round_len;
4050 4050 ppb_ranges_t range[PCICFG_RANGE_LEN];
4051 4051 int bus_range[2];
4052 4052 pcicfg_phdl_t phdl;
4053 4053 int count;
4054 4054 uint64_t pcibus_base, pcibus_alen;
4055 4055 uint64_t max_bus;
4056 4056 uint8_t pcie_device_type = 0;
4057 4057 uint_t pf_mem_supported = 0;
4058 4058 dev_info_t *new_device;
4059 4059 int trans_device;
4060 4060 int ari_mode = B_FALSE;
4061 4061 int max_function = PCI_MAX_FUNCTIONS;
4062 4062
4063 4063 io_answer = io_base = io_alen = io_size = 0;
4064 4064 pf_mem_answer = pf_mem_base = pf_mem_size = pf_mem_alen = 0;
4065 4065
4066 4066 /*
4067 4067 * Set "device_type" to "pci", the actual type will be set later
4068 4068 * by pcicfg_set_busnode_props() below. This is needed as the
4069 4069 * pcicfg_ra_free() below would update "available" property based
4070 4070 * on "device_type".
4071 4071 *
4072 4072 * This code can be removed later after PCI configurator is changed
4073 4073 * to use PCIRM, which automatically update properties upon allocation
4074 4074 * and free, at that time we'll be able to remove the code inside
4075 4075 * ndi_ra_alloc/free() which currently updates "available" property
4076 4076 * for pci/pcie devices in pcie fabric.
4077 4077 */
4078 4078 if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child,
4079 4079 "device_type", "pci") != DDI_SUCCESS) {
4080 4080 DEBUG0("Failed to set \"device_type\" props\n");
4081 4081 return (PCICFG_FAILURE);
4082 4082 }
4083 4083
4084 4084 /*
4085 4085 * setup resource maps for the bridge node
4086 4086 */
4087 4087 if (ndi_ra_map_setup(new_child, NDI_RA_TYPE_PCI_BUSNUM)
4088 4088 == NDI_FAILURE) {
4089 4089 DEBUG0("Can not setup resource map - NDI_RA_TYPE_PCI_BUSNUM\n");
4090 4090 rval = PCICFG_FAILURE;
4091 4091 goto cleanup;
4092 4092 }
4093 4093 if (ndi_ra_map_setup(new_child, NDI_RA_TYPE_MEM) == NDI_FAILURE) {
4094 4094 DEBUG0("Can not setup resource map - NDI_RA_TYPE_MEM\n");
4095 4095 rval = PCICFG_FAILURE;
4096 4096 goto cleanup;
4097 4097 }
4098 4098 if (ndi_ra_map_setup(new_child, NDI_RA_TYPE_IO) == NDI_FAILURE) {
4099 4099 DEBUG0("Can not setup resource map - NDI_RA_TYPE_IO\n");
4100 4100 rval = PCICFG_FAILURE;
4101 4101 goto cleanup;
4102 4102 }
4103 4103 if (ndi_ra_map_setup(new_child, NDI_RA_TYPE_PCI_PREFETCH_MEM) ==
4104 4104 NDI_FAILURE) {
4105 4105 DEBUG0("Can not setup resource map -"
4106 4106 " NDI_RA_TYPE_PCI_PREFETCH_MEM\n");
4107 4107 rval = PCICFG_FAILURE;
4108 4108 goto cleanup;
4109 4109 }
4110 4110
4111 4111 /*
4112 4112 * Allocate bus range pool for the bridge.
4113 4113 */
4114 4114 bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
4115 4115 req.ra_flags = (NDI_RA_ALLOC_BOUNDED | NDI_RA_ALLOC_PARTIAL_OK);
4116 4116 req.ra_boundbase = 0;
4117 4117 req.ra_boundlen = req.ra_len = (PCI_MAX_BUS_NUM -1);
4118 4118 req.ra_align_mask = 0; /* no alignment needed */
4119 4119
4120 4120 rval = ndi_ra_alloc(ddi_get_parent(new_child), &req,
4121 4121 &pcibus_base, &pcibus_alen, NDI_RA_TYPE_PCI_BUSNUM, NDI_RA_PASS);
4122 4122
4123 4123 if (rval != NDI_SUCCESS) {
4124 4124 if (rval == NDI_RA_PARTIAL_REQ) {
4125 4125 /*EMPTY*/
4126 4126 DEBUG0("NDI_RA_PARTIAL_REQ returned for bus range\n");
4127 4127 } else {
4128 4128 DEBUG0(
4129 4129 "Failed to allocate bus range for bridge\n");
4130 4130 rval = PCICFG_NORESRC;
4131 4131 goto cleanup;
4132 4132 }
4133 4133 }
4134 4134
4135 4135 DEBUG2("Bus Range Allocated [base=%d] [len=%d]\n",
4136 4136 pcibus_base, pcibus_alen);
4137 4137
4138 4138 /*
4139 4139 * Put available bus range into the pool.
4140 4140 * Take the first one for this bridge to use and don't give
4141 4141 * to child.
4142 4142 */
4143 4143 (void) ndi_ra_free(new_child, pcibus_base+1, pcibus_alen-1,
4144 4144 NDI_RA_TYPE_PCI_BUSNUM, NDI_RA_PASS);
4145 4145
4146 4146 next_bus = pcibus_base;
4147 4147 max_bus = pcibus_base + pcibus_alen - 1;
4148 4148
4149 4149 new_bus = next_bus;
4150 4150
4151 4151 DEBUG1("NEW bus found ->[%d]\n", new_bus);
4152 4152
4153 4153 /* Keep track of highest bus for subordinate bus programming */
4154 4154 *highest_bus = new_bus;
4155 4155
4156 4156 /*
4157 4157 * Allocate (non-prefetchable) Memory Space for Bridge
4158 4158 */
4159 4159 bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
4160 4160 req.ra_flags = (NDI_RA_ALLOC_BOUNDED | NDI_RA_ALLOC_PARTIAL_OK);
4161 4161 req.ra_boundbase = 0;
4162 4162 /*
4163 4163 * limit the boundlen,len to a 32b quantity. It should be Ok to
4164 4164 * lose alignment-based-size of resource due to this.
4165 4165 */
4166 4166 req.ra_boundlen = PCICFG_4GIG_LIMIT;
4167 4167 req.ra_len = PCICFG_4GIG_LIMIT; /* Get as big as possible */
4168 4168 req.ra_align_mask =
4169 4169 PCICFG_MEMGRAN - 1; /* 1M alignment on memory space */
4170 4170
4171 4171 rval = ndi_ra_alloc(ddi_get_parent(new_child), &req,
4172 4172 &mem_answer, &mem_alen, NDI_RA_TYPE_MEM, NDI_RA_PASS);
4173 4173
4174 4174 if (rval != NDI_SUCCESS) {
4175 4175 if (rval == NDI_RA_PARTIAL_REQ) {
4176 4176 /*EMPTY*/
4177 4177 DEBUG0("NDI_RA_PARTIAL_REQ returned\n");
4178 4178 } else {
4179 4179 DEBUG0(
4180 4180 "Failed to allocate memory for bridge\n");
4181 4181 rval = PCICFG_NORESRC;
4182 4182 goto cleanup;
4183 4183 }
4184 4184 }
4185 4185
4186 4186 DEBUG3("Bridge Memory Allocated [0x%x.%x] len [0x%x]\n",
4187 4187 PCICFG_HIADDR(mem_answer),
4188 4188 PCICFG_LOADDR(mem_answer),
4189 4189 mem_alen);
4190 4190
4191 4191 /*
4192 4192 * Put available memory into the pool.
4193 4193 */
4194 4194 (void) ndi_ra_free(new_child, mem_answer, mem_alen, NDI_RA_TYPE_MEM,
4195 4195 NDI_RA_PASS);
4196 4196
4197 4197 mem_base = mem_answer;
4198 4198
4199 4199 /*
4200 4200 * Allocate I/O Space for Bridge
4201 4201 */
4202 4202 bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
4203 4203 req.ra_align_mask = PCICFG_IOGRAN - 1; /* 4k alignment */
4204 4204 req.ra_boundbase = 0;
4205 4205 req.ra_boundlen = PCICFG_4GIG_LIMIT;
4206 4206 req.ra_flags = (NDI_RA_ALLOC_BOUNDED | NDI_RA_ALLOC_PARTIAL_OK);
4207 4207 req.ra_len = PCICFG_4GIG_LIMIT; /* Get as big as possible */
4208 4208
4209 4209 rval = ndi_ra_alloc(ddi_get_parent(new_child), &req, &io_answer,
4210 4210 &io_alen, NDI_RA_TYPE_IO, NDI_RA_PASS);
4211 4211
4212 4212 if (rval != NDI_SUCCESS) {
4213 4213 if (rval == NDI_RA_PARTIAL_REQ) {
4214 4214 /*EMPTY*/
4215 4215 DEBUG0("NDI_RA_PARTIAL_REQ returned\n");
4216 4216 } else {
4217 4217 DEBUG0("Failed to allocate io space for bridge\n");
4218 4218 /* i/o space is an optional requirement so continue */
4219 4219 }
4220 4220 }
4221 4221
4222 4222 DEBUG3("Bridge IO Space Allocated [0x%x.%x] len [0x%x]\n",
4223 4223 PCICFG_HIADDR(io_answer), PCICFG_LOADDR(io_answer), io_alen);
4224 4224
4225 4225 /*
4226 4226 * Put available I/O into the pool.
4227 4227 */
4228 4228 (void) ndi_ra_free(new_child, io_answer, io_alen, NDI_RA_TYPE_IO,
4229 4229 NDI_RA_PASS);
4230 4230
4231 4231 io_base = io_answer;
4232 4232
4233 4233 /*
4234 4234 * Check if the bridge supports Prefetchable memory range.
4235 4235 * If it does, then we setup PF memory range for the bridge.
4236 4236 * Otherwise, we skip the step of setting up PF memory
4237 4237 * range for it. This could cause config operation to
4238 4238 * fail if any devices under the bridge need PF memory.
4239 4239 */
4240 4240 /* write a non zero value to the PF BASE register */
4241 4241 pci_config_put16(h, PCI_BCNF_PF_BASE_LOW, 0xfff0);
4242 4242 /* if the read returns zero then PF range is not supported */
4243 4243 if (pci_config_get16(h, PCI_BCNF_PF_BASE_LOW) == 0) {
4244 4244 /* bridge doesn't support PF memory range */
4245 4245 goto pf_setup_end;
4246 4246 } else {
4247 4247 pf_mem_supported = 1;
4248 4248 /* reset the PF BASE register */
4249 4249 pci_config_put16(h, PCI_BCNF_PF_BASE_LOW, 0);
4250 4250 }
4251 4251
4252 4252 /*
4253 4253 * Bridge supports PF mem range; Allocate PF Memory Space for it.
4254 4254 *
4255 4255 * Note: Both non-prefetchable and prefetchable memory space
4256 4256 * allocations are made within 32bit space. Currently, BIOSs
4257 4257 * allocate device memory for PCI devices within the 32bit space
4258 4258 * so this will not be a problem.
4259 4259 */
4260 4260 bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
4261 4261 req.ra_flags = NDI_RA_ALLOC_PARTIAL_OK | NDI_RA_ALLOC_BOUNDED;
4262 4262 req.ra_boundbase = 0;
4263 4263 req.ra_len = PCICFG_4GIG_LIMIT; /* Get as big as possible */
4264 4264 req.ra_align_mask =
4265 4265 PCICFG_MEMGRAN - 1; /* 1M alignment on memory space */
4266 4266
4267 4267 rval = ndi_ra_alloc(ddi_get_parent(new_child), &req,
4268 4268 &pf_mem_answer, &pf_mem_alen, NDI_RA_TYPE_PCI_PREFETCH_MEM,
4269 4269 NDI_RA_PASS);
4270 4270
4271 4271 if (rval != NDI_SUCCESS) {
4272 4272 if (rval == NDI_RA_PARTIAL_REQ) {
4273 4273 /*EMPTY*/
4274 4274 DEBUG0("NDI_RA_PARTIAL_REQ returned\n");
4275 4275 } else {
4276 4276 DEBUG0(
4277 4277 "Failed to allocate PF memory for bridge\n");
4278 4278 /* PF mem is an optional requirement so continue */
4279 4279 }
4280 4280 }
4281 4281
4282 4282 DEBUG3("Bridge PF Memory Allocated [0x%x.%x] len [0x%x]\n",
4283 4283 PCICFG_HIADDR(pf_mem_answer),
4284 4284 PCICFG_LOADDR(pf_mem_answer),
4285 4285 pf_mem_alen);
4286 4286
4287 4287 /*
4288 4288 * Put available PF memory into the pool.
4289 4289 */
4290 4290 (void) ndi_ra_free(new_child, pf_mem_answer, pf_mem_alen,
4291 4291 NDI_RA_TYPE_PCI_PREFETCH_MEM, NDI_RA_PASS);
4292 4292
4293 4293 pf_mem_base = pf_mem_answer;
4294 4294
4295 4295 /*
4296 4296 * Program the PF memory base register with the
4297 4297 * start of the memory range
4298 4298 */
4299 4299 pci_config_put16(h, PCI_BCNF_PF_BASE_LOW,
4300 4300 PCICFG_HIWORD(PCICFG_LOADDR(pf_mem_answer)));
4301 4301 pci_config_put32(h, PCI_BCNF_PF_BASE_HIGH,
4302 4302 PCICFG_HIADDR(pf_mem_answer));
4303 4303
4304 4304 /*
4305 4305 * Program the PF memory limit register with the
4306 4306 * end of the memory range.
4307 4307 */
4308 4308 pci_config_put16(h, PCI_BCNF_PF_LIMIT_LOW,
4309 4309 PCICFG_HIWORD(PCICFG_LOADDR(
4310 4310 PCICFG_ROUND_DOWN((pf_mem_answer + pf_mem_alen),
4311 4311 PCICFG_MEMGRAN) - 1)));
4312 4312 pci_config_put32(h, PCI_BCNF_PF_LIMIT_HIGH,
4313 4313 PCICFG_HIADDR(PCICFG_ROUND_DOWN((pf_mem_answer + pf_mem_alen),
4314 4314 PCICFG_MEMGRAN) - 1));
4315 4315
4316 4316 /*
4317 4317 * Allocate the chunk of PF memory (if any) not programmed into the
4318 4318 * bridge because of the round down.
4319 4319 */
4320 4320 if (PCICFG_ROUND_DOWN((pf_mem_answer + pf_mem_alen), PCICFG_MEMGRAN)
4321 4321 != (pf_mem_answer + pf_mem_alen)) {
4322 4322 DEBUG0("Need to allocate Memory round off chunk\n");
4323 4323 bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
4324 4324 req.ra_flags = NDI_RA_ALLOC_SPECIFIED;
4325 4325 req.ra_addr = PCICFG_ROUND_DOWN((pf_mem_answer + pf_mem_alen),
4326 4326 PCICFG_MEMGRAN);
4327 4327 req.ra_len = (pf_mem_answer + pf_mem_alen) -
4328 4328 (PCICFG_ROUND_DOWN((pf_mem_answer + pf_mem_alen),
4329 4329 PCICFG_MEMGRAN));
4330 4330
4331 4331 (void) ndi_ra_alloc(new_child, &req,
4332 4332 &round_answer, &round_len, NDI_RA_TYPE_PCI_PREFETCH_MEM,
4333 4333 NDI_RA_PASS);
4334 4334 }
4335 4335
4336 4336 pf_setup_end:
4337 4337
4338 4338 /*
4339 4339 * Program the memory base register with the
4340 4340 * start of the memory range
4341 4341 */
4342 4342 pci_config_put16(h, PCI_BCNF_MEM_BASE,
4343 4343 PCICFG_HIWORD(PCICFG_LOADDR(mem_answer)));
4344 4344
4345 4345 /*
4346 4346 * Program the memory limit register with the
4347 4347 * end of the memory range.
4348 4348 */
4349 4349
4350 4350 pci_config_put16(h, PCI_BCNF_MEM_LIMIT,
4351 4351 PCICFG_HIWORD(PCICFG_LOADDR(
4352 4352 PCICFG_ROUND_DOWN((mem_answer + mem_alen), PCICFG_MEMGRAN) - 1)));
4353 4353
4354 4354 /*
4355 4355 * Allocate the chunk of memory (if any) not programmed into the
4356 4356 * bridge because of the round down.
4357 4357 */
4358 4358 if (PCICFG_ROUND_DOWN((mem_answer + mem_alen), PCICFG_MEMGRAN)
4359 4359 != (mem_answer + mem_alen)) {
4360 4360 DEBUG0("Need to allocate Memory round off chunk\n");
4361 4361 bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
4362 4362 req.ra_flags = NDI_RA_ALLOC_SPECIFIED;
4363 4363 req.ra_addr = PCICFG_ROUND_DOWN((mem_answer + mem_alen),
4364 4364 PCICFG_MEMGRAN);
4365 4365 req.ra_len = (mem_answer + mem_alen) -
4366 4366 (PCICFG_ROUND_DOWN((mem_answer + mem_alen),
4367 4367 PCICFG_MEMGRAN));
4368 4368
4369 4369 (void) ndi_ra_alloc(new_child, &req,
4370 4370 &round_answer, &round_len, NDI_RA_TYPE_MEM, NDI_RA_PASS);
4371 4371 }
4372 4372
4373 4373 /*
4374 4374 * Program the I/O Space Base
4375 4375 */
4376 4376 pci_config_put8(h, PCI_BCNF_IO_BASE_LOW,
4377 4377 PCICFG_HIBYTE(PCICFG_LOWORD(
4378 4378 PCICFG_LOADDR(io_answer))));
4379 4379
4380 4380 pci_config_put16(h, PCI_BCNF_IO_BASE_HI,
4381 4381 PCICFG_HIWORD(PCICFG_LOADDR(io_answer)));
4382 4382
4383 4383 /*
4384 4384 * Program the I/O Space Limit
4385 4385 */
4386 4386 pci_config_put8(h, PCI_BCNF_IO_LIMIT_LOW,
4387 4387 PCICFG_HIBYTE(PCICFG_LOWORD(
4388 4388 PCICFG_LOADDR(PCICFG_ROUND_DOWN(io_answer + io_alen,
4389 4389 PCICFG_IOGRAN)))) - 1);
4390 4390
4391 4391 pci_config_put16(h, PCI_BCNF_IO_LIMIT_HI,
4392 4392 PCICFG_HIWORD(PCICFG_LOADDR(
4393 4393 PCICFG_ROUND_DOWN(io_answer + io_alen, PCICFG_IOGRAN)))
4394 4394 - 1);
4395 4395
4396 4396 /*
4397 4397 * Allocate the chunk of I/O (if any) not programmed into the
4398 4398 * bridge because of the round down.
4399 4399 */
4400 4400 if (PCICFG_ROUND_DOWN((io_answer + io_alen), PCICFG_IOGRAN)
4401 4401 != (io_answer + io_alen)) {
4402 4402 DEBUG0("Need to allocate I/O round off chunk\n");
4403 4403 bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
4404 4404 req.ra_flags = NDI_RA_ALLOC_SPECIFIED;
4405 4405 req.ra_addr = PCICFG_ROUND_DOWN((io_answer + io_alen),
4406 4406 PCICFG_IOGRAN);
4407 4407 req.ra_len = (io_answer + io_alen) -
4408 4408 (PCICFG_ROUND_DOWN((io_answer + io_alen),
4409 4409 PCICFG_IOGRAN));
4410 4410
4411 4411 (void) ndi_ra_alloc(new_child, &req,
4412 4412 &round_answer, &round_len, NDI_RA_TYPE_IO, NDI_RA_PASS);
4413 4413 }
4414 4414
4415 4415 (void) pcicfg_set_bus_numbers(h, bus, new_bus, max_bus);
4416 4416
4417 4417 /*
4418 4418 * Setup "ranges" and "bus-range" properties before onlining
4419 4419 * the bridge.
4420 4420 */
4421 4421 bzero((caddr_t)range, sizeof (ppb_ranges_t) * PCICFG_RANGE_LEN);
4422 4422
4423 4423 range[0].child_high = range[0].parent_high |= (PCI_REG_REL_M |
4424 4424 PCI_ADDR_IO);
4425 4425 range[0].child_low = range[0].parent_low = io_base;
4426 4426 range[1].child_high = range[1].parent_high |=
4427 4427 (PCI_REG_REL_M | PCI_ADDR_MEM32);
4428 4428 range[1].child_low = range[1].parent_low = mem_base;
4429 4429 range[2].child_high = range[2].parent_high |=
4430 4430 (PCI_REG_REL_M | PCI_ADDR_MEM64 | PCI_REG_PF_M);
4431 4431 range[2].child_low = range[2].parent_low = pf_mem_base;
4432 4432
4433 4433 range[0].size_low = io_alen;
4434 4434 (void) pcicfg_update_ranges_prop(new_child, &range[0]);
4435 4435 range[1].size_low = mem_alen;
4436 4436 (void) pcicfg_update_ranges_prop(new_child, &range[1]);
4437 4437 range[2].size_low = pf_mem_alen;
4438 4438 (void) pcicfg_update_ranges_prop(new_child, &range[2]);
4439 4439
4440 4440 bus_range[0] = new_bus;
4441 4441 bus_range[1] = max_bus;
4442 4442 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, new_child,
4443 4443 "bus-range", bus_range, 2);
4444 4444
4445 4445 /*
4446 4446 * Reset the secondary bus
4447 4447 */
4448 4448 pci_config_put16(h, PCI_BCNF_BCNTRL,
4449 4449 pci_config_get16(h, PCI_BCNF_BCNTRL) | 0x40);
4450 4450
4451 4451 drv_usecwait(100);
4452 4452
4453 4453 pci_config_put16(h, PCI_BCNF_BCNTRL,
4454 4454 pci_config_get16(h, PCI_BCNF_BCNTRL) & ~0x40);
4455 4455
4456 4456 /*
4457 4457 * Clear status bits
4458 4458 */
4459 4459 pci_config_put16(h, PCI_BCNF_SEC_STATUS, 0xffff);
4460 4460
4461 4461 /*
4462 4462 * Needs to be set to this value
4463 4463 */
4464 4464 pci_config_put8(h, PCI_CONF_ILINE, 0xf);
4465 4465
4466 4466 /* check our device_type as defined by Open Firmware */
4467 4467 if (pcicfg_pcie_device_type(new_child, h) == DDI_SUCCESS)
4468 4468 pcie_device_type = 1;
4469 4469
4470 4470 /*
4471 4471 * Set bus properties
4472 4472 */
4473 4473 if (pcicfg_set_busnode_props(new_child, pcie_device_type)
4474 4474 != PCICFG_SUCCESS) {
4475 4475 DEBUG0("Failed to set busnode props\n");
4476 4476 rval = PCICFG_FAILURE;
4477 4477 goto cleanup;
4478 4478 }
4479 4479
4480 4480 (void) pcicfg_device_on(h);
4481 4481
4482 4482 if (is_pcie)
4483 4483 (void) pcie_init_bus(new_child, 0, PCIE_BUS_FINAL);
4484 4484 if (ndi_devi_online(new_child, NDI_NO_EVENT|NDI_CONFIG)
4485 4485 != NDI_SUCCESS) {
4486 4486 DEBUG0("Unable to online bridge\n");
4487 4487 rval = PCICFG_FAILURE;
4488 4488 goto cleanup;
4489 4489 }
4490 4490
4491 4491 DEBUG0("Bridge is ONLINE\n");
4492 4492
4493 4493 /*
4494 4494 * After a Reset, we need to wait 2^25 clock cycles before the
4495 4495 * first Configuration access. The worst case is 33MHz, which
4496 4496 * is a 1 second wait.
4497 4497 */
4498 4498 drv_usecwait(pcicfg_sec_reset_delay);
4499 4499
4500 4500 /*
4501 4501 * Probe all children devices
4502 4502 */
4503 4503 DEBUG0("Bridge Programming Complete - probe children\n");
4504 4504 ndi_devi_enter(new_child, &count);
4505 4505 for (i = 0; ((i < PCI_MAX_DEVICES) && (ari_mode == B_FALSE));
4506 4506 i++) {
4507 4507 for (j = 0; j < max_function; ) {
4508 4508 if (ari_mode)
4509 4509 trans_device = j >> 3;
4510 4510 else
4511 4511 trans_device = i;
4512 4512
4513 4513 if ((rval = pcicfg_probe_children(new_child,
4514 4514 new_bus, trans_device, j & 7, highest_bus,
4515 4515 0, is_pcie)) != PCICFG_SUCCESS) {
4516 4516 if (rval == PCICFG_NODEVICE) {
4517 4517 DEBUG3("No Device at bus [0x%x]"
4518 4518 "device [0x%x] "
4519 4519 "func [0x%x]\n", new_bus,
4520 4520 trans_device, j & 7);
4521 4521
4522 4522 if (j)
4523 4523 goto next;
4524 4524 } else
4525 4525 /*EMPTY*/
4526 4526 DEBUG3("Failed to configure bus "
4527 4527 "[0x%x] device [0x%x] "
4528 4528 "func [0x%x]\n", new_bus,
4529 4529 trans_device, j & 7);
4530 4530 break;
4531 4531 }
4532 4532 next:
4533 4533 new_device = pcicfg_devi_find(new_child, trans_device,
4534 4534 (j & 7));
4535 4535
4536 4536 /*
4537 4537 * Determine if ARI Forwarding should be enabled.
4538 4538 */
4539 4539 if (j == 0) {
4540 4540 if (new_device == NULL)
4541 4541 break;
4542 4542
4543 4543 if ((pcie_ari_supported(new_child) ==
4544 4544 PCIE_ARI_FORW_SUPPORTED) &&
4545 4545 (pcie_ari_device(new_device) ==
4546 4546 PCIE_ARI_DEVICE)) {
4547 4547 if (pcie_ari_enable(new_child) ==
4548 4548 DDI_SUCCESS) {
4549 4549 (void) ddi_prop_create(
4550 4550 DDI_DEV_T_NONE,
4551 4551 new_child,
4552 4552 DDI_PROP_CANSLEEP,
4553 4553 "ari-enabled", NULL, 0);
4554 4554 ari_mode = B_TRUE;
4555 4555 max_function =
4556 4556 PCICFG_MAX_ARI_FUNCTION;
4557 4557 }
4558 4558 }
4559 4559 }
4560 4560 if (ari_mode == B_TRUE) {
4561 4561 int next_function;
4562 4562
4563 4563 if (new_device == NULL)
4564 4564 break;
4565 4565
4566 4566 if (pcie_ari_get_next_function(new_device,
4567 4567 &next_function) != DDI_SUCCESS)
4568 4568 break;
4569 4569
4570 4570 j = next_function;
4571 4571
4572 4572 if (next_function == 0)
4573 4573 break;
4574 4574 } else
4575 4575 j++;
4576 4576
4577 4577 }
4578 4578 /* if any function fails to be configured, no need to proceed */
4579 4579 if (rval != PCICFG_NODEVICE)
4580 4580 break;
4581 4581 }
4582 4582 ndi_devi_exit(new_child, count);
4583 4583
4584 4584 /*
4585 4585 * Offline the bridge to allow reprogramming of resources.
4586 4586 *
4587 4587 * This should always succeed since nobody else has started to
4588 4588 * use it yet, failing to detach the driver would indicate a bug.
4589 4589 * Also in that case it's better just panic than allowing the
4590 4590 * configurator to proceed with BAR reprogramming without bridge
4591 4591 * driver detached.
4592 4592 */
4593 4593 VERIFY(ndi_devi_offline(new_child, NDI_NO_EVENT|NDI_UNCONFIG)
4594 4594 == NDI_SUCCESS);
4595 4595 if (is_pcie)
4596 4596 pcie_fini_bus(new_child, PCIE_BUS_INITIAL);
4597 4597
4598 4598 phdl.dip = new_child;
4599 4599 phdl.memory_base = mem_answer;
4600 4600 phdl.io_base = io_answer;
4601 4601 phdl.pf_memory_base = pf_mem_answer;
4602 4602 phdl.error = PCICFG_SUCCESS; /* in case of empty child tree */
4603 4603
4604 4604 ndi_devi_enter(ddi_get_parent(new_child), &count);
4605 4605 ddi_walk_devs(new_child, pcicfg_find_resource_end, (void *)&phdl);
4606 4606 ndi_devi_exit(ddi_get_parent(new_child), count);
4607 4607
4608 4608 num_slots = pcicfg_get_nslots(new_child, h);
4609 4609 mem_end = PCICFG_ROUND_UP(phdl.memory_base, PCICFG_MEMGRAN);
4610 4610 io_end = PCICFG_ROUND_UP(phdl.io_base, PCICFG_IOGRAN);
4611 4611 pf_mem_end = PCICFG_ROUND_UP(phdl.pf_memory_base, PCICFG_MEMGRAN);
4612 4612
4613 4613 DEBUG4("Start of Unallocated Bridge(%d slots) Resources Mem=0x%lx "
4614 4614 "I/O=0x%lx PF_mem=%x%lx\n", num_slots, mem_end, io_end, pf_mem_end);
4615 4615
4616 4616 /*
4617 4617 * Before probing the children we've allocated maximum MEM/IO
4618 4618 * resources from parent, and updated "available" property
4619 4619 * accordingly. Later we'll be giving up unused resources to
4620 4620 * the parent, thus we need to destroy "available" property
4621 4621 * here otherwise it will be out-of-sync with the actual free
4622 4622 * resources this bridge has. This property will be rebuilt below
4623 4623 * with the actual free resources reserved for hotplug slots
4624 4624 * (if any).
4625 4625 */
4626 4626 (void) ndi_prop_remove(DDI_DEV_T_NONE, new_child, "available");
4627 4627 /*
4628 4628 * if the bridge a slots, then preallocate. If not, assume static
4629 4629 * configuration. Also check for preallocation limits and spit
4630 4630 * warning messages appropriately (perhaps some can be in debug mode).
4631 4631 */
4632 4632 if (num_slots) {
4633 4633 uint64_t mem_reqd = mem_answer +
4634 4634 (num_slots * pcicfg_slot_memsize);
4635 4635 uint64_t io_reqd = io_answer +
4636 4636 (num_slots * pcicfg_slot_iosize);
4637 4637 uint64_t pf_mem_reqd = pf_mem_answer +
4638 4638 (num_slots * pcicfg_slot_pf_memsize);
4639 4639 uint8_t highest_bus_reqd = new_bus +
4640 4640 (num_slots * pcicfg_slot_busnums);
4641 4641 #ifdef DEBUG
4642 4642 if (mem_end > mem_reqd)
4643 4643 DEBUG3("Memory space consumed by bridge more "
4644 4644 "than planned for %d slot(s)(%" PRIx64 ",%"
4645 4645 PRIx64 ")", num_slots, mem_answer, mem_end);
4646 4646 if (io_end > io_reqd)
4647 4647 DEBUG3("IO space consumed by bridge more than"
4648 4648 " planned for %d slot(s)(%" PRIx64 ",%" PRIx64 ")",
4649 4649 num_slots, io_answer, io_end);
4650 4650 if (pf_mem_end > pf_mem_reqd)
4651 4651 DEBUG3("PF Memory space consumed by bridge"
4652 4652 " more than planned for %d slot(s)(%" PRIx64 ",%"
4653 4653 PRIx64 ")", num_slots, pf_mem_answer, pf_mem_end);
4654 4654 if (*highest_bus > highest_bus_reqd)
4655 4655 DEBUG3("Buses consumed by bridge more "
4656 4656 "than planned for %d slot(s)(%x, %x)",
4657 4657 num_slots, new_bus, *highest_bus);
4658 4658
4659 4659 if (mem_reqd > (mem_answer + mem_alen))
4660 4660 DEBUG3("Memory space required by bridge more "
4661 4661 "than available for %d slot(s)(%" PRIx64 ",%"
4662 4662 PRIx64 ")", num_slots, mem_answer, mem_end);
4663 4663 if (io_reqd > (io_answer + io_alen))
4664 4664 DEBUG3("IO space required by bridge more than"
4665 4665 "available for %d slot(s)(%" PRIx64 ",%" PRIx64 ")",
4666 4666 num_slots, io_answer, io_end);
4667 4667 if (pf_mem_reqd > (pf_mem_answer + pf_mem_alen))
4668 4668 DEBUG3("PF Memory space required by bridge"
4669 4669 " more than available for %d slot(s)(%" PRIx64 ",%"
4670 4670 PRIx64 ")", num_slots, pf_mem_answer, pf_mem_end);
4671 4671 if (highest_bus_reqd > max_bus)
4672 4672 DEBUG3("Bus numbers required by bridge more "
4673 4673 "than available for %d slot(s)(%x, %x)",
4674 4674 num_slots, new_bus, *highest_bus);
4675 4675 #endif
4676 4676 mem_end = MAX((MIN(mem_reqd, (mem_answer + mem_alen))),
4677 4677 mem_end);
4678 4678 io_end = MAX((MIN(io_reqd, (io_answer + io_alen))), io_end);
4679 4679 pf_mem_end = MAX((MIN(pf_mem_reqd, (pf_mem_answer +
4680 4680 pf_mem_alen))), pf_mem_end);
4681 4681 *highest_bus = MAX((MIN(highest_bus_reqd, max_bus)),
4682 4682 *highest_bus);
4683 4683 DEBUG4("mem_end %lx, io_end %lx, pf_mem_end %lx"
4684 4684 " highest_bus %x\n", mem_end, io_end, pf_mem_end,
4685 4685 *highest_bus);
4686 4686 }
4687 4687
4688 4688 /*
4689 4689 * Give back unused memory space to parent.
4690 4690 */
4691 4691 (void) ndi_ra_free(ddi_get_parent(new_child), mem_end,
4692 4692 (mem_answer + mem_alen) - mem_end, NDI_RA_TYPE_MEM, NDI_RA_PASS);
4693 4693
4694 4694 if (mem_end == mem_answer) {
4695 4695 DEBUG0("No memory resources used\n");
4696 4696 /*
4697 4697 * To prevent the bridge from forwarding any Memory
4698 4698 * transactions, the Memory Limit will be programmed
4699 4699 * with a smaller value than the Memory Base.
4700 4700 */
4701 4701 pci_config_put16(h, PCI_BCNF_MEM_BASE, 0xffff);
4702 4702 pci_config_put16(h, PCI_BCNF_MEM_LIMIT, 0);
4703 4703
4704 4704 mem_size = 0;
4705 4705 } else {
4706 4706 /*
4707 4707 * Reprogram the end of the memory.
4708 4708 */
4709 4709 pci_config_put16(h, PCI_BCNF_MEM_LIMIT,
4710 4710 PCICFG_HIWORD(mem_end) - 1);
4711 4711 mem_size = mem_end - mem_base;
4712 4712 }
4713 4713
4714 4714 /*
4715 4715 * Give back unused io space to parent.
4716 4716 */
4717 4717 (void) ndi_ra_free(ddi_get_parent(new_child),
4718 4718 io_end, (io_answer + io_alen) - io_end,
4719 4719 NDI_RA_TYPE_IO, NDI_RA_PASS);
4720 4720
4721 4721 if (io_end == io_answer) {
4722 4722 DEBUG0("No IO Space resources used\n");
4723 4723
4724 4724 /*
4725 4725 * To prevent the bridge from forwarding any I/O
4726 4726 * transactions, the I/O Limit will be programmed
4727 4727 * with a smaller value than the I/O Base.
4728 4728 */
4729 4729 pci_config_put8(h, PCI_BCNF_IO_LIMIT_LOW, 0);
4730 4730 pci_config_put16(h, PCI_BCNF_IO_LIMIT_HI, 0);
4731 4731 pci_config_put8(h, PCI_BCNF_IO_BASE_LOW, 0xff);
4732 4732 pci_config_put16(h, PCI_BCNF_IO_BASE_HI, 0);
4733 4733
4734 4734 io_size = 0;
4735 4735 } else {
4736 4736 /*
4737 4737 * Reprogram the end of the io space.
4738 4738 */
4739 4739 pci_config_put8(h, PCI_BCNF_IO_LIMIT_LOW,
4740 4740 PCICFG_HIBYTE(PCICFG_LOWORD(
4741 4741 PCICFG_LOADDR(io_end) - 1)));
4742 4742
4743 4743 pci_config_put16(h, PCI_BCNF_IO_LIMIT_HI,
4744 4744 PCICFG_HIWORD(PCICFG_LOADDR(io_end - 1)));
4745 4745
4746 4746 io_size = io_end - io_base;
4747 4747 }
4748 4748
4749 4749 /*
4750 4750 * Give back unused PF memory space to parent.
4751 4751 */
4752 4752 if (pf_mem_supported) {
4753 4753 (void) ndi_ra_free(ddi_get_parent(new_child),
4754 4754 pf_mem_end, (pf_mem_answer + pf_mem_alen) - pf_mem_end,
4755 4755 NDI_RA_TYPE_PCI_PREFETCH_MEM, NDI_RA_PASS);
4756 4756
4757 4757 if (pf_mem_end == pf_mem_answer) {
4758 4758 DEBUG0("No PF memory resources used\n");
4759 4759 /*
4760 4760 * To prevent the bridge from forwarding any PF Memory
4761 4761 * transactions, the PF Memory Limit will be programmed
4762 4762 * with a smaller value than the Memory Base.
4763 4763 */
4764 4764 pci_config_put16(h, PCI_BCNF_PF_BASE_LOW, 0xfff0);
4765 4765 pci_config_put32(h, PCI_BCNF_PF_BASE_HIGH, 0xffffffff);
4766 4766 pci_config_put16(h, PCI_BCNF_PF_LIMIT_LOW, 0);
4767 4767 pci_config_put32(h, PCI_BCNF_PF_LIMIT_HIGH, 0);
4768 4768
4769 4769 pf_mem_size = 0;
4770 4770 } else {
4771 4771 /*
4772 4772 * Reprogram the end of the PF memory range.
4773 4773 */
4774 4774 pci_config_put16(h, PCI_BCNF_PF_LIMIT_LOW,
4775 4775 PCICFG_HIWORD(PCICFG_LOADDR(pf_mem_end - 1)));
4776 4776 pci_config_put32(h, PCI_BCNF_PF_LIMIT_HIGH,
4777 4777 PCICFG_HIADDR(pf_mem_end - 1));
4778 4778 pf_mem_size = pf_mem_end - pf_mem_base;
4779 4779 }
4780 4780 }
4781 4781
4782 4782 if ((max_bus - *highest_bus) > 0) {
4783 4783 /*
4784 4784 * Give back unused bus numbers
4785 4785 */
4786 4786 (void) ndi_ra_free(ddi_get_parent(new_child),
4787 4787 *highest_bus+1, max_bus - *highest_bus,
4788 4788 NDI_RA_TYPE_PCI_BUSNUM, NDI_RA_PASS);
4789 4789 }
4790 4790
4791 4791 /*
4792 4792 * Set bus numbers to ranges encountered during scan
4793 4793 */
4794 4794 (void) pcicfg_set_bus_numbers(h, bus, new_bus, *highest_bus);
4795 4795
4796 4796 /*
4797 4797 * Remove the ranges property if it exists since we will create
4798 4798 * a new one.
4799 4799 */
4800 4800 (void) ndi_prop_remove(DDI_DEV_T_NONE, new_child, "ranges");
4801 4801
4802 4802 DEBUG2("Creating Ranges property - Mem Address %lx Mem Size %x\n",
4803 4803 mem_base, mem_size);
4804 4804 DEBUG2(" - I/O Address %lx I/O Size %x\n",
4805 4805 io_base, io_size);
4806 4806 DEBUG2(" - PF Mem address %lx PF Mem Size %x\n",
4807 4807 pf_mem_base, pf_mem_size);
4808 4808
4809 4809 bzero((caddr_t)range, sizeof (ppb_ranges_t) * PCICFG_RANGE_LEN);
4810 4810
4811 4811 range[0].child_high = range[0].parent_high |= (PCI_REG_REL_M |
4812 4812 PCI_ADDR_IO);
4813 4813 range[0].child_low = range[0].parent_low = io_base;
4814 4814 range[1].child_high = range[1].parent_high |=
4815 4815 (PCI_REG_REL_M | PCI_ADDR_MEM32);
4816 4816 range[1].child_low = range[1].parent_low = mem_base;
4817 4817 range[2].child_high = range[2].parent_high |=
4818 4818 (PCI_REG_REL_M | PCI_ADDR_MEM64 | PCI_REG_PF_M);
4819 4819 range[2].child_low = range[2].parent_low = pf_mem_base;
4820 4820
4821 4821 if (io_size > 0) {
4822 4822 range[0].size_low = io_size;
4823 4823 (void) pcicfg_update_ranges_prop(new_child, &range[0]);
4824 4824 }
4825 4825 if (mem_size > 0) {
4826 4826 range[1].size_low = mem_size;
4827 4827 (void) pcicfg_update_ranges_prop(new_child, &range[1]);
4828 4828 }
4829 4829 if (pf_mem_size > 0) {
4830 4830 range[2].size_low = pf_mem_size;
4831 4831 (void) pcicfg_update_ranges_prop(new_child, &range[2]);
4832 4832 }
4833 4833
4834 4834 bus_range[0] = pci_config_get8(h, PCI_BCNF_SECBUS);
4835 4835 bus_range[1] = pci_config_get8(h, PCI_BCNF_SUBBUS);
4836 4836 DEBUG1("End of bridge probe: bus_range[0] = %d\n", bus_range[0]);
4837 4837 DEBUG1("End of bridge probe: bus_range[1] = %d\n", bus_range[1]);
4838 4838
4839 4839 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, new_child,
4840 4840 "bus-range", bus_range, 2);
4841 4841
4842 4842 rval = PCICFG_SUCCESS;
4843 4843
4844 4844 PCICFG_DUMP_BRIDGE_CONFIG(h);
4845 4845
4846 4846 cleanup:
4847 4847 /* free up resources (for error return case only) */
4848 4848 if (rval != PCICFG_SUCCESS) {
4849 4849 if (mem_alen)
4850 4850 (void) ndi_ra_free(ddi_get_parent(new_child), mem_base,
4851 4851 mem_alen, NDI_RA_TYPE_MEM, NDI_RA_PASS);
4852 4852 if (io_alen)
4853 4853 (void) ndi_ra_free(ddi_get_parent(new_child), io_base,
4854 4854 io_alen, NDI_RA_TYPE_IO, NDI_RA_PASS);
4855 4855 if (pf_mem_alen)
4856 4856 (void) ndi_ra_free(ddi_get_parent(new_child),
4857 4857 pf_mem_base, pf_mem_alen,
4858 4858 NDI_RA_TYPE_PCI_PREFETCH_MEM, NDI_RA_PASS);
4859 4859 if (pcibus_alen)
4860 4860 (void) ndi_ra_free(ddi_get_parent(new_child),
4861 4861 pcibus_base, pcibus_alen, NDI_RA_TYPE_PCI_BUSNUM,
4862 4862 NDI_RA_PASS);
4863 4863 }
4864 4864
4865 4865 /* free up any resource maps setup for the bridge node */
4866 4866 (void) ndi_ra_map_destroy(new_child, NDI_RA_TYPE_PCI_BUSNUM);
4867 4867 (void) ndi_ra_map_destroy(new_child, NDI_RA_TYPE_IO);
4868 4868 (void) ndi_ra_map_destroy(new_child, NDI_RA_TYPE_MEM);
4869 4869 (void) ndi_ra_map_destroy(new_child, NDI_RA_TYPE_PCI_PREFETCH_MEM);
4870 4870
4871 4871 return (rval);
4872 4872 }
4873 4873
4874 4874 static int
4875 4875 pcicfg_find_resource_end(dev_info_t *dip, void *hdl)
4876 4876 {
4877 4877 pcicfg_phdl_t *entry = (pcicfg_phdl_t *)hdl;
4878 4878 pci_regspec_t *pci_ap;
4879 4879 int length;
4880 4880 int rcount;
4881 4881 int i;
4882 4882
4883 4883 entry->error = PCICFG_SUCCESS;
4884 4884
4885 4885 if (dip == entry->dip) {
4886 4886 DEBUG0("Don't include parent bridge node\n");
4887 4887 return (DDI_WALK_CONTINUE);
4888 4888 } else {
4889 4889 if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
4890 4890 DDI_PROP_DONTPASS, "assigned-addresses",
4891 4891 (caddr_t)&pci_ap, &length) != DDI_PROP_SUCCESS) {
4892 4892 DEBUG0("Node doesn't have assigned-addresses\n");
4893 4893 return (DDI_WALK_CONTINUE);
4894 4894 }
4895 4895
4896 4896 rcount = length / sizeof (pci_regspec_t);
4897 4897
4898 4898 for (i = 0; i < rcount; i++) {
4899 4899
4900 4900 switch (PCI_REG_ADDR_G(pci_ap[i].pci_phys_hi)) {
4901 4901
4902 4902 case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
4903 4903 if (pci_ap[i].pci_phys_hi & PCI_REG_PF_M) {
4904 4904 if ((pci_ap[i].pci_phys_low +
4905 4905 pci_ap[i].pci_size_low) >
4906 4906 entry->pf_memory_base) {
4907 4907 entry->pf_memory_base =
4908 4908 pci_ap[i].pci_phys_low +
4909 4909 pci_ap[i].pci_size_low;
4910 4910 }
4911 4911 } else {
4912 4912 if ((pci_ap[i].pci_phys_low +
4913 4913 pci_ap[i].pci_size_low) >
4914 4914 entry->memory_base) {
4915 4915 entry->memory_base =
4916 4916 pci_ap[i].pci_phys_low +
4917 4917 pci_ap[i].pci_size_low;
4918 4918 }
4919 4919 }
4920 4920 break;
4921 4921 case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
4922 4922 if (pci_ap[i].pci_phys_hi & PCI_REG_PF_M) {
4923 4923 if ((PCICFG_LADDR(
4924 4924 pci_ap[i].pci_phys_low,
4925 4925 pci_ap[i].pci_phys_mid) +
4926 4926 pci_ap[i].pci_size_low) >
4927 4927 entry->pf_memory_base) {
4928 4928 entry->pf_memory_base =
4929 4929 PCICFG_LADDR(
4930 4930 pci_ap[i].pci_phys_low,
4931 4931 pci_ap[i].pci_phys_mid) +
4932 4932 pci_ap[i].pci_size_low;
4933 4933 }
4934 4934 } else {
4935 4935 if ((PCICFG_LADDR(
4936 4936 pci_ap[i].pci_phys_low,
4937 4937 pci_ap[i].pci_phys_mid) +
4938 4938 pci_ap[i].pci_size_low) >
4939 4939 entry->memory_base) {
4940 4940 entry->memory_base =
4941 4941 PCICFG_LADDR(
4942 4942 pci_ap[i].pci_phys_low,
4943 4943 pci_ap[i].pci_phys_mid) +
4944 4944 pci_ap[i].pci_size_low;
4945 4945 }
4946 4946 }
4947 4947 break;
4948 4948 case PCI_REG_ADDR_G(PCI_ADDR_IO):
4949 4949 if ((pci_ap[i].pci_phys_low +
4950 4950 pci_ap[i].pci_size_low) >
4951 4951 entry->io_base) {
4952 4952 entry->io_base =
4953 4953 pci_ap[i].pci_phys_low +
4954 4954 pci_ap[i].pci_size_low;
4955 4955 }
4956 4956 break;
4957 4957 }
4958 4958 }
4959 4959
4960 4960 /*
4961 4961 * free the memory allocated by ddi_getlongprop
4962 4962 */
4963 4963 kmem_free(pci_ap, length);
4964 4964
4965 4965 /*
4966 4966 * continue the walk to the next sibling to sum memory
4967 4967 */
4968 4968 return (DDI_WALK_CONTINUE);
4969 4969 }
4970 4970 }
4971 4971
4972 4972 /*
4973 4973 * Make "parent" be the parent of the "child" dip
4974 4974 */
4975 4975 static void
4976 4976 pcicfg_reparent_node(dev_info_t *child, dev_info_t *parent)
4977 4977 {
4978 4978 int circ;
4979 4979 dev_info_t *opdip;
4980 4980
4981 4981 ASSERT(i_ddi_node_state(child) <= DS_LINKED);
4982 4982 /*
4983 4983 * Unlink node from tree before reparenting
4984 4984 */
4985 4985 opdip = ddi_get_parent(child);
4986 4986 ndi_devi_enter(opdip, &circ);
4987 4987 (void) i_ndi_unconfig_node(child, DS_PROTO, 0);
4988 4988 ndi_devi_exit(opdip, circ);
4989 4989
4990 4990 DEVI(child)->devi_parent = DEVI(parent);
4991 4991 DEVI(child)->devi_bus_ctl = DEVI(parent);
4992 4992 (void) ndi_devi_bind_driver(child, 0);
4993 4993 }
4994 4994
4995 4995 /*
4996 4996 * Return PCICFG_SUCCESS if device exists at the specified address.
4997 4997 * Return PCICFG_NODEVICE is no device exists at the specified address.
4998 4998 */
4999 4999 int
5000 5000 pcicfg_config_setup(dev_info_t *dip, ddi_acc_handle_t *handle)
5001 5001 {
5002 5002 caddr_t cfgaddr;
5003 5003 ddi_device_acc_attr_t attr;
5004 5004 dev_info_t *anode;
5005 5005 int status;
5006 5006 int rlen;
5007 5007 pci_regspec_t *reg;
5008 5008 int ret = DDI_SUCCESS;
5009 5009 int16_t tmp;
5010 5010
5011 5011 /*
5012 5012 * Get the pci register spec from the node
5013 5013 */
5014 5014 status = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg",
5015 5015 (caddr_t)®, &rlen);
5016 5016
5017 5017 switch (status) {
5018 5018 case DDI_PROP_SUCCESS:
5019 5019 break;
5020 5020 case DDI_PROP_NO_MEMORY:
5021 5021 DEBUG0("reg present, but unable to get memory\n");
5022 5022 return (PCICFG_FAILURE);
5023 5023 default:
5024 5024 DEBUG0("no reg property\n");
5025 5025 return (PCICFG_FAILURE);
5026 5026 }
5027 5027
5028 5028 anode = dip;
5029 5029 DEBUG2("conf_map: dip=%p, anode=%p\n", dip, anode);
5030 5030
5031 5031 attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
5032 5032 attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
5033 5033 attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
5034 5034
5035 5035 if (ddi_regs_map_setup(anode, 0, &cfgaddr, 0, 0, &attr, handle)
5036 5036 != DDI_SUCCESS) {
5037 5037 DEBUG0("Failed to setup registers\n");
5038 5038 kmem_free((caddr_t)reg, rlen);
5039 5039 return (PCICFG_FAILURE);
5040 5040 }
5041 5041
5042 5042 /*
5043 5043 * need to use DDI interfaces as the conf space is
5044 5044 * cannot be directly accessed by the host.
5045 5045 */
5046 5046 tmp = (int16_t)ddi_get16(*handle, (uint16_t *)cfgaddr);
5047 5047 if ((tmp == (int16_t)0xffff) || (tmp == -1)) {
5048 5048 DEBUG1("NO DEVICEFOUND, read %x\n", tmp);
5049 5049 ret = PCICFG_NODEVICE;
5050 5050 } else {
5051 5051 if (tmp == 0) {
5052 5052 DEBUG0("Device Not Ready yet ?");
5053 5053 ret = PCICFG_NODEVICE;
5054 5054 } else {
5055 5055 DEBUG1("DEVICEFOUND, read %x\n", tmp);
5056 5056 ret = PCICFG_SUCCESS;
5057 5057 }
5058 5058 }
5059 5059
5060 5060 if (ret == PCICFG_NODEVICE)
5061 5061 ddi_regs_map_free(handle);
5062 5062 kmem_free((caddr_t)reg, rlen);
5063 5063
5064 5064 return (ret);
5065 5065
5066 5066 }
5067 5067
5068 5068 static void
5069 5069 pcicfg_config_teardown(ddi_acc_handle_t *handle)
5070 5070 {
5071 5071 (void) ddi_regs_map_free(handle);
5072 5072 }
5073 5073
5074 5074 static int
5075 5075 pcicfg_add_config_reg(dev_info_t *dip,
5076 5076 uint_t bus, uint_t device, uint_t func)
5077 5077 {
5078 5078 int reg[10] = { PCI_ADDR_CONFIG, 0, 0, 0, 0};
5079 5079
5080 5080 reg[0] = PCICFG_MAKE_REG_HIGH(bus, device, func, 0);
5081 5081
5082 5082 return (ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, "reg", reg, 5));
5083 5083 }
5084 5084
5085 5085 static int
5086 5086 pcicfg_ari_configure(dev_info_t *dip)
5087 5087 {
5088 5088 if (pcie_ari_supported(dip) == PCIE_ARI_FORW_NOT_SUPPORTED)
5089 5089 return (DDI_FAILURE);
5090 5090
5091 5091 /*
5092 5092 * Until we have resource balancing, dynamically configure
5093 5093 * ARI functions without firmware assistamce.
5094 5094 */
5095 5095 return (DDI_FAILURE);
5096 5096 }
5097 5097
5098 5098
5099 5099 #ifdef DEBUG
5100 5100 static void
5101 5101 debug(char *fmt, uintptr_t a1, uintptr_t a2, uintptr_t a3,
5102 5102 uintptr_t a4, uintptr_t a5)
5103 5103 {
5104 5104 if (pcicfg_debug > 1) {
5105 5105 prom_printf("pcicfg: ");
5106 5106 prom_printf(fmt, a1, a2, a3, a4, a5);
5107 5107 }
5108 5108 }
5109 5109 #endif
5110 5110
5111 5111 /*ARGSUSED*/
5112 5112 static uint8_t
5113 5113 pcicfg_get_nslots(dev_info_t *dip, ddi_acc_handle_t handle)
5114 5114 {
5115 5115 uint16_t cap_id_loc, slot_id_loc;
5116 5116 uint8_t num_slots = 0;
5117 5117
5118 5118 /* just depend on the pcie_cap for now. */
5119 5119 (void) PCI_CAP_LOCATE(handle, PCI_CAP_ID_PCI_E, &cap_id_loc);
5120 5120 (void) PCI_CAP_LOCATE(handle, PCI_CAP_ID_SLOT_ID, &slot_id_loc);
5121 5121 if (cap_id_loc != PCI_CAP_NEXT_PTR_NULL) {
5122 5122 if (pci_config_get8(handle, cap_id_loc + PCI_CAP_ID_REGS_OFF) &
5123 5123 PCIE_PCIECAP_SLOT_IMPL)
5124 5124 num_slots = 1;
5125 5125 } else /* not a PCIe switch/bridge. Must be a PCI-PCI[-X] bridge */
5126 5126 if (slot_id_loc != PCI_CAP_NEXT_PTR_NULL) {
5127 5127 uint8_t esr_reg = pci_config_get8(handle, slot_id_loc + 2);
5128 5128 num_slots = PCI_CAPSLOT_NSLOTS(esr_reg);
5129 5129 }
5130 5130 /* XXX - need to cover PCI-PCIe bridge with n slots */
5131 5131 return (num_slots);
5132 5132 }
5133 5133
5134 5134 /*ARGSUSED*/
5135 5135 static int
5136 5136 pcicfg_pcie_dev(dev_info_t *dip, ddi_acc_handle_t handle)
5137 5137 {
5138 5138 /* get parent device's device_type property */
5139 5139 char *device_type;
5140 5140 int val;
5141 5141 dev_info_t *pdip = ddi_get_parent(dip);
5142 5142
5143 5143 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip, DDI_PROP_DONTPASS,
5144 5144 "device_type", &device_type) != DDI_PROP_SUCCESS) {
5145 5145 DEBUG2("device_type property missing for %s#%d",
5146 5146 ddi_get_name(pdip), ddi_get_instance(pdip));
5147 5147 return (DDI_FAILURE);
5148 5148 }
5149 5149 DEBUG1("device_type=<%s>\n", device_type);
5150 5150
5151 5151 val = DDI_FAILURE;
5152 5152 if (strcmp(device_type, "pciex") == 0)
5153 5153 val = DDI_SUCCESS;
5154 5154 ddi_prop_free(device_type);
5155 5155 return (val);
5156 5156 }
5157 5157
5158 5158 static int
5159 5159 pcicfg_pcie_device_type(dev_info_t *dip, ddi_acc_handle_t handle)
5160 5160 {
5161 5161 int port_type = pcicfg_pcie_port_type(dip, handle);
5162 5162
5163 5163 DEBUG1("device port_type = %x\n", port_type);
5164 5164 /* No PCIe CAP regs, we are not PCIe device_type */
5165 5165 if (port_type < 0)
5166 5166 return (DDI_FAILURE);
5167 5167
5168 5168 /* check for all PCIe device_types */
5169 5169 if ((port_type == PCIE_PCIECAP_DEV_TYPE_UP) ||
5170 5170 (port_type == PCIE_PCIECAP_DEV_TYPE_DOWN) ||
5171 5171 (port_type == PCIE_PCIECAP_DEV_TYPE_ROOT) ||
5172 5172 (port_type == PCIE_PCIECAP_DEV_TYPE_PCI2PCIE))
5173 5173 return (DDI_SUCCESS);
5174 5174
5175 5175 return (DDI_FAILURE);
5176 5176
5177 5177 }
5178 5178
5179 5179 /*ARGSUSED*/
5180 5180 static int
5181 5181 pcicfg_pcie_port_type(dev_info_t *dip, ddi_acc_handle_t handle)
5182 5182 {
5183 5183 int port_type = -1;
5184 5184 uint16_t cap_loc;
5185 5185
5186 5186 /* Note: need to look at the port type information here */
5187 5187 (void) PCI_CAP_LOCATE(handle, PCI_CAP_ID_PCI_E, &cap_loc);
5188 5188 if (cap_loc != PCI_CAP_NEXT_PTR_NULL)
5189 5189 port_type = pci_config_get16(handle,
5190 5190 cap_loc + PCIE_PCIECAP) & PCIE_PCIECAP_DEV_TYPE_MASK;
5191 5191
5192 5192 return (port_type);
5193 5193 }
5194 5194
5195 5195 /*
5196 5196 * Return true if the devinfo node is in a PCI Express hierarchy.
5197 5197 */
5198 5198 static boolean_t
5199 5199 is_pcie_fabric(dev_info_t *dip)
5200 5200 {
5201 5201 dev_info_t *root = ddi_root_node();
5202 5202 dev_info_t *pdip;
5203 5203 boolean_t found = B_FALSE;
5204 5204 char *bus;
5205 5205
5206 5206 /*
5207 5207 * Does this device reside in a pcie fabric ?
5208 5208 */
5209 5209 for (pdip = dip; pdip && (pdip != root) && !found;
5210 5210 pdip = ddi_get_parent(pdip)) {
5211 5211 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip,
5212 5212 DDI_PROP_DONTPASS, "device_type", &bus) !=
5213 5213 DDI_PROP_SUCCESS)
5214 5214 break;
5215 5215
5216 5216 if (strcmp(bus, "pciex") == 0)
5217 5217 found = B_TRUE;
5218 5218
5219 5219 ddi_prop_free(bus);
5220 5220 }
5221 5221
5222 5222 return (found);
5223 5223 }
↓ open down ↓ |
4828 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX