2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * CDDL HEADER START
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf *
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 *
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * or http://www.opensolaris.org/os/licensing.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * See the License for the specific language governing permissions
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * and limitations under the License.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf *
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 *
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * CDDL HEADER END
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Use is subject to license terms.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * srn Provide apm-like interfaces to Xorg
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/types.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/errno.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/modctl.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/conf.h> /* driver flags and functions */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/open.h> /* OTYP_CHR definition */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/stat.h> /* S_IFCHR definition */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/pathname.h> /* name -> dev_info xlation */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/kmem.h> /* memory alloc stuff */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/debug.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/pm.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/ddi.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/sunddi.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/epm.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/vfs.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/mode.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/mkdev.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/promif.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/consdev.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/ddi_impldefs.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/poll.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/note.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/taskq.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/policy.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/srn.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Minor number is instance<<8 + clone minor from range 1-255;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * But only one will be allocated
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#define SRN_MINOR_TO_CLONE(minor) ((minor) & (SRN_MAX_CLONE - 1))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#define SU 0x002
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#define SG 0x004
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfextern kmutex_t srn_clone_lock; /* protects srn_clones array */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfextern kcondvar_t srn_clones_cv[SRN_MAX_CLONE];
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfextern uint_t srn_poll_cnt[SRN_MAX_CLONE];
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
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 */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic struct srnstate {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf dev_info_t *srn_dip; /* ptr to our dev_info node */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf int srn_instance; /* for ddi_get_instance() */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf uchar_t srn_clones[SRN_MAX_CLONE]; /* unique opens */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf struct cred *srn_cred[SRN_MAX_CLONE]; /* cred for each open */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf int srn_type[SRN_MAX_CLONE]; /* type of handshake */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf int srn_delivered[SRN_MAX_CLONE];
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn_event_info_t srn_pending[SRN_MAX_CLONE];
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel int srn_fault[SRN_MAX_CLONE];
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf} srn = { NULL, -1};
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyftypedef struct srnstate *srn_state_t;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfkcondvar_t srn_clones_cv[SRN_MAX_CLONE];
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfuint_t srn_poll_cnt[SRN_MAX_CLONE]; /* count of events for poll */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfint srn_apm_count;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfint srn_autosx_count;
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel/* Number of seconds to wait for clients to ack a poll */
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishelint srn_timeout = 10;
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstruct pollhead srn_pollhead[SRN_MAX_CLONE];
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int srn_open(dev_t *, int, int, cred_t *);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int srn_close(dev_t, int, int, cred_t *);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int srn_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int srn_chpoll(dev_t, short, int, short *, struct pollhead **);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic struct cb_ops srn_cb_ops = {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn_open, /* open */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn_close, /* close */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf nodev, /* strategy */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf nodev, /* print */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf nodev, /* dump */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf nodev, /* read */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf nodev, /* write */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn_ioctl, /* ioctl */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf nodev, /* devmap */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf nodev, /* mmap */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf nodev, /* segmap */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn_chpoll, /* poll */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ddi_prop_op, /* prop_op */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf NULL, /* streamtab */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf D_NEW | D_MP /* driver compatibility flag */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf};
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int srn_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf void **result);
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);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic void srn_notify(int type, int event);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic struct dev_ops srn_ops = {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf DEVO_REV, /* devo_rev */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf 0, /* refcnt */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn_getinfo, /* info */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf nulldev, /* identify */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf nulldev, /* probe */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn_attach, /* attach */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn_detach, /* detach */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf nodev, /* reset */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf &srn_cb_ops, /* driver operations */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf NULL, /* bus operations */
193974072f41a843678abf5f61979c748687e66bSherry Moore NULL, /* power */
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_quiesce_not_needed, /* quiesce */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf};
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic struct modldrv modldrv = {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf &mod_driverops,
193974072f41a843678abf5f61979c748687e66bSherry Moore "srn driver",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf &srn_ops
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf};
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic struct modlinkage modlinkage = {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf MODREV_1, &modldrv, 0
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf};
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/* Local functions */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfint
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf_init(void)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (mod_install(&modlinkage));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfint
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf_fini(void)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (mod_remove(&modlinkage));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfint
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf_info(struct modinfo *modinfop)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (mod_info(&modlinkage, modinfop));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfsrn_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf int i;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf extern void (*srn_signal)(int, int);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf switch (cmd) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf case DDI_ATTACH:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (srn.srn_instance != -1) /* Only allow one instance */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (DDI_FAILURE);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn.srn_instance = ddi_get_instance(dip);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (ddi_create_minor_node(dip, "srn", S_IFCHR,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (srn.srn_instance << 8) + 0, DDI_PSEUDO, 0)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf != DDI_SUCCESS) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (DDI_FAILURE);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn.srn_dip = dip; /* srn_init and getinfo depend on it */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf for (i = 0; i < SRN_MAX_CLONE; i++)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf cv_init(&srn_clones_cv[i], NULL, CV_DEFAULT, NULL);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn.srn_instance = ddi_get_instance(dip);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_enter(&srn_clone_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn_signal = srn_notify;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_exit(&srn_clone_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ddi_report_dev(dip);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (DDI_SUCCESS);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf default:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (DDI_FAILURE);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/* ARGSUSED */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfsrn_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf int i;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf extern int srn_inuse;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf extern void (*srn_signal)(int, int);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf switch (cmd) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf case DDI_DETACH:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_enter(&srn_clone_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf while (srn_inuse) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_exit(&srn_clone_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf delay(1);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_enter(&srn_clone_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn_signal = NULL;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_exit(&srn_clone_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf for (i = 0; i < SRN_MAX_CLONE; i++)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf cv_destroy(&srn_clones_cv[i]);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ddi_remove_minor_node(dip, NULL);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn.srn_instance = -1;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (DDI_SUCCESS);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf default:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (DDI_FAILURE);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#ifdef DEBUG
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfchar *srn_cmd_string;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfint srn_cmd;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#endif
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Returns true if permission granted by credentials
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * XXX
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfsrn_perms(int perm, cred_t *cr)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
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);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfsrn_chpoll(dev_t dev, short events, int anyyet, short *reventsp,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf struct pollhead **phpp)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel extern struct pollhead srn_pollhead[];
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf int clone;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf clone = SRN_MINOR_TO_CLONE(getminor(dev));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if ((events & (POLLIN | POLLRDNORM)) && srn_poll_cnt[clone]) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf *reventsp |= (POLLIN | POLLRDNORM);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf } else {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf *reventsp = 0;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (!anyyet) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf *phpp = &srn_pollhead[clone];
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*ARGSUSED*/
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfsrn_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf dev_t dev;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf int instance;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf switch (infocmd) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf case DDI_INFO_DEVT2DEVINFO:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (srn.srn_instance == -1)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (DDI_FAILURE);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf *result = srn.srn_dip;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (DDI_SUCCESS);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf case DDI_INFO_DEVT2INSTANCE:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf dev = (dev_t)arg;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf instance = getminor(dev) >> 8;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf *result = (void *)(uintptr_t)instance;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (DDI_SUCCESS);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf default:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (DDI_FAILURE);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*ARGSUSED1*/
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfsrn_open(dev_t *devp, int flag, int otyp, cred_t *cr)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf int clone;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (otyp != OTYP_CHR)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (EINVAL);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_enter(&srn_clone_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf for (clone = 1; clone < SRN_MAX_CLONE - 1; clone++)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (!srn.srn_clones[clone])
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf break;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (clone == SRN_MAX_CLONE) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_exit(&srn_clone_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (ENXIO);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn.srn_cred[clone] = cr;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ASSERT(srn_apm_count >= 0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn_apm_count++;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn.srn_type[clone] = SRN_TYPE_APM;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf crhold(cr);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf *devp = makedevice(getmajor(*devp), (srn.srn_instance << 8) +
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf clone);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn.srn_clones[clone] = 1;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn.srn_cred[clone] = cr;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf crhold(cr);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_exit(&srn_clone_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("srn open OK\n"))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*ARGSUSED1*/
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfsrn_close(dev_t dev, int flag, int otyp, cred_t *cr)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf int clone;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (otyp != OTYP_CHR)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (EINVAL);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf clone = SRN_MINOR_TO_CLONE(getminor(dev));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("srn_close: minor %x, clone %x\n", getminor(dev),
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf clone))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_enter(&srn_clone_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf crfree(srn.srn_cred[clone]);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn.srn_cred[clone] = 0;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn_poll_cnt[clone] = 0;
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel srn.srn_fault[clone] = 0;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (srn.srn_pending[clone].ae_type || srn.srn_delivered[clone]) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn.srn_pending[clone].ae_type = 0;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn.srn_delivered[clone] = 0;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf cv_signal(&srn_clones_cv[clone]);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf switch (srn.srn_type[clone]) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf case SRN_TYPE_AUTOSX:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ASSERT(srn_autosx_count);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn_autosx_count--;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf break;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf case SRN_TYPE_APM:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ASSERT(srn_apm_count);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn_apm_count--;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf break;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf default:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ASSERT(0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (EINVAL);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn.srn_clones[clone] = 0;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_exit(&srn_clone_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*ARGSUSED*/
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfsrn_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, int *rval_p)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf int clone = SRN_MINOR_TO_CLONE(getminor(dev));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("ioctl: %x: begin\n", cmd))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf switch (cmd) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf case SRN_IOC_NEXTEVENT:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf case SRN_IOC_SUSPEND:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf case SRN_IOC_RESUME:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf case SRN_IOC_AUTOSX:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf break;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf default:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (ENOTTY);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (!srn_perms(SU | SG, srn.srn_cred[clone])) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (EPERM);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf switch (cmd) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf case SRN_IOC_AUTOSX:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("SRN_IOC_AUTOSX entered\n"))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_enter(&srn_clone_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (!srn.srn_clones[clone]) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, (" ioctl !srn_clones--EINVAL\n"))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_exit(&srn_clone_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (EINVAL);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (srn.srn_pending[clone].ae_type) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("AUTOSX while pending--EBUSY\n"))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_exit(&srn_clone_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (EBUSY);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (srn.srn_type[clone] == SRN_TYPE_AUTOSX) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("AUTOSX already--EBUSY\n"))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_exit(&srn_clone_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (EBUSY);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ASSERT(srn.srn_type[clone] == SRN_TYPE_APM);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn.srn_type[clone] = SRN_TYPE_AUTOSX;
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel srn.srn_fault[clone] = 0;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn_apm_count--;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ASSERT(srn_apm_count >= 0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ASSERT(srn_autosx_count >= 0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn_autosx_count++;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_exit(&srn_clone_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("SRN_IOC_AUTOSX returns success\n"))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf case SRN_IOC_NEXTEVENT:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
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
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("SRN_IOC_NEXTEVENT entered\n"))
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel if (srn.srn_fault[clone]) {
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel PMD(PMD_SX, ("SRN_IOC_NEXTEVENT clone %d fault "
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel "cleared\n", clone))
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel srn.srn_fault[clone] = 0;
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_enter(&srn_clone_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (srn_poll_cnt[clone] == 0) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_exit(&srn_clone_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("SRN_IOC_NEXTEVENT clone %d "
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf "EWOULDBLOCK\n", clone))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (EWOULDBLOCK);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ASSERT(srn.srn_pending[clone].ae_type);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (ddi_copyout(&srn.srn_pending[clone], (void *)arg,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf sizeof (srn_event_info_t), mode) != 0) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_exit(&srn_clone_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("SRN_IOC_NEXTEVENT clone %d EFAULT\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf clone))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (EFAULT);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (srn.srn_type[clone] == SRN_TYPE_APM)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn.srn_delivered[clone] =
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn.srn_pending[clone].ae_type;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("SRN_IOC_NEXTEVENT clone %d delivered %x\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf clone, srn.srn_pending[clone].ae_type))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn_poll_cnt[clone] = 0;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_exit(&srn_clone_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf case SRN_IOC_SUSPEND:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /* ack suspend */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("SRN_IOC_SUSPEND entered clone %d\n", clone))
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel if (srn.srn_fault[clone]) {
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel PMD(PMD_SX, ("SRN_IOC_SUSPEND clone %d fault "
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel "cleared\n", clone))
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel srn.srn_fault[clone] = 0;
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_enter(&srn_clone_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (srn.srn_delivered[clone] != SRN_SUSPEND_REQ) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_exit(&srn_clone_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("SRN_IOC_SUSPEND EINVAL\n"))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (EINVAL);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn.srn_delivered[clone] = 0;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn.srn_pending[clone].ae_type = 0;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /* notify the kernel suspend thread to continue */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("SRN_IOC_SUSPEND clone %d ok\n", clone))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf cv_signal(&srn_clones_cv[clone]);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_exit(&srn_clone_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf case SRN_IOC_RESUME:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /* ack resume */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("SRN_IOC_RESUME entered clone %d\n", clone))
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel if (srn.srn_fault[clone]) {
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel PMD(PMD_SX, ("SRN_IOC_RESUME clone %d fault "
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel "cleared\n", clone))
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel srn.srn_fault[clone] = 0;
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_enter(&srn_clone_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (srn.srn_delivered[clone] != SRN_NORMAL_RESUME) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_exit(&srn_clone_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("SRN_IOC_RESUME EINVAL\n"))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (EINVAL);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn.srn_delivered[clone] = 0;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn.srn_pending[clone].ae_type = 0;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /* notify the kernel resume thread to continue */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("SRN_IOC_RESUME ok for clone %d\n", clone))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf cv_signal(&srn_clones_cv[clone]);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_exit(&srn_clone_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf default:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("srn_ioctl unknown cmd EINVAL\n"))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (EINVAL);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
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 */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfvoid
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfsrn_notify(int type, int event)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf int clone, count;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("srn_notify entered with type %d, event 0x%x\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf type, event));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ASSERT(mutex_owned(&srn_clone_lock));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf switch (type) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf case SRN_TYPE_APM:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (srn_apm_count == 0) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("no apm types\n"))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf count = srn_apm_count;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf break;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf case SRN_TYPE_AUTOSX:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (srn_autosx_count == 0) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("no autosx types\n"))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf count = srn_autosx_count;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf break;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf default:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ASSERT(0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf break;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ASSERT(count > 0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("count %d\n", count))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf for (clone = 0; clone < SRN_MAX_CLONE; clone++) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (srn.srn_type[clone] == type) {
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel#ifdef DEBUG
b785f896a48d487b0368ef79094294b7f0e9b1d5Randy Fishel if (type == SRN_TYPE_APM && !srn.srn_fault[clone]) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ASSERT(srn.srn_pending[clone].ae_type == 0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ASSERT(srn_poll_cnt[clone] == 0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ASSERT(srn.srn_delivered[clone] == 0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel#endif
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn.srn_pending[clone].ae_type = event;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn_poll_cnt[clone] = 1;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("pollwake %d\n", clone))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf pollwakeup(&srn_pollhead[clone], (POLLRDNORM | POLLIN));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf count--;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (count == 0)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf break;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (type == SRN_TYPE_AUTOSX) { /* we don't wait */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("Not waiting for AUTOSX ack\n"))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ASSERT(type == SRN_TYPE_APM);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /* otherwise wait for acks */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfrestart:
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
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
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf for (clone = 1; clone < SRN_MAX_CLONE; clone++) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (srn.srn_clones[clone] == 0 ||
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf srn.srn_type[clone] != SRN_TYPE_APM)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf continue;
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, "
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf "event %x\n", clone, event))
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel if (cv_timedwait(&srn_clones_cv[clone],
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel &srn_clone_lock, ddi_get_lbolt() +
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel drv_usectohz(srn_timeout * 1000000)) == -1) {
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel /*
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel * Client didn't respond, mark it as faulted
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel * and continue as if a regular signal.
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel */
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel PMD(PMD_SX, ("srn_notify: clone %d did not "
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel "ack event %x\n", clone, event))
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel cmn_err(CE_WARN, "srn_notify: clone %d did "
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel "not ack event %x\n", clone, event);
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel srn.srn_fault[clone] = 1;
2fc97812365263561512aff4b02a22807e9a13a7Randy Fishel }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf goto restart;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("srn_notify done with %x\n", event))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}