1dc90e123SRobert Mustacchi /*
2dc90e123SRobert Mustacchi * This file and its contents are supplied under the terms of the
3dc90e123SRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
4dc90e123SRobert Mustacchi * You may only use this file in accordance with the terms of version
5dc90e123SRobert Mustacchi * 1.0 of the CDDL.
6dc90e123SRobert Mustacchi *
7dc90e123SRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
8dc90e123SRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
9dc90e123SRobert Mustacchi * http://www.illumos.org/license/CDDL.
10dc90e123SRobert Mustacchi */
11dc90e123SRobert Mustacchi
12dc90e123SRobert Mustacchi /*
13dc90e123SRobert Mustacchi * Copyright 2019 Joyent, Inc.
14dc90e123SRobert Mustacchi */
15dc90e123SRobert Mustacchi
16dc90e123SRobert Mustacchi /*
17dc90e123SRobert Mustacchi * Chipset Enumeration
18dc90e123SRobert Mustacchi *
19dc90e123SRobert Mustacchi * Most x86 systems have some form of chipset which are components that exist on
20dc90e123SRobert Mustacchi * the motherboard that provide additional services that range from I/O such as
21dc90e123SRobert Mustacchi * memory and PCIe controllers (though as of this writing those mostly are a
22dc90e123SRobert Mustacchi * part of the CPU now) to additional functionality like Ethernet and USB
23dc90e123SRobert Mustacchi * controllers. At the moment, this module opts to enumerate a chipset node if
24dc90e123SRobert Mustacchi * there's something that exists under it that we care about such as:
25dc90e123SRobert Mustacchi *
26dc90e123SRobert Mustacchi * o Temperature sensors
27dc90e123SRobert Mustacchi * o Firmware modules
28dc90e123SRobert Mustacchi *
29dc90e123SRobert Mustacchi * If we do not detect anything, then we do not bother enumerating and trying to
30dc90e123SRobert Mustacchi * determine the different chipsets that are on the system. Currently, the only
31dc90e123SRobert Mustacchi * method for doing this is the presence of an Intel platform controller hub
32dc90e123SRobert Mustacchi * (PCH) temperature sensor.
33dc90e123SRobert Mustacchi */
34dc90e123SRobert Mustacchi
35dc90e123SRobert Mustacchi #include <fcntl.h>
36dc90e123SRobert Mustacchi #include <sys/types.h>
37dc90e123SRobert Mustacchi #include <sys/stat.h>
38dc90e123SRobert Mustacchi #include <string.h>
39dc90e123SRobert Mustacchi
40dc90e123SRobert Mustacchi #include <sys/fm/protocol.h>
41dc90e123SRobert Mustacchi #include <fm/topo_mod.h>
42dc90e123SRobert Mustacchi #include <fm/topo_list.h>
43dc90e123SRobert Mustacchi #include <fm/topo_method.h>
44dc90e123SRobert Mustacchi
45dc90e123SRobert Mustacchi #include <topo_sensor.h>
46dc90e123SRobert Mustacchi
47dc90e123SRobert Mustacchi #define CHIPSET_VERSION 1
48dc90e123SRobert Mustacchi
49dc90e123SRobert Mustacchi /*
50dc90e123SRobert Mustacchi * This is the path to the temperature sensor that, if present, indicates we
51dc90e123SRobert Mustacchi * should construct a chipset node.
52dc90e123SRobert Mustacchi */
53dc90e123SRobert Mustacchi static const char *topo_chipset_temp_sensor =
54dc90e123SRobert Mustacchi "/dev/sensors/temperature/pch/ts.0";
55dc90e123SRobert Mustacchi
56dc90e123SRobert Mustacchi /*
57dc90e123SRobert Mustacchi * Attempt to determine if there is enough information for us to enumerate a
58dc90e123SRobert Mustacchi * chipset node, which usually means that we would enumerate something under it
59dc90e123SRobert Mustacchi * such as a temperature sensor or provide information about some piece of
60dc90e123SRobert Mustacchi * firmware that it has. Currently, if there is no temperature sensor, then we
61dc90e123SRobert Mustacchi * don't consider one to be present and don't do anything else.
62dc90e123SRobert Mustacchi */
63dc90e123SRobert Mustacchi static boolean_t
topo_chipset_present(void)64dc90e123SRobert Mustacchi topo_chipset_present(void)
65dc90e123SRobert Mustacchi {
66dc90e123SRobert Mustacchi struct stat st;
67dc90e123SRobert Mustacchi
68dc90e123SRobert Mustacchi if (stat(topo_chipset_temp_sensor, &st) == 0 &&
69dc90e123SRobert Mustacchi S_ISCHR(st.st_mode)) {
70dc90e123SRobert Mustacchi return (B_TRUE);
71dc90e123SRobert Mustacchi }
72dc90e123SRobert Mustacchi
73dc90e123SRobert Mustacchi return (B_FALSE);
74dc90e123SRobert Mustacchi }
75dc90e123SRobert Mustacchi
76dc90e123SRobert Mustacchi static int
topo_chipset_enum(topo_mod_t * mod,tnode_t * pnode,const char * name,topo_instance_t min,topo_instance_t max,void * modarg,void * data)77dc90e123SRobert Mustacchi topo_chipset_enum(topo_mod_t *mod, tnode_t *pnode, const char *name,
78dc90e123SRobert Mustacchi topo_instance_t min, topo_instance_t max, void *modarg, void *data)
79dc90e123SRobert Mustacchi {
80dc90e123SRobert Mustacchi int ret;
81dc90e123SRobert Mustacchi nvlist_t *fmri = NULL, *auth = NULL, *presource = NULL;
82dc90e123SRobert Mustacchi tnode_t *tn = NULL;
83dc90e123SRobert Mustacchi const topo_instance_t inst = 0;
84dc90e123SRobert Mustacchi
85dc90e123SRobert Mustacchi topo_mod_dprintf(mod, "chipset_enum: asked to enumerate %s", name);
86dc90e123SRobert Mustacchi
87dc90e123SRobert Mustacchi if (strcmp(name, CHIPSET) != 0) {
88dc90e123SRobert Mustacchi topo_mod_dprintf(mod, "chipset_enum: asked to enumerate "
89dc90e123SRobert Mustacchi "unknown component");
90dc90e123SRobert Mustacchi return (topo_mod_seterrno(mod, EMOD_UKNOWN_ENUM));
91dc90e123SRobert Mustacchi }
92dc90e123SRobert Mustacchi
93dc90e123SRobert Mustacchi if (!topo_chipset_present()) {
94*6597d6fcSRobert Mustacchi topo_mod_dprintf(mod, "chipset_enum: no %s device present",
95*6597d6fcSRobert Mustacchi name);
96dc90e123SRobert Mustacchi return (0);
97dc90e123SRobert Mustacchi }
98dc90e123SRobert Mustacchi
99dc90e123SRobert Mustacchi if ((auth = topo_mod_auth(mod, pnode)) == NULL) {
100dc90e123SRobert Mustacchi topo_mod_dprintf(mod, "chipset_enum: failed to get topo "
101dc90e123SRobert Mustacchi "auth: %s", topo_mod_errmsg(mod));
102dc90e123SRobert Mustacchi /* topo_mod_auth() sets the module error */
103dc90e123SRobert Mustacchi ret = -1;
104dc90e123SRobert Mustacchi goto err;
105dc90e123SRobert Mustacchi }
106dc90e123SRobert Mustacchi
107dc90e123SRobert Mustacchi if ((fmri = topo_mod_hcfmri(mod, pnode, FM_HC_SCHEME_VERSION,
108dc90e123SRobert Mustacchi CHIPSET, inst, NULL, auth, NULL, NULL, NULL)) == NULL) {
109dc90e123SRobert Mustacchi topo_mod_dprintf(mod, "chipset_enum: failed to get FMRI: %s",
110dc90e123SRobert Mustacchi topo_mod_errmsg(mod));
111dc90e123SRobert Mustacchi /* topo_mod_hcfmri() sets the module error */
112dc90e123SRobert Mustacchi ret = -1;
113dc90e123SRobert Mustacchi goto err;
114dc90e123SRobert Mustacchi }
115dc90e123SRobert Mustacchi
116dc90e123SRobert Mustacchi if ((tn = topo_node_bind(mod, pnode, CHIPSET, inst, fmri)) == NULL) {
117dc90e123SRobert Mustacchi topo_mod_dprintf(mod, "chipset_enum: failed to bind node: %s",
118dc90e123SRobert Mustacchi topo_mod_errmsg(mod));
119dc90e123SRobert Mustacchi ret = -1;
120dc90e123SRobert Mustacchi goto err;
121dc90e123SRobert Mustacchi }
122dc90e123SRobert Mustacchi
123dc90e123SRobert Mustacchi if (topo_node_resource(pnode, &presource, &ret) != 0) {
124dc90e123SRobert Mustacchi topo_mod_dprintf(mod, "chipset_enum: failed to get parent "
125dc90e123SRobert Mustacchi "resource %s\n", topo_strerror(ret));
126dc90e123SRobert Mustacchi ret = topo_mod_seterrno(mod, ret);
127dc90e123SRobert Mustacchi goto err;
128dc90e123SRobert Mustacchi }
129dc90e123SRobert Mustacchi
130dc90e123SRobert Mustacchi if (topo_node_fru_set(tn, presource, 0, &ret) != 0) {
131dc90e123SRobert Mustacchi topo_mod_dprintf(mod, "chipset_enum: failed to set FRU: %s",
132dc90e123SRobert Mustacchi topo_strerror(ret));
133dc90e123SRobert Mustacchi ret = topo_mod_seterrno(mod, ret);
134dc90e123SRobert Mustacchi goto err;
135dc90e123SRobert Mustacchi }
136dc90e123SRobert Mustacchi
137dc90e123SRobert Mustacchi /*
138dc90e123SRobert Mustacchi * Finally, create the temperature sensor.
139dc90e123SRobert Mustacchi */
1401045e13aSRobert Mustacchi if ((ret = topo_sensor_create_scalar_sensor(mod, tn,
141dc90e123SRobert Mustacchi topo_chipset_temp_sensor, "temp")) != 0) {
142dc90e123SRobert Mustacchi topo_mod_dprintf(mod, "failed to create chipset temperature "
143dc90e123SRobert Mustacchi "sensor");
144dc90e123SRobert Mustacchi goto err;
145dc90e123SRobert Mustacchi }
146dc90e123SRobert Mustacchi
147dc90e123SRobert Mustacchi nvlist_free(auth);
148dc90e123SRobert Mustacchi nvlist_free(fmri);
149dc90e123SRobert Mustacchi nvlist_free(presource);
150dc90e123SRobert Mustacchi return (0);
151dc90e123SRobert Mustacchi err:
152dc90e123SRobert Mustacchi nvlist_free(auth);
153dc90e123SRobert Mustacchi nvlist_free(fmri);
154dc90e123SRobert Mustacchi nvlist_free(presource);
155dc90e123SRobert Mustacchi topo_node_unbind(tn);
156dc90e123SRobert Mustacchi return (ret);
157dc90e123SRobert Mustacchi }
158dc90e123SRobert Mustacchi
159dc90e123SRobert Mustacchi static const topo_modops_t chipset_ops = {
160dc90e123SRobert Mustacchi topo_chipset_enum, NULL
161dc90e123SRobert Mustacchi };
162dc90e123SRobert Mustacchi
163dc90e123SRobert Mustacchi static topo_modinfo_t chipset_mod = {
164dc90e123SRobert Mustacchi CHIPSET, FM_FMRI_SCHEME_HC, CHIPSET_VERSION, &chipset_ops
165dc90e123SRobert Mustacchi };
166dc90e123SRobert Mustacchi
167dc90e123SRobert Mustacchi int
_topo_init(topo_mod_t * mod,topo_version_t version)168dc90e123SRobert Mustacchi _topo_init(topo_mod_t *mod, topo_version_t version)
169dc90e123SRobert Mustacchi {
170dc90e123SRobert Mustacchi if (getenv("TOPOCHIPSETDEBUG") != NULL) {
171dc90e123SRobert Mustacchi topo_mod_setdebug(mod);
172dc90e123SRobert Mustacchi }
173dc90e123SRobert Mustacchi
174dc90e123SRobert Mustacchi topo_mod_dprintf(mod, "_mod_init: initializing %s enumerator\n",
175dc90e123SRobert Mustacchi CHIPSET);
176dc90e123SRobert Mustacchi
177dc90e123SRobert Mustacchi if (version != -1) {
178dc90e123SRobert Mustacchi
179dc90e123SRobert Mustacchi }
180dc90e123SRobert Mustacchi
181dc90e123SRobert Mustacchi if (topo_mod_register(mod, &chipset_mod, TOPO_VERSION) != 0) {
182dc90e123SRobert Mustacchi return (-1);
183dc90e123SRobert Mustacchi }
184dc90e123SRobert Mustacchi
185dc90e123SRobert Mustacchi return (0);
186dc90e123SRobert Mustacchi }
187dc90e123SRobert Mustacchi
188dc90e123SRobert Mustacchi void
_topo_fini(topo_mod_t * mod)189dc90e123SRobert Mustacchi _topo_fini(topo_mod_t *mod)
190dc90e123SRobert Mustacchi {
191dc90e123SRobert Mustacchi }
192