17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
544961713Sgirish  * Common Development and Distribution License (the "License").
644961713Sgirish  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
2208c92e0eSMary Beale  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  *  PICL Ontario platform plug-in to message the SC to light
287c478bd9Sstevel@tonic-gate  *  or extinguish the hdd 'OK2RM' ready-to-service light in
297c478bd9Sstevel@tonic-gate  *  the event of a soft unconfigure or configure, respectively.
3008c92e0eSMary Beale  *
3108c92e0eSMary Beale  *  Erie platforms (T1000) do not have ok-to-remove LEDs
3208c92e0eSMary Beale  *  so they do not need handlers for the SBL events.
337c478bd9Sstevel@tonic-gate  */
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #include <picl.h>
367c478bd9Sstevel@tonic-gate #include <picltree.h>
377c478bd9Sstevel@tonic-gate #include <picldefs.h>
387c478bd9Sstevel@tonic-gate #include <stdio.h>
397c478bd9Sstevel@tonic-gate #include <umem.h>
407c478bd9Sstevel@tonic-gate #include <unistd.h>
417c478bd9Sstevel@tonic-gate #include <libnvpair.h>
427c478bd9Sstevel@tonic-gate #include <strings.h>
437c478bd9Sstevel@tonic-gate #include <syslog.h>
447c478bd9Sstevel@tonic-gate #include <dlfcn.h>
457c478bd9Sstevel@tonic-gate #include <link.h>
467c478bd9Sstevel@tonic-gate #include <signal.h>
476fec3791Sjesseb #include <sys/types.h>
486fec3791Sjesseb #include <sys/stat.h>
496fec3791Sjesseb #include <fcntl.h>
506fec3791Sjesseb #include <sys/param.h>
516fec3791Sjesseb #include <sys/raidioctl.h>
5208c92e0eSMary Beale #include <sys/utsname.h>
5308c92e0eSMary Beale #include <sys/systeminfo.h>
547c478bd9Sstevel@tonic-gate #include <libpcp.h>
557c478bd9Sstevel@tonic-gate #include "piclsbl.h"
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate #include "errno.h"
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate #pragma init(piclsbl_register)
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate static void *pcp_handle;
627c478bd9Sstevel@tonic-gate 
636fec3791Sjesseb static char hba_devctl[MAXPATHLEN];
646fec3791Sjesseb 
657c478bd9Sstevel@tonic-gate static int (* pcp_init_ptr)();
667c478bd9Sstevel@tonic-gate static int (* pcp_send_recv_ptr)();
677c478bd9Sstevel@tonic-gate static int (* pcp_close_ptr)();
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate static int load_pcp_libs(void);
707c478bd9Sstevel@tonic-gate static void piclsbl_init(void);
717c478bd9Sstevel@tonic-gate static void piclsbl_fini(void);
727c478bd9Sstevel@tonic-gate static void piclsbl_register(void);
737c478bd9Sstevel@tonic-gate static void piclsbl_handler(const char *ename, const void *earg,
747c478bd9Sstevel@tonic-gate 				size_t size, void *cookie);
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate static picld_plugin_reg_t piclsbl_reg = {
777c478bd9Sstevel@tonic-gate 	PICLD_PLUGIN_VERSION_1,
787c478bd9Sstevel@tonic-gate 	PICLD_PLUGIN_CRITICAL,
797c478bd9Sstevel@tonic-gate 	"piclsbl",
807c478bd9Sstevel@tonic-gate 	piclsbl_init,
817c478bd9Sstevel@tonic-gate 	piclsbl_fini
827c478bd9Sstevel@tonic-gate };
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate /*
857c478bd9Sstevel@tonic-gate  * called from init to load the pcp library
867c478bd9Sstevel@tonic-gate  */
877c478bd9Sstevel@tonic-gate static int
load_pcp_libs()887c478bd9Sstevel@tonic-gate load_pcp_libs()
897c478bd9Sstevel@tonic-gate {
907c478bd9Sstevel@tonic-gate 	char pcp_dl_lib[80];
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate 	(void) snprintf(pcp_dl_lib, sizeof (pcp_dl_lib), "%s%s",
9308c92e0eSMary Beale 	    LIB_PCP_PATH, PCPLIB);
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 	/* load the library and set up function pointers */
967c478bd9Sstevel@tonic-gate 	if ((pcp_handle = dlopen(pcp_dl_lib, RTLD_NOW)) == (void *) NULL)
977c478bd9Sstevel@tonic-gate 		return (1);
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate 	pcp_init_ptr = (int(*)())dlsym(pcp_handle, "pcp_init");
1007c478bd9Sstevel@tonic-gate 	pcp_close_ptr = (int(*)())dlsym(pcp_handle, "pcp_close");
1017c478bd9Sstevel@tonic-gate 	pcp_send_recv_ptr = (int(*)())dlsym(pcp_handle, "pcp_send_recv");
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate 	if (pcp_init_ptr == NULL || pcp_send_recv_ptr == NULL ||
10408c92e0eSMary Beale 	    pcp_close_ptr == NULL)
1057c478bd9Sstevel@tonic-gate 		return (1);
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate 	return (0);
1087c478bd9Sstevel@tonic-gate }
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate /*
1117c478bd9Sstevel@tonic-gate  * callback routine for ptree_walk_tree_by_class()
1127c478bd9Sstevel@tonic-gate  */
1137c478bd9Sstevel@tonic-gate static int
cb_find_disk(picl_nodehdl_t node,void * args)1147c478bd9Sstevel@tonic-gate cb_find_disk(picl_nodehdl_t node, void *args)
1157c478bd9Sstevel@tonic-gate {
1167c478bd9Sstevel@tonic-gate 	disk_lookup_t *lookup  = (disk_lookup_t *)args;
1177c478bd9Sstevel@tonic-gate 	int status = -1;
1186fec3791Sjesseb 	char *n;
1197c478bd9Sstevel@tonic-gate 	char path[PICL_PROPNAMELEN_MAX];
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate 	status = ptree_get_propval_by_name(node, "Path", (void *)&path,
1227c478bd9Sstevel@tonic-gate 	    PICL_PROPNAMELEN_MAX);
1237c478bd9Sstevel@tonic-gate 	if (status != PICL_SUCCESS) {
1247c478bd9Sstevel@tonic-gate 		return (PICL_WALK_CONTINUE);
1257c478bd9Sstevel@tonic-gate 	}
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	if (strcmp(path, lookup->path) == 0) {
1287c478bd9Sstevel@tonic-gate 		lookup->disk = node;
1297c478bd9Sstevel@tonic-gate 		lookup->result = DISK_FOUND;
1306fec3791Sjesseb 
1316fec3791Sjesseb 		/* store the HBA's device path for use in check_raid() */
1326fec3791Sjesseb 		n = strstr(path, "/sd");
1336fec3791Sjesseb 		strncpy(n, "\0", 1);
1346fec3791Sjesseb 		(void) snprintf(hba_devctl, MAXPATHLEN, "/devices%s:devctl",
13508c92e0eSMary Beale 		    path);
1366fec3791Sjesseb 
1377c478bd9Sstevel@tonic-gate 		return (PICL_WALK_TERMINATE);
1387c478bd9Sstevel@tonic-gate 	}
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 	return (PICL_WALK_CONTINUE);
1417c478bd9Sstevel@tonic-gate }
1427c478bd9Sstevel@tonic-gate 
1436fec3791Sjesseb /*
1446fec3791Sjesseb  * check a target for RAID membership
1456fec3791Sjesseb  */
1466fec3791Sjesseb static int
check_raid(int target)1476fec3791Sjesseb check_raid(int target)
1486fec3791Sjesseb {
1496fec3791Sjesseb 	raid_config_t config;
1506fec3791Sjesseb 	int fd;
1516fec3791Sjesseb 	int numvols;
1526fec3791Sjesseb 	int i;
1536fec3791Sjesseb 	int j;
1546fec3791Sjesseb 
1556fec3791Sjesseb 	/*
1566fec3791Sjesseb 	 * hba_devctl is set to the onboard hba, so it will
1576fec3791Sjesseb 	 * always house any onboard RAID volumes
1586fec3791Sjesseb 	 */
1596fec3791Sjesseb 	if ((fd = open(hba_devctl, O_RDONLY)) < 0) {
1606fec3791Sjesseb 		syslog(LOG_ERR, "%s", strerror(errno));
1616fec3791Sjesseb 		return (0);
1626fec3791Sjesseb 	}
1636fec3791Sjesseb 
1646fec3791Sjesseb 	/*
1656fec3791Sjesseb 	 * look up the RAID configurations for the onboard
1666fec3791Sjesseb 	 * HBA and check target against all member targets
1676fec3791Sjesseb 	 */
1686fec3791Sjesseb 	if (ioctl(fd, RAID_NUMVOLUMES, &numvols)) {
1696fec3791Sjesseb 		syslog(LOG_ERR, "%s", strerror(errno));
1706fec3791Sjesseb 		(void) close(fd);
1716fec3791Sjesseb 		return (0);
1726fec3791Sjesseb 	}
1736fec3791Sjesseb 
1746fec3791Sjesseb 	for (i = 0; i < numvols; i++) {
1756fec3791Sjesseb 		config.unitid = i;
1766fec3791Sjesseb 		if (ioctl(fd, RAID_GETCONFIG, &config)) {
1776fec3791Sjesseb 			syslog(LOG_ERR, "%s", strerror(errno));
1786fec3791Sjesseb 			(void) close(fd);
1796fec3791Sjesseb 			return (0);
1806fec3791Sjesseb 		}
1816fec3791Sjesseb 
1826fec3791Sjesseb 		for (j = 0; j < config.ndisks; j++) {
1836fec3791Sjesseb 			if (config.disk[j] == target) {
1846fec3791Sjesseb 				(void) close(fd);
1856fec3791Sjesseb 				return (1);
1866fec3791Sjesseb 			}
1876fec3791Sjesseb 		}
1886fec3791Sjesseb 	}
1896fec3791Sjesseb 	(void) close(fd);
1906fec3791Sjesseb 	return (0);
1916fec3791Sjesseb }
1926fec3791Sjesseb 
1937c478bd9Sstevel@tonic-gate /*
1947c478bd9Sstevel@tonic-gate  * Ontario SBL event handler, subscribed to:
195*ada2da53SToomas Soome  *	PICLEVENT_SYSEVENT_DEVICE_ADDED
196*ada2da53SToomas Soome  *	PICLEVENT_SYSEVENT_DEVICE_REMOVED
1977c478bd9Sstevel@tonic-gate  */
1987c478bd9Sstevel@tonic-gate static void
piclsbl_handler(const char * ename,const void * earg,size_t size,void * cookie)1997c478bd9Sstevel@tonic-gate piclsbl_handler(const char *ename, const void *earg, size_t size,
200*ada2da53SToomas Soome     void *cookie)
2017c478bd9Sstevel@tonic-gate {
2027c478bd9Sstevel@tonic-gate 	char		*devfs_path;
2037c478bd9Sstevel@tonic-gate 	char		hdd_location[PICL_PROPNAMELEN_MAX];
2047c478bd9Sstevel@tonic-gate 	nvlist_t	*nvlp = NULL;
2057c478bd9Sstevel@tonic-gate 	pcp_msg_t	send_msg;
2067c478bd9Sstevel@tonic-gate 	pcp_msg_t	recv_msg;
2077c478bd9Sstevel@tonic-gate 	pcp_sbl_req_t	*req_ptr = NULL;
2087c478bd9Sstevel@tonic-gate 	pcp_sbl_resp_t	*resp_ptr = NULL;
2097c478bd9Sstevel@tonic-gate 	int		status = -1;
2106fec3791Sjesseb 	int		target;
2117c478bd9Sstevel@tonic-gate 	disk_lookup_t	lookup;
2125db09ef5Smvgr 	int		channel_fd;
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 	/*
2157c478bd9Sstevel@tonic-gate 	 * setup the request data to attach to the libpcp msg
2167c478bd9Sstevel@tonic-gate 	 */
2177c478bd9Sstevel@tonic-gate 	if ((req_ptr = (pcp_sbl_req_t *)umem_zalloc(sizeof (pcp_sbl_req_t),
21808c92e0eSMary Beale 	    UMEM_DEFAULT)) == NULL)
2197c478bd9Sstevel@tonic-gate 		goto sbl_return;
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 	/*
2227c478bd9Sstevel@tonic-gate 	 * This plugin serves to enable or disable the blue RAS
2237c478bd9Sstevel@tonic-gate 	 * 'ok-to-remove' LED that is on each of the 4 disks on the
2247c478bd9Sstevel@tonic-gate 	 * Ontario.  We catch the event via the picl handler, and
2257c478bd9Sstevel@tonic-gate 	 * if the event is DEVICE_ADDED for one of our onboard disks,
2267c478bd9Sstevel@tonic-gate 	 * then we'll be turning off the LED. Otherwise, if the event
2277c478bd9Sstevel@tonic-gate 	 * is DEVICE_REMOVED, then we turn it on.
2287c478bd9Sstevel@tonic-gate 	 */
2297c478bd9Sstevel@tonic-gate 	if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_ADDED) == 0)
2307c478bd9Sstevel@tonic-gate 		req_ptr->sbl_action = PCP_SBL_DISABLE;
2317c478bd9Sstevel@tonic-gate 	else if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_REMOVED) == 0)
2327c478bd9Sstevel@tonic-gate 		req_ptr->sbl_action = PCP_SBL_ENABLE;
2337c478bd9Sstevel@tonic-gate 	else
2347c478bd9Sstevel@tonic-gate 		goto sbl_return;
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 	/*
2377c478bd9Sstevel@tonic-gate 	 * retrieve the device's physical path from the event payload
2387c478bd9Sstevel@tonic-gate 	 */
239*ada2da53SToomas Soome 	if (nvlist_unpack((char *)earg, size, &nvlp, 0))
2407c478bd9Sstevel@tonic-gate 		goto sbl_return;
2417c478bd9Sstevel@tonic-gate 	if (nvlist_lookup_string(nvlp, "devfs-path", &devfs_path))
2427c478bd9Sstevel@tonic-gate 		goto sbl_return;
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 	/*
2457c478bd9Sstevel@tonic-gate 	 * look for this disk in the picl tree, and if it's
2467c478bd9Sstevel@tonic-gate 	 * location indicates that it's one of our internal
2477c478bd9Sstevel@tonic-gate 	 * disks, then set sbl_id to incdicate which one.
2487c478bd9Sstevel@tonic-gate 	 * otherwise, return as it is not one of our disks.
2497c478bd9Sstevel@tonic-gate 	 */
2507c478bd9Sstevel@tonic-gate 	lookup.path = strdup(devfs_path);
251*ada2da53SToomas Soome 	lookup.disk = 0;
2527c478bd9Sstevel@tonic-gate 	lookup.result = DISK_NOT_FOUND;
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 	/* first, find the disk */
2557c478bd9Sstevel@tonic-gate 	status = ptree_walk_tree_by_class(root_node, "disk", (void *)&lookup,
25608c92e0eSMary Beale 	    cb_find_disk);
2577c478bd9Sstevel@tonic-gate 	if (status != PICL_SUCCESS)
2587c478bd9Sstevel@tonic-gate 		goto sbl_return;
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate 	if (lookup.result == DISK_FOUND) {
2617c478bd9Sstevel@tonic-gate 		/* now, lookup it's location in the node */
2627c478bd9Sstevel@tonic-gate 		status = ptree_get_propval_by_name(lookup.disk, "Location",
26308c92e0eSMary Beale 		    (void *)&hdd_location, PICL_PROPNAMELEN_MAX);
2647c478bd9Sstevel@tonic-gate 		if (status != PICL_SUCCESS) {
2657c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, "piclsbl: failed hdd discovery");
2667c478bd9Sstevel@tonic-gate 			goto sbl_return;
2677c478bd9Sstevel@tonic-gate 		}
2687c478bd9Sstevel@tonic-gate 	}
2697c478bd9Sstevel@tonic-gate 
27044961713Sgirish 	/*
27144961713Sgirish 	 * Strip off the target from the NAC name.
27244961713Sgirish 	 * The disk NAC will always be HDD#
27344961713Sgirish 	 */
27444961713Sgirish 	if (strncmp(hdd_location, NAC_DISK_PREFIX,
27508c92e0eSMary Beale 	    strlen(NAC_DISK_PREFIX)) == 0) {
27608c92e0eSMary Beale 		(void) sscanf(hdd_location, "%*3s%d", &req_ptr->sbl_id);
27708c92e0eSMary Beale 		target = (int)req_ptr->sbl_id;
2786fec3791Sjesseb 	} else {
27908c92e0eSMary Beale 		/* this is not one of the onboard disks */
28008c92e0eSMary Beale 		goto sbl_return;
2816fec3791Sjesseb 	}
2826fec3791Sjesseb 
2836fec3791Sjesseb 	/*
2846fec3791Sjesseb 	 * check the onboard RAID configuration for this disk. if it is
2856fec3791Sjesseb 	 * a member of a RAID and is not the RAID itself, ignore the event
2866fec3791Sjesseb 	 */
2876fec3791Sjesseb 	if (check_raid(target))
2887c478bd9Sstevel@tonic-gate 		goto sbl_return;
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate 	/*
2917c478bd9Sstevel@tonic-gate 	 * we have the information we need, init the platform channel.
2927c478bd9Sstevel@tonic-gate 	 * the platform channel driver will only allow one connection
2937c478bd9Sstevel@tonic-gate 	 * at a time on this socket. on the offchance that more than
2947c478bd9Sstevel@tonic-gate 	 * one event comes in, we'll retry to initialize this connection
2957c478bd9Sstevel@tonic-gate 	 * up to 3 times
2967c478bd9Sstevel@tonic-gate 	 */
2975db09ef5Smvgr 	if ((channel_fd = (*pcp_init_ptr)(LED_CHANNEL)) < 0) {
2987c478bd9Sstevel@tonic-gate 		/* failed to init; wait and retry up to 3 times */
2997c478bd9Sstevel@tonic-gate 		int s = PCPINIT_TIMEOUT;
3007c478bd9Sstevel@tonic-gate 		int retries = 0;
3016fec3791Sjesseb 		while (++retries) {
3027c478bd9Sstevel@tonic-gate 			(void) sleep(s);
3035db09ef5Smvgr 			if ((channel_fd = (*pcp_init_ptr)(LED_CHANNEL)) >= 0)
3047c478bd9Sstevel@tonic-gate 				break;
3057c478bd9Sstevel@tonic-gate 			else if (retries == 3) {
3067c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR, "piclsbl: ",
30708c92e0eSMary Beale 				    "SC channel initialization failed");
3087c478bd9Sstevel@tonic-gate 				goto sbl_return;
3097c478bd9Sstevel@tonic-gate 			}
3107c478bd9Sstevel@tonic-gate 			/* continue */
3117c478bd9Sstevel@tonic-gate 		}
3127c478bd9Sstevel@tonic-gate 	}
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 	/*
3157c478bd9Sstevel@tonic-gate 	 * populate the message for libpcp
3167c478bd9Sstevel@tonic-gate 	 */
3177c478bd9Sstevel@tonic-gate 	send_msg.msg_type = PCP_SBL_CONTROL;
318*ada2da53SToomas Soome 	send_msg.sub_type = 0;
3197c478bd9Sstevel@tonic-gate 	send_msg.msg_len = sizeof (pcp_sbl_req_t);
3207c478bd9Sstevel@tonic-gate 	send_msg.msg_data = (uint8_t *)req_ptr;
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 	/*
3237c478bd9Sstevel@tonic-gate 	 * send the request, receive the response
3247c478bd9Sstevel@tonic-gate 	 */
3255db09ef5Smvgr 	if ((*pcp_send_recv_ptr)(channel_fd, &send_msg, &recv_msg,
32608c92e0eSMary Beale 	    PCPCOMM_TIMEOUT) < 0) {
3277c478bd9Sstevel@tonic-gate 		/* we either timed out or erred; either way try again */
3287c478bd9Sstevel@tonic-gate 		int s = PCPCOMM_TIMEOUT;
3297c478bd9Sstevel@tonic-gate 		(void) sleep(s);
3305db09ef5Smvgr 		if ((*pcp_send_recv_ptr)(channel_fd, &send_msg, &recv_msg,
33108c92e0eSMary Beale 		    PCPCOMM_TIMEOUT) < 0) {
3327c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, "piclsbl: communication failure");
3337c478bd9Sstevel@tonic-gate 			goto sbl_return;
3347c478bd9Sstevel@tonic-gate 		}
3357c478bd9Sstevel@tonic-gate 	}
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 	/*
3387c478bd9Sstevel@tonic-gate 	 * validate that this data was meant for us
3397c478bd9Sstevel@tonic-gate 	 */
3407c478bd9Sstevel@tonic-gate 	if (recv_msg.msg_type != PCP_SBL_CONTROL_R) {
3417c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "piclsbl: unbound packet received");
3427c478bd9Sstevel@tonic-gate 		goto sbl_return;
3437c478bd9Sstevel@tonic-gate 	}
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 	/*
3467c478bd9Sstevel@tonic-gate 	 * verify that the LED action has taken place
3477c478bd9Sstevel@tonic-gate 	 */
3487c478bd9Sstevel@tonic-gate 	resp_ptr = (pcp_sbl_resp_t *)recv_msg.msg_data;
3497c478bd9Sstevel@tonic-gate 	if (resp_ptr->status == PCP_SBL_ERROR) {
3507c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "piclsbl: OK2RM LED action error");
3517c478bd9Sstevel@tonic-gate 		goto sbl_return;
3527c478bd9Sstevel@tonic-gate 	}
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 	/*
3557c478bd9Sstevel@tonic-gate 	 * ensure the LED action taken is the one requested
3567c478bd9Sstevel@tonic-gate 	 */
3577c478bd9Sstevel@tonic-gate 	if ((req_ptr->sbl_action == PCP_SBL_DISABLE) &&
35808c92e0eSMary Beale 	    (resp_ptr->sbl_state != SBL_STATE_OFF))
3597c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "piclsbl: OK2RM LED not OFF after disk "
36008c92e0eSMary Beale 		    "configuration");
3617c478bd9Sstevel@tonic-gate 	else if ((req_ptr->sbl_action == PCP_SBL_ENABLE) &&
36208c92e0eSMary Beale 	    (resp_ptr->sbl_state != SBL_STATE_ON))
3637c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "piclsbl: OK2RM LED not ON after disk "
36408c92e0eSMary Beale 		    "unconfiguration");
3657c478bd9Sstevel@tonic-gate 	else if (resp_ptr->sbl_state == SBL_STATE_UNKNOWN)
3667c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "piclsbl: OK2RM LED set to unknown state");
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate sbl_return:
3696fec3791Sjesseb 
3705db09ef5Smvgr 	(*pcp_close_ptr)(channel_fd);
3717c478bd9Sstevel@tonic-gate 	if (req_ptr != NULL)
3727c478bd9Sstevel@tonic-gate 		umem_free(req_ptr, sizeof (pcp_sbl_req_t));
3737c478bd9Sstevel@tonic-gate 	if (resp_ptr != NULL)
3747c478bd9Sstevel@tonic-gate 		free(resp_ptr);
375aab83bb8SJosef 'Jeff' Sipek 	nvlist_free(nvlp);
3767c478bd9Sstevel@tonic-gate }
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate static void
piclsbl_init(void)3797c478bd9Sstevel@tonic-gate piclsbl_init(void)
3807c478bd9Sstevel@tonic-gate {
38108c92e0eSMary Beale 	char	platbuf[SYS_NMLN];
38208c92e0eSMary Beale 
38308c92e0eSMary Beale 	/* check for Erie platform name */
38408c92e0eSMary Beale 	if ((sysinfo(SI_PLATFORM, platbuf, SYS_NMLN) != -1) &&
38508c92e0eSMary Beale 	    ((strcmp(platbuf, ERIE_PLATFORM) == 0) ||
38608c92e0eSMary Beale 	    (strcmp(platbuf, ERIE_PLATFORM2) == 0)))
38708c92e0eSMary Beale 		return;
38808c92e0eSMary Beale 
3897c478bd9Sstevel@tonic-gate 	/* retrieve the root node for lookups in the event handler */
390*ada2da53SToomas Soome 	if ((ptree_get_root(&root_node)) != 0)
3917c478bd9Sstevel@tonic-gate 		return;
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 	/* load libpcp */
3947c478bd9Sstevel@tonic-gate 	if (load_pcp_libs()) {
3957c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "piclsbl: failed to load libpcp");
3967c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "piclsbl: aborting");
3977c478bd9Sstevel@tonic-gate 		return;
3987c478bd9Sstevel@tonic-gate 	}
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 	/*
4017c478bd9Sstevel@tonic-gate 	 * register piclsbl_handler for both "sysevent-device-added" and
4027c478bd9Sstevel@tonic-gate 	 * and for "sysevent-device-removed" PICL events
4037c478bd9Sstevel@tonic-gate 	 */
4047c478bd9Sstevel@tonic-gate 	(void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
4057c478bd9Sstevel@tonic-gate 	    piclsbl_handler, NULL);
4067c478bd9Sstevel@tonic-gate 	(void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
4077c478bd9Sstevel@tonic-gate 	    piclsbl_handler, NULL);
4087c478bd9Sstevel@tonic-gate }
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate static void
piclsbl_fini(void)4117c478bd9Sstevel@tonic-gate piclsbl_fini(void)
4127c478bd9Sstevel@tonic-gate {
4137c478bd9Sstevel@tonic-gate 	/* unregister the event handler */
4147c478bd9Sstevel@tonic-gate 	(void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
4157c478bd9Sstevel@tonic-gate 	    piclsbl_handler, NULL);
4167c478bd9Sstevel@tonic-gate 	(void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
4177c478bd9Sstevel@tonic-gate 	    piclsbl_handler, NULL);
4187c478bd9Sstevel@tonic-gate }
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate static void
piclsbl_register(void)4217c478bd9Sstevel@tonic-gate piclsbl_register(void)
4227c478bd9Sstevel@tonic-gate {
4237c478bd9Sstevel@tonic-gate 	picld_plugin_register(&piclsbl_reg);
4247c478bd9Sstevel@tonic-gate }
425