1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #pragma ident "%Z%%M% %I% %E% SMI"
27
28 /*
29 * PCI nexus utility routines:
30 * property and config routines for attach()
31 * reg/intr/range/assigned-address property routines for bus_map()
32 * init_child()
33 * fault handling
34 */
35
36 #include <sys/types.h>
37 #include <sys/kmem.h>
38 #include <sys/async.h>
39 #include <sys/sysmacros.h>
40 #include <sys/sunddi.h>
41 #include <sys/sunndi.h>
42 #include <sys/fm/protocol.h>
43 #include <sys/fm/io/pci.h>
44 #include <sys/fm/util.h>
45 #include <sys/ddi_impldefs.h>
46 #include <sys/pci/pci_obj.h>
47
48 /*LINTLIBRARY*/
49
50 /*
51 * get_pci_properties
52 *
53 * This function is called from the attach routine to get the key
54 * properties of the pci nodes.
55 *
56 * used by: pci_attach()
57 *
58 * return value: DDI_FAILURE on failure
59 */
60 int
get_pci_properties(pci_t * pci_p,dev_info_t * dip)61 get_pci_properties(pci_t *pci_p, dev_info_t *dip)
62 {
63 int i;
64
65 /*
66 * Get the device's port id.
67 */
68 if ((pci_p->pci_id = (uint32_t)pci_get_portid(dip)) == -1u) {
69 cmn_err(CE_WARN, "%s%d: no portid property\n",
70 ddi_driver_name(dip), ddi_get_instance(dip));
71 return (DDI_FAILURE);
72 }
73
74 /*
75 * Get the bus-ranges property.
76 */
77 i = sizeof (pci_p->pci_bus_range);
78 if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
79 "bus-range", (caddr_t)&pci_p->pci_bus_range, &i) != DDI_SUCCESS) {
80 cmn_err(CE_WARN, "%s%d: no bus-range property\n",
81 ddi_driver_name(dip), ddi_get_instance(dip));
82 return (DDI_FAILURE);
83 }
84 DEBUG2(DBG_ATTACH, dip, "get_pci_properties: bus-range (%x,%x)\n",
85 pci_p->pci_bus_range.lo, pci_p->pci_bus_range.hi);
86
87 /*
88 * disable streaming cache if necessary, this must be done
89 * before PBM is configured.
90 */
91 if (ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
92 "no-streaming-cache")) {
93 pci_stream_buf_enable = 0;
94 pci_stream_buf_exists = 0;
95 }
96
97 /*
98 * Get the ranges property.
99 */
100 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "ranges",
101 (caddr_t)&pci_p->pci_ranges, &pci_p->pci_ranges_length) !=
102 DDI_SUCCESS) {
103
104 cmn_err(CE_WARN, "%s%d: no ranges property\n",
105 ddi_driver_name(dip), ddi_get_instance(dip));
106 return (DDI_FAILURE);
107 }
108 pci_fix_ranges(pci_p->pci_ranges,
109 pci_p->pci_ranges_length / sizeof (pci_ranges_t));
110
111 /*
112 * Determine the number upa slot interrupts.
113 */
114 pci_p->pci_numproxy = pci_get_numproxy(pci_p->pci_dip);
115 DEBUG1(DBG_ATTACH, dip, "get_pci_properties: numproxy=%d\n",
116 pci_p->pci_numproxy);
117
118 pci_p->pci_thermal_interrupt =
119 ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
120 "thermal-interrupt", -1);
121 DEBUG1(DBG_ATTACH, dip, "get_pci_properties: thermal_interrupt=%d\n",
122 pci_p->pci_thermal_interrupt);
123 return (DDI_SUCCESS);
124 }
125
126 /*
127 * free_pci_properties:
128 *
129 * This routine frees the memory used to cache the
130 * "ranges" properties of the pci bus device node.
131 *
132 * used by: pci_detach()
133 *
134 * return value: none
135 */
136 void
free_pci_properties(pci_t * pci_p)137 free_pci_properties(pci_t *pci_p)
138 {
139 kmem_free(pci_p->pci_ranges, pci_p->pci_ranges_length);
140 }
141
142 /*
143 * pci_reloc_reg
144 *
145 * If the "reg" entry (*pci_rp) is relocatable, lookup "assigned-addresses"
146 * property to fetch corresponding relocated address.
147 *
148 * used by: pci_map()
149 *
150 * return value:
151 *
152 * DDI_SUCCESS - on success
153 * DDI_ME_INVAL - regspec is invalid
154 */
155 int
pci_reloc_reg(dev_info_t * dip,dev_info_t * rdip,pci_t * pci_p,pci_regspec_t * rp)156 pci_reloc_reg(dev_info_t *dip, dev_info_t *rdip, pci_t *pci_p,
157 pci_regspec_t *rp)
158 {
159 int assign_len, assign_entries, i;
160 pci_regspec_t *assign_p;
161 register uint32_t phys_hi = rp->pci_phys_hi;
162
163 DEBUG5(DBG_MAP | DBG_CONT, dip, "\tpci_reloc_reg fr: %x.%x.%x %x.%x\n",
164 rp->pci_phys_hi, rp->pci_phys_mid, rp->pci_phys_low,
165 rp->pci_size_hi, rp->pci_size_low);
166
167 if ((phys_hi & PCI_RELOCAT_B) || !(phys_hi & PCI_ADDR_MASK))
168 return (DDI_SUCCESS);
169
170 /* phys_mid must be 0 regardless space type. */
171 if (rp->pci_phys_mid != 0 || rp->pci_size_hi != 0) {
172 DEBUG0(DBG_MAP | DBG_CONT, pci_p->pci_dip,
173 "phys_mid or size_hi not 0\n");
174 return (DDI_ME_INVAL);
175 }
176
177 if (ddi_getlongprop(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS,
178 "assigned-addresses", (caddr_t)&assign_p, &assign_len))
179 return (DDI_ME_INVAL);
180
181 assign_entries = assign_len / sizeof (pci_regspec_t);
182 for (i = 0; i < assign_entries; i++, assign_p++) {
183 uint32_t space_type = phys_hi & PCI_REG_ADDR_M;
184 uint32_t assign_type = assign_p->pci_phys_hi & PCI_REG_ADDR_M;
185 uint32_t assign_addr = PCI_REG_BDFR_G(assign_p->pci_phys_hi);
186
187 if (PCI_REG_BDFR_G(phys_hi) != assign_addr)
188 continue;
189 if (space_type == assign_type) { /* exact match */
190 rp->pci_phys_low += assign_p->pci_phys_low;
191 break;
192 }
193 if (space_type == PCI_ADDR_MEM64 &&
194 assign_type == PCI_ADDR_MEM32) {
195 rp->pci_phys_low += assign_p->pci_phys_low;
196 rp->pci_phys_hi ^= PCI_ADDR_MEM64 ^ PCI_ADDR_MEM32;
197 break;
198 }
199 }
200 kmem_free(assign_p - i, assign_len);
201 DEBUG5(DBG_MAP | DBG_CONT, dip, "\tpci_reloc_reg to: %x.%x.%x %x.%x\n",
202 rp->pci_phys_hi, rp->pci_phys_mid, rp->pci_phys_low,
203 rp->pci_size_hi, rp->pci_size_low);
204 return (i < assign_entries ? DDI_SUCCESS : DDI_ME_INVAL);
205 }
206
207 /*
208 * use "ranges" to translate relocated pci regspec into parent space
209 */
210 int
pci_xlate_reg(pci_t * pci_p,pci_regspec_t * pci_rp,struct regspec * new_rp)211 pci_xlate_reg(pci_t *pci_p, pci_regspec_t *pci_rp, struct regspec *new_rp)
212 {
213 int n;
214 pci_ranges_t *rng_p = pci_p->pci_ranges;
215 int rng_n = pci_p->pci_ranges_length / sizeof (pci_ranges_t);
216
217 uint32_t space_type = PCI_REG_ADDR_G(pci_rp->pci_phys_hi);
218 uint32_t reg_end, reg_begin = pci_rp->pci_phys_low;
219 uint32_t sz = pci_rp->pci_size_low;
220
221 uint32_t rng_begin, rng_end;
222
223 if (space_type == PCI_REG_ADDR_G(PCI_ADDR_CONFIG)) {
224 if (reg_begin > PCI_CONF_HDR_SIZE)
225 return (DDI_ME_INVAL);
226 sz = sz ? MIN(sz, PCI_CONF_HDR_SIZE) : PCI_CONF_HDR_SIZE;
227 reg_begin += pci_rp->pci_phys_hi;
228 }
229 reg_end = reg_begin + sz - 1;
230
231 for (n = 0; n < rng_n; n++, rng_p++) {
232 if (space_type != PCI_REG_ADDR_G(rng_p->child_high))
233 continue; /* not the same space type */
234
235 rng_begin = rng_p->child_low;
236 if (space_type == PCI_REG_ADDR_G(PCI_ADDR_CONFIG))
237 rng_begin += rng_p->child_high;
238
239 rng_end = rng_begin + rng_p->size_low - 1;
240 if (reg_begin >= rng_begin && reg_end <= rng_end)
241 break;
242 }
243 if (n >= rng_n)
244 return (DDI_ME_REGSPEC_RANGE);
245
246 new_rp->regspec_addr = reg_begin - rng_begin + rng_p->parent_low;
247 new_rp->regspec_bustype = rng_p->parent_high;
248 new_rp->regspec_size = sz;
249 DEBUG4(DBG_MAP | DBG_CONT, pci_p->pci_dip,
250 "\tpci_xlate_reg: entry %d new_rp %x.%x %x\n",
251 n, new_rp->regspec_bustype, new_rp->regspec_addr, sz);
252
253 return (DDI_SUCCESS);
254 }
255
256
257 /*
258 * report_dev
259 *
260 * This function is called from our control ops routine on a
261 * DDI_CTLOPS_REPORTDEV request.
262 *
263 * The display format is
264 *
265 * <name><inst> at <pname><pinst> device <dev> function <func>
266 *
267 * where
268 *
269 * <name> this device's name property
270 * <inst> this device's instance number
271 * <name> parent device's name property
272 * <inst> parent device's instance number
273 * <dev> this device's device number
274 * <func> this device's function number
275 */
276 int
report_dev(dev_info_t * dip)277 report_dev(dev_info_t *dip)
278 {
279 if (dip == (dev_info_t *)0)
280 return (DDI_FAILURE);
281 cmn_err(CE_CONT, "?PCI-device: %s@%s, %s%d\n",
282 ddi_node_name(dip), ddi_get_name_addr(dip),
283 ddi_driver_name(dip),
284 ddi_get_instance(dip));
285 return (DDI_SUCCESS);
286 }
287
288
289 /*
290 * reg property for pcimem nodes that covers the entire address
291 * space for the node: config, io, or memory.
292 */
293 pci_regspec_t pci_pcimem_reg[3] =
294 {
295 {PCI_ADDR_CONFIG, 0, 0, 0, 0x800000 },
296 {(uint_t)(PCI_ADDR_IO|PCI_RELOCAT_B), 0, 0, 0, PCI_IO_SIZE },
297 {(uint_t)(PCI_ADDR_MEM32|PCI_RELOCAT_B), 0, 0, 0, PCI_MEM_SIZE }
298 };
299
300 /*
301 * name_child
302 *
303 * This function is called from init_child to name a node. It is
304 * also passed as a callback for node merging functions.
305 *
306 * return value: DDI_SUCCESS, DDI_FAILURE
307 */
308 static int
name_child(dev_info_t * child,char * name,int namelen)309 name_child(dev_info_t *child, char *name, int namelen)
310 {
311 pci_regspec_t *pci_rp;
312 int reglen;
313 uint_t func;
314 char **unit_addr;
315 uint_t n;
316
317 /*
318 * Set the address portion of the node name based on
319 * unit-address property, if it exists.
320 * The interpretation of the unit-address is DD[,F]
321 * where DD is the device id and F is the function.
322 */
323 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, child,
324 DDI_PROP_DONTPASS, "unit-address", &unit_addr, &n) ==
325 DDI_PROP_SUCCESS) {
326 if (n != 1 || *unit_addr == NULL || **unit_addr == 0) {
327 cmn_err(CE_WARN, "unit-address property in %s.conf"
328 " not well-formed", ddi_driver_name(child));
329 ddi_prop_free(unit_addr);
330 return (DDI_FAILURE);
331 }
332 (void) snprintf(name, namelen, "%s", *unit_addr);
333 ddi_prop_free(unit_addr);
334 return (DDI_SUCCESS);
335 }
336
337 /*
338 * The unit-address property is does not exist. Set the address
339 * portion of the node name based on the function and device number.
340 */
341 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
342 "reg", (int **)&pci_rp, (uint_t *)®len) == DDI_SUCCESS) {
343 if (((reglen * sizeof (int)) % sizeof (pci_regspec_t)) != 0) {
344 cmn_err(CE_WARN, "reg property not well-formed");
345 return (DDI_FAILURE);
346 }
347
348 func = PCI_REG_FUNC_G(pci_rp[0].pci_phys_hi);
349 if (func != 0)
350 (void) snprintf(name, namelen, "%x,%x",
351 PCI_REG_DEV_G(pci_rp[0].pci_phys_hi), func);
352 else
353 (void) snprintf(name, namelen, "%x",
354 PCI_REG_DEV_G(pci_rp[0].pci_phys_hi));
355 ddi_prop_free(pci_rp);
356 return (DDI_SUCCESS);
357 }
358
359 cmn_err(CE_WARN, "cannot name pci child '%s'", ddi_node_name(child));
360 return (DDI_FAILURE);
361 }
362
363 int
uninit_child(pci_t * pci_p,dev_info_t * child)364 uninit_child(pci_t *pci_p, dev_info_t *child)
365 {
366 DEBUG2(DBG_CTLOPS, pci_p->pci_dip,
367 "DDI_CTLOPS_UNINITCHILD: arg=%s%d\n",
368 ddi_driver_name(child), ddi_get_instance(child));
369
370
371 (void) pm_uninit_child(child);
372
373 ddi_set_name_addr(child, NULL);
374 ddi_remove_minor_node(child, NULL);
375 impl_rem_dev_props(child);
376
377 DEBUG0(DBG_PWR, ddi_get_parent(child), "\n\n");
378
379 /*
380 * Handle chip specific post-uninit-child tasks.
381 */
382 pci_post_uninit_child(pci_p);
383
384 return (DDI_SUCCESS);
385 }
386
387 /*
388 * init_child
389 *
390 * This function is called from our control ops routine on a
391 * DDI_CTLOPS_INITCHILD request. It builds and sets the device's
392 * parent private data area.
393 *
394 * used by: pci_ctlops()
395 *
396 * return value: none
397 */
398 int
init_child(pci_t * pci_p,dev_info_t * child)399 init_child(pci_t *pci_p, dev_info_t *child)
400 {
401 pci_regspec_t *pci_rp;
402 char name[10];
403 ddi_acc_handle_t config_handle;
404 uint16_t command_preserve, command;
405 uint8_t bcr;
406 uint8_t header_type, min_gnt;
407 uint16_t latency_timer;
408 uint_t n;
409 int i, no_config;
410
411 /*
412 * The following is a special case for pcimem nodes.
413 * For these nodes we create a reg property with a
414 * single entry that covers the entire address space
415 * for the node (config, io or memory).
416 */
417 if (strcmp(ddi_driver_name(child), "pcimem") == 0) {
418 (void) ddi_prop_create(DDI_DEV_T_NONE, child,
419 DDI_PROP_CANSLEEP, "reg", (caddr_t)pci_pcimem_reg,
420 sizeof (pci_pcimem_reg));
421 ddi_set_name_addr(child, "0");
422 ddi_set_parent_data(child, NULL);
423 return (DDI_SUCCESS);
424 }
425
426 /*
427 * Check whether the node has config space or is a hard decode
428 * node (possibly created by a driver.conf file).
429 */
430 no_config = ddi_prop_get_int(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
431 "no-config", 0);
432
433 /*
434 * Pseudo nodes indicate a prototype node with per-instance
435 * properties to be merged into the real h/w device node.
436 * However, do not merge if the no-config property is set
437 * (see PSARC 2000/088).
438 */
439 if ((ndi_dev_is_persistent_node(child) == 0) && (no_config == 0)) {
440 extern int pci_allow_pseudo_children;
441
442 if (ddi_getlongprop(DDI_DEV_T_ANY, child,
443 DDI_PROP_DONTPASS, "reg", (caddr_t)&pci_rp, &i) ==
444 DDI_SUCCESS) {
445 cmn_err(CE_WARN, "cannot merge prototype from %s.conf",
446 ddi_driver_name(child));
447 kmem_free(pci_rp, i);
448 return (DDI_NOT_WELL_FORMED);
449 }
450 /*
451 * Name the child
452 */
453 if (name_child(child, name, 10) != DDI_SUCCESS)
454 return (DDI_FAILURE);
455
456 ddi_set_name_addr(child, name);
457 ddi_set_parent_data(child, NULL);
458
459 /*
460 * Try to merge the properties from this prototype
461 * node into real h/w nodes.
462 */
463 if (ndi_merge_node(child, name_child) == DDI_SUCCESS) {
464 /*
465 * Merged ok - return failure to remove the node.
466 */
467 ddi_set_name_addr(child, NULL);
468 return (DDI_FAILURE);
469 }
470
471 /* workaround for ddivs to run under PCI */
472 if (pci_allow_pseudo_children)
473 return (DDI_SUCCESS);
474
475 cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged",
476 ddi_driver_name(child), ddi_get_name_addr(child),
477 ddi_driver_name(child));
478 ddi_set_name_addr(child, NULL);
479 return (DDI_NOT_WELL_FORMED);
480 }
481
482 if (name_child(child, name, 10) != DDI_SUCCESS)
483 return (DDI_FAILURE);
484 ddi_set_name_addr(child, name);
485
486 if (no_config != 0) {
487 /*
488 * There is no config space so there's nothing more to do.
489 */
490 return (DDI_SUCCESS);
491 }
492
493 if (pm_init_child(child) != DDI_SUCCESS)
494 return (DDI_FAILURE);
495
496
497 /*
498 * If configuration registers were previously saved by
499 * child (before it went to D3), then let the child do the
500 * restore to set up the config regs as it'll first need to
501 * power the device out of D3.
502 */
503 if (ddi_prop_exists(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
504 "config-regs-saved-by-child") == 1) {
505 DEBUG0(DBG_PWR, child,
506 "INITCHILD: config regs to be restored by child\n");
507
508 return (DDI_SUCCESS);
509 }
510
511 DEBUG2(DBG_PWR, ddi_get_parent(child),
512 "INITCHILD: config regs setup for %s@%s\n",
513 ddi_node_name(child), ddi_get_name_addr(child));
514
515 /*
516 * Map the child configuration space to for initialization.
517 * We assume the obp will do the following in the devices
518 * config space:
519 *
520 * Set the latency-timer register to values appropriate
521 * for the devices on the bus (based on other devices
522 * MIN_GNT and MAX_LAT registers.
523 *
524 * Set the fast back-to-back enable bit in the command
525 * register if it's supported and all devices on the bus
526 * have the capability.
527 *
528 */
529 if (pci_config_setup(child, &config_handle) != DDI_SUCCESS) {
530 (void) pm_uninit_child(child);
531 ddi_set_name_addr(child, NULL);
532
533 return (DDI_FAILURE);
534 }
535
536 /*
537 * Determine the configuration header type.
538 */
539 header_type = pci_config_get8(config_handle, PCI_CONF_HEADER);
540 DEBUG2(DBG_INIT_CLD, pci_p->pci_dip, "%s: header_type=%x\n",
541 ddi_driver_name(child), header_type);
542
543 /*
544 * Support for "command-preserve" property. Note that we
545 * add PCI_COMM_BACK2BACK_ENAB to the bits to be preserved
546 * since the obp will set this if the device supports and
547 * all targets on the same bus support it. Since psycho
548 * doesn't support PCI_COMM_BACK2BACK_ENAB, it will never
549 * be set. This is just here in case future revs do support
550 * PCI_COMM_BACK2BACK_ENAB.
551 */
552 command_preserve =
553 ddi_prop_get_int(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
554 "command-preserve", 0);
555 DEBUG2(DBG_INIT_CLD, pci_p->pci_dip, "%s: command-preserve=%x\n",
556 ddi_driver_name(child), command_preserve);
557 command = pci_config_get16(config_handle, PCI_CONF_COMM);
558 command &= (command_preserve | PCI_COMM_BACK2BACK_ENAB);
559 command |= (pci_command_default & ~command_preserve);
560 pci_config_put16(config_handle, PCI_CONF_COMM, command);
561 command = pci_config_get16(config_handle, PCI_CONF_COMM);
562 DEBUG2(DBG_INIT_CLD, pci_p->pci_dip, "%s: command=%x\n",
563 ddi_driver_name(child),
564 pci_config_get16(config_handle, PCI_CONF_COMM));
565
566 /*
567 * If the device has a bus control register then program it
568 * based on the settings in the command register.
569 */
570 if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) {
571 bcr = pci_config_get8(config_handle, PCI_BCNF_BCNTRL);
572 if (pci_command_default & PCI_COMM_PARITY_DETECT)
573 bcr |= PCI_BCNF_BCNTRL_PARITY_ENABLE;
574 if (pci_command_default & PCI_COMM_SERR_ENABLE)
575 bcr |= PCI_BCNF_BCNTRL_SERR_ENABLE;
576 bcr |= PCI_BCNF_BCNTRL_MAST_AB_MODE;
577 pci_config_put8(config_handle, PCI_BCNF_BCNTRL, bcr);
578 }
579
580 /*
581 * Initialize cache-line-size configuration register if needed.
582 */
583 if (pci_set_cache_line_size_register &&
584 ddi_getprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
585 "cache-line-size", 0) == 0) {
586
587 pci_config_put8(config_handle, PCI_CONF_CACHE_LINESZ,
588 PCI_CACHE_LINE_SIZE);
589 n = pci_config_get8(config_handle, PCI_CONF_CACHE_LINESZ);
590 if (n != 0)
591 (void) ndi_prop_update_int(DDI_DEV_T_NONE, child,
592 "cache-line-size", n);
593 }
594
595 /*
596 * Initialize latency timer registers if needed.
597 */
598 if (pci_set_latency_timer_register &&
599 ddi_getprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
600 "latency-timer", 0) == 0) {
601
602 latency_timer = pci_latency_timer;
603 if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) {
604 pci_config_put8(config_handle, PCI_BCNF_LATENCY_TIMER,
605 latency_timer);
606 } else {
607 min_gnt = pci_config_get8(config_handle,
608 PCI_CONF_MIN_G);
609 DEBUG2(DBG_INIT_CLD, pci_p->pci_dip, "%s: min_gnt=%x\n",
610 ddi_driver_name(child), min_gnt);
611 if (min_gnt != 0) {
612 switch (pci_p->pci_pbm_p->pbm_speed) {
613 case PBM_SPEED_33MHZ:
614 latency_timer = min_gnt * 8;
615 break;
616 case PBM_SPEED_66MHZ:
617 latency_timer = min_gnt * 4;
618 break;
619 }
620 }
621 }
622 latency_timer = MIN(latency_timer, 0xff);
623 pci_config_put8(config_handle, PCI_CONF_LATENCY_TIMER,
624 latency_timer);
625 n = pci_config_get8(config_handle, PCI_CONF_LATENCY_TIMER);
626 if (n != 0)
627 (void) ndi_prop_update_int(DDI_DEV_T_NONE, child,
628 "latency-timer", n);
629 }
630
631 pci_config_teardown(&config_handle);
632
633 /*
634 * Handle chip specific init-child tasks.
635 */
636 pci_post_init_child(pci_p, child);
637
638 return (DDI_SUCCESS);
639 }
640
641 /*
642 * get_nreg_set
643 *
644 * Given a dev info pointer to a pci child, this routine returns the
645 * number of sets in its "reg" property.
646 *
647 * used by: pci_ctlops() - DDI_CTLOPS_NREGS
648 *
649 * return value: # of reg sets on success, zero on error
650 */
651 uint_t
get_nreg_set(dev_info_t * child)652 get_nreg_set(dev_info_t *child)
653 {
654 pci_regspec_t *pci_rp;
655 int i, n;
656
657 /*
658 * Get the reg property for the device.
659 */
660 if (ddi_getlongprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, "reg",
661 (caddr_t)&pci_rp, &i) != DDI_SUCCESS)
662 return (0);
663
664 n = i / (int)sizeof (pci_regspec_t);
665 kmem_free(pci_rp, i);
666 return (n);
667 }
668
669
670 /*
671 * get_nintr
672 *
673 * Given a dev info pointer to a pci child, this routine returns the
674 * number of items in its "interrupts" property.
675 *
676 * used by: pci_ctlops() - DDI_CTLOPS_NREGS
677 *
678 * return value: # of interrupts on success, zero on error
679 */
680 uint_t
get_nintr(dev_info_t * child)681 get_nintr(dev_info_t *child)
682 {
683 int *pci_ip;
684 int i, n;
685
686 if (ddi_getlongprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
687 "interrupts", (caddr_t)&pci_ip, &i) != DDI_SUCCESS)
688 return (0);
689
690 n = i / (int)sizeof (uint_t);
691 kmem_free(pci_ip, i);
692 return (n);
693 }
694
695 uint64_t
pci_get_cfg_pabase(pci_t * pci_p)696 pci_get_cfg_pabase(pci_t *pci_p)
697 {
698 int i;
699 pci_ranges_t *rangep = pci_p->pci_ranges;
700 int nrange = pci_p->pci_ranges_length / sizeof (pci_ranges_t);
701 uint32_t cfg_space_type = PCI_REG_ADDR_G(PCI_ADDR_CONFIG);
702
703 ASSERT(cfg_space_type == 0);
704
705 for (i = 0; i < nrange; i++, rangep++) {
706 if (PCI_REG_ADDR_G(rangep->child_high) == cfg_space_type)
707 break;
708 }
709
710 if (i >= nrange)
711 cmn_err(CE_PANIC, "no cfg space in pci(%p) ranges prop.\n",
712 (void *)pci_p);
713
714 return (((uint64_t)rangep->parent_high << 32) | rangep->parent_low);
715 }
716
717 int
pci_cfg_report(dev_info_t * dip,ddi_fm_error_t * derr,pci_errstate_t * pci_err_p,int caller,uint32_t prierr)718 pci_cfg_report(dev_info_t *dip, ddi_fm_error_t *derr, pci_errstate_t *pci_err_p,
719 int caller, uint32_t prierr)
720 {
721 int fatal = 0;
722 int nonfatal = 0;
723 int i;
724
725 ASSERT(dip);
726
727 derr->fme_ena = derr->fme_ena ? derr->fme_ena :
728 fm_ena_generate(0, FM_ENA_FMT1);
729
730 for (i = 0; pci_err_tbl[i].err_class != NULL; i++) {
731 if (pci_err_p->pci_cfg_stat & pci_err_tbl[i].reg_bit) {
732 char buf[FM_MAX_CLASS];
733
734 (void) snprintf(buf, FM_MAX_CLASS, "%s.%s",
735 PCI_ERROR_SUBCLASS,
736 pci_err_tbl[i].err_class);
737 ddi_fm_ereport_post(dip, buf, derr->fme_ena,
738 DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
739 PCI_CONFIG_STATUS, DATA_TYPE_UINT16,
740 pci_err_p->pci_cfg_stat,
741 PCI_CONFIG_COMMAND, DATA_TYPE_UINT16,
742 pci_err_p->pci_cfg_comm,
743 PCI_PA, DATA_TYPE_UINT64,
744 pci_err_p->pci_pa,
745 NULL);
746
747 switch (pci_err_tbl[i].reg_bit) {
748 case PCI_STAT_S_SYSERR:
749 /*
750 * address parity error on dma - treat as fatal
751 */
752 fatal++;
753 break;
754 case PCI_STAT_R_MAST_AB:
755 case PCI_STAT_R_TARG_AB:
756 case PCI_STAT_S_PERROR:
757 if (prierr) {
758 /*
759 * piow case are already handled in
760 * pbm_afsr_report()
761 */
762 break;
763 }
764 if (caller != PCI_TRAP_CALL) {
765 /*
766 * if we haven't come from trap handler
767 * we won't have an address
768 */
769 fatal++;
770 break;
771 }
772
773 /*
774 * queue target ereport - use return from
775 * pci_lookup_handle() to determine if sync
776 * or async
777 */
778 nonfatal++;
779 pci_target_enqueue(derr->fme_ena,
780 pci_err_tbl[i].terr_class,
781 PCI_ERROR_SUBCLASS,
782 (uint64_t)derr->fme_bus_specific);
783 break;
784 default:
785 /*
786 * dpe on dma write or ta on dma
787 */
788 nonfatal++;
789 break;
790 }
791 }
792 }
793
794 if (fatal)
795 return (DDI_FM_FATAL);
796 else if (nonfatal)
797 return (DDI_FM_NONFATAL);
798
799 return (DDI_FM_OK);
800 }
801
802 void
pci_child_cfg_save(dev_info_t * dip)803 pci_child_cfg_save(dev_info_t *dip)
804 {
805 dev_info_t *cdip;
806 int ret = DDI_SUCCESS;
807
808 /*
809 * Save the state of the configuration headers of child
810 * nodes.
811 */
812
813 for (cdip = ddi_get_child(dip); cdip != NULL;
814 cdip = ddi_get_next_sibling(cdip)) {
815
816 /*
817 * Not interested in children who are not already
818 * init'ed. They will be set up in init_child().
819 */
820 if (i_ddi_node_state(cdip) < DS_INITIALIZED) {
821 DEBUG2(DBG_DETACH, dip, "DDI_SUSPEND: skipping "
822 "%s%d not in CF1\n", ddi_driver_name(cdip),
823 ddi_get_instance(cdip));
824
825 continue;
826 }
827
828 /*
829 * Only save config registers if not already saved by child.
830 */
831 if (ddi_prop_exists(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS,
832 SAVED_CONFIG_REGS) == 1) {
833
834 continue;
835 }
836
837 /*
838 * The nexus needs to save config registers. Create a property
839 * so it knows to restore on resume.
840 */
841 ret = ndi_prop_create_boolean(DDI_DEV_T_NONE, cdip,
842 "nexus-saved-config-regs");
843
844 if (ret != DDI_PROP_SUCCESS) {
845 cmn_err(CE_WARN, "%s%d can't update prop %s",
846 ddi_driver_name(cdip), ddi_get_instance(cdip),
847 "nexus-saved-config-regs");
848 }
849
850 (void) pci_save_config_regs(cdip);
851 }
852 }
853
854 void
pci_child_cfg_restore(dev_info_t * dip)855 pci_child_cfg_restore(dev_info_t *dip)
856 {
857 dev_info_t *cdip;
858
859 /*
860 * Restore config registers for children that did not save
861 * their own registers. Children pwr states are UNKNOWN after
862 * a resume since it is possible for the PM framework to call
863 * resume without an actual power cycle. (ie if suspend fails).
864 */
865 for (cdip = ddi_get_child(dip); cdip != NULL;
866 cdip = ddi_get_next_sibling(cdip)) {
867
868 /*
869 * Not interested in children who are not already
870 * init'ed. They will be set up by init_child().
871 */
872 if (i_ddi_node_state(cdip) < DS_INITIALIZED) {
873 DEBUG2(DBG_DETACH, dip,
874 "DDI_RESUME: skipping %s%d not in CF1\n",
875 ddi_driver_name(cdip), ddi_get_instance(cdip));
876 continue;
877 }
878
879 /*
880 * Only restore config registers if saved by nexus.
881 */
882 if (ddi_prop_exists(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS,
883 "nexus-saved-config-regs") == 1) {
884 (void) pci_restore_config_regs(cdip);
885
886 DEBUG2(DBG_PWR, dip,
887 "DDI_RESUME: nexus restoring %s%d config regs\n",
888 ddi_driver_name(cdip), ddi_get_instance(cdip));
889
890 if (ndi_prop_remove(DDI_DEV_T_NONE, cdip,
891 "nexus-saved-config-regs") != DDI_PROP_SUCCESS) {
892 cmn_err(CE_WARN, "%s%d can't remove prop %s",
893 ddi_driver_name(cdip),
894 ddi_get_instance(cdip),
895 "nexus-saved-config-regs");
896 }
897 }
898 }
899 }
900