Home | History | Annotate | Download | only in io
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /*
     27  * nulldriver - null device driver
     28  *
     29  * The nulldriver is used to associate a solaris driver with a specific
     30  * device without enabling external device access.
     31  *
     32  * The driver can be used to:
     33  *
     34  * o Prevent external access to specific devices/hardware by associating a
     35  *   high-precedence 'compatible' binding, including a path-oriented alias,
     36  *   with nulldriver.
     37  *
     38  * o Enable a nexus bus_config implementation to perform dynamic child
     39  *   discovery by creating a child 'probe' devinfo node, bound to
     40  *   nulldriver, at the specific child @unit-addresses associated with
     41  *   discovery.  With a nulldriver bound 'probe' node, nexus driver
     42  *   bus_config discovery code can use the same devinfo node oriented
     43  *   transport services for both discovery and normal-operation: which
     44  *   is a significant simplification.  While nulldriver prevents external
     45  *   device access, a nexus driver can still internally use the transport
     46  *   services.
     47  *
     48  *   A scsi(4) example of this type of use is SCSA enumeration services
     49  *   issuing a scsi REPORT_LUN command to a lun-0 'probe' node bound to
     50  *   nulldriver in order to discover all luns supported by a target.
     51  */
     52 
     53 #include <sys/modctl.h>
     54 #include <sys/conf.h>
     55 #include <sys/ddi.h>
     56 #include <sys/sunddi.h>
     57 #include <sys/cmn_err.h>
     58 
     59 static int nulldriver_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
     60 static int nulldriver_probe(dev_info_t *);
     61 static int nulldriver_attach(dev_info_t *, ddi_attach_cmd_t);
     62 static int nulldriver_detach(dev_info_t *, ddi_detach_cmd_t);
     63 
     64 static struct cb_ops nulldriver_cb_ops = {
     65 	nodev,				/* open */
     66 	nodev,				/* close */
     67 	nodev,				/* strategy */
     68 	nodev,				/* print */
     69 	nodev,				/* dump */
     70 	nodev,				/* read */
     71 	nodev,				/* write */
     72 	nodev,				/* ioctl */
     73 	nodev,				/* devmap */
     74 	nodev,				/* mmap */
     75 	nodev,				/* segmap */
     76 	nochpoll,			/* poll */
     77 	ddi_prop_op,			/* cb_prop_op */
     78 	0,				/* streamtab  */
     79 	D_MP | D_NEW | D_HOTPLUG	/* Driver compatibility flag */
     80 };
     81 
     82 static struct dev_ops nulldriver_dev_ops = {
     83 	DEVO_REV,			/* devo_rev, */
     84 	0,				/* refcnt  */
     85 	nulldriver_getinfo,		/* info */
     86 	nodev,				/* identify */
     87 	nulldriver_probe,		/* probe */
     88 	nulldriver_attach,		/* attach */
     89 	nulldriver_detach,		/* detach */
     90 	nodev,				/* reset */
     91 	&nulldriver_cb_ops,		/* driver operations */
     92 	(struct bus_ops *)0,		/* bus operations */
     93 	NULL,				/* power */
     94 	ddi_quiesce_not_needed,		/* quiesce */
     95 };
     96 
     97 static struct modldrv modldrv = {
     98 	&mod_driverops, "nulldriver 1.1", &nulldriver_dev_ops
     99 };
    100 
    101 static struct modlinkage modlinkage = {
    102 	MODREV_1, &modldrv, NULL
    103 };
    104 
    105 int
    106 _init(void)
    107 {
    108 	return (mod_install(&modlinkage));
    109 }
    110 
    111 int
    112 _fini(void)
    113 {
    114 	return (mod_remove(&modlinkage));
    115 }
    116 
    117 int
    118 _info(struct modinfo *modinfop)
    119 {
    120 	return (mod_info(&modlinkage, modinfop));
    121 }
    122 
    123 /*ARGSUSED*/
    124 static int
    125 nulldriver_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd,
    126     void *arg, void **result)
    127 {
    128 	return (DDI_FAILURE);
    129 }
    130 
    131 /*ARGSUSED*/
    132 static int
    133 nulldriver_probe(dev_info_t *dip)
    134 {
    135 	/*
    136 	 * We want to succeed probe so that the node gets assigned a unit
    137 	 * address "@addr".
    138 	 */
    139 	if (ddi_dev_is_sid(dip) == DDI_SUCCESS)
    140 		return (DDI_PROBE_DONTCARE);
    141 	return (DDI_PROBE_DONTCARE);
    142 }
    143 
    144 /*
    145  * nulldriver_attach()
    146  *	attach(9e) entrypoint.
    147  */
    148 /* ARGSUSED */
    149 static int
    150 nulldriver_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
    151 {
    152 	switch (cmd) {
    153 	case DDI_ATTACH:
    154 	case DDI_RESUME:
    155 		return (DDI_SUCCESS);
    156 
    157 	case DDI_PM_RESUME:
    158 	default:
    159 		return (DDI_FAILURE);
    160 	}
    161 }
    162 
    163 /*
    164  * nulldriver_detach()
    165  *	detach(9E) entrypoint
    166  */
    167 /* ARGSUSED */
    168 static int
    169 nulldriver_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
    170 {
    171 	switch (cmd) {
    172 	case DDI_DETACH:
    173 	case DDI_SUSPEND:
    174 		return (DDI_SUCCESS);
    175 
    176 	case DDI_PM_SUSPEND:
    177 	default:
    178 		return (DDI_FAILURE);
    179 	}
    180 }
    181