12912Sartem /***************************************************************************
22912Sartem *
32912Sartem * sysevent.c : Solaris sysevents
42912Sartem *
56112Sqz150045 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
62912Sartem * Use is subject to license terms.
72912Sartem *
82912Sartem * Licensed under the Academic Free License version 2.1
92912Sartem *
102912Sartem **************************************************************************/
112912Sartem
123121Sartem #ifdef HAVE_CONFIG_H
136654Snp146283 #include <config.h>
143121Sartem #endif
153121Sartem
162912Sartem #include <stdio.h>
172912Sartem #include <unistd.h>
182912Sartem #include <stdlib.h>
192912Sartem #include <string.h>
202912Sartem #include <errno.h>
212912Sartem #include <fcntl.h>
222912Sartem #include <sys/dkio.h>
232912Sartem #include <sys/stat.h>
242912Sartem #include <libdevinfo.h>
252912Sartem #include <libsysevent.h>
262912Sartem #include <sys/sysevent/dev.h>
276573Sphitran #include <sys/sysevent/pwrctl.h>
286654Snp146283 #include <sys/sysevent/dr.h>
292912Sartem #include <glib.h>
306654Snp146283 #include <config_admin.h>
316654Snp146283 #include <kstat.h>
322912Sartem
332912Sartem #include "../osspec.h"
342912Sartem #include "../logger.h"
352912Sartem #include "../hald.h"
362912Sartem #include "../hald_dbus.h"
372912Sartem #include "../device_info.h"
382912Sartem #include "../util.h"
392912Sartem #include "osspec_solaris.h"
402912Sartem #include "hotplug.h"
412912Sartem #include "devinfo.h"
422912Sartem #include "devinfo_storage.h"
434035Sphitran #include "devinfo_acpi.h"
446112Sqz150045 #include "devinfo_usb.h"
452912Sartem #include "sysevent.h"
466654Snp146283 #include "devinfo_misc.h"
476654Snp146283 #include "devinfo_cpu.h"
482912Sartem
492912Sartem #ifndef ESC_LOFI
506112Sqz150045 #define ESC_LOFI "lofi"
512912Sartem #endif
522912Sartem
532912Sartem static void sysevent_dev_handler(sysevent_t *);
542912Sartem static gboolean sysevent_iochannel_data(GIOChannel *, GIOCondition, gpointer);
552912Sartem static void sysevent_dev_add(gchar *, gchar *);
562912Sartem static void sysevent_dev_remove(gchar *, gchar *);
572912Sartem static void sysevent_dev_branch(gchar *);
582912Sartem static void sysevent_lofi_add(gchar *, gchar *);
592912Sartem static void sysevent_lofi_remove(gchar *, gchar *);
606112Sqz150045 static void sysevent_devfs_add(gchar *);
616573Sphitran static void sysevent_pwrctl(gchar *, gchar *, gchar *, gchar *, gchar *,
626573Sphitran gchar *, uint_t);
636654Snp146283 static void sysevent_process_dr(gchar *, gchar *);
642912Sartem
652912Sartem static sysevent_handle_t *shp;
662912Sartem
672912Sartem static int sysevent_pipe_fds[2];
682912Sartem static GIOChannel *sysevent_iochannel;
692912Sartem static guint sysevent_source_id;
702912Sartem
712912Sartem gboolean
sysevent_init(void)722912Sartem sysevent_init(void)
732912Sartem {
742912Sartem GError *err = NULL;
756573Sphitran const char *subcl[6];
762912Sartem
776112Sqz150045 /*
782912Sartem * pipe used to serialize sysevents through the main loop
796112Sqz150045 */
806112Sqz150045 if (pipe (sysevent_pipe_fds) != 0) {
816112Sqz150045 HAL_INFO (("pipe() failed errno=%d", errno));
822912Sartem return (FALSE);
836112Sqz150045 }
846112Sqz150045 sysevent_iochannel = g_io_channel_unix_new (sysevent_pipe_fds[0]);
852912Sartem if (sysevent_iochannel == NULL) {
866112Sqz150045 HAL_INFO (("g_io_channel_unix_new failed"));
872912Sartem return (FALSE);
882912Sartem }
892912Sartem g_io_channel_set_flags (sysevent_iochannel, G_IO_FLAG_NONBLOCK, &err);
906112Sqz150045 sysevent_source_id = g_io_add_watch (
916112Sqz150045 sysevent_iochannel, G_IO_IN, sysevent_iochannel_data, NULL);
922912Sartem
932912Sartem shp = sysevent_bind_handle(sysevent_dev_handler);
942912Sartem if (shp == NULL) {
952912Sartem HAL_INFO (("sysevent_bind_handle failed %d", errno));
962912Sartem return (FALSE);
972912Sartem }
982912Sartem
992912Sartem subcl[0] = ESC_DISK;
1002912Sartem subcl[1] = ESC_LOFI;
1013536Sjacobs subcl[2] = ESC_PRINTER;
1023536Sjacobs if (sysevent_subscribe_event(shp, EC_DEV_ADD, subcl, 3) != 0) {
1032912Sartem HAL_INFO (("subscribe(dev_add) failed %d", errno));
1042912Sartem sysevent_unbind_handle(shp);
1052912Sartem return (FALSE);
1062912Sartem }
1073536Sjacobs if (sysevent_subscribe_event(shp, EC_DEV_REMOVE, subcl, 3) != 0) {
1082912Sartem HAL_INFO (("subscribe(dev_remove) failed %d", errno));
1092912Sartem sysevent_unbind_handle(shp);
1102912Sartem return (FALSE);
1112912Sartem }
1122912Sartem
1132912Sartem subcl[0] = ESC_DEV_BRANCH_REMOVE;
1142912Sartem if (sysevent_subscribe_event(shp, EC_DEV_BRANCH, subcl, 1) != 0) {
1152912Sartem HAL_INFO (("subscribe(dev_branch) failed %d", errno));
1162912Sartem sysevent_unbind_handle(shp);
1172912Sartem return (FALSE);
1182912Sartem }
1192912Sartem
1206573Sphitran subcl[0] = ESC_PWRCTL_ADD;
1216573Sphitran subcl[1] = ESC_PWRCTL_REMOVE;
1226573Sphitran subcl[2] = ESC_PWRCTL_STATE_CHANGE;
1236573Sphitran subcl[3] = ESC_PWRCTL_BRIGHTNESS_UP;
1246573Sphitran subcl[4] = ESC_PWRCTL_BRIGHTNESS_DOWN;
1256573Sphitran subcl[5] = ESC_PWRCTL_POWER_BUTTON;
1266573Sphitran if (sysevent_subscribe_event(shp, EC_PWRCTL, subcl, 6) != 0) {
1276112Sqz150045 HAL_INFO(("subscribe(dev_add) failed %d", errno));
1286112Sqz150045 sysevent_unbind_handle(shp);
1296112Sqz150045 return (FALSE);
1306112Sqz150045 }
1316112Sqz150045
1326112Sqz150045 subcl[0] = ESC_DEVFS_DEVI_ADD;
1336112Sqz150045 if (sysevent_subscribe_event(shp, EC_DEVFS, subcl, 1) != 0) {
1346112Sqz150045 HAL_INFO (("subscribe(EC_DEVFS) failed %d", errno));
1356112Sqz150045 sysevent_unbind_handle(shp);
1366112Sqz150045 return (FALSE);
1376112Sqz150045 }
1384035Sphitran
1396654Snp146283 subcl[0] = ESC_DR_AP_STATE_CHANGE;
1406654Snp146283 if (sysevent_subscribe_event(shp, EC_DR, subcl, 1) != 0) {
1416654Snp146283 HAL_INFO (("subscribe(dynamic reconfiguration) failed %d",
1426654Snp146283 errno));
1436654Snp146283 sysevent_unbind_handle(shp);
1446654Snp146283 return (FALSE);
1456654Snp146283 }
1466654Snp146283
1472912Sartem return (B_TRUE);
1482912Sartem }
1492912Sartem
1502912Sartem void
sysevent_fini(void)1512912Sartem sysevent_fini(void)
1522912Sartem {
1532912Sartem sysevent_unbind_handle(shp);
1542912Sartem shp = NULL;
1552912Sartem }
1562912Sartem
1572912Sartem static void
sysevent_dev_handler(sysevent_t * ev)1582912Sartem sysevent_dev_handler(sysevent_t *ev)
1592912Sartem {
1602912Sartem char *class;
1612912Sartem char *subclass;
1622912Sartem nvlist_t *attr_list;
1632912Sartem char *phys_path;
1642912Sartem char *dev_name;
1654035Sphitran char *dev_hid;
1664035Sphitran char *dev_uid;
1674035Sphitran uint_t dev_index;
1682912Sartem char s[1024];
1692912Sartem ssize_t nwritten;
1702912Sartem
1712912Sartem if ((class = sysevent_get_class_name(ev)) == NULL)
1722912Sartem return;
1732912Sartem
1742912Sartem if ((subclass = sysevent_get_subclass_name(ev)) == NULL)
1752912Sartem return;
1762912Sartem
1772912Sartem if (sysevent_get_attr_list(ev, &attr_list) != 0)
1782912Sartem return;
1792912Sartem
1806112Sqz150045 if (strcmp(class, EC_DEVFS) == 0) {
1816112Sqz150045 if (nvlist_lookup_string(attr_list, DEVFS_PATHNAME, &phys_path) != 0) {
1826112Sqz150045 goto out;
1836112Sqz150045 }
1846112Sqz150045
1856112Sqz150045 snprintf(s, sizeof (s), "%s %s %s\n",
1866112Sqz150045 class, subclass, phys_path);
1876112Sqz150045 nwritten = write(sysevent_pipe_fds[1], s, strlen(s) + 1);
1886112Sqz150045
1896112Sqz150045 HAL_INFO (("sysevent_dev_handler: wrote %d bytes", nwritten));
1906112Sqz150045 goto out;
1916112Sqz150045 }
1926112Sqz150045
1936573Sphitran if (strcmp(class, EC_PWRCTL) == 0) {
1946573Sphitran if (nvlist_lookup_string(attr_list, PWRCTL_DEV_PHYS_PATH,
1954035Sphitran &phys_path) != 0) {
1964035Sphitran goto out;
1974035Sphitran }
1986654Snp146283 } else if (strcmp(class, EC_DR) == 0) {
1996654Snp146283 if (nvlist_lookup_string(attr_list, DR_AP_ID,
2006654Snp146283 &phys_path) != 0) {
2016654Snp146283 goto out;
2026654Snp146283 }
2034035Sphitran } else if (nvlist_lookup_string(attr_list, DEV_PHYS_PATH, &phys_path)
2044035Sphitran != 0) {
2052912Sartem goto out;
2064035Sphitran }
2072912Sartem
2086654Snp146283 /*
2096654Snp146283 * In case of EC_DR, use dev_name to store DR_HINT val
2106654Snp146283 */
2116654Snp146283 if (strcmp(class, EC_DR) == 0) {
2126654Snp146283 if (nvlist_lookup_string(attr_list, DR_HINT, &dev_name) != 0) {
2136654Snp146283 goto out;
2146654Snp146283 }
2156654Snp146283 } else if (nvlist_lookup_string(attr_list, DEV_NAME, &dev_name) != 0) {
2166573Sphitran if (strcmp(class, EC_PWRCTL) == 0) {
2174035Sphitran dev_name = "noname";
2184035Sphitran } else {
2194035Sphitran dev_name = "";
2204035Sphitran }
2214035Sphitran }
2222912Sartem
2236573Sphitran if (nvlist_lookup_string(attr_list, PWRCTL_DEV_HID, &dev_hid) != 0) {
2246112Sqz150045 dev_hid = "";
2254035Sphitran }
2266573Sphitran if (nvlist_lookup_string(attr_list, PWRCTL_DEV_UID, &dev_uid) != 0) {
2276112Sqz150045 dev_uid = "";
2284035Sphitran }
2296573Sphitran if (nvlist_lookup_uint32(attr_list, PWRCTL_DEV_INDEX, &dev_index)
2304035Sphitran != 0) {
2316112Sqz150045 dev_index = 0;
2324035Sphitran }
2334035Sphitran
2344035Sphitran snprintf(s, sizeof (s), "%s %s %s %s %s %s %d\n",
2354035Sphitran class, subclass, phys_path, dev_name, dev_hid, dev_uid, dev_index);
2362912Sartem nwritten = write(sysevent_pipe_fds[1], s, strlen(s) + 1);
2372912Sartem
2382912Sartem HAL_INFO (("sysevent_dev_handler: wrote %d bytes", nwritten));
2392912Sartem
2402912Sartem out:
2412912Sartem nvlist_free(attr_list);
2422912Sartem }
2432912Sartem
2442912Sartem static gboolean
sysevent_iochannel_data(GIOChannel * source,GIOCondition condition,gpointer user_data)2452912Sartem sysevent_iochannel_data (GIOChannel *source,
2466112Sqz150045 GIOCondition condition,
2476112Sqz150045 gpointer user_data)
2482912Sartem {
2496112Sqz150045 GError *err = NULL;
2502912Sartem gchar *s = NULL;
2512912Sartem gsize len;
2522912Sartem int matches;
2532912Sartem gchar class[1024];
2542912Sartem gchar subclass[1024];
2552912Sartem gchar phys_path[1024];
2562912Sartem gchar dev_name[1024];
2576112Sqz150045 gchar dev_uid[1024];
2586112Sqz150045 gchar dev_hid[1024];
2594035Sphitran uint_t dev_index;
2602912Sartem
2612912Sartem HAL_INFO (("sysevent_iochannel_data"));
2622912Sartem
2632912Sartem while (g_io_channel_read_line (sysevent_iochannel, &s, &len, NULL,
2646112Sqz150045 &err) == G_IO_STATUS_NORMAL) {
2652912Sartem if (len == 0) {
2662912Sartem break;
2672912Sartem }
2686654Snp146283 HAL_INFO (("IOChannel val => %s", s));
2694035Sphitran class[0] = subclass[0] = phys_path[0] = dev_name[0] =
2704035Sphitran dev_hid[0] = dev_uid[0] = '\0';
2714035Sphitran matches = sscanf(s, "%s %s %s %s %s %s %d", class, subclass,
2724035Sphitran phys_path, dev_name, dev_hid, dev_uid, &dev_index);
2732912Sartem g_free (s);
2742912Sartem s = NULL;
2752912Sartem if (matches < 3) {
2762912Sartem continue;
2772912Sartem }
2782912Sartem HAL_INFO (("sysevent: class=%s, sub=%s", class, subclass));
2792912Sartem
2802912Sartem if (strcmp(class, EC_DEV_ADD) == 0) {
2813536Sjacobs if ((strcmp(subclass, ESC_DISK) == 0) ||
2823536Sjacobs (strcmp(subclass, ESC_PRINTER) == 0)) {
2832912Sartem sysevent_dev_add(phys_path, dev_name);
2842912Sartem } else if (strcmp(subclass, ESC_LOFI) == 0) {
2852912Sartem sysevent_lofi_add(phys_path, dev_name);
2862912Sartem }
2872912Sartem } else if (strcmp(class, EC_DEV_REMOVE) == 0) {
2883536Sjacobs if ((strcmp(subclass, ESC_DISK) == 0) ||
2893536Sjacobs (strcmp(subclass, ESC_PRINTER) == 0)) {
2902912Sartem sysevent_dev_remove(phys_path, dev_name);
2912912Sartem } else if (strcmp(subclass, ESC_LOFI) == 0) {
2922912Sartem sysevent_lofi_remove(phys_path, dev_name);
2932912Sartem }
2942912Sartem } else if (strcmp(class, EC_DEV_BRANCH) == 0) {
2952912Sartem sysevent_dev_branch(phys_path);
2966573Sphitran } else if (strcmp(class, EC_PWRCTL) == 0) {
2976573Sphitran sysevent_pwrctl(class, subclass, phys_path,
2986573Sphitran dev_name, dev_hid, dev_uid, dev_index);
2996112Sqz150045 } else if (strcmp(class, EC_DEVFS) == 0) {
3006112Sqz150045 if (strcmp(subclass, ESC_DEVFS_DEVI_ADD) == 0) {
3016112Sqz150045 sysevent_devfs_add(phys_path);
3026112Sqz150045 }
3036654Snp146283 } else if (strcmp(class, EC_DR) == 0) {
3046654Snp146283 /*
3056654Snp146283 * Note: AP_ID is stored in phys_path and HINT is
3066654Snp146283 * stored in dev_name, to avoid creating seperate
3076654Snp146283 * variables and multiple conditions checking
3086654Snp146283 */
3096654Snp146283 HAL_DEBUG (("In %s, AP_ID-> %s, Hint-> %s", class,
3106654Snp146283 phys_path, dev_name));
3116654Snp146283 if (strcmp(subclass, ESC_DR_AP_STATE_CHANGE) == 0) {
3126654Snp146283 sysevent_process_dr(phys_path, dev_name);
3136654Snp146283 }
3146112Sqz150045 }
3152912Sartem }
3162912Sartem
3172912Sartem if (err) {
3182912Sartem g_error_free (err);
3192912Sartem }
3202912Sartem
3212912Sartem return (TRUE);
3222912Sartem }
3232912Sartem
3242912Sartem static void
sysevent_dev_add(gchar * devfs_path,gchar * name)3252912Sartem sysevent_dev_add(gchar *devfs_path, gchar *name)
3262912Sartem {
3272912Sartem gchar *parent_devfs_path, *hotplug_devfs_path;
3282912Sartem HalDevice *parent;
3292912Sartem
3302912Sartem HAL_INFO (("dev_add: %s %s", name, devfs_path));
3312912Sartem
3326112Sqz150045 parent = hal_util_find_closest_ancestor (devfs_path, &parent_devfs_path, &hotplug_devfs_path);
3332912Sartem if (parent == NULL) {
3342912Sartem return;
3352912Sartem }
3362912Sartem
3372912Sartem HAL_INFO (("dev_add: parent=%s", parent_devfs_path));
3382912Sartem HAL_INFO (("dev_add: real=%s", hotplug_devfs_path));
3392912Sartem
3402912Sartem devinfo_add (parent, hotplug_devfs_path);
3412912Sartem
3422912Sartem g_free (parent_devfs_path);
3432912Sartem g_free (hotplug_devfs_path);
3442912Sartem
3452912Sartem hotplug_event_process_queue ();
3462912Sartem }
3472912Sartem
3482912Sartem static void
sysevent_dev_remove(gchar * devfs_path,gchar * name)3492912Sartem sysevent_dev_remove(gchar *devfs_path, gchar *name)
3502912Sartem {
3512912Sartem HAL_INFO (("dev_remove: %s %s", name, devfs_path));
3522912Sartem
3532912Sartem devinfo_remove_branch (devfs_path, NULL);
3542912Sartem hotplug_event_process_queue ();
3552912Sartem }
3562912Sartem
3572912Sartem static void
sysevent_dev_branch(gchar * devfs_path)3582912Sartem sysevent_dev_branch(gchar *devfs_path)
3592912Sartem {
3602912Sartem HAL_INFO (("branch_remove: %s", devfs_path));
3612912Sartem
3622912Sartem devinfo_remove_branch (devfs_path, NULL);
3632912Sartem hotplug_event_process_queue ();
3642912Sartem }
3652912Sartem
3662912Sartem static void
sysevent_lofi_add(gchar * devfs_path,gchar * name)3672912Sartem sysevent_lofi_add(gchar *devfs_path, gchar *name)
3682912Sartem {
3692912Sartem di_node_t node;
3702912Sartem const char *parent_udi;
3712912Sartem HalDevice *d, *parent;
3722912Sartem
3732912Sartem HAL_INFO (("lofi_add: %s %s", name, devfs_path));
3742912Sartem
3752912Sartem if ((d = hal_device_store_match_key_value_string (hald_get_gdl (),
3762912Sartem "solaris.devfs_path", devfs_path)) == NULL) {
3772912Sartem HAL_INFO (("device not found in GDL %s", devfs_path));
3782912Sartem return;
3792912Sartem }
3802912Sartem parent_udi = hal_device_property_get_string (d, "info.parent");
3812912Sartem if ((parent_udi == NULL) || (strlen(parent_udi) == 0)) {
3822912Sartem HAL_INFO (("parent not found in GDL %s", parent_udi));
3832912Sartem return;
3842912Sartem }
3852912Sartem if ((parent = hal_device_store_match_key_value_string (hald_get_gdl (),
3862912Sartem "info.udi", parent_udi)) == NULL) {
3872912Sartem HAL_INFO (("parent not found in GDL %s", parent_udi));
3882912Sartem return;
3892912Sartem }
3902912Sartem
3912912Sartem if ((node = di_init (devfs_path, DINFOCPYALL)) == DI_NODE_NIL) {
3922912Sartem HAL_INFO (("device not found in devinfo %s", devfs_path));
3932912Sartem return;
3942912Sartem }
3952912Sartem
3963121Sartem HAL_INFO (("device %s parent %s", hal_device_get_udi (d), parent_udi));
3972912Sartem devinfo_lofi_add_major (parent, node, devfs_path, NULL, TRUE, d);
3982912Sartem
3992912Sartem di_fini (node);
4002912Sartem
4012912Sartem hotplug_event_process_queue ();
4022912Sartem }
4032912Sartem
4042912Sartem static void
sysevent_lofi_remove(gchar * parent_devfs_path,gchar * name)4052912Sartem sysevent_lofi_remove(gchar *parent_devfs_path, gchar *name)
4062912Sartem {
4072912Sartem devinfo_lofi_remove_minor(parent_devfs_path, name);
4082912Sartem hotplug_event_process_queue ();
4092912Sartem }
4106112Sqz150045
4116112Sqz150045 static HalDevice *
lookup_parent(char * devfs_path)4126112Sqz150045 lookup_parent(char *devfs_path)
4136112Sqz150045 {
4146112Sqz150045 gchar *path = NULL;
4156112Sqz150045 HalDevice *parent = NULL;
4166112Sqz150045 char *p;
4176112Sqz150045
4186112Sqz150045 path = strdup (devfs_path);
4196112Sqz150045 p = strrchr (path, '/');
4206112Sqz150045 if (p == NULL) {
4216112Sqz150045 free (path);
4226112Sqz150045 return (NULL);
4236112Sqz150045 }
4246112Sqz150045 *p = '\0';
4256112Sqz150045
4266112Sqz150045 /* Look up the parent node in the gdl. */
4276112Sqz150045 parent = hal_device_store_match_key_value_string (hald_get_gdl (),
4286112Sqz150045 "solaris.devfs_path", path);
4296112Sqz150045
4306112Sqz150045 if (parent == NULL) {
4316112Sqz150045 /* Look up the parent node in the tdl. */
4326112Sqz150045 parent = hal_device_store_match_key_value_string (hald_get_tdl (),
4336112Sqz150045 "solaris.devfs_path", path);
4346112Sqz150045 }
4356112Sqz150045
4366112Sqz150045 free (path);
4376112Sqz150045 return (parent);
4386112Sqz150045 }
4396112Sqz150045
4406112Sqz150045 /*
4416112Sqz150045 * Handle the USB bus devices hot plugging events.
4426112Sqz150045 */
4436112Sqz150045 static void
sysevent_devfs_add(gchar * devfs_path)4446112Sqz150045 sysevent_devfs_add(gchar *devfs_path)
4456112Sqz150045 {
4466112Sqz150045 di_node_t node;
4476112Sqz150045 HalDevice *parent;
4486112Sqz150045 char *driver_name;
4496112Sqz150045
4506112Sqz150045 HAL_INFO (("devfs_handle: %s", devfs_path));
4516112Sqz150045
4526112Sqz150045 if ((node = di_init (devfs_path, DINFOCPYALL)) == DI_NODE_NIL) {
4536112Sqz150045 HAL_INFO (("device not found in devinfo %s", devfs_path));
4546112Sqz150045 return;
4556112Sqz150045 }
4566112Sqz150045
4576112Sqz150045 if ((driver_name = di_driver_name (node)) == NULL)
4586112Sqz150045 goto out;
4596112Sqz150045
4606112Sqz150045 /* The disk and printer devices are handled by EC_DEV_ADD class. */
4616112Sqz150045 if ((strcmp (driver_name, "scsa2usb") == 0) ||
4626112Sqz150045 (strcmp (driver_name, "usbprn") == 0))
4636112Sqz150045 goto out;
4646112Sqz150045
4656112Sqz150045 if ((parent = lookup_parent (devfs_path)) == NULL)
4666112Sqz150045 goto out;
4676112Sqz150045
4686112Sqz150045 devinfo_usb_add (parent, node, devfs_path, NULL);
4696112Sqz150045
4706112Sqz150045 di_fini (node);
4716112Sqz150045
4726112Sqz150045 hotplug_event_process_queue ();
4736112Sqz150045
4746112Sqz150045 return;
4756112Sqz150045
4766112Sqz150045 out:
4776112Sqz150045 di_fini (node);
4786112Sqz150045 }
4796573Sphitran
4806573Sphitran static void
sysevent_pwrctl(gchar * class,gchar * subclass,gchar * phys_path,gchar * dev_name,gchar * dev_hid,gchar * dev_uid,uint_t dev_index)4816573Sphitran sysevent_pwrctl(gchar *class, gchar *subclass, gchar *phys_path,
4826573Sphitran gchar *dev_name, gchar *dev_hid, gchar *dev_uid, uint_t dev_index)
4836573Sphitran {
4846573Sphitran const gchar prefix[] = "/org/freedesktop/Hal/devices/pseudo/acpi_drv_0";
4856573Sphitran gchar udi[HAL_PATH_MAX];
4866573Sphitran
4876573Sphitran if (strcmp(dev_hid, "PNP0C0A") == 0) {
4886573Sphitran snprintf(udi, sizeof(udi), "%s_battery%d_0", prefix, dev_index);
489*7651SPhi.Tran@Sun.COM devinfo_battery_rescan(phys_path, udi);
4906573Sphitran } else if (strcmp(dev_hid, "ACPI0003") == 0) {
4916573Sphitran snprintf(udi, sizeof (udi), "%s_ac%d_0", prefix, dev_index);
492*7651SPhi.Tran@Sun.COM devinfo_battery_rescan(phys_path, udi);
4936573Sphitran } else if (strcmp(dev_hid, "PNP0C0D") == 0) {
4946573Sphitran snprintf(udi, sizeof (udi), "%s_lid_0", prefix);
495*7651SPhi.Tran@Sun.COM devinfo_lid_event(subclass, udi);
4966573Sphitran } else if (strcmp(subclass, ESC_PWRCTL_POWER_BUTTON) == 0) {
497*7651SPhi.Tran@Sun.COM devinfo_power_button_event();
4986573Sphitran } else if ((strcmp(subclass, ESC_PWRCTL_BRIGHTNESS_UP) == 0) ||
4996573Sphitran (strcmp(subclass, ESC_PWRCTL_BRIGHTNESS_DOWN) == 0)) {
500*7651SPhi.Tran@Sun.COM devinfo_brightness_hotkeys_event(subclass);
5016573Sphitran } else {
5026573Sphitran HAL_INFO(("Unmatched EC_PWRCTL"));
5036573Sphitran }
5046573Sphitran }
5056654Snp146283
5066654Snp146283 static void
sysevent_dr_remove_cpu()5076654Snp146283 sysevent_dr_remove_cpu()
5086654Snp146283 {
5096654Snp146283
5106654Snp146283 HalDeviceStore *gdl;
5116654Snp146283 GSList *iter;
5126654Snp146283 HalDevice *d, *del_dev;
5136654Snp146283 int cpu_id, del_cpuid;
5146654Snp146283 kstat_ctl_t *kc;
5156654Snp146283 kstat_t *ksp;
5166654Snp146283 kstat_named_t *ksdata;
5176654Snp146283 const char *cpu_devfs_path;
5186654Snp146283 /*
5196654Snp146283 * Find the CPU's that are DR removed. For each "processor" device in
5206654Snp146283 * HAL device tree, check if it has its corresponding kstat_info. If
5216654Snp146283 * not, then, that cpu has been removed and can remove the entry from
5226654Snp146283 * HAL entry
5236654Snp146283 */
5246654Snp146283
5256654Snp146283 HAL_DEBUG (("sysevent_dr_remove_cpu()"));
5266654Snp146283 kc = kstat_open ();
5276654Snp146283 if (kc == NULL) {
5286654Snp146283 HAL_INFO (("Error in removing HAL cpu entry during DR. Could"
5296654Snp146283 " not open kstat to get cpu info: %s", strerror (errno)));
5306654Snp146283 return;
5316654Snp146283 }
5326654Snp146283
5336654Snp146283 /*
5346654Snp146283 * Iterate through the HAL device list to get the processor devices
5356654Snp146283 */
5366654Snp146283 gdl = hald_get_gdl ();
5376654Snp146283 iter = gdl->devices;
5386654Snp146283
5396654Snp146283 while (iter != NULL) {
5406654Snp146283 d = HAL_DEVICE (iter->data);
5416654Snp146283
5426654Snp146283 if (!hal_device_has_property (d, "processor.number")) {
5436654Snp146283 iter = iter->next;
5446654Snp146283 continue;
5456654Snp146283 }
5466654Snp146283
5476654Snp146283 cpu_id = hal_device_property_get_int (d, "processor.number");
5486654Snp146283
5496654Snp146283 /*
5506654Snp146283 * Check if the above cpu_id has its info in kstat
5516654Snp146283 */
5526654Snp146283
5536654Snp146283 ksp = kstat_lookup (kc, "cpu_info", cpu_id, NULL);
5546654Snp146283 if (ksp != NULL) {
5556654Snp146283 iter = iter->next;
5566654Snp146283 continue;
5576654Snp146283 }
5586654Snp146283 /*
5596654Snp146283 * kstat info not found. Delete the device entry
5606654Snp146283 */
5616654Snp146283 HAL_INFO ((" Remove CPU entry: %d", cpu_id));
5626654Snp146283 iter = iter->next;
5636654Snp146283 cpu_devfs_path = hal_device_property_get_string (d,
5646654Snp146283 "solaris.devfs_path");
5656654Snp146283 if (cpu_devfs_path == NULL) {
5666654Snp146283 HAL_INFO (("Could not get cpu_devfs_path to "
5676654Snp146283 "remove for cpu_id %d", cpu_id));
5686654Snp146283 } else {
5696654Snp146283 /*
5706654Snp146283 * Remove the cpu device
5716654Snp146283 */
5726654Snp146283 HAL_DEBUG (("Queue %s for removal", cpu_devfs_path));
5736654Snp146283 devinfo_remove_enqueue ((char *)cpu_devfs_path, NULL);
5746654Snp146283 hotplug_event_process_queue ();
5756654Snp146283 }
5766654Snp146283 }
5776654Snp146283
5786654Snp146283 if (kc) {
5796654Snp146283 kstat_close (kc);
5806654Snp146283 }
5816654Snp146283 }
5826654Snp146283
5836654Snp146283 int
sysevent_dr_insert_cpu(di_node_t node,void * arg)5846654Snp146283 sysevent_dr_insert_cpu(di_node_t node, void *arg)
5856654Snp146283 {
5866654Snp146283 char *devfs_path;
5876654Snp146283 char *device_type = NULL;
5886654Snp146283 DevinfoDevHandler *dh;
5896654Snp146283
5906654Snp146283 dh = &devinfo_cpu_handler;
5916654Snp146283 devfs_path = di_devfs_path (node);
5926654Snp146283
5936654Snp146283 (void) di_prop_lookup_strings (DDI_DEV_T_ANY, node, "device_type",
5946654Snp146283 &device_type);
5956654Snp146283
5966654Snp146283 dh->add (NULL, node, devfs_path, device_type);
5976654Snp146283
5986654Snp146283 di_devfs_path_free (devfs_path);
5996654Snp146283 return (DI_WALK_CONTINUE);
6006654Snp146283 }
6016654Snp146283
6026654Snp146283 /*
6036654Snp146283 * Remove/Add the DR event device
6046654Snp146283 * Note: Currently it supports only CPU DR events
6056654Snp146283 */
6066654Snp146283 static void
sysevent_process_dr(gchar * ap_id,gchar * hint_val)6076654Snp146283 sysevent_process_dr(gchar *ap_id, gchar *hint_val)
6086654Snp146283 {
6096654Snp146283 cfga_err_t cfgerr;
6106654Snp146283 cfga_list_data_t *cfg_stat;
6116654Snp146283 int nlist;
6126654Snp146283 char *errstr;
6136654Snp146283 di_node_t root_node;
6146654Snp146283
6156654Snp146283 if ((ap_id == NULL) || (hint_val == NULL))
6166654Snp146283 return;
6176654Snp146283 HAL_DEBUG (("sysevent_process_dr: %s", ap_id));
6186654Snp146283
6196654Snp146283 cfgerr = config_list_ext (1, (char *const *)&ap_id, &cfg_stat, &nlist,
6206654Snp146283 NULL, NULL, &errstr, 0);
6216654Snp146283
6226654Snp146283 if (cfgerr != CFGA_OK) {
6236654Snp146283 HAL_INFO (("DR sysevent process %d config_list_ext error: %s",
6246654Snp146283 ap_id, errstr));
6256654Snp146283 goto out;
6266654Snp146283 }
6276654Snp146283 /*
6286654Snp146283 * Check if the device type is CPU
6296654Snp146283 */
6306654Snp146283 HAL_DEBUG ((" Ap-Type: %s, State: %d", cfg_stat->ap_type,
6316654Snp146283 cfg_stat->ap_r_state));
6326654Snp146283 if (strcmp (cfg_stat->ap_type, "CPU") == 0) {
6336654Snp146283 if (strcmp (hint_val, DR_HINT_REMOVE) == 0) {
6346654Snp146283 sysevent_dr_remove_cpu();
6356654Snp146283 } else if (strcmp (hint_val, DR_HINT_INSERT) == 0) {
6366654Snp146283 /*
6376654Snp146283 * Go through the device list and add the new cpu
6386654Snp146283 * entries into HAL
6396654Snp146283 */
6406654Snp146283 if ((root_node =
6416654Snp146283 di_init ("/", DINFOCPYALL)) == DI_NODE_NIL) {
6426654Snp146283 HAL_INFO (("di_init failed. "\
6436654Snp146283 "Cannot insert CPU"));
6446654Snp146283 goto out;
6456654Snp146283 }
6466654Snp146283 di_walk_node (root_node, DI_WALK_CLDFIRST, NULL,
6476654Snp146283 sysevent_dr_insert_cpu);
6486654Snp146283 di_fini (root_node);
6496654Snp146283 hotplug_event_process_queue ();
6506654Snp146283 }
6516654Snp146283 } else {
6526654Snp146283 HAL_INFO (("Not a CPU, so cannot DR"));
6536654Snp146283 }
6546654Snp146283
6556654Snp146283 out:
6566654Snp146283 if (cfg_stat)
6576654Snp146283 free (cfg_stat);
6586654Snp146283 if (errstr)
6596654Snp146283 free (errstr);
6606654Snp146283 }
661