2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * CDDL HEADER START
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * The contents of this file are subject to the terms of the
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Common Development and Distribution License (the "License").
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * You may not use this file except in compliance with the License.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * See the License for the specific language governing permissions
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * and limitations under the License.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * When distributing Covered Code, include this CDDL HEADER in each
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * If applicable, add the following below this CDDL HEADER, with the
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * fields enclosed by brackets "[]" replaced with your own identifying
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * information: Portions Copyright [yyyy] [name of copyright owner]
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * CDDL HEADER END
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Use is subject to license terms.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * srn Provide apm-like interfaces to Xorg
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/conf.h> /* driver flags and functions */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/pathname.h> /* name -> dev_info xlation */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Minor number is instance<<8 + clone minor from range 1-255;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * But only one will be allocated
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#define SRN_MINOR_TO_CLONE(minor) ((minor) & (SRN_MAX_CLONE - 1))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfextern kmutex_t srn_clone_lock; /* protects srn_clones array */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * The soft state of the srn driver. Since there will only be
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * one of these, just reference it through a static struct.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf uchar_t srn_clones[SRN_MAX_CLONE]; /* unique opens */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf struct cred *srn_cred[SRN_MAX_CLONE]; /* cred for each open */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfuint_t srn_poll_cnt[SRN_MAX_CLONE]; /* count of events for poll */
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel/* Number of seconds to wait for clients to ack a poll */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int srn_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int srn_chpoll(dev_t, short, int, short *, struct pollhead **);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int srn_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int srn_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int srn_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf 0, /* refcnt */
193974072f41a843678abf5f61979c748687e66bSherry Moore "srn driver",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/* Local functions */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf extern void (*srn_signal)(int, int);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (srn.srn_instance != -1) /* Only allow one instance */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn.srn_dip = dip; /* srn_init and getinfo depend on it */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf for (i = 0; i < SRN_MAX_CLONE; i++)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/* ARGSUSED */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf extern void (*srn_signal)(int, int);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf for (i = 0; i < SRN_MAX_CLONE; i++)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Returns true if permission granted by credentials
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if ((perm & SU) && secpolicy_power_mgmt(cr) == 0) /* privileged? */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (1);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if ((perm & SG) && (crgetgid(cr) == 0)) /* group 0 is ok */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (1);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfsrn_chpoll(dev_t dev, short events, int anyyet, short *reventsp,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if ((events & (POLLIN | POLLRDNORM)) && srn_poll_cnt[clone]) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*ARGSUSED*/
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfsrn_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*ARGSUSED1*/
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf *devp = makedevice(getmajor(*devp), (srn.srn_instance << 8) +
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*ARGSUSED1*/
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("srn_close: minor %x, clone %x\n", getminor(dev),
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (srn.srn_pending[clone].ae_type || srn.srn_delivered[clone]) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*ARGSUSED*/
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfsrn_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, int *rval_p)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * return the next suspend or resume event; there should
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * be one, cause we only get called if we've signalled a
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * poll data completion
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * then wake up the kernel thread sleeping for the delivery
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel PMD(PMD_SX, ("SRN_IOC_NEXTEVENT clone %d fault "
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (ddi_copyout(&srn.srn_pending[clone], (void *)arg,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("SRN_IOC_NEXTEVENT clone %d delivered %x\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /* ack suspend */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("SRN_IOC_SUSPEND entered clone %d\n", clone))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /* notify the kernel suspend thread to continue */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("SRN_IOC_SUSPEND clone %d ok\n", clone))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /* ack resume */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("SRN_IOC_RESUME entered clone %d\n", clone))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /* notify the kernel resume thread to continue */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("SRN_IOC_RESUME ok for clone %d\n", clone))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * A very simple handshake with the srn driver,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * only one outstanding event at a time.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * The OS delivers the event and depending on type,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * either blocks waiting for the ack, or drives on
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("srn_notify entered with type %d, event 0x%x\n",
b785f896a48d487b0368ef79094294b7f0e9b1d5Randy Fishel if (type == SRN_TYPE_APM && !srn.srn_fault[clone]) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf pollwakeup(&srn_pollhead[clone], (POLLRDNORM | POLLIN));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /* otherwise wait for acks */
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel * We wait until all of the pending events are cleared.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * We have to start over every time we do a cv_wait because
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * we give up the mutex and can be re-entered
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel if (srn.srn_pending[clone].ae_type && !srn.srn_fault[clone]) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("srn_notify waiting for ack for clone %d, "
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel * Client didn't respond, mark it as faulted
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel * and continue as if a regular signal.