1 /***************************************************************************
3 * devinfo_cpu : cpu devices
5 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
6 * Use is subject to license terms.
8 * Licensed under the Academic Free License version 2.1
10 **************************************************************************/
12 #pragma ident "%Z%%M% %I% %E% SMI"
21 #include <sys/utsname.h>
22 #include <libdevinfo.h>
23 #include <sys/systeminfo.h>
25 #include "../osspec.h"
26 #include "../logger.h"
28 #include "../hald_dbus.h"
29 #include "../device_info.h"
31 #include "devinfo_cpu.h"
33 static HalDevice
*devinfo_cpu_add(HalDevice
*, di_node_t
, char *, char *);
35 DevinfoDevHandler devinfo_cpu_handler
= {
45 devinfo_cpu_add(HalDevice
*parent
, di_node_t node
, char *devfs_path
, char *device_type
)
49 char *prom_device_type
= NULL
;
51 static int cpu_id
= -1;
53 di_prom_handle_t phdl
;
56 kstat_named_t
*ksdata
;
57 dbus_bool_t is_supp_freqs
;
58 char udi
[HAL_PATH_MAX
];
59 char *driver_name
, *s
;
60 char cpu_devfs_path
[HAL_PATH_MAX
];
63 * If it is x86, the software device tree node will have the
64 * device_type information which is the one passed above. If it is
65 * NULL, check if the node has a PROM entry, and check the device_type
66 * in case of sparc. Else return NULL
68 if (device_type
== NULL
) {
70 * Check the device type if it has a PROM entry. Because
71 * in sparc, the device_type entry will in the PROM node
73 if (di_nodeid (node
) == DI_PROM_NODEID
) {
74 phdl
= di_prom_init ();
75 if (phdl
== DI_PROM_HANDLE_NIL
) {
76 HAL_ERROR (("Error in Initializing the PROM "
77 "handle to find cpu device: %s",
81 if (di_prom_prop_lookup_strings (phdl
, node
,
82 "device_type", &prom_device_type
) == -1) {
86 if (strcmp (prom_device_type
, "cpu") != 0) {
91 * Get cpuid if available
93 if (di_prom_prop_lookup_ints (phdl
, node
,
94 "cpuid", &int_cpu_id
) > 0) {
98 * There is no cpuid entry in this arch.Just
99 * increment the cpuid which will be the
109 } else if (strcmp (device_type
, "cpu") == 0) {
111 * This is a x86 arch, because software device tree node
112 * has the device_type entry for cpu. The "reg" property
113 * will have the cpuid. If not just increment the cpuid
114 * which will be the current cpu instance in the kstat
116 if (di_prop_lookup_ints (DDI_DEV_T_ANY
, node
,
117 "reg", &int_cpu_id
) > 0) {
118 cpu_id
= *int_cpu_id
;
121 * There is no cpuid entry in this arch. Just
122 * increment the cpuid which will be the
132 HAL_DEBUG (("CPUID=> %x", cpu_id
));
134 d
= hal_device_new ();
137 * devinfo_set_default_properties () uses di_instance() as part of
138 * the udi. For some solaris devices like cpu di_instance() is not
139 * present and it returns -1. For the udi to be unique can use the
142 hal_device_property_set_string (d
, "info.parent",
143 "/org/freedesktop/Hal/devices/local");
146 * If cpu driver is not installed, then devfs_path returned by
147 * libdevinfo will be same for all cpu's.
148 * Since HAL stores the devices in its tree based on the devfs_path,
149 * To make it unique, will be concatenating devfs_path with cpu_id
151 if (di_driver_name (node
) == NULL
) {
152 snprintf (cpu_devfs_path
, HAL_PATH_MAX
, "%s_%d",
155 snprintf (cpu_devfs_path
, HAL_PATH_MAX
, "%s", devfs_path
);
158 HAL_DEBUG(("DevfsPath=> %s, CPUID=> %d", cpu_devfs_path
, cpu_id
));
160 hal_util_compute_udi (hald_get_gdl (), udi
, sizeof (udi
),
161 "/org/freedesktop/Hal/devices%s_%d", cpu_devfs_path
, cpu_id
);
162 hal_device_set_udi (d
, udi
);
163 hal_device_property_set_string (d
, "info.udi", udi
);
164 if (di_prop_lookup_strings (DDI_DEV_T_ANY
, node
, "model", &s
) > 0) {
165 hal_device_property_set_string (d
, "info.product", s
);
167 hal_device_property_set_string (d
, "info.product",
168 di_node_name (node
));
170 hal_device_property_set_string (d
, "solaris.devfs_path",
172 if ((driver_name
= di_driver_name (node
)) != NULL
) {
173 hal_device_property_set_string (d
, "info.solaris.driver",
177 hal_device_add_capability (d
, "processor");
179 hal_device_property_set_int (d
, "processor.number", cpu_id
);
182 * Get the cpu related info from the kstat
186 HAL_ERROR (("Could not open kstat to get cpu info: %s",
191 ksp
= kstat_lookup (kc
, "cpu_info", cpu_id
, NULL
);
193 HAL_ERROR (("Could not lookup kstat to get cpu info: %s",
201 kstat_read (kc
, ksp
, NULL
);
202 ksdata
= (kstat_named_t
*)kstat_data_lookup (ksp
, "clock_MHz");
203 if (ksdata
== NULL
) {
204 HAL_ERROR (("Could not get kstat clock_MHz data for cpu: %s",
208 clock_mhz
= (uint64_t)ksdata
->value
.l
;
210 if (hal_device_property_set_uint64 (d
, "processor.maximum_speed",
211 clock_mhz
) == FALSE
) {
212 HAL_INFO (("Could not set the processor speed device prop"));
216 ksdata
= (kstat_named_t
*)kstat_data_lookup (ksp
,
217 "supported_frequencies_Hz");
218 if (ksdata
== NULL
) {
219 HAL_INFO (("Could not get kstat supported_frequencies_Hz data"
220 " for cpu: %s", strerror (errno
)));
221 is_supp_freqs
= FALSE
;
224 * If more than one freq is supported, then they are seperated
227 if (strstr (ksdata
->value
.str
.addr
.ptr
, ":") == NULL
) {
228 is_supp_freqs
= FALSE
;
230 is_supp_freqs
= TRUE
;
234 if (hal_device_property_set_bool (d
, "processor.can_throttle",
235 is_supp_freqs
) == FALSE
) {
236 HAL_INFO (("Could not set the processor.can_throttle"
245 devinfo_add_enqueue (d
, cpu_devfs_path
, &devinfo_cpu_handler
);