15295Srandyf /*
25295Srandyf * CDDL HEADER START
35295Srandyf *
45295Srandyf * The contents of this file are subject to the terms of the
55295Srandyf * Common Development and Distribution License (the "License").
65295Srandyf * You may not use this file except in compliance with the License.
75295Srandyf *
85295Srandyf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95295Srandyf * or http://www.opensolaris.org/os/licensing.
105295Srandyf * See the License for the specific language governing permissions
115295Srandyf * and limitations under the License.
125295Srandyf *
135295Srandyf * When distributing Covered Code, include this CDDL HEADER in each
145295Srandyf * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155295Srandyf * If applicable, add the following below this CDDL HEADER, with the
165295Srandyf * fields enclosed by brackets "[]" replaced with your own identifying
175295Srandyf * information: Portions Copyright [yyyy] [name of copyright owner]
185295Srandyf *
195295Srandyf * CDDL HEADER END
205295Srandyf */
215295Srandyf
225295Srandyf /*
2310311SRandy.Fishel@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
245295Srandyf * Use is subject to license terms.
255295Srandyf */
265295Srandyf
275295Srandyf
285295Srandyf /*
295295Srandyf * srn Provide apm-like interfaces to Xorg
305295Srandyf */
315295Srandyf
325295Srandyf #include <sys/types.h>
335295Srandyf #include <sys/errno.h>
345295Srandyf #include <sys/modctl.h>
355295Srandyf #include <sys/conf.h> /* driver flags and functions */
365295Srandyf #include <sys/open.h> /* OTYP_CHR definition */
375295Srandyf #include <sys/stat.h> /* S_IFCHR definition */
385295Srandyf #include <sys/pathname.h> /* name -> dev_info xlation */
395295Srandyf #include <sys/kmem.h> /* memory alloc stuff */
405295Srandyf #include <sys/debug.h>
415295Srandyf #include <sys/pm.h>
425295Srandyf #include <sys/ddi.h>
435295Srandyf #include <sys/sunddi.h>
445295Srandyf #include <sys/epm.h>
455295Srandyf #include <sys/vfs.h>
465295Srandyf #include <sys/mode.h>
475295Srandyf #include <sys/mkdev.h>
485295Srandyf #include <sys/promif.h>
495295Srandyf #include <sys/consdev.h>
505295Srandyf #include <sys/ddi_impldefs.h>
515295Srandyf #include <sys/poll.h>
525295Srandyf #include <sys/note.h>
535295Srandyf #include <sys/taskq.h>
545295Srandyf #include <sys/policy.h>
555295Srandyf #include <sys/srn.h>
565295Srandyf
575295Srandyf /*
585295Srandyf * Minor number is instance<<8 + clone minor from range 1-255;
595295Srandyf * But only one will be allocated
605295Srandyf */
615295Srandyf #define SRN_MINOR_TO_CLONE(minor) ((minor) & (SRN_MAX_CLONE - 1))
625295Srandyf #define SU 0x002
635295Srandyf #define SG 0x004
645295Srandyf
655295Srandyf extern kmutex_t srn_clone_lock; /* protects srn_clones array */
665295Srandyf extern kcondvar_t srn_clones_cv[SRN_MAX_CLONE];
675295Srandyf extern uint_t srn_poll_cnt[SRN_MAX_CLONE];
685295Srandyf
695295Srandyf /*
705295Srandyf * The soft state of the srn driver. Since there will only be
715295Srandyf * one of these, just reference it through a static struct.
725295Srandyf */
735295Srandyf static struct srnstate {
745295Srandyf dev_info_t *srn_dip; /* ptr to our dev_info node */
755295Srandyf int srn_instance; /* for ddi_get_instance() */
765295Srandyf uchar_t srn_clones[SRN_MAX_CLONE]; /* unique opens */
775295Srandyf struct cred *srn_cred[SRN_MAX_CLONE]; /* cred for each open */
785295Srandyf int srn_type[SRN_MAX_CLONE]; /* type of handshake */
795295Srandyf int srn_delivered[SRN_MAX_CLONE];
805295Srandyf srn_event_info_t srn_pending[SRN_MAX_CLONE];
8110311SRandy.Fishel@Sun.COM int srn_fault[SRN_MAX_CLONE];
825295Srandyf } srn = { NULL, -1};
835295Srandyf typedef struct srnstate *srn_state_t;
845295Srandyf
855295Srandyf kcondvar_t srn_clones_cv[SRN_MAX_CLONE];
865295Srandyf uint_t srn_poll_cnt[SRN_MAX_CLONE]; /* count of events for poll */
875295Srandyf int srn_apm_count;
885295Srandyf int srn_autosx_count;
8910311SRandy.Fishel@Sun.COM /* Number of seconds to wait for clients to ack a poll */
9010311SRandy.Fishel@Sun.COM int srn_timeout = 10;
9110311SRandy.Fishel@Sun.COM
925295Srandyf struct pollhead srn_pollhead[SRN_MAX_CLONE];
935295Srandyf
945295Srandyf static int srn_open(dev_t *, int, int, cred_t *);
955295Srandyf static int srn_close(dev_t, int, int, cred_t *);
965295Srandyf static int srn_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
975295Srandyf static int srn_chpoll(dev_t, short, int, short *, struct pollhead **);
985295Srandyf
995295Srandyf static struct cb_ops srn_cb_ops = {
1005295Srandyf srn_open, /* open */
1015295Srandyf srn_close, /* close */
1025295Srandyf nodev, /* strategy */
1035295Srandyf nodev, /* print */
1045295Srandyf nodev, /* dump */
1055295Srandyf nodev, /* read */
1065295Srandyf nodev, /* write */
1075295Srandyf srn_ioctl, /* ioctl */
1085295Srandyf nodev, /* devmap */
1095295Srandyf nodev, /* mmap */
1105295Srandyf nodev, /* segmap */
1115295Srandyf srn_chpoll, /* poll */
1125295Srandyf ddi_prop_op, /* prop_op */
1135295Srandyf NULL, /* streamtab */
1145295Srandyf D_NEW | D_MP /* driver compatibility flag */
1155295Srandyf };
1165295Srandyf
1175295Srandyf static int srn_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
1185295Srandyf void **result);
1195295Srandyf static int srn_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
1205295Srandyf static int srn_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
1215295Srandyf static void srn_notify(int type, int event);
1225295Srandyf
1235295Srandyf static struct dev_ops srn_ops = {
1245295Srandyf DEVO_REV, /* devo_rev */
1255295Srandyf 0, /* refcnt */
1265295Srandyf srn_getinfo, /* info */
1275295Srandyf nulldev, /* identify */
1285295Srandyf nulldev, /* probe */
1295295Srandyf srn_attach, /* attach */
1305295Srandyf srn_detach, /* detach */
1315295Srandyf nodev, /* reset */
1325295Srandyf &srn_cb_ops, /* driver operations */
1335295Srandyf NULL, /* bus operations */
1347656SSherry.Moore@Sun.COM NULL, /* power */
1357656SSherry.Moore@Sun.COM ddi_quiesce_not_needed, /* quiesce */
1365295Srandyf };
1375295Srandyf
1385295Srandyf static struct modldrv modldrv = {
1395295Srandyf &mod_driverops,
1407656SSherry.Moore@Sun.COM "srn driver",
1415295Srandyf &srn_ops
1425295Srandyf };
1435295Srandyf
1445295Srandyf static struct modlinkage modlinkage = {
1455295Srandyf MODREV_1, &modldrv, 0
1465295Srandyf };
1475295Srandyf
1485295Srandyf /* Local functions */
1495295Srandyf
1505295Srandyf int
_init(void)1515295Srandyf _init(void)
1525295Srandyf {
1535295Srandyf return (mod_install(&modlinkage));
1545295Srandyf }
1555295Srandyf
1565295Srandyf int
_fini(void)1575295Srandyf _fini(void)
1585295Srandyf {
1595295Srandyf return (mod_remove(&modlinkage));
1605295Srandyf }
1615295Srandyf
1625295Srandyf int
_info(struct modinfo * modinfop)1635295Srandyf _info(struct modinfo *modinfop)
1645295Srandyf {
1655295Srandyf return (mod_info(&modlinkage, modinfop));
1665295Srandyf }
1675295Srandyf
1685295Srandyf static int
srn_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)1695295Srandyf srn_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1705295Srandyf {
1715295Srandyf int i;
1725295Srandyf extern void (*srn_signal)(int, int);
1735295Srandyf
1745295Srandyf switch (cmd) {
1755295Srandyf
1765295Srandyf case DDI_ATTACH:
1775295Srandyf if (srn.srn_instance != -1) /* Only allow one instance */
1785295Srandyf return (DDI_FAILURE);
1795295Srandyf srn.srn_instance = ddi_get_instance(dip);
1805295Srandyf if (ddi_create_minor_node(dip, "srn", S_IFCHR,
1815295Srandyf (srn.srn_instance << 8) + 0, DDI_PSEUDO, 0)
1825295Srandyf != DDI_SUCCESS) {
1835295Srandyf return (DDI_FAILURE);
1845295Srandyf }
1855295Srandyf srn.srn_dip = dip; /* srn_init and getinfo depend on it */
1865295Srandyf
1875295Srandyf for (i = 0; i < SRN_MAX_CLONE; i++)
1885295Srandyf cv_init(&srn_clones_cv[i], NULL, CV_DEFAULT, NULL);
1895295Srandyf
1905295Srandyf srn.srn_instance = ddi_get_instance(dip);
1915295Srandyf mutex_enter(&srn_clone_lock);
1925295Srandyf srn_signal = srn_notify;
1935295Srandyf mutex_exit(&srn_clone_lock);
1945295Srandyf ddi_report_dev(dip);
1955295Srandyf return (DDI_SUCCESS);
1965295Srandyf
1975295Srandyf default:
1985295Srandyf return (DDI_FAILURE);
1995295Srandyf }
2005295Srandyf }
2015295Srandyf
2025295Srandyf /* ARGSUSED */
2035295Srandyf static int
srn_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)2045295Srandyf srn_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
2055295Srandyf {
2065295Srandyf int i;
2075295Srandyf extern int srn_inuse;
2085295Srandyf extern void (*srn_signal)(int, int);
2095295Srandyf
2105295Srandyf switch (cmd) {
2115295Srandyf case DDI_DETACH:
2125295Srandyf
2135295Srandyf mutex_enter(&srn_clone_lock);
2145295Srandyf while (srn_inuse) {
2155295Srandyf mutex_exit(&srn_clone_lock);
2165295Srandyf delay(1);
2175295Srandyf mutex_enter(&srn_clone_lock);
2185295Srandyf }
2195295Srandyf srn_signal = NULL;
2205295Srandyf mutex_exit(&srn_clone_lock);
2215295Srandyf
2225295Srandyf for (i = 0; i < SRN_MAX_CLONE; i++)
2235295Srandyf cv_destroy(&srn_clones_cv[i]);
2245295Srandyf
2255295Srandyf ddi_remove_minor_node(dip, NULL);
2265295Srandyf srn.srn_instance = -1;
2275295Srandyf return (DDI_SUCCESS);
2285295Srandyf
2295295Srandyf default:
2305295Srandyf return (DDI_FAILURE);
2315295Srandyf }
2325295Srandyf }
2335295Srandyf
2345295Srandyf
2355295Srandyf #ifdef DEBUG
2365295Srandyf char *srn_cmd_string;
2375295Srandyf int srn_cmd;
2385295Srandyf #endif
2395295Srandyf
2405295Srandyf /*
2415295Srandyf * Returns true if permission granted by credentials
2425295Srandyf * XXX
2435295Srandyf */
2445295Srandyf static int
srn_perms(int perm,cred_t * cr)2455295Srandyf srn_perms(int perm, cred_t *cr)
2465295Srandyf {
2475295Srandyf if ((perm & SU) && secpolicy_power_mgmt(cr) == 0) /* privileged? */
2485295Srandyf return (1);
2495295Srandyf if ((perm & SG) && (crgetgid(cr) == 0)) /* group 0 is ok */
2505295Srandyf return (1);
2515295Srandyf return (0);
2525295Srandyf }
2535295Srandyf
2545295Srandyf static int
srn_chpoll(dev_t dev,short events,int anyyet,short * reventsp,struct pollhead ** phpp)2555295Srandyf srn_chpoll(dev_t dev, short events, int anyyet, short *reventsp,
2565295Srandyf struct pollhead **phpp)
2575295Srandyf {
25810311SRandy.Fishel@Sun.COM extern struct pollhead srn_pollhead[];
2595295Srandyf int clone;
2605295Srandyf
2615295Srandyf clone = SRN_MINOR_TO_CLONE(getminor(dev));
2625295Srandyf if ((events & (POLLIN | POLLRDNORM)) && srn_poll_cnt[clone]) {
2635295Srandyf *reventsp |= (POLLIN | POLLRDNORM);
2645295Srandyf } else {
2655295Srandyf *reventsp = 0;
2665295Srandyf if (!anyyet) {
2675295Srandyf *phpp = &srn_pollhead[clone];
2685295Srandyf }
2695295Srandyf }
2705295Srandyf return (0);
2715295Srandyf }
2725295Srandyf
2735295Srandyf /*ARGSUSED*/
2745295Srandyf static int
srn_getinfo(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)2755295Srandyf srn_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
2765295Srandyf {
2775295Srandyf dev_t dev;
2785295Srandyf int instance;
2795295Srandyf
2805295Srandyf switch (infocmd) {
2815295Srandyf case DDI_INFO_DEVT2DEVINFO:
2825295Srandyf if (srn.srn_instance == -1)
2835295Srandyf return (DDI_FAILURE);
2845295Srandyf *result = srn.srn_dip;
2855295Srandyf return (DDI_SUCCESS);
2865295Srandyf
2875295Srandyf case DDI_INFO_DEVT2INSTANCE:
2885295Srandyf dev = (dev_t)arg;
2895295Srandyf instance = getminor(dev) >> 8;
2905295Srandyf *result = (void *)(uintptr_t)instance;
2915295Srandyf return (DDI_SUCCESS);
2925295Srandyf
2935295Srandyf default:
2945295Srandyf return (DDI_FAILURE);
2955295Srandyf }
2965295Srandyf }
2975295Srandyf
2985295Srandyf
2995295Srandyf /*ARGSUSED1*/
3005295Srandyf static int
srn_open(dev_t * devp,int flag,int otyp,cred_t * cr)3015295Srandyf srn_open(dev_t *devp, int flag, int otyp, cred_t *cr)
3025295Srandyf {
3035295Srandyf int clone;
3045295Srandyf
3055295Srandyf if (otyp != OTYP_CHR)
3065295Srandyf return (EINVAL);
3075295Srandyf
3085295Srandyf mutex_enter(&srn_clone_lock);
3095295Srandyf for (clone = 1; clone < SRN_MAX_CLONE - 1; clone++)
3105295Srandyf if (!srn.srn_clones[clone])
3115295Srandyf break;
3125295Srandyf
3135295Srandyf if (clone == SRN_MAX_CLONE) {
3145295Srandyf mutex_exit(&srn_clone_lock);
3155295Srandyf return (ENXIO);
3165295Srandyf }
3175295Srandyf srn.srn_cred[clone] = cr;
3185295Srandyf ASSERT(srn_apm_count >= 0);
3195295Srandyf srn_apm_count++;
3205295Srandyf srn.srn_type[clone] = SRN_TYPE_APM;
3215295Srandyf crhold(cr);
3225295Srandyf
3235295Srandyf *devp = makedevice(getmajor(*devp), (srn.srn_instance << 8) +
3245295Srandyf clone);
3255295Srandyf srn.srn_clones[clone] = 1;
3265295Srandyf srn.srn_cred[clone] = cr;
3275295Srandyf crhold(cr);
3285295Srandyf mutex_exit(&srn_clone_lock);
3295295Srandyf PMD(PMD_SX, ("srn open OK\n"))
3305295Srandyf return (0);
3315295Srandyf }
3325295Srandyf
3335295Srandyf /*ARGSUSED1*/
3345295Srandyf static int
srn_close(dev_t dev,int flag,int otyp,cred_t * cr)3355295Srandyf srn_close(dev_t dev, int flag, int otyp, cred_t *cr)
3365295Srandyf {
3375295Srandyf int clone;
3385295Srandyf
3395295Srandyf if (otyp != OTYP_CHR)
3405295Srandyf return (EINVAL);
3415295Srandyf
3425295Srandyf clone = SRN_MINOR_TO_CLONE(getminor(dev));
3435295Srandyf PMD(PMD_SX, ("srn_close: minor %x, clone %x\n", getminor(dev),
3445295Srandyf clone))
3455295Srandyf mutex_enter(&srn_clone_lock);
3465295Srandyf crfree(srn.srn_cred[clone]);
3475295Srandyf srn.srn_cred[clone] = 0;
3485295Srandyf srn_poll_cnt[clone] = 0;
34910311SRandy.Fishel@Sun.COM srn.srn_fault[clone] = 0;
3505295Srandyf if (srn.srn_pending[clone].ae_type || srn.srn_delivered[clone]) {
3515295Srandyf srn.srn_pending[clone].ae_type = 0;
3525295Srandyf srn.srn_delivered[clone] = 0;
3535295Srandyf cv_signal(&srn_clones_cv[clone]);
3545295Srandyf }
3555295Srandyf switch (srn.srn_type[clone]) {
3565295Srandyf case SRN_TYPE_AUTOSX:
3575295Srandyf ASSERT(srn_autosx_count);
3585295Srandyf srn_autosx_count--;
3595295Srandyf break;
3605295Srandyf case SRN_TYPE_APM:
3615295Srandyf ASSERT(srn_apm_count);
3625295Srandyf srn_apm_count--;
3635295Srandyf break;
3645295Srandyf default:
3655295Srandyf ASSERT(0);
3665295Srandyf return (EINVAL);
3675295Srandyf }
3685295Srandyf srn.srn_clones[clone] = 0;
3695295Srandyf mutex_exit(&srn_clone_lock);
3705295Srandyf return (0);
3715295Srandyf }
3725295Srandyf
3735295Srandyf /*ARGSUSED*/
3745295Srandyf static int
srn_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * cr,int * rval_p)3755295Srandyf srn_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, int *rval_p)
3765295Srandyf {
3775295Srandyf int clone = SRN_MINOR_TO_CLONE(getminor(dev));
3785295Srandyf
3795295Srandyf PMD(PMD_SX, ("ioctl: %x: begin\n", cmd))
3805295Srandyf
3815295Srandyf switch (cmd) {
3825295Srandyf case SRN_IOC_NEXTEVENT:
3835295Srandyf case SRN_IOC_SUSPEND:
3845295Srandyf case SRN_IOC_RESUME:
3855295Srandyf case SRN_IOC_AUTOSX:
3865295Srandyf break;
3875295Srandyf default:
3885295Srandyf return (ENOTTY);
3895295Srandyf }
3905295Srandyf
3915295Srandyf if (!srn_perms(SU | SG, srn.srn_cred[clone])) {
3925295Srandyf return (EPERM);
3935295Srandyf }
3945295Srandyf switch (cmd) {
3955295Srandyf case SRN_IOC_AUTOSX:
3965295Srandyf PMD(PMD_SX, ("SRN_IOC_AUTOSX entered\n"))
3975295Srandyf mutex_enter(&srn_clone_lock);
3985295Srandyf if (!srn.srn_clones[clone]) {
3995295Srandyf PMD(PMD_SX, (" ioctl !srn_clones--EINVAL\n"))
4005295Srandyf mutex_exit(&srn_clone_lock);
4015295Srandyf return (EINVAL);
4025295Srandyf }
4035295Srandyf if (srn.srn_pending[clone].ae_type) {
4045295Srandyf PMD(PMD_SX, ("AUTOSX while pending--EBUSY\n"))
4055295Srandyf mutex_exit(&srn_clone_lock);
4065295Srandyf return (EBUSY);
4075295Srandyf }
4085295Srandyf if (srn.srn_type[clone] == SRN_TYPE_AUTOSX) {
4095295Srandyf PMD(PMD_SX, ("AUTOSX already--EBUSY\n"))
4105295Srandyf mutex_exit(&srn_clone_lock);
4115295Srandyf return (EBUSY);
4125295Srandyf }
4135295Srandyf ASSERT(srn.srn_type[clone] == SRN_TYPE_APM);
4145295Srandyf srn.srn_type[clone] = SRN_TYPE_AUTOSX;
41510311SRandy.Fishel@Sun.COM srn.srn_fault[clone] = 0;
4165295Srandyf srn_apm_count--;
4175295Srandyf ASSERT(srn_apm_count >= 0);
4185295Srandyf ASSERT(srn_autosx_count >= 0);
4195295Srandyf srn_autosx_count++;
4205295Srandyf mutex_exit(&srn_clone_lock);
4215295Srandyf PMD(PMD_SX, ("SRN_IOC_AUTOSX returns success\n"))
4225295Srandyf return (0);
4235295Srandyf
4245295Srandyf case SRN_IOC_NEXTEVENT:
4255295Srandyf /*
4265295Srandyf * return the next suspend or resume event; there should
4275295Srandyf * be one, cause we only get called if we've signalled a
4285295Srandyf * poll data completion
4295295Srandyf * then wake up the kernel thread sleeping for the delivery
4305295Srandyf */
4315295Srandyf PMD(PMD_SX, ("SRN_IOC_NEXTEVENT entered\n"))
43210311SRandy.Fishel@Sun.COM if (srn.srn_fault[clone]) {
43310311SRandy.Fishel@Sun.COM PMD(PMD_SX, ("SRN_IOC_NEXTEVENT clone %d fault "
43410311SRandy.Fishel@Sun.COM "cleared\n", clone))
43510311SRandy.Fishel@Sun.COM srn.srn_fault[clone] = 0;
43610311SRandy.Fishel@Sun.COM }
4375295Srandyf mutex_enter(&srn_clone_lock);
4385295Srandyf if (srn_poll_cnt[clone] == 0) {
4395295Srandyf mutex_exit(&srn_clone_lock);
4405295Srandyf PMD(PMD_SX, ("SRN_IOC_NEXTEVENT clone %d "
4415295Srandyf "EWOULDBLOCK\n", clone))
4425295Srandyf return (EWOULDBLOCK);
4435295Srandyf }
4445295Srandyf ASSERT(srn.srn_pending[clone].ae_type);
4455295Srandyf if (ddi_copyout(&srn.srn_pending[clone], (void *)arg,
4465295Srandyf sizeof (srn_event_info_t), mode) != 0) {
4475295Srandyf mutex_exit(&srn_clone_lock);
4485295Srandyf PMD(PMD_SX, ("SRN_IOC_NEXTEVENT clone %d EFAULT\n",
4495295Srandyf clone))
4505295Srandyf return (EFAULT);
4515295Srandyf }
4525295Srandyf if (srn.srn_type[clone] == SRN_TYPE_APM)
4535295Srandyf srn.srn_delivered[clone] =
4545295Srandyf srn.srn_pending[clone].ae_type;
4555295Srandyf PMD(PMD_SX, ("SRN_IOC_NEXTEVENT clone %d delivered %x\n",
4565295Srandyf clone, srn.srn_pending[clone].ae_type))
4575295Srandyf srn_poll_cnt[clone] = 0;
4585295Srandyf mutex_exit(&srn_clone_lock);
4595295Srandyf return (0);
4605295Srandyf
4615295Srandyf case SRN_IOC_SUSPEND:
4625295Srandyf /* ack suspend */
4635295Srandyf PMD(PMD_SX, ("SRN_IOC_SUSPEND entered clone %d\n", clone))
46410311SRandy.Fishel@Sun.COM if (srn.srn_fault[clone]) {
46510311SRandy.Fishel@Sun.COM PMD(PMD_SX, ("SRN_IOC_SUSPEND clone %d fault "
46610311SRandy.Fishel@Sun.COM "cleared\n", clone))
46710311SRandy.Fishel@Sun.COM srn.srn_fault[clone] = 0;
46810311SRandy.Fishel@Sun.COM }
4695295Srandyf mutex_enter(&srn_clone_lock);
4705295Srandyf if (srn.srn_delivered[clone] != SRN_SUSPEND_REQ) {
4715295Srandyf mutex_exit(&srn_clone_lock);
4725295Srandyf PMD(PMD_SX, ("SRN_IOC_SUSPEND EINVAL\n"))
4735295Srandyf return (EINVAL);
4745295Srandyf }
4755295Srandyf srn.srn_delivered[clone] = 0;
4765295Srandyf srn.srn_pending[clone].ae_type = 0;
4775295Srandyf /* notify the kernel suspend thread to continue */
4785295Srandyf PMD(PMD_SX, ("SRN_IOC_SUSPEND clone %d ok\n", clone))
4795295Srandyf cv_signal(&srn_clones_cv[clone]);
4805295Srandyf mutex_exit(&srn_clone_lock);
4815295Srandyf return (0);
4825295Srandyf
4835295Srandyf case SRN_IOC_RESUME:
4845295Srandyf /* ack resume */
4855295Srandyf PMD(PMD_SX, ("SRN_IOC_RESUME entered clone %d\n", clone))
48610311SRandy.Fishel@Sun.COM if (srn.srn_fault[clone]) {
48710311SRandy.Fishel@Sun.COM PMD(PMD_SX, ("SRN_IOC_RESUME clone %d fault "
48810311SRandy.Fishel@Sun.COM "cleared\n", clone))
48910311SRandy.Fishel@Sun.COM srn.srn_fault[clone] = 0;
49010311SRandy.Fishel@Sun.COM }
4915295Srandyf mutex_enter(&srn_clone_lock);
4925295Srandyf if (srn.srn_delivered[clone] != SRN_NORMAL_RESUME) {
4935295Srandyf mutex_exit(&srn_clone_lock);
4945295Srandyf PMD(PMD_SX, ("SRN_IOC_RESUME EINVAL\n"))
4955295Srandyf return (EINVAL);
4965295Srandyf }
4975295Srandyf srn.srn_delivered[clone] = 0;
4985295Srandyf srn.srn_pending[clone].ae_type = 0;
4995295Srandyf /* notify the kernel resume thread to continue */
5005295Srandyf PMD(PMD_SX, ("SRN_IOC_RESUME ok for clone %d\n", clone))
5015295Srandyf cv_signal(&srn_clones_cv[clone]);
5025295Srandyf mutex_exit(&srn_clone_lock);
5035295Srandyf return (0);
5045295Srandyf
5055295Srandyf default:
5065295Srandyf PMD(PMD_SX, ("srn_ioctl unknown cmd EINVAL\n"))
5075295Srandyf return (EINVAL);
5085295Srandyf }
5095295Srandyf }
5105295Srandyf /*
5115295Srandyf * A very simple handshake with the srn driver,
5125295Srandyf * only one outstanding event at a time.
5135295Srandyf * The OS delivers the event and depending on type,
5145295Srandyf * either blocks waiting for the ack, or drives on
5155295Srandyf */
5165295Srandyf void
srn_notify(int type,int event)5175295Srandyf srn_notify(int type, int event)
5185295Srandyf {
5195295Srandyf int clone, count;
5205295Srandyf PMD(PMD_SX, ("srn_notify entered with type %d, event 0x%x\n",
5215295Srandyf type, event));
5225295Srandyf ASSERT(mutex_owned(&srn_clone_lock));
5235295Srandyf switch (type) {
5245295Srandyf case SRN_TYPE_APM:
5255295Srandyf if (srn_apm_count == 0) {
5265295Srandyf PMD(PMD_SX, ("no apm types\n"))
5275295Srandyf return;
5285295Srandyf }
5295295Srandyf count = srn_apm_count;
5305295Srandyf break;
5315295Srandyf case SRN_TYPE_AUTOSX:
5325295Srandyf if (srn_autosx_count == 0) {
5335295Srandyf PMD(PMD_SX, ("no autosx types\n"))
5345295Srandyf return;
5355295Srandyf }
5365295Srandyf count = srn_autosx_count;
5375295Srandyf break;
5385295Srandyf default:
5395295Srandyf ASSERT(0);
5405295Srandyf break;
5415295Srandyf }
5425295Srandyf ASSERT(count > 0);
5435295Srandyf PMD(PMD_SX, ("count %d\n", count))
5445295Srandyf for (clone = 0; clone < SRN_MAX_CLONE; clone++) {
5455295Srandyf if (srn.srn_type[clone] == type) {
54610311SRandy.Fishel@Sun.COM #ifdef DEBUG
547*10642SRandy.Fishel@Sun.COM if (type == SRN_TYPE_APM && !srn.srn_fault[clone]) {
5485295Srandyf ASSERT(srn.srn_pending[clone].ae_type == 0);
5495295Srandyf ASSERT(srn_poll_cnt[clone] == 0);
5505295Srandyf ASSERT(srn.srn_delivered[clone] == 0);
5515295Srandyf }
55210311SRandy.Fishel@Sun.COM #endif
5535295Srandyf srn.srn_pending[clone].ae_type = event;
5545295Srandyf srn_poll_cnt[clone] = 1;
5555295Srandyf PMD(PMD_SX, ("pollwake %d\n", clone))
5565295Srandyf pollwakeup(&srn_pollhead[clone], (POLLRDNORM | POLLIN));
5575295Srandyf count--;
5585295Srandyf if (count == 0)
5595295Srandyf break;
5605295Srandyf }
5615295Srandyf }
5625295Srandyf if (type == SRN_TYPE_AUTOSX) { /* we don't wait */
5635295Srandyf PMD(PMD_SX, ("Not waiting for AUTOSX ack\n"))
5645295Srandyf return;
5655295Srandyf }
5665295Srandyf ASSERT(type == SRN_TYPE_APM);
5675295Srandyf /* otherwise wait for acks */
5685295Srandyf restart:
5695295Srandyf /*
57010311SRandy.Fishel@Sun.COM * We wait until all of the pending events are cleared.
5715295Srandyf * We have to start over every time we do a cv_wait because
5725295Srandyf * we give up the mutex and can be re-entered
5735295Srandyf */
5745295Srandyf for (clone = 1; clone < SRN_MAX_CLONE; clone++) {
5755295Srandyf if (srn.srn_clones[clone] == 0 ||
5765295Srandyf srn.srn_type[clone] != SRN_TYPE_APM)
5775295Srandyf continue;
57810311SRandy.Fishel@Sun.COM if (srn.srn_pending[clone].ae_type && !srn.srn_fault[clone]) {
5795295Srandyf PMD(PMD_SX, ("srn_notify waiting for ack for clone %d, "
5805295Srandyf "event %x\n", clone, event))
58110311SRandy.Fishel@Sun.COM if (cv_timedwait(&srn_clones_cv[clone],
58210311SRandy.Fishel@Sun.COM &srn_clone_lock, ddi_get_lbolt() +
58310311SRandy.Fishel@Sun.COM drv_usectohz(srn_timeout * 1000000)) == -1) {
58410311SRandy.Fishel@Sun.COM /*
58510311SRandy.Fishel@Sun.COM * Client didn't respond, mark it as faulted
58610311SRandy.Fishel@Sun.COM * and continue as if a regular signal.
58710311SRandy.Fishel@Sun.COM */
58810311SRandy.Fishel@Sun.COM PMD(PMD_SX, ("srn_notify: clone %d did not "
58910311SRandy.Fishel@Sun.COM "ack event %x\n", clone, event))
59010311SRandy.Fishel@Sun.COM cmn_err(CE_WARN, "srn_notify: clone %d did "
59110311SRandy.Fishel@Sun.COM "not ack event %x\n", clone, event);
59210311SRandy.Fishel@Sun.COM srn.srn_fault[clone] = 1;
59310311SRandy.Fishel@Sun.COM }
5945295Srandyf goto restart;
5955295Srandyf }
5965295Srandyf }
5975295Srandyf PMD(PMD_SX, ("srn_notify done with %x\n", event))
5985295Srandyf }
599