xref: /illumos-gate/usr/src/uts/sun4u/io/epic.c (revision 08219281)
1d58fda43Sjbeloro /*
2d58fda43Sjbeloro  * CDDL HEADER START
3d58fda43Sjbeloro  *
4d58fda43Sjbeloro  * The contents of this file are subject to the terms of the
519397407SSherry Moore  * Common Development and Distribution License (the "License").
619397407SSherry Moore  * You may not use this file except in compliance with the License.
7d58fda43Sjbeloro  *
8d58fda43Sjbeloro  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9d58fda43Sjbeloro  * or http://www.opensolaris.org/os/licensing.
10d58fda43Sjbeloro  * See the License for the specific language governing permissions
11d58fda43Sjbeloro  * and limitations under the License.
12d58fda43Sjbeloro  *
13d58fda43Sjbeloro  * When distributing Covered Code, include this CDDL HEADER in each
14d58fda43Sjbeloro  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15d58fda43Sjbeloro  * If applicable, add the following below this CDDL HEADER, with the
16d58fda43Sjbeloro  * fields enclosed by brackets "[]" replaced with your own identifying
17d58fda43Sjbeloro  * information: Portions Copyright [yyyy] [name of copyright owner]
18d58fda43Sjbeloro  *
19d58fda43Sjbeloro  * CDDL HEADER END
20d58fda43Sjbeloro  */
21d58fda43Sjbeloro 
22d58fda43Sjbeloro /*
2319397407SSherry Moore  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24d58fda43Sjbeloro  * Use is subject to license terms.
25d58fda43Sjbeloro  */
26d58fda43Sjbeloro 
27d58fda43Sjbeloro 
28d58fda43Sjbeloro /*
29d58fda43Sjbeloro  * Driver to control Alert and Power LEDs  for the Seattle platform.
30d58fda43Sjbeloro  * Alert LED is also known as Service (required).
31d58fda43Sjbeloro  * Power LED is also known as Activity.
32d58fda43Sjbeloro  */
33d58fda43Sjbeloro #include <sys/types.h>
34d58fda43Sjbeloro #include <sys/time.h>
35d58fda43Sjbeloro #include <sys/errno.h>
36d58fda43Sjbeloro #include <sys/cmn_err.h>
37d58fda43Sjbeloro #include <sys/param.h>
38d58fda43Sjbeloro #include <sys/modctl.h>
39d58fda43Sjbeloro #include <sys/conf.h>
40d58fda43Sjbeloro #include <sys/open.h>
41d58fda43Sjbeloro #include <sys/stat.h>
42d58fda43Sjbeloro #include <sys/clock.h>
43d58fda43Sjbeloro #include <sys/ddi.h>
44d58fda43Sjbeloro #include <sys/sunddi.h>
45d58fda43Sjbeloro #include <sys/file.h>
46d58fda43Sjbeloro #include <sys/note.h>
47d58fda43Sjbeloro #include <sys/epic.h>
48d58fda43Sjbeloro 
49d58fda43Sjbeloro 
50d58fda43Sjbeloro /*
51d58fda43Sjbeloro  * Some #defs that must be here as they differ for power.c
52d58fda43Sjbeloro  * and epic.c
53d58fda43Sjbeloro  */
54d58fda43Sjbeloro #define	EPIC_REGS_OFFSET	0x00
55d58fda43Sjbeloro #define	EPIC_REGS_LEN		0x80
56d58fda43Sjbeloro 
57d58fda43Sjbeloro #define	EPIC_IND_DATA		0x40
58d58fda43Sjbeloro #define	EPIC_IND_ADDR		0x41
59d58fda43Sjbeloro #define	EPIC_WRITE_MASK		0x80
60d58fda43Sjbeloro 
61d58fda43Sjbeloro /* dev_ops and cb_ops entry point function declarations */
62d58fda43Sjbeloro static int	epic_attach(dev_info_t *, ddi_attach_cmd_t);
63d58fda43Sjbeloro static int	epic_detach(dev_info_t *, ddi_detach_cmd_t);
64d58fda43Sjbeloro static int	epic_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
65d58fda43Sjbeloro static int	epic_open(dev_t *, int, int, cred_t *);
66d58fda43Sjbeloro static int	epic_close(dev_t, int, int, cred_t *);
67d58fda43Sjbeloro static int	epic_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
68d58fda43Sjbeloro 
69d58fda43Sjbeloro struct cb_ops epic_cb_ops = {
70d58fda43Sjbeloro 	epic_open,		/* open */
71d58fda43Sjbeloro 	epic_close,		/* close */
72d58fda43Sjbeloro 	nodev,			/* strategy */
73d58fda43Sjbeloro 	nodev,			/* print */
74d58fda43Sjbeloro 	nodev,			/* dump */
75d58fda43Sjbeloro 	nodev,			/* read */
76d58fda43Sjbeloro 	nodev,			/* write */
77d58fda43Sjbeloro 	epic_ioctl,		/* ioctl */
78d58fda43Sjbeloro 	nodev,			/* devmap */
79d58fda43Sjbeloro 	nodev,			/* mmap */
80d58fda43Sjbeloro 	ddi_segmap,		/* segmap */
81d58fda43Sjbeloro 	nochpoll,		/* poll */
82d58fda43Sjbeloro 	ddi_prop_op,		/* cb_prop_op */
83d58fda43Sjbeloro 	NULL,			/* streamtab - for STREAMS drivers */
84d58fda43Sjbeloro 	D_NEW | D_MP		/* driver compatibility flag */
85d58fda43Sjbeloro };
86d58fda43Sjbeloro 
87d58fda43Sjbeloro static struct dev_ops epic_dev_ops = {
88d58fda43Sjbeloro 	DEVO_REV,		/* driver build version */
89d58fda43Sjbeloro 	0,			/* device reference count */
90d58fda43Sjbeloro 	epic_getinfo,
91d58fda43Sjbeloro 	nulldev,
92d58fda43Sjbeloro 	nulldev,		/* probe */
93d58fda43Sjbeloro 	epic_attach,
94d58fda43Sjbeloro 	epic_detach,
95d58fda43Sjbeloro 	nulldev,		/* reset */
96d58fda43Sjbeloro 	&epic_cb_ops,
97d58fda43Sjbeloro 	(struct bus_ops *)NULL,
9819397407SSherry Moore 	nulldev,		/* power */
9919397407SSherry Moore 	ddi_quiesce_not_supported,	/* devo_quiesce */
100d58fda43Sjbeloro };
101d58fda43Sjbeloro 
102d58fda43Sjbeloro 
103d58fda43Sjbeloro /*
104d58fda43Sjbeloro  * Soft state
105d58fda43Sjbeloro  */
106d58fda43Sjbeloro struct epic_softc {
107d58fda43Sjbeloro 	dev_info_t	*dip;
108d58fda43Sjbeloro 	kmutex_t	mutex;
109d58fda43Sjbeloro 	uint8_t		*cmd_reg;
110d58fda43Sjbeloro 	ddi_acc_handle_t cmd_handle;
111d58fda43Sjbeloro };
112d58fda43Sjbeloro 
113d58fda43Sjbeloro #define	getsoftc(inst)	((struct epic_softc *)ddi_get_soft_state(statep, \
114d58fda43Sjbeloro (inst)))
115d58fda43Sjbeloro 
116d58fda43Sjbeloro /* module configuration stuff */
117d58fda43Sjbeloro static void    *statep;
118d58fda43Sjbeloro extern struct mod_ops mod_driverops;
119d58fda43Sjbeloro 
120d58fda43Sjbeloro static struct modldrv modldrv = {
121d58fda43Sjbeloro 	&mod_driverops,
12219397407SSherry Moore 	"epic_client driver",
123d58fda43Sjbeloro 	&epic_dev_ops
124d58fda43Sjbeloro };
125d58fda43Sjbeloro 
126d58fda43Sjbeloro static struct modlinkage modlinkage = {
127d58fda43Sjbeloro 	MODREV_1,
128d58fda43Sjbeloro 	&modldrv,
129d58fda43Sjbeloro 	0
130d58fda43Sjbeloro };
131d58fda43Sjbeloro 
132d58fda43Sjbeloro int
_init(void)133d58fda43Sjbeloro _init(void)
134d58fda43Sjbeloro {
135d58fda43Sjbeloro 	int e;
136d58fda43Sjbeloro 
137d58fda43Sjbeloro 	if ((e = ddi_soft_state_init(&statep,
138d58fda43Sjbeloro 		sizeof (struct epic_softc), 0)) != 0) {
139d58fda43Sjbeloro 		return (e);
140d58fda43Sjbeloro 	}
141d58fda43Sjbeloro 
142d58fda43Sjbeloro 	if ((e = mod_install(&modlinkage)) != 0)
143d58fda43Sjbeloro 		ddi_soft_state_fini(&statep);
144d58fda43Sjbeloro 
145d58fda43Sjbeloro 	return (e);
146d58fda43Sjbeloro }
147d58fda43Sjbeloro 
148d58fda43Sjbeloro int
_fini(void)149d58fda43Sjbeloro _fini(void)
150d58fda43Sjbeloro {
151d58fda43Sjbeloro 	int e;
152d58fda43Sjbeloro 
153d58fda43Sjbeloro 	if ((e = mod_remove(&modlinkage)) != 0)
154d58fda43Sjbeloro 		return (e);
155d58fda43Sjbeloro 
156d58fda43Sjbeloro 	ddi_soft_state_fini(&statep);
157d58fda43Sjbeloro 
158d58fda43Sjbeloro 	return (DDI_SUCCESS);
159d58fda43Sjbeloro }
160d58fda43Sjbeloro 
161d58fda43Sjbeloro int
_info(struct modinfo * modinfop)162d58fda43Sjbeloro _info(struct modinfo *modinfop)
163d58fda43Sjbeloro {
164d58fda43Sjbeloro 	return (mod_info(&modlinkage, modinfop));
165d58fda43Sjbeloro }
166d58fda43Sjbeloro 
167d58fda43Sjbeloro /*ARGSUSED*/
168d58fda43Sjbeloro static int
epic_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** result)169d58fda43Sjbeloro epic_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
170d58fda43Sjbeloro {
171d58fda43Sjbeloro 	int	inst;
172d58fda43Sjbeloro 	int	retval = DDI_SUCCESS;
173d58fda43Sjbeloro 	struct epic_softc *softc;
174d58fda43Sjbeloro 
175d58fda43Sjbeloro 	inst = (getminor((dev_t)arg));
176d58fda43Sjbeloro 
177d58fda43Sjbeloro 	switch (cmd) {
178d58fda43Sjbeloro 	case DDI_INFO_DEVT2DEVINFO:
179d58fda43Sjbeloro 		if ((softc = getsoftc(inst)) == NULL) {
180d58fda43Sjbeloro 			*result = (void *)NULL;
181d58fda43Sjbeloro 			retval = DDI_FAILURE;
182d58fda43Sjbeloro 		} else
183d58fda43Sjbeloro 			*result = (void *)softc->dip;
184d58fda43Sjbeloro 		break;
185d58fda43Sjbeloro 
186d58fda43Sjbeloro 	case DDI_INFO_DEVT2INSTANCE:
187bd9d7d01Sanovick 		*result = (void *)(uintptr_t)inst;
188d58fda43Sjbeloro 		break;
189d58fda43Sjbeloro 
190d58fda43Sjbeloro 	default:
191d58fda43Sjbeloro 		retval = DDI_FAILURE;
192d58fda43Sjbeloro 	}
193d58fda43Sjbeloro 
194d58fda43Sjbeloro 	return (retval);
195d58fda43Sjbeloro }
196d58fda43Sjbeloro 
197d58fda43Sjbeloro static int
epic_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)198d58fda43Sjbeloro epic_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
199d58fda43Sjbeloro {
200d58fda43Sjbeloro 	int inst;
201d58fda43Sjbeloro 	struct epic_softc *softc = NULL;
202d58fda43Sjbeloro 	int minor;
203d58fda43Sjbeloro 	char name[MAXNAMELEN];
204d58fda43Sjbeloro 	ddi_device_acc_attr_t dev_attr;
205d58fda43Sjbeloro 	int res;
206d58fda43Sjbeloro 
207d58fda43Sjbeloro 	switch (cmd) {
208d58fda43Sjbeloro 	case DDI_ATTACH:
209d58fda43Sjbeloro 		inst = ddi_get_instance(dip);
210d58fda43Sjbeloro 		(void) sprintf(name, "env-monitor%d", inst);
211d58fda43Sjbeloro 		minor = inst;
212d58fda43Sjbeloro 		if (ddi_create_minor_node(dip, name, S_IFCHR, minor,
213*08219281SToomas Soome 		    DDI_PSEUDO, 0) == DDI_FAILURE) {
214d58fda43Sjbeloro 			cmn_err(CE_WARN,
215d58fda43Sjbeloro 			    "ddi_create_minor_node() failed for inst %d\n",
216d58fda43Sjbeloro 			    inst);
217d58fda43Sjbeloro 			return (DDI_FAILURE);
218d58fda43Sjbeloro 		}
219d58fda43Sjbeloro 
220d58fda43Sjbeloro 		/* Allocate a soft state structure for this instance */
221d58fda43Sjbeloro 		if (ddi_soft_state_zalloc(statep, inst) != DDI_SUCCESS) {
222d58fda43Sjbeloro 			cmn_err(CE_WARN, " ddi_soft_state_zalloc() failed "
223d58fda43Sjbeloro 			    "for inst %d\n", inst);
224d58fda43Sjbeloro 			break;
225d58fda43Sjbeloro 		}
226d58fda43Sjbeloro 
227d58fda43Sjbeloro 		/* Setup soft state */
228d58fda43Sjbeloro 		if ((softc = getsoftc(inst)) == NULL) {
229d58fda43Sjbeloro 			break;
230d58fda43Sjbeloro 		}
231d58fda43Sjbeloro 		softc->dip = dip;
232d58fda43Sjbeloro 		mutex_init(&softc->mutex, NULL, MUTEX_DRIVER, NULL);
233d58fda43Sjbeloro 
234d58fda43Sjbeloro 		/* Setup device attributes */
235d58fda43Sjbeloro 		dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
236d58fda43Sjbeloro 		dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
237d58fda43Sjbeloro 		dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
238d58fda43Sjbeloro 
239d58fda43Sjbeloro 		res = ddi_regs_map_setup(dip, 0, (caddr_t *)&softc->cmd_reg,
24019397407SSherry Moore 		    EPIC_REGS_OFFSET, EPIC_REGS_LEN, &dev_attr,
24119397407SSherry Moore 		    &softc->cmd_handle);
242d58fda43Sjbeloro 
243d58fda43Sjbeloro 		if (res != DDI_SUCCESS) {
244d58fda43Sjbeloro 			cmn_err(CE_WARN, "ddi_regs_map_setup() failed\n");
245d58fda43Sjbeloro 			break;
246d58fda43Sjbeloro 		}
247d58fda43Sjbeloro 
248d58fda43Sjbeloro 		ddi_report_dev(dip);
249d58fda43Sjbeloro 
250d58fda43Sjbeloro 
251d58fda43Sjbeloro 		return (DDI_SUCCESS);
252d58fda43Sjbeloro 
253d58fda43Sjbeloro 	case DDI_RESUME:
254d58fda43Sjbeloro 		return (DDI_SUCCESS);
255d58fda43Sjbeloro 
256d58fda43Sjbeloro 	default:
257d58fda43Sjbeloro 		return (DDI_FAILURE);
258d58fda43Sjbeloro 	}
259d58fda43Sjbeloro 
260d58fda43Sjbeloro 	/* Attach failed */
261d58fda43Sjbeloro 	/* Free soft state, if allocated. remove minor node if added earlier */
262d58fda43Sjbeloro 	if (softc)
263d58fda43Sjbeloro 		ddi_soft_state_free(statep, inst);
264d58fda43Sjbeloro 
265d58fda43Sjbeloro 	ddi_remove_minor_node(dip, NULL);
266d58fda43Sjbeloro 
267d58fda43Sjbeloro 	return (DDI_FAILURE);
268d58fda43Sjbeloro }
269d58fda43Sjbeloro 
270d58fda43Sjbeloro static int
epic_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)271d58fda43Sjbeloro epic_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
272d58fda43Sjbeloro {
273d58fda43Sjbeloro 	int inst;
274d58fda43Sjbeloro 	struct epic_softc *softc;
275d58fda43Sjbeloro 
276d58fda43Sjbeloro 	switch (cmd) {
277d58fda43Sjbeloro 	case DDI_DETACH:
278d58fda43Sjbeloro 		inst = ddi_get_instance(dip);
279d58fda43Sjbeloro 		if ((softc = getsoftc(inst)) == NULL)
280d58fda43Sjbeloro 			return (ENXIO);
281d58fda43Sjbeloro 
282d58fda43Sjbeloro 		(void) ddi_regs_map_free(&softc->cmd_handle);
283d58fda43Sjbeloro 
284d58fda43Sjbeloro 
285d58fda43Sjbeloro 		/* Free the soft state and remove minor node added earlier */
286d58fda43Sjbeloro 		mutex_destroy(&softc->mutex);
287d58fda43Sjbeloro 		ddi_soft_state_free(statep, inst);
288d58fda43Sjbeloro 		ddi_remove_minor_node(dip, NULL);
289d58fda43Sjbeloro 		return (DDI_SUCCESS);
290d58fda43Sjbeloro 
291d58fda43Sjbeloro 	case DDI_SUSPEND:
292d58fda43Sjbeloro 		return (DDI_SUCCESS);
293d58fda43Sjbeloro 
294d58fda43Sjbeloro 	default:
295d58fda43Sjbeloro 		return (DDI_FAILURE);
296d58fda43Sjbeloro 	}
297d58fda43Sjbeloro }
298d58fda43Sjbeloro 
299d58fda43Sjbeloro /*ARGSUSED*/
300d58fda43Sjbeloro static int
epic_open(dev_t * devp,int flag,int otyp,cred_t * credp)301d58fda43Sjbeloro epic_open(dev_t *devp, int flag, int otyp, cred_t *credp)
302d58fda43Sjbeloro {
303d58fda43Sjbeloro 	_NOTE(ARGUNUSED(flag))
304d58fda43Sjbeloro 	_NOTE(ARGUNUSED(otyp))
305d58fda43Sjbeloro 	_NOTE(ARGUNUSED(credp))
306d58fda43Sjbeloro 
307d58fda43Sjbeloro 	int	inst = getminor(*devp);
308d58fda43Sjbeloro 
309d58fda43Sjbeloro 	return (getsoftc(inst) == NULL ? ENXIO : 0);
310d58fda43Sjbeloro }
311d58fda43Sjbeloro 
312d58fda43Sjbeloro /*ARGSUSED*/
313d58fda43Sjbeloro static int
epic_close(dev_t dev,int flag,int otyp,cred_t * credp)314d58fda43Sjbeloro epic_close(dev_t dev, int flag, int otyp, cred_t *credp)
315d58fda43Sjbeloro {
316d58fda43Sjbeloro 	_NOTE(ARGUNUSED(flag))
317d58fda43Sjbeloro 	_NOTE(ARGUNUSED(otyp))
318d58fda43Sjbeloro 	_NOTE(ARGUNUSED(credp))
319d58fda43Sjbeloro 
320d58fda43Sjbeloro 	int	inst = getminor(dev);
321d58fda43Sjbeloro 
322d58fda43Sjbeloro 	return (getsoftc(inst) == NULL ? ENXIO : 0);
323d58fda43Sjbeloro }
324d58fda43Sjbeloro 
325d58fda43Sjbeloro /*ARGSUSED*/
326d58fda43Sjbeloro static int
epic_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)327d58fda43Sjbeloro epic_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
328*08219281SToomas Soome     int *rvalp)
329d58fda43Sjbeloro {
330d58fda43Sjbeloro 	_NOTE(ARGUNUSED(credp))
331d58fda43Sjbeloro 
332d58fda43Sjbeloro 	int	inst;
333d58fda43Sjbeloro 	struct epic_softc *softc;
334d58fda43Sjbeloro 	uint8_t	in_command;
335d58fda43Sjbeloro 
336d58fda43Sjbeloro 	inst = getminor(dev);
337d58fda43Sjbeloro 	if ((softc = getsoftc(inst)) == NULL)
338d58fda43Sjbeloro 		return (ENXIO);
339d58fda43Sjbeloro 
340d58fda43Sjbeloro 	mutex_enter(&softc->mutex);
341d58fda43Sjbeloro 
342d58fda43Sjbeloro 	switch (cmd) {
343d58fda43Sjbeloro 	case EPIC_SET_POWER_LED:
34419397407SSherry Moore 		EPIC_WRITE(softc->cmd_handle, softc->cmd_reg,
34519397407SSherry Moore 		    EPIC_IND_LED_STATE0, EPIC_POWER_LED_MASK,
34619397407SSherry Moore 		    EPIC_POWER_LED_ON);
34719397407SSherry Moore 		break;
348d58fda43Sjbeloro 	case EPIC_RESET_POWER_LED:
34919397407SSherry Moore 		EPIC_WRITE(softc->cmd_handle, softc->cmd_reg,
35019397407SSherry Moore 		    EPIC_IND_LED_STATE0, EPIC_POWER_LED_MASK,
35119397407SSherry Moore 		    EPIC_POWER_LED_OFF);
35219397407SSherry Moore 		break;
353d58fda43Sjbeloro 	case EPIC_SB_BL_POWER_LED:
35419397407SSherry Moore 		EPIC_WRITE(softc->cmd_handle, softc->cmd_reg,
35519397407SSherry Moore 		    EPIC_IND_LED_STATE0, EPIC_POWER_LED_MASK,
35619397407SSherry Moore 		    EPIC_POWER_LED_SB_BLINK);
35719397407SSherry Moore 		break;
358d58fda43Sjbeloro 	case EPIC_FAST_BL_POWER_LED:
35919397407SSherry Moore 		EPIC_WRITE(softc->cmd_handle, softc->cmd_reg,
36019397407SSherry Moore 		    EPIC_IND_LED_STATE0, EPIC_POWER_LED_MASK,
36119397407SSherry Moore 		    EPIC_POWER_LED_FAST_BLINK);
36219397407SSherry Moore 		break;
363d58fda43Sjbeloro 	case EPIC_SET_ALERT_LED:
36419397407SSherry Moore 		EPIC_WRITE(softc->cmd_handle, softc->cmd_reg,
36519397407SSherry Moore 		    EPIC_IND_LED_STATE0, EPIC_ALERT_LED_MASK,
36619397407SSherry Moore 		    EPIC_ALERT_LED_ON);
36719397407SSherry Moore 		break;
368d58fda43Sjbeloro 	case EPIC_RESET_ALERT_LED:
36919397407SSherry Moore 		EPIC_WRITE(softc->cmd_handle, softc->cmd_reg,
37019397407SSherry Moore 		    EPIC_IND_LED_STATE0, EPIC_ALERT_LED_MASK,
37119397407SSherry Moore 		    EPIC_ALERT_LED_OFF);
37219397407SSherry Moore 		break;
373d58fda43Sjbeloro 	case EPIC_GET_FW:
37419397407SSherry Moore 		EPIC_READ(softc->cmd_handle, softc->cmd_reg,
37519397407SSherry Moore 		    in_command, EPIC_IND_FW_VERSION);
37619397407SSherry Moore 		if (ddi_copyout((void *)(&in_command), (void *)arg,
37719397407SSherry Moore 		    sizeof (in_command), mode) != DDI_SUCCESS) {
37819397407SSherry Moore 			mutex_exit(&softc->mutex);
37919397407SSherry Moore 			return (EFAULT);
38019397407SSherry Moore 		}
38119397407SSherry Moore 		break;
382d58fda43Sjbeloro 	default:
383d58fda43Sjbeloro 		mutex_exit(&softc->mutex);
384d58fda43Sjbeloro 		cmn_err(CE_WARN, "epic: cmd %d is not valid", cmd);
385d58fda43Sjbeloro 		return (EINVAL);
386d58fda43Sjbeloro 	}
387d58fda43Sjbeloro 
388d58fda43Sjbeloro 	mutex_exit(&softc->mutex);
389d58fda43Sjbeloro 	return (0);
390d58fda43Sjbeloro }
391