4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
26 #include <fm/topo_hc.h>
27 #include <sys/fm/util.h>
28 #include <libxml/xpath.h>
29 #include <libxml/parser.h>
30 #include <libxml/xpathInternals.h>
31 #include <libxml/tree.h>
33 #include "fabric-xlate.h"
35 #define HAS_PROP(node, name) xmlHasProp(node, (const xmlChar *)name)
36 #define GET_PROP(node, name) ((char *)xmlGetProp(node, (const xmlChar *)name))
37 #define FREE_PROP(prop) xmlFree((xmlChar *)prop)
39 extern xmlXPathContextPtr fab_xpathCtx
;
43 fab_prep_basic_erpt(fmd_hdl_t
*hdl
, nvlist_t
*nvl
, nvlist_t
*erpt
,
49 nvlist_t
*detector
, *new_detector
;
53 /* Grab the tod, ena and detector(FMRI) */
54 err
|= nvlist_lookup_uint64_array(nvl
, "__tod", &now
, &nelem
);
55 err
|= nvlist_lookup_uint64(nvl
, "ena", &ena
);
56 err
|= nvlist_lookup_nvlist(nvl
, FM_EREPORT_DETECTOR
, &detector
);
60 /* Make a copy of the detector */
61 err
= nvlist_dup(detector
, &new_detector
, NV_UNIQUE_NAME
);
65 /* Copy the tod and ena to erpt */
66 (void) nvlist_add_uint64(erpt
, FM_EREPORT_ENA
, ena
);
67 (void) nvlist_add_uint64_array(erpt
, "__tod", now
, nelem
);
70 * Create the correct ROOT FMRI from PCIe leaf fabric ereports. Used
71 * only by fab_prep_fake_rc_erpt. See the fab_pciex_fake_rc_erpt_tbl
72 * comments for more information.
74 if (isRC
&& fab_get_rcpath(hdl
, nvl
, rcpath
)) {
75 /* Create the correct PCIe RC new_detector aka FMRI */
76 (void) nvlist_remove(new_detector
, FM_FMRI_DEV_PATH
,
78 (void) nvlist_add_string(new_detector
, FM_FMRI_DEV_PATH
,
82 /* Copy the FMRI to erpt */
83 (void) nvlist_add_nvlist(erpt
, FM_EREPORT_DETECTOR
, new_detector
);
85 nvlist_free(new_detector
);
90 fab_send_tgt_erpt(fmd_hdl_t
*hdl
, fab_data_t
*data
, const char *class,
93 nvlist_t
*nvl
= data
->nvl
;
101 tgt_trans
= data
->pcie_ue_tgt_trans
;
102 tgt_addr
= data
->pcie_ue_tgt_addr
;
103 tgt_bdf
= data
->pcie_ue_tgt_bdf
;
105 tgt_trans
= data
->pcie_sue_tgt_trans
;
106 tgt_addr
= data
->pcie_sue_tgt_addr
;
107 tgt_bdf
= data
->pcie_sue_tgt_bdf
;
110 fmd_hdl_debug(hdl
, "Sending Target Ereport: "
111 "type 0x%x addr 0x%llx fltbdf 0x%x\n",
112 tgt_trans
, tgt_addr
, tgt_bdf
);
117 if ((tgt_trans
== PF_ADDR_PIO
) && tgt_addr
)
118 fmri
= fab_find_addr(hdl
, nvl
, tgt_addr
);
119 else if ((tgt_trans
== PF_ADDR_CFG
|| (tgt_trans
== PF_ADDR_DMA
)) &&
121 fmri
= fab_find_bdf(hdl
, nvl
, tgt_bdf
);
130 /* Allocate space for new erpt */
131 if (nvlist_alloc(&erpt
, NV_UNIQUE_NAME
, 0) != 0)
134 /* Generate the target ereport class */
135 (void) snprintf(fab_buf
, FM_MAX_CLASS
, "ereport.io.%s.%s",
136 PCI_ERROR_SUBCLASS
, class);
137 (void) nvlist_add_string(erpt
, FM_CLASS
, fab_buf
);
139 /* Grab the tod, ena and detector(FMRI) */
140 err
|= nvlist_lookup_uint64_array(nvl
, "__tod", &now
, &nelem
);
141 err
|= nvlist_lookup_uint64(nvl
, "ena", &ena
);
143 /* Copy the tod and ena to erpt */
144 (void) nvlist_add_uint64(erpt
, FM_EREPORT_ENA
, ena
);
145 (void) nvlist_add_uint64_array(erpt
, "__tod", now
, nelem
);
147 /* Create the correct FMRI */
148 if (nvlist_alloc(&detector
, NV_UNIQUE_NAME
, 0) != 0) {
152 (void) nvlist_add_uint8(detector
, FM_VERSION
,
153 FM_DEV_SCHEME_VERSION
);
154 (void) nvlist_add_string(detector
, FM_FMRI_SCHEME
,
156 (void) nvlist_add_string(detector
, FM_FMRI_DEV_PATH
, fmri
);
157 (void) nvlist_add_nvlist(erpt
, FM_EREPORT_DETECTOR
, detector
);
158 nvlist_free(detector
);
160 /* Add the address payload */
161 (void) nvlist_add_uint64(erpt
, PCI_PA
, tgt_addr
);
163 fmd_hdl_debug(hdl
, "Sending target ereport: %s 0x%x\n",
165 fmd_xprt_post(hdl
, fab_fmd_xprt
, erpt
, 0);
166 if (fmd_xprt_error(hdl
, fab_fmd_xprt
))
168 fmd_hdl_strfree(hdl
, fmri
);
171 "Cannot find Target FMRI addr:0x%llx bdf 0x%x\n",
179 fmd_hdl_debug(hdl
, "Failed to send Target PCI ereport\n");
183 fab_send_erpt(fmd_hdl_t
*hdl
, fab_data_t
*data
, fab_err_tbl_t
*tbl
)
185 fab_erpt_tbl_t
*erpt_tbl
, *entry
;
189 erpt_tbl
= tbl
->erpt_tbl
;
190 if (tbl
->reg_size
== 16) {
191 reg
= (uint32_t)*((uint16_t *)
192 ((uint32_t)data
+ tbl
->reg_offset
));
194 reg
= *((uint32_t *)((uint32_t)data
+ tbl
->reg_offset
));
197 for (entry
= erpt_tbl
; entry
->err_class
; entry
++) {
198 if (!(reg
& entry
->reg_bit
))
201 if (nvlist_alloc(&erpt
, NV_UNIQUE_NAME
, 0) != 0)
203 if (tbl
->fab_prep(hdl
, data
, erpt
, entry
) != 0) {
204 fmd_hdl_debug(hdl
, "Prepping ereport failed: "
205 "class = %s\n", entry
->err_class
);
210 if (data
->pcie_rp_send_all
) {
211 fab_send_erpt_all_rps(hdl
, erpt
);
216 fmd_hdl_debug(hdl
, "Sending ereport: %s 0x%x\n", fab_buf
, reg
);
217 fmd_xprt_post(hdl
, fab_fmd_xprt
, erpt
, 0);
218 if (fmd_xprt_error(hdl
, fab_fmd_xprt
)) {
219 fmd_hdl_debug(hdl
, "Failed to send PCI ereport\n");
226 fmd_hdl_debug(hdl
, "Failed to send PCI ereport\n");
230 fab_xpath_query(fmd_hdl_t
*hdl
, const char *query
)
232 xmlXPathObjectPtr xpathObj
;
236 fmd_hdl_debug(hdl
, "xpathObj query %s\n", query
);
238 xpathObj
= xmlXPathEvalExpression((const xmlChar
*)query
,
241 if (xpathObj
== NULL
)
244 fmd_hdl_debug(hdl
, "xpathObj 0x%p type %d\n", xpathObj
,
246 nodes
= xpathObj
->nodesetval
;
249 temp
= (char *)xmlNodeGetContent(nodes
->nodeTab
[0]);
250 fmd_hdl_debug(hdl
, "query result: %s\n", temp
);
251 res
= fmd_hdl_strdup(hdl
, temp
, FMD_SLEEP
);
253 xmlXPathFreeObject(xpathObj
);
256 xmlXPathFreeObject(xpathObj
);
260 #define FAB_HC2DEV_QUERY_SIZE_MIN 160
261 #define FAB_HC2DEV_QUERY_SIZE(sz) \
262 ((sz + FAB_HC2DEV_QUERY_SIZE_MIN) * sizeof (char))
265 * hc_path is in form of "/motherboard=0/hostbridge=0/pciexrc=0"
268 fab_hc2dev(fmd_hdl_t
*hdl
, const char *hc_path
, char **dev_path
)
271 uint_t len
= FAB_HC2DEV_QUERY_SIZE_MIN
+ strlen(hc_path
);
273 query
= fmd_hdl_alloc(hdl
, len
, FMD_SLEEP
);
274 (void) snprintf(query
, len
, "//propval[@name='resource' and contains("
275 "substring(@value, string-length(@value) - %d + 1), '%s')]"
276 "/parent::*/following-sibling::*/propval[@name='dev']/@value",
277 strlen(hc_path
) + 1, hc_path
);
279 *dev_path
= fab_xpath_query(hdl
, query
);
281 fmd_hdl_free(hdl
, query
, len
);
283 return (*dev_path
!= NULL
);
287 fab_hc_path(fmd_hdl_t
*hdl
, nvlist_t
*detector
, char **hcpath
, size_t *lenp
)
289 char c
, *name
, *id
, *buf
;
292 size_t len
= 0, buf_size
= 0;
294 if (nvlist_lookup_nvlist_array(detector
, FM_FMRI_HC_LIST
, &hcl
,
298 for (i
= 0; i
< size
; i
++) {
299 if (nvlist_lookup_string(hcl
[i
], FM_FMRI_HC_NAME
, &name
) != 0)
301 if (nvlist_lookup_string(hcl
[i
], FM_FMRI_HC_ID
, &id
) != 0)
303 buf_size
+= snprintf(&c
, 1, "/%s=%s", name
, id
);
307 buf
= fmd_hdl_alloc(hdl
, buf_size
, FMD_SLEEP
);
309 for (i
= 0; i
< size
; i
++) {
310 (void) nvlist_lookup_string(hcl
[i
], FM_FMRI_HC_NAME
, &name
);
311 (void) nvlist_lookup_string(hcl
[i
], FM_FMRI_HC_ID
, &id
);
312 len
+= snprintf(buf
+ len
, buf_size
- len
, "/%s=%s", name
, id
);
322 fab_hc2dev_nvl(fmd_hdl_t
*hdl
, nvlist_t
*detector
, char **dev_path
)
327 if (! fab_hc_path(hdl
, detector
, &hcl
, &len
))
330 (void) fab_hc2dev(hdl
, hcl
, dev_path
);
332 fmd_hdl_free(hdl
, hcl
, len
);
334 return (*dev_path
!= NULL
);
338 fab_get_hcpath(fmd_hdl_t
*hdl
, nvlist_t
*nvl
, char **hcpath
, size_t *len
)
343 if (nvlist_lookup_nvlist(nvl
, FM_EREPORT_DETECTOR
, &detector
) != 0 ||
344 nvlist_lookup_string(detector
, FM_FMRI_SCHEME
, &scheme
) != 0 ||
345 ! STRCMP(scheme
, FM_FMRI_SCHEME_HC
))
348 return (fab_hc_path(hdl
, detector
, hcpath
, len
));
352 fab_find_rppath_by_df(fmd_hdl_t
*hdl
, nvlist_t
*nvl
, uint8_t df
)
359 (void) snprintf(str
, sizeof (str
), "%0hhx", df
);
362 * get the string form of the hc detector, eg
363 * /chassis=0/motherboard=0/hostbridge=0
365 if (!fab_get_hcpath(hdl
, nvl
, &hcpath
, &len
))
369 * Explanation of the XSL XPATH Query
370 * Line 1: Look at all nodes with the node name "propval"
371 * Line 2: See if the "BDF" of the node matches DF
372 * Line 3-4: See if the the node is pciexrc
373 * Line 5-6: See if the "ASRU" contains root complex
374 * Line 7-8: Go up one level and get prop value of io/dev
376 (void) snprintf(query
, sizeof (query
), "//propval["
377 "@name='BDF' and contains(substring(@value, "
378 "string-length(@value) - 1), '%s')]"
379 "/parent::*/parent::*/propgroup[@name='pci']/propval"
380 "[@name='extended-capabilities' and @value='%s']"
381 "/parent::*/parent::*/propgroup[@name='protocol']"
382 "/propval[@name='resource' and contains(@value, '%s')]"
383 "/parent::*/parent::*/propgroup[@name='io']"
384 "/propval[@name='dev']/@value", str
, PCIEX_ROOT
, hcpath
);
386 fmd_hdl_free(hdl
, hcpath
, len
);
388 return (fab_xpath_query(hdl
, query
));
392 fab_find_rppath_by_devbdf(fmd_hdl_t
*hdl
, nvlist_t
*nvl
, pcie_req_id_t bdf
)
394 xmlXPathObjectPtr xpathObj
;
399 int i
, size
, bus
, dev
, fn
;
403 if (bdf
!= (uint16_t)-1) {
404 bus
= (bdf
& PCIE_REQ_ID_BUS_MASK
) >> PCIE_REQ_ID_BUS_SHIFT
;
405 dev
= (bdf
& PCIE_REQ_ID_DEV_MASK
) >> PCIE_REQ_ID_DEV_SHIFT
;
406 fn
= (bdf
& PCIE_REQ_ID_FUNC_MASK
) >> PCIE_REQ_ID_FUNC_SHIFT
;
410 * get the string form of the hc detector, eg
411 * /chassis=0/motherboard=0/hostbridge=0
413 if (!fab_get_hcpath(hdl
, nvl
, &hcpath
, &len
))
417 * Explanation of the XSL XPATH Query
418 * Line 1: Look at all nodes with the node name "propval"
419 * Line 2-3: See if the "value" of the node ends with correct PCIEx BDF
420 * Line 4-5: See if the "value" of the node ends with correct PCI BDF
421 * Line 6: Go up one level to the parent of the current node
422 * Line 7: See if child node contains "ASRU" with the same PCIe Root
423 * Line 8: Go up see all the ancestors
425 (void) snprintf(query
, sizeof (query
), "//propval["
426 "contains(substring(@value, string-length(@value) - 34), "
427 "'pciexbus=%d/pciexdev=%d/pciexfn=%d') or "
428 "contains(substring(@value, string-length(@value) - 28), "
429 "'pcibus=%d/pcidev=%d/pcifn=%d')"
431 "*/propval[@name='resource' and contains(@value, '%s')]"
433 bus
, dev
, fn
, bus
, dev
, fn
, hcpath
);
435 fmd_hdl_free(hdl
, hcpath
, len
);
437 fmd_hdl_debug(hdl
, "xpathObj query %s\n", query
);
439 xpathObj
= xmlXPathEvalExpression((const xmlChar
*)query
, fab_xpathCtx
);
441 if (xpathObj
== NULL
)
444 nodes
= xpathObj
->nodesetval
;
445 size
= (nodes
) ? nodes
->nodeNr
: 0;
447 fmd_hdl_debug(hdl
, "xpathObj 0x%p type %d size %d\n",
448 xpathObj
, xpathObj
->type
, size
);
450 for (i
= 0; i
< size
; i
++) {
451 devNode
= nodes
->nodeTab
[i
];
452 if (STRCMP(devNode
->name
, "range") &&
453 HAS_PROP(devNode
, "name")) {
454 char *tprop
= GET_PROP(devNode
, "name");
456 /* find "range name='pciexrc'" in ancestors */
457 if (STRCMP(tprop
, PCIEX_ROOT
)) {
458 /* go down to the pciexrc instance node */
460 devNode
= nodes
->nodeTab
[i
+1];
469 /* Traverse down the xml tree to find the right propgroup */
470 for (devNode
= devNode
->children
; devNode
; devNode
= devNode
->next
) {
471 if (STRCMP(devNode
->name
, "propgroup")) {
472 char *tprop
= GET_PROP(devNode
, "name");
474 if (STRCMP(tprop
, "io")) {
484 /* Retrive the "dev" propval and return */
485 for (devNode
= devNode
->children
; devNode
; devNode
= devNode
->next
) {
486 if (STRCMP(devNode
->name
, "propval")) {
487 char *tprop
= GET_PROP(devNode
, "name");
489 if (STRCMP(tprop
, "dev")) {
490 temp
= GET_PROP(devNode
, "value");
491 retval
= fmd_hdl_strdup(hdl
, temp
, FMD_SLEEP
);
492 fmd_hdl_debug(hdl
, "RP Path: %s\n", retval
);
494 xmlXPathFreeObject(xpathObj
);
502 if (xpathObj
!= NULL
)
503 xmlXPathFreeObject(xpathObj
);
508 fab_find_rppath_by_devpath(fmd_hdl_t
*hdl
, const char *devpath
)
513 * Explanation of the XSL XPATH Query
514 * Line 1: Look at all nodes with the node name "propval"
515 * Line 2: See if the node is pciexrc
516 * Line 3: Go up to the io pgroup
517 * Line 4: See if the "dev" prop is parent of devpath
518 * Line 5: Get the 'dev' prop
520 (void) snprintf(query
, sizeof (query
), "//propval"
521 "[@name='extended-capabilities' and @value='%s']"
522 "/parent::*/parent::*/propgroup[@name='io']"
523 "/propval[@name='dev' and starts-with('%s', concat(@value, '/'))]"
524 "/@value", PCIEX_ROOT
, devpath
);
526 return (fab_xpath_query(hdl
, query
));
531 fab_get_rcpath(fmd_hdl_t
*hdl
, nvlist_t
*nvl
, char *rcpath
)
536 if (nvlist_lookup_nvlist(nvl
, FM_EREPORT_DETECTOR
, &detector
) != 0)
538 if (nvlist_lookup_string(detector
, FM_FMRI_SCHEME
, &scheme
) != 0)
541 if (STRCMP(scheme
, FM_FMRI_SCHEME_DEV
)) {
542 if (nvlist_lookup_string(detector
, FM_FMRI_DEV_PATH
,
545 (void) strncpy(rcpath
, path
, FM_MAX_CLASS
);
546 } else if (STRCMP(scheme
, FM_FMRI_SCHEME_HC
)) {
548 * This should only occur for ereports that come from the RC
549 * itself. In this case convert HC scheme to dev path.
551 if (fab_hc2dev_nvl(hdl
, detector
, &path
)) {
552 (void) strncpy(rcpath
, path
, FM_MAX_CLASS
);
553 fmd_hdl_strfree(hdl
, path
);
562 * Extract the RC path by taking the first device in the dev path
564 * /pci@0,0/pci8086,3605@2/pci8086,3500@0/pci8086,3514@1/pci8086,105e@0
568 path
= strchr(rcpath
+ 1, '/');
578 fab_find_bdf(fmd_hdl_t
*hdl
, nvlist_t
*nvl
, pcie_req_id_t bdf
)
585 if (bdf
!= (uint16_t)-1) {
586 bus
= (bdf
& PCIE_REQ_ID_BUS_MASK
) >> PCIE_REQ_ID_BUS_SHIFT
;
587 dev
= (bdf
& PCIE_REQ_ID_DEV_MASK
) >> PCIE_REQ_ID_DEV_SHIFT
;
588 fn
= (bdf
& PCIE_REQ_ID_FUNC_MASK
) >> PCIE_REQ_ID_FUNC_SHIFT
;
591 if (!fab_get_rcpath(hdl
, nvl
, rcpath
))
595 * Explanation of the XSL XPATH Query
596 * Line 1: Look at all nodes with the node name "propval"
597 * Line 2-3: See if the "value" of the node ends with correct PCIEx BDF
598 * Line 4-5: See if the "value" of the node ends with correct PCI BDF
599 * Line 6: Go up one level to the parent of the current node
600 * Line 7: See if child node contains "ASRU" with the same PCIe Root
601 * Line 8: Traverse up the parent and the other siblings and look for
602 * the io "propgroup" and get the value of the dev "propval"
604 (void) snprintf(query
, sizeof (query
), "//propval["
605 "contains(substring(@value, string-length(@value) - 34), "
606 "'pciexbus=%d/pciexdev=%d/pciexfn=%d') or "
607 "contains(substring(@value, string-length(@value) - 28), "
608 "'pcibus=%d/pcidev=%d/pcifn=%d')"
610 "*/propval[@name='ASRU' and contains(@value, '%s')]"
611 "/parent::*/following-sibling::*[@name='io']/propval[@name='dev']/"
612 "@value", bus
, dev
, fn
, bus
, dev
, fn
, rcpath
);
614 retval
= fab_xpath_query(hdl
, query
);
616 fmd_hdl_debug(hdl
, "BDF Dev Path: %s\n", retval
);
624 fab_find_addr(fmd_hdl_t
*hdl
, nvlist_t
*nvl
, uint64_t addr
)
626 xmlXPathObjectPtr xpathObj
;
634 pci_regspec_t
*assign_p
;
638 if (!fab_get_rcpath(hdl
, nvl
, rcpath
))
641 (void) snprintf(query
, sizeof (query
), "//propval["
642 "@name='ASRU' and contains(@value, '%s')]/"
643 "parent::*/following-sibling::*[@name='pci']/"
644 "propval[@name='assigned-addresses']", rcpath
);
646 fmd_hdl_debug(hdl
, "xpathObj query %s\n", query
);
648 xpathObj
= xmlXPathEvalExpression((const xmlChar
*)query
, fab_xpathCtx
);
650 if (xpathObj
== NULL
)
653 fmd_hdl_debug(hdl
, "xpathObj 0x%p type %d\n", xpathObj
, xpathObj
->type
);
655 nodes
= xpathObj
->nodesetval
;
656 size
= (nodes
) ? nodes
->nodeNr
: 0;
658 /* Decode the list of assigned addresses xml nodes for each device */
659 for (i
= 0; i
< size
; i
++) {
662 devNode
= nodes
->nodeTab
[i
];
663 if (!HAS_PROP(devNode
, "value"))
666 /* Convert "string" assigned-addresses to pci_regspec_t */
668 tprop
= GET_PROP(devNode
, "value");
669 for (token
= strtok(tprop
, " "); token
;
670 token
= strtok(NULL
, " ")) {
671 prop
[j
++] = strtoul(token
, (char **)NULL
, 16);
673 prop
[j
] = (uint32_t)-1;
676 /* Check if address belongs to this device */
677 for (assign_p
= (pci_regspec_t
*)prop
;
678 assign_p
->pci_phys_hi
!= (uint_t
)-1; assign_p
++) {
679 low
= assign_p
->pci_phys_low
;
680 hi
= low
+ assign_p
->pci_size_low
;
681 if ((addr
< hi
) && (addr
>= low
)) {
682 fmd_hdl_debug(hdl
, "Found Address\n");
690 /* Traverse up the xml tree and back down to find the right propgroup */
691 for (devNode
= devNode
->parent
->parent
->children
;
692 devNode
; devNode
= devNode
->next
) {
695 tprop
= GET_PROP(devNode
, "name");
696 if (STRCMP(devNode
->name
, "propgroup") &&
697 STRCMP(tprop
, "io")) {
706 /* Retrive the "dev" propval and return */
707 for (devNode
= devNode
->children
; devNode
; devNode
= devNode
->next
) {
710 tprop
= GET_PROP(devNode
, "name");
711 if (STRCMP(devNode
->name
, "propval") &&
712 STRCMP(tprop
, "dev")) {
714 temp
= GET_PROP(devNode
, "value");
715 retval
= fmd_hdl_strdup(hdl
, temp
, FMD_SLEEP
);
716 fmd_hdl_debug(hdl
, "Addr Dev Path: %s\n", retval
);
718 xmlXPathFreeObject(xpathObj
);
724 if (xpathObj
!= NULL
)
725 xmlXPathFreeObject(xpathObj
);
730 fab_pr(fmd_hdl_t
*hdl
, fmd_event_t
*ep
, nvlist_t
*nvl
)
734 for (nvp
= nvlist_next_nvpair(nvl
, NULL
);
736 nvp
= nvlist_next_nvpair(nvl
, nvp
)) {
738 data_type_t type
= nvpair_type(nvp
);
739 const char *name
= nvpair_name(nvp
);
754 if (STRCMP(name
, FM_CLASS
))
755 continue; /* already printed by caller */
757 fmd_hdl_debug(hdl
, " %s=", name
);
760 case DATA_TYPE_BOOLEAN
:
761 fmd_hdl_debug(hdl
, "DATA_TYPE_BOOLEAN 1");
764 case DATA_TYPE_BOOLEAN_VALUE
:
765 (void) nvpair_value_boolean_value(nvp
, &b
);
766 fmd_hdl_debug(hdl
, "DATA_TYPE_BOOLEAN_VALUE %d",
771 (void) nvpair_value_byte(nvp
, &i8
);
772 fmd_hdl_debug(hdl
, "DATA_TYPE_BYTE 0x%x", i8
);
776 (void) nvpair_value_int8(nvp
, (void *)&i8
);
777 fmd_hdl_debug(hdl
, "DATA_TYPE_INT8 0x%x", i8
);
780 case DATA_TYPE_UINT8
:
781 (void) nvpair_value_uint8(nvp
, &i8
);
782 fmd_hdl_debug(hdl
, "DATA_TYPE_UINT8 0x%x", i8
);
785 case DATA_TYPE_INT16
:
786 (void) nvpair_value_int16(nvp
, (void *)&i16
);
787 fmd_hdl_debug(hdl
, "DATA_TYPE_INT16 0x%x", i16
);
790 case DATA_TYPE_UINT16
:
791 (void) nvpair_value_uint16(nvp
, &i16
);
792 fmd_hdl_debug(hdl
, "DATA_TYPE_UINT16 0x%x", i16
);
795 case DATA_TYPE_INT32
:
796 (void) nvpair_value_int32(nvp
, (void *)&i32
);
797 fmd_hdl_debug(hdl
, "DATA_TYPE_INT32 0x%x", i32
);
800 case DATA_TYPE_UINT32
:
801 (void) nvpair_value_uint32(nvp
, &i32
);
802 fmd_hdl_debug(hdl
, "DATA_TYPE_UINT32 0x%x", i32
);
805 case DATA_TYPE_INT64
:
806 (void) nvpair_value_int64(nvp
, (void *)&i64
);
807 fmd_hdl_debug(hdl
, "DATA_TYPE_INT64 0x%llx",
811 case DATA_TYPE_UINT64
:
812 (void) nvpair_value_uint64(nvp
, &i64
);
813 fmd_hdl_debug(hdl
, "DATA_TYPE_UINT64 0x%llx",
817 case DATA_TYPE_HRTIME
:
818 (void) nvpair_value_hrtime(nvp
, (void *)&i64
);
819 fmd_hdl_debug(hdl
, "DATA_TYPE_HRTIME 0x%llx",
823 case DATA_TYPE_STRING
:
824 (void) nvpair_value_string(nvp
, &str
);
825 fmd_hdl_debug(hdl
, "DATA_TYPE_STRING \"%s\"",
826 str
? str
: "<NULL>");
829 case DATA_TYPE_NVLIST
:
830 fmd_hdl_debug(hdl
, "[");
831 (void) nvpair_value_nvlist(nvp
, &cnv
);
832 fab_pr(hdl
, NULL
, cnv
);
833 fmd_hdl_debug(hdl
, " ]");
836 case DATA_TYPE_BOOLEAN_ARRAY
:
837 case DATA_TYPE_BYTE_ARRAY
:
838 case DATA_TYPE_INT8_ARRAY
:
839 case DATA_TYPE_UINT8_ARRAY
:
840 case DATA_TYPE_INT16_ARRAY
:
841 case DATA_TYPE_UINT16_ARRAY
:
842 case DATA_TYPE_INT32_ARRAY
:
843 case DATA_TYPE_UINT32_ARRAY
:
844 case DATA_TYPE_INT64_ARRAY
:
845 case DATA_TYPE_UINT64_ARRAY
:
846 case DATA_TYPE_STRING_ARRAY
:
847 fmd_hdl_debug(hdl
, "[...]");
849 case DATA_TYPE_NVLIST_ARRAY
:
851 (void) nvpair_value_nvlist_array(nvp
, &nvlarr
,
854 for (arri
= 0; arri
< arrsize
; arri
++) {
855 fab_pr(hdl
, ep
, nvlarr
[arri
]);
859 case DATA_TYPE_UNKNOWN
:
860 fmd_hdl_debug(hdl
, "<unknown>");
867 fab_get_rpdev(fmd_hdl_t
*hdl
)
872 (void) snprintf(query
, sizeof (query
), "//propval["
873 "@name='extended-capabilities' and contains(@value, '%s')]"
874 "/parent::*/parent::*/propgroup[@name='io']"
875 "/propval[@name='dev']/@value", PCIEX_ROOT
);
877 retval
= fab_xpath_query(hdl
, query
);
879 fmd_hdl_debug(hdl
, "Root port path is %s\n", retval
);
887 fab_send_erpt_all_rps(fmd_hdl_t
*hdl
, nvlist_t
*erpt
)
889 xmlXPathObjectPtr xpathObj
;
891 char *rppath
, *hbpath
;
893 nvlist_t
*detector
, *nvl
;
897 /* get hostbridge's path */
898 if (!fab_get_hcpath(hdl
, erpt
, &hbpath
, &len
)) {
900 "fab_send_erpt_on_all_rps: fab_get_hcpath() failed.\n");
904 (void) snprintf(query
, sizeof (query
), "//propval["
905 "@name='extended-capabilities' and contains(@value, '%s')]"
906 "/parent::*/parent::*/propgroup[@name='protocol']"
907 "/propval[@name='resource' and contains(@value, '%s/')"
908 "]/parent::*/parent::*/propgroup[@name='io']"
909 "/propval[@name='dev']/@value", PCIEX_ROOT
, hbpath
);
911 fmd_hdl_free(hdl
, hbpath
, len
);
913 fmd_hdl_debug(hdl
, "xpathObj query %s\n", query
);
915 xpathObj
= xmlXPathEvalExpression((const xmlChar
*)query
, fab_xpathCtx
);
917 if (xpathObj
== NULL
)
920 nodes
= xpathObj
->nodesetval
;
921 size
= (nodes
) ? nodes
->nodeNr
: 0;
923 fmd_hdl_debug(hdl
, "xpathObj 0x%p type %d size %d\n",
924 xpathObj
, xpathObj
->type
, size
);
926 for (i
= 0; i
< size
; i
++) {
927 rppath
= (char *)xmlNodeGetContent(nodes
->nodeTab
[i
]);
928 fmd_hdl_debug(hdl
, "query result: %s\n", rppath
);
930 nvl
= detector
= NULL
;
931 if (nvlist_dup(erpt
, &nvl
, NV_UNIQUE_NAME
) != 0 ||
932 nvlist_alloc(&detector
, NV_UNIQUE_NAME
, 0) != 0) {
939 * set the detector in the original ereport to the root port
941 (void) nvlist_add_string(detector
, FM_VERSION
,
942 FM_DEV_SCHEME_VERSION
);
943 (void) nvlist_add_string(detector
, FM_FMRI_SCHEME
,
945 (void) nvlist_add_string(detector
, FM_FMRI_DEV_PATH
,
947 (void) nvlist_remove_all(nvl
, FM_EREPORT_DETECTOR
);
948 (void) nvlist_add_nvlist(nvl
, FM_EREPORT_DETECTOR
,
950 nvlist_free(detector
);
953 fmd_hdl_debug(hdl
, "Sending ereport: %s\n", fab_buf
);
954 fmd_xprt_post(hdl
, fab_fmd_xprt
, nvl
, 0);
955 if (fmd_xprt_error(hdl
, fab_fmd_xprt
))
957 "Failed to send PCI ereport\n");
960 xmlXPathFreeObject(xpathObj
);