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