xref: /onnv-gate/usr/src/cmd/hal/hald/solaris/sysevent.c (revision 7651:0cebc536e909)
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