/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2012 Milan Jurik. All rights reserved.
*/
#define __NSC_GEN__
#include "../nsctl.h"
#ifdef DS_DDICT
#include "../contract.h"
#endif
extern void nscsetup();
extern int _nsc_init_raw(int);
extern void _nsc_deinit_raw();
extern void _nsc_init_start();
extern void _nsc_init_os(), _nsc_deinit_os();
extern void _nsc_init_dev(), _nsc_init_mem();
extern void _nsc_init_gen(), _nsc_init_rmlock();
extern void _nsc_init_resv(), _nsc_deinit_resv();
extern void _nsc_init_frz(), _nsc_deinit_frz();
extern void _nsc_init_ncio(), _nsc_deinit_ncio();
extern void _nsc_deinit_mem(), _nsc_deinit_rmlock();
extern void _nsc_deinit_dev();
extern int _nsc_frz_start(char *, int *);
extern int _nsc_frz_stop(char *, int *);
extern int _nsc_frz_isfrozen(char *, int *);
extern nsc_mem_t *_nsc_local_mem;
extern nsc_rmhdr_t *_nsc_rmhdr_ptr;
extern nsc_def_t _nsc_raw_def[];
extern int _nsc_raw_flags;
int _nsc_init_done = 0;
/* Maximum number of devices - tunable in nsctl.conf */
static int _nsc_max_devices;
/* Internal version of _nsc_max_devices */
int _nsc_maxdev;
extern void _nsc_global_setup(void);
static int nsc_load(), nsc_unload();
static void nscteardown();
/*
* Solaris specific driver module interface code.
*/
static int _nsctl_print(dev_t, char *);
nscopen, /* open */
nscclose, /* close */
nodev, /* not a block driver, strategy not an entry point */
_nsctl_print, /* no print routine */
nodev, /* no dump routine */
nscread, /* read */
nscwrite, /* write */
(int (*)()) nscioctl, /* ioctl */
nodev, /* no devmap routine */
nodev, /* no mmap routine */
nodev, /* no segmap routine */
nochpoll, /* no chpoll routine */
0, /* not a STREAMS driver, no cb_str routine */
nodev, /* aread */
nodev, /* awrite */
};
DEVO_REV, /* Driver build version */
0, /* device reference count */
nulldev, /* Identify */
nulldev, /* Probe */
nodev, /* Reset */
(struct bus_ops *)0
};
"nws:Control:" ISS_VERSION_STR,
};
};
/*
* Solaris module load time code
*/
int nsc_min_nodeid;
int nsc_max_nodeid;
int
_init(void)
{
int err;
if (!err)
if (err) {
(void) nsc_unload();
}
return (err);
}
/*
* Solaris module unload time code
*/
int
_fini(void)
{
int err;
err = nsc_unload();
}
return (err);
}
/*
* Solaris module info code
*/
int
{
}
/*
* Attach an instance of the device. This happens before an open
* can succeed.
*/
static int
{
int rc;
if (cmd == DDI_ATTACH) {
/* Announce presence of the device */
/*
* Get the node parameters now that we can look up.
*/
"nsc_min_nodeid", 0);
"nsc_max_nodeid", 5);
"nsc_max_devices", 128);
nscsetup();
/*
* Init raw requires the _nsc_max_devices value and so
* cannot be done before the nsc_max_devices property has
* been read which can only be done after the module is
* attached and we have a dip.
*/
"!nsctl: unable to initialize raw io provider: %d",
rc);
return (DDI_FAILURE);
}
/*
* Init rest of soft state structure
*/
DDI_PSEUDO, 0);
if (rc != DDI_SUCCESS) {
/* free anything we allocated here */
"!_nsctl_attach: ddi_create_minor_node failed %d",
rc);
return (DDI_FAILURE);
}
/* Announce presence of the device */
/* mark the device as attached, opens may proceed */
return (DDI_SUCCESS);
} else
return (DDI_FAILURE);
}
static int
{
if (cmd == DDI_DETACH) {
nscteardown();
return (DDI_SUCCESS);
}
else
return (DDI_FAILURE);
}
/* ARGSUSED */
static int
{
int rc;
switch (cmd) {
case DDI_INFO_DEVT2INSTANCE:
/* The "instance" number is the minor number */
rc = DDI_SUCCESS;
break;
case DDI_INFO_DEVT2DEVINFO:
rc = DDI_SUCCESS;
break;
default:
rc = DDI_FAILURE;
break;
}
return (rc);
}
/* ARGSUSED */
static int
{
return (0);
}
void
nsc_init()
{
if (_nsc_init_done)
return;
_nsc_init_os();
(void) _nsc_init_power();
/*
* When using mc, nscsetup is done through mc callback to global_init.
*/
nscsetup();
if (!_nsc_raw_io)
_nsc_init_done = 1;
}
/*
* Called after the mc refresh is complete (SEG_INIT callbacks have
* been received) and module _attach() is done. Only does any real
* work when all of the above conditions have been met.
*/
void
nscsetup()
{
return;
0, _nsc_local_mem);
if (!_nsc_minor_fd) {
return;
}
0, _nsc_local_mem);
if (!_nsc_minor_slp) {
}
}
static void
{
int i;
if (_nsc_minor_fd == NULL)
return;
#ifdef DEBUG
/* Check all devices were closed. Index 0 is the prototype dev. */
for (i = 1; i < _nsc_maxdev; i++) {
}
#endif /* DEBUG */
}
int
nsc_load()
{
nsc_init();
return (0);
}
int
{
if (!_nsc_init_done) {
return (0);
}
nscteardown();
(void) _nsc_deinit_power();
if (_nsc_vchr_io)
(void) nsc_unregister_io(_nsc_vchr_io, 0);
if (_nsc_file_io)
(void) nsc_unregister_io(_nsc_file_io, 0);
_nsc_vchr_io = NULL;
_nsc_file_io = NULL;
if (_nsc_raw_io)
(void) nsc_unregister_io(_nsc_raw_io, 0);
_nsc_raw_io = NULL;
_nsc_init_done = 0;
return (0);
}
/* ARGSUSED */
int
{
int i, error;
return (error);
if (!_nsc_minor_fd || !_nsc_minor_slp)
return (ENXIO);
return (ENXIO);
for (i = 1; i < _nsc_maxdev; i++) {
if (_nsc_minor_slp[i] == NULL) {
_nsc_minor_slp[i] = slp;
break;
}
}
if (i >= _nsc_maxdev) {
return (EAGAIN);
}
return (0);
}
int
{
int rc;
return (ENOMEM);
}
return (EFAULT);
}
if (_nsc_minor_fd[mindev]) {
return (EBUSY);
}
return (rc);
}
return (rc);
}
}
*rvp = 0;
return (0);
}
/* ARGSUSED */
int
{
if (!_nsc_minor_fd || !_nsc_minor_slp)
return (0);
return (0);
return (0);
}
/* ARGSUSED */
int
{
return (EIO);
return (rc);
}
if (resv)
return (rc);
}
/* ARGSUSED */
int
{
return (EIO);
return (rc);
}
if (resv)
return (rc);
}
int
{
int rc;
return (EIO);
return (EBUSY);
}
return (rc);
}
*rvp = 0;
return (0);
}
int
{
return (EIO);
return (EINVAL);
}
*rvp = 0;
return (0);
}
int
{
return (EIO);
return (rc);
}
if (resv)
return (EFAULT);
}
return (rc);
}
/* ARGSUSED */
int
{
int rc = 0;
*rvp = 0;
switch (cmd) {
case NSCIOC_OPEN:
break;
case NSCIOC_RESERVE:
break;
case NSCIOC_RELEASE:
break;
case NSCIOC_PARTSIZE:
break;
case NSCIOC_FREEZE:
break;
}
else {
}
break;
case NSCIOC_UNFREEZE:
break;
}
else {
}
break;
case NSCIOC_ISFROZEN:
break;
}
else {
}
break;
#ifdef ENABLE_POWER_MSG
case NSCIOC_POWERMSG:
break;
#endif
case NSCIOC_NSKERND:
break;
/* return sizes of global memory segments */
case NSCIOC_GLOBAL_SIZES:
if (!_nsc_init_done) {
break;
}
break;
/* return contents of global segments */
case NSCIOC_GLOBAL_DATA:
if (!_nsc_init_done) {
break;
}
break;
/*
* nvmem systems:
* clear the hdr dirty bit to prevent loading from nvme on reboot
*/
case NSCIOC_NVMEM_CLEANF:
break;
case NSCIOC_NVMEM_CLEAN:
rc = _nsc_clear_dirty(0);
break;
case NSCIOC_BSIZE:
break;
}
break;
}
if (rc == 0) {
break;
}
}
break;
default:
return (ENOTTY);
}
}
}
return (rc);
}
int
nsc_max_devices(void)
{
return (_nsc_max_devices);
}
/*
* Used by _nsc_global_setup() in case nvram is dirty and has saved a different
* value for nsc_max_devices. We need to use the saved value, not the new
* one configured by the user.
*/
void
{
}