xref: /onnv-gate/usr/src/uts/common/avs/ns/nsctl/nsc_power.c (revision 7836:4e95154b5b7a)
1*7836SJohn.Forte@Sun.COM /*
2*7836SJohn.Forte@Sun.COM  * CDDL HEADER START
3*7836SJohn.Forte@Sun.COM  *
4*7836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
5*7836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
6*7836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
7*7836SJohn.Forte@Sun.COM  *
8*7836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*7836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*7836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
11*7836SJohn.Forte@Sun.COM  * and limitations under the License.
12*7836SJohn.Forte@Sun.COM  *
13*7836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*7836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*7836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*7836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*7836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*7836SJohn.Forte@Sun.COM  *
19*7836SJohn.Forte@Sun.COM  * CDDL HEADER END
20*7836SJohn.Forte@Sun.COM  */
21*7836SJohn.Forte@Sun.COM /*
22*7836SJohn.Forte@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*7836SJohn.Forte@Sun.COM  * Use is subject to license terms.
24*7836SJohn.Forte@Sun.COM  */
25*7836SJohn.Forte@Sun.COM 
26*7836SJohn.Forte@Sun.COM #include <sys/types.h>
27*7836SJohn.Forte@Sun.COM #include <sys/ksynch.h>
28*7836SJohn.Forte@Sun.COM #include <sys/kmem.h>
29*7836SJohn.Forte@Sun.COM #include <sys/file.h>
30*7836SJohn.Forte@Sun.COM #include <sys/errno.h>
31*7836SJohn.Forte@Sun.COM #include <sys/open.h>
32*7836SJohn.Forte@Sun.COM #include <sys/cred.h>
33*7836SJohn.Forte@Sun.COM #include <sys/conf.h>
34*7836SJohn.Forte@Sun.COM #include <sys/uio.h>
35*7836SJohn.Forte@Sun.COM #include <sys/cmn_err.h>
36*7836SJohn.Forte@Sun.COM 
37*7836SJohn.Forte@Sun.COM #define	__NSC_GEN__
38*7836SJohn.Forte@Sun.COM #include "nsc_dev.h"
39*7836SJohn.Forte@Sun.COM #include "nsc_ioctl.h"
40*7836SJohn.Forte@Sun.COM #include "nsc_power.h"
41*7836SJohn.Forte@Sun.COM #include "../nsctl.h"
42*7836SJohn.Forte@Sun.COM 
43*7836SJohn.Forte@Sun.COM extern nsc_mem_t *_nsc_local_mem;
44*7836SJohn.Forte@Sun.COM static  int null_power(void);
45*7836SJohn.Forte@Sun.COM 
46*7836SJohn.Forte@Sun.COM 
47*7836SJohn.Forte@Sun.COM typedef struct _nsc_power_s {
48*7836SJohn.Forte@Sun.COM 	struct _nsc_power_s *next;	/* chain */
49*7836SJohn.Forte@Sun.COM 	char *name;			/* module name */
50*7836SJohn.Forte@Sun.COM 	void (*pw_power_lost)(int);	/* callback power lost(rideout) */
51*7836SJohn.Forte@Sun.COM 	void (*pw_power_ok)(void);	/* callback power ok */
52*7836SJohn.Forte@Sun.COM 	void (*pw_power_down)(void);
53*7836SJohn.Forte@Sun.COM 				/* callback power down (shutdown imminent) */
54*7836SJohn.Forte@Sun.COM } _nsc_power_t;
55*7836SJohn.Forte@Sun.COM 
56*7836SJohn.Forte@Sun.COM #define	_P(x)	(((long)(&((_nsc_power_t *)0)->x))/sizeof (long))
57*7836SJohn.Forte@Sun.COM 
58*7836SJohn.Forte@Sun.COM static nsc_def_t _nsc_power_def[] = {
59*7836SJohn.Forte@Sun.COM 	"Power_Lost",	(uintptr_t)null_power,	_P(pw_power_lost),
60*7836SJohn.Forte@Sun.COM 	"Power_OK",	(uintptr_t)null_power,	_P(pw_power_ok),
61*7836SJohn.Forte@Sun.COM 	"Power_Down",	(uintptr_t)null_power,	_P(pw_power_down),
62*7836SJohn.Forte@Sun.COM 	0,		0,			0,
63*7836SJohn.Forte@Sun.COM };
64*7836SJohn.Forte@Sun.COM 
65*7836SJohn.Forte@Sun.COM static _nsc_power_t *_power_clients;
66*7836SJohn.Forte@Sun.COM static kmutex_t _power_mutex;
67*7836SJohn.Forte@Sun.COM 
68*7836SJohn.Forte@Sun.COM 
null_power(void)69*7836SJohn.Forte@Sun.COM static int null_power(void)
70*7836SJohn.Forte@Sun.COM /*
71*7836SJohn.Forte@Sun.COM  * init null_power - dummy power routine for clients that choose not
72*7836SJohn.Forte@Sun.COM  * to implement all the power hooks.
73*7836SJohn.Forte@Sun.COM  *
74*7836SJohn.Forte@Sun.COM  */
75*7836SJohn.Forte@Sun.COM {
76*7836SJohn.Forte@Sun.COM 	return (0);
77*7836SJohn.Forte@Sun.COM }
78*7836SJohn.Forte@Sun.COM 
79*7836SJohn.Forte@Sun.COM /*
80*7836SJohn.Forte@Sun.COM  * int
81*7836SJohn.Forte@Sun.COM  * _nsc_power
82*7836SJohn.Forte@Sun.COM  *	Call registered clients of the generic power ioctls.
83*7836SJohn.Forte@Sun.COM  *
84*7836SJohn.Forte@Sun.COM  * Calling/Exit State:
85*7836SJohn.Forte@Sun.COM  *	Calls all the registered clients with a message describing the
86*7836SJohn.Forte@Sun.COM  *      current state of the power for the system.
87*7836SJohn.Forte@Sun.COM  */
88*7836SJohn.Forte@Sun.COM int
_nsc_power(blind_t argp,int * rvp)89*7836SJohn.Forte@Sun.COM _nsc_power(blind_t argp, int *rvp)
90*7836SJohn.Forte@Sun.COM {
91*7836SJohn.Forte@Sun.COM 	nsc_power_ctl_t opc;
92*7836SJohn.Forte@Sun.COM 	_nsc_power_t *pp;
93*7836SJohn.Forte@Sun.COM 
94*7836SJohn.Forte@Sun.COM 	*rvp = 0;
95*7836SJohn.Forte@Sun.COM 	if (copyin((void *) argp, &opc, sizeof (nsc_power_ctl_t)))
96*7836SJohn.Forte@Sun.COM 		return (EFAULT);
97*7836SJohn.Forte@Sun.COM 	mutex_enter(&_power_mutex);
98*7836SJohn.Forte@Sun.COM 
99*7836SJohn.Forte@Sun.COM 	pp = _power_clients;
100*7836SJohn.Forte@Sun.COM 	while (pp) {
101*7836SJohn.Forte@Sun.COM 		switch ((nsc_power_ops_t)opc.msg) {
102*7836SJohn.Forte@Sun.COM 
103*7836SJohn.Forte@Sun.COM 	case Power_OK:
104*7836SJohn.Forte@Sun.COM 			(*pp->pw_power_ok)();
105*7836SJohn.Forte@Sun.COM 			break;
106*7836SJohn.Forte@Sun.COM 
107*7836SJohn.Forte@Sun.COM 	case Power_Down:
108*7836SJohn.Forte@Sun.COM 			(*pp->pw_power_down)();
109*7836SJohn.Forte@Sun.COM 			break;
110*7836SJohn.Forte@Sun.COM 
111*7836SJohn.Forte@Sun.COM 	case Power_Lost:
112*7836SJohn.Forte@Sun.COM 			(*pp->pw_power_lost)(opc.arg1);
113*7836SJohn.Forte@Sun.COM 			break;
114*7836SJohn.Forte@Sun.COM 
115*7836SJohn.Forte@Sun.COM 	default:
116*7836SJohn.Forte@Sun.COM 			mutex_exit(&_power_mutex);
117*7836SJohn.Forte@Sun.COM 			return (EINVAL);
118*7836SJohn.Forte@Sun.COM 		}
119*7836SJohn.Forte@Sun.COM 
120*7836SJohn.Forte@Sun.COM 		pp = pp->next;
121*7836SJohn.Forte@Sun.COM 	}
122*7836SJohn.Forte@Sun.COM 	mutex_exit(&_power_mutex);
123*7836SJohn.Forte@Sun.COM 	return (0);
124*7836SJohn.Forte@Sun.COM }
125*7836SJohn.Forte@Sun.COM 
126*7836SJohn.Forte@Sun.COM /*
127*7836SJohn.Forte@Sun.COM  * int
128*7836SJohn.Forte@Sun.COM  * _nsc_init_power (void)
129*7836SJohn.Forte@Sun.COM  *	Initialise power ioctl subsystem.
130*7836SJohn.Forte@Sun.COM  *
131*7836SJohn.Forte@Sun.COM  * Calling/Exit State:
132*7836SJohn.Forte@Sun.COM  *	Called at driver initialisation time to allocate necessary
133*7836SJohn.Forte@Sun.COM  *	data structures.
134*7836SJohn.Forte@Sun.COM  */
135*7836SJohn.Forte@Sun.COM int
_nsc_init_power(void)136*7836SJohn.Forte@Sun.COM _nsc_init_power(void)
137*7836SJohn.Forte@Sun.COM {
138*7836SJohn.Forte@Sun.COM 	mutex_init(&_power_mutex, NULL, MUTEX_DRIVER, NULL);
139*7836SJohn.Forte@Sun.COM 	return (0);
140*7836SJohn.Forte@Sun.COM }
141*7836SJohn.Forte@Sun.COM 
142*7836SJohn.Forte@Sun.COM /*
143*7836SJohn.Forte@Sun.COM  * int
144*7836SJohn.Forte@Sun.COM  * _nsc_deinit_power (void)
145*7836SJohn.Forte@Sun.COM  *	Initialise power ioctl subsystem.
146*7836SJohn.Forte@Sun.COM  *
147*7836SJohn.Forte@Sun.COM  * Calling/Exit State:
148*7836SJohn.Forte@Sun.COM  *	Called at driver initialisation time to allocate necessary
149*7836SJohn.Forte@Sun.COM  *	data structures.
150*7836SJohn.Forte@Sun.COM  */
151*7836SJohn.Forte@Sun.COM int
_nsc_deinit_power(void)152*7836SJohn.Forte@Sun.COM _nsc_deinit_power(void)
153*7836SJohn.Forte@Sun.COM {
154*7836SJohn.Forte@Sun.COM 	_nsc_power_t *pp, *npp;
155*7836SJohn.Forte@Sun.COM 
156*7836SJohn.Forte@Sun.COM 	mutex_enter(&_power_mutex);
157*7836SJohn.Forte@Sun.COM 	pp = _power_clients;
158*7836SJohn.Forte@Sun.COM 	while (pp) {
159*7836SJohn.Forte@Sun.COM 		npp = pp->next;
160*7836SJohn.Forte@Sun.COM 		nsc_kmem_free(pp, sizeof (_nsc_power_t));
161*7836SJohn.Forte@Sun.COM 		pp = npp;
162*7836SJohn.Forte@Sun.COM 	}
163*7836SJohn.Forte@Sun.COM 	_power_clients = NULL;
164*7836SJohn.Forte@Sun.COM 	mutex_exit(&_power_mutex);
165*7836SJohn.Forte@Sun.COM 	mutex_destroy(&_power_mutex);
166*7836SJohn.Forte@Sun.COM 	return (0);
167*7836SJohn.Forte@Sun.COM }
168*7836SJohn.Forte@Sun.COM 
169*7836SJohn.Forte@Sun.COM /*
170*7836SJohn.Forte@Sun.COM  * blind_t
171*7836SJohn.Forte@Sun.COM  * nsc_register_power (char *name, nsc_def_t *def)
172*7836SJohn.Forte@Sun.COM  *	Register an power ioctl client.
173*7836SJohn.Forte@Sun.COM  *
174*7836SJohn.Forte@Sun.COM  * Calling/Exit State:
175*7836SJohn.Forte@Sun.COM  *	Returns a token for use in future calls to nsc_unregister_power.
176*7836SJohn.Forte@Sun.COM  *      If a client with the same name is already registered then NULL
177*7836SJohn.Forte@Sun.COM  *      is return to indicate failure.
178*7836SJohn.Forte@Sun.COM  *	If registration fails NULL is returned.
179*7836SJohn.Forte@Sun.COM  *
180*7836SJohn.Forte@Sun.COM  * Description:
181*7836SJohn.Forte@Sun.COM  *	Registers an power ioctl client for notifications during subsequent
182*7836SJohn.Forte@Sun.COM  *      ioctl from UPS/PCU management.
183*7836SJohn.Forte@Sun.COM  */
184*7836SJohn.Forte@Sun.COM blind_t
nsc_register_power(char * name,nsc_def_t * def)185*7836SJohn.Forte@Sun.COM nsc_register_power(char *name, nsc_def_t *def)
186*7836SJohn.Forte@Sun.COM {
187*7836SJohn.Forte@Sun.COM 	_nsc_power_t *entry, *pp;
188*7836SJohn.Forte@Sun.COM 
189*7836SJohn.Forte@Sun.COM 
190*7836SJohn.Forte@Sun.COM 	entry = nsc_kmem_alloc(sizeof (_nsc_power_t), 0, _nsc_local_mem);
191*7836SJohn.Forte@Sun.COM 
192*7836SJohn.Forte@Sun.COM 	if (entry == NULL)
193*7836SJohn.Forte@Sun.COM 		return (NULL);
194*7836SJohn.Forte@Sun.COM 	nsc_decode_param(def, _nsc_power_def, (long *)entry);
195*7836SJohn.Forte@Sun.COM 
196*7836SJohn.Forte@Sun.COM 	mutex_enter(&_power_mutex);
197*7836SJohn.Forte@Sun.COM 
198*7836SJohn.Forte@Sun.COM 	for (pp = _power_clients; pp; pp = pp->next) {
199*7836SJohn.Forte@Sun.COM 		if (strcmp(pp->name, name) == 0) {
200*7836SJohn.Forte@Sun.COM 			mutex_exit(&_power_mutex);
201*7836SJohn.Forte@Sun.COM 			nsc_kmem_free(entry, sizeof (_nsc_power_t));
202*7836SJohn.Forte@Sun.COM 			return (NULL);
203*7836SJohn.Forte@Sun.COM 		}
204*7836SJohn.Forte@Sun.COM 	}
205*7836SJohn.Forte@Sun.COM 	entry->name = name;
206*7836SJohn.Forte@Sun.COM 
207*7836SJohn.Forte@Sun.COM 	entry->next = _power_clients;
208*7836SJohn.Forte@Sun.COM 	_power_clients = entry;
209*7836SJohn.Forte@Sun.COM 	mutex_exit(&_power_mutex);
210*7836SJohn.Forte@Sun.COM 	return ((blind_t)entry);
211*7836SJohn.Forte@Sun.COM }
212*7836SJohn.Forte@Sun.COM 
213*7836SJohn.Forte@Sun.COM /*
214*7836SJohn.Forte@Sun.COM  * int
215*7836SJohn.Forte@Sun.COM  * nsc_unregister_power (blind_t powerp)
216*7836SJohn.Forte@Sun.COM  *	Un-register a power ioctl client.
217*7836SJohn.Forte@Sun.COM  *
218*7836SJohn.Forte@Sun.COM  * Calling/Exit State:
219*7836SJohn.Forte@Sun.COM  *	Returns 0 on success, otherwise returns an error code.
220*7836SJohn.Forte@Sun.COM  *
221*7836SJohn.Forte@Sun.COM  * Description:
222*7836SJohn.Forte@Sun.COM  *	The specified power ioctl client is un-registered if possible.
223*7836SJohn.Forte@Sun.COM  *      Zero is returned on success otherwise an error code.
224*7836SJohn.Forte@Sun.COM  */
225*7836SJohn.Forte@Sun.COM int
nsc_unregister_power(blind_t powerp)226*7836SJohn.Forte@Sun.COM nsc_unregister_power(blind_t powerp)
227*7836SJohn.Forte@Sun.COM {
228*7836SJohn.Forte@Sun.COM 	_nsc_power_t **xpp, *entry;
229*7836SJohn.Forte@Sun.COM 
230*7836SJohn.Forte@Sun.COM 	entry = (_nsc_power_t *)powerp;
231*7836SJohn.Forte@Sun.COM 	if (entry == NULL)
232*7836SJohn.Forte@Sun.COM 		return (EINVAL);
233*7836SJohn.Forte@Sun.COM 
234*7836SJohn.Forte@Sun.COM 	mutex_enter(&_power_mutex);
235*7836SJohn.Forte@Sun.COM 
236*7836SJohn.Forte@Sun.COM 	for (xpp = &_power_clients; *xpp; xpp = &(*xpp)->next)
237*7836SJohn.Forte@Sun.COM 		if (*xpp == entry)
238*7836SJohn.Forte@Sun.COM 			break;
239*7836SJohn.Forte@Sun.COM 
240*7836SJohn.Forte@Sun.COM 	if (*xpp == NULL) {
241*7836SJohn.Forte@Sun.COM 		mutex_exit(&_power_mutex);
242*7836SJohn.Forte@Sun.COM 		return (EALREADY);
243*7836SJohn.Forte@Sun.COM 	}
244*7836SJohn.Forte@Sun.COM 	*xpp = entry->next;
245*7836SJohn.Forte@Sun.COM 	mutex_exit(&_power_mutex);
246*7836SJohn.Forte@Sun.COM 	nsc_kmem_free(entry, sizeof (_nsc_power_t));
247*7836SJohn.Forte@Sun.COM 
248*7836SJohn.Forte@Sun.COM 	return (0);
249*7836SJohn.Forte@Sun.COM }
250