10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
55331Samw * Common Development and Distribution License (the "License").
65331Samw * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*7862SRichard.Bean@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #include <sys/types.h>
270Sstevel@tonic-gate #include <sys/modctl.h>
280Sstevel@tonic-gate #include <sys/stat.h>
290Sstevel@tonic-gate #include <sys/proc.h>
300Sstevel@tonic-gate #include <sys/ddi.h>
310Sstevel@tonic-gate #include <sys/sunddi.h>
320Sstevel@tonic-gate #include <sys/kmem.h>
330Sstevel@tonic-gate #include <sys/file.h>
340Sstevel@tonic-gate #include <sys/rsm/rsm_common.h>
350Sstevel@tonic-gate #include <sys/rsm/rsmpi.h>
360Sstevel@tonic-gate #include <sys/rsm/rsmpi_driver.h>
370Sstevel@tonic-gate
380Sstevel@tonic-gate /* lint -w2 */
390Sstevel@tonic-gate static struct modlmisc modlmisc = {
40*7862SRichard.Bean@Sun.COM &mod_miscops, "RSMOPS module",
410Sstevel@tonic-gate };
420Sstevel@tonic-gate
430Sstevel@tonic-gate static struct modlinkage modlinkage = {
440Sstevel@tonic-gate MODREV_1, (void *)&modlmisc, NULL
450Sstevel@tonic-gate };
460Sstevel@tonic-gate
470Sstevel@tonic-gate static kmutex_t rsmops_lock;
480Sstevel@tonic-gate
490Sstevel@tonic-gate static rsmops_drv_t *rsmops_drv_head = NULL;
500Sstevel@tonic-gate
510Sstevel@tonic-gate static int rsmops_threads_started = 0;
520Sstevel@tonic-gate
530Sstevel@tonic-gate int
_init(void)540Sstevel@tonic-gate _init(void)
550Sstevel@tonic-gate {
560Sstevel@tonic-gate int err;
570Sstevel@tonic-gate
580Sstevel@tonic-gate mutex_init(&rsmops_lock, NULL, MUTEX_DEFAULT, NULL);
590Sstevel@tonic-gate
600Sstevel@tonic-gate if ((err = mod_install(&modlinkage)) != 0)
610Sstevel@tonic-gate mutex_destroy(&rsmops_lock);
620Sstevel@tonic-gate
630Sstevel@tonic-gate return (err);
640Sstevel@tonic-gate }
650Sstevel@tonic-gate
660Sstevel@tonic-gate int
_fini(void)670Sstevel@tonic-gate _fini(void)
680Sstevel@tonic-gate {
690Sstevel@tonic-gate int err;
700Sstevel@tonic-gate
710Sstevel@tonic-gate mutex_enter(&rsmops_lock);
720Sstevel@tonic-gate if (rsmops_drv_head) {
730Sstevel@tonic-gate /* Somebody is still registered with us - we cannot unload */
740Sstevel@tonic-gate mutex_exit(&rsmops_lock);
750Sstevel@tonic-gate return (EBUSY);
760Sstevel@tonic-gate }
770Sstevel@tonic-gate if (rsmops_threads_started) {
780Sstevel@tonic-gate /*
790Sstevel@tonic-gate * Some threads have been started. We do not have any
800Sstevel@tonic-gate * well-supported way of checking whether they have all
810Sstevel@tonic-gate * exited. For now, fail attempt to unload if we have
820Sstevel@tonic-gate * ever started any threads. This is overkill, but ...
830Sstevel@tonic-gate */
840Sstevel@tonic-gate mutex_exit(&rsmops_lock);
850Sstevel@tonic-gate return (EBUSY);
860Sstevel@tonic-gate }
870Sstevel@tonic-gate mutex_exit(&rsmops_lock);
880Sstevel@tonic-gate
890Sstevel@tonic-gate if ((err = mod_remove(&modlinkage)) == 0)
900Sstevel@tonic-gate mutex_destroy(&rsmops_lock);
910Sstevel@tonic-gate return (err);
920Sstevel@tonic-gate }
930Sstevel@tonic-gate
940Sstevel@tonic-gate int
_info(struct modinfo * modinfop)950Sstevel@tonic-gate _info(struct modinfo *modinfop)
960Sstevel@tonic-gate {
970Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop));
980Sstevel@tonic-gate }
990Sstevel@tonic-gate
1000Sstevel@tonic-gate static void
rsmops_thread_entry(rsmops_drv_t * p_drv)1010Sstevel@tonic-gate rsmops_thread_entry(rsmops_drv_t *p_drv)
1020Sstevel@tonic-gate {
1030Sstevel@tonic-gate /* p_drv->ctrl_cnt has already been increased by the time we get here */
1040Sstevel@tonic-gate ASSERT(p_drv->drv.rsm_thread_entry_pt);
1050Sstevel@tonic-gate
1060Sstevel@tonic-gate /* call the driver with the thread */
1070Sstevel@tonic-gate (*(p_drv->drv.rsm_thread_entry_pt))(p_drv->drv.drv_name);
1080Sstevel@tonic-gate
1090Sstevel@tonic-gate /* thread has returned */
1100Sstevel@tonic-gate mutex_enter(&rsmops_lock);
1110Sstevel@tonic-gate p_drv->ctrl_cnt--;
1120Sstevel@tonic-gate mutex_exit(&rsmops_lock);
1130Sstevel@tonic-gate }
1140Sstevel@tonic-gate
1150Sstevel@tonic-gate /* This is expected to be called from the driver's init function */
1160Sstevel@tonic-gate int
rsm_register_driver(rsmops_registry_t * p_registry)1170Sstevel@tonic-gate rsm_register_driver(rsmops_registry_t *p_registry)
1180Sstevel@tonic-gate {
1190Sstevel@tonic-gate rsmops_drv_t **pp_tail;
1200Sstevel@tonic-gate rsmops_drv_t *p;
1210Sstevel@tonic-gate
1220Sstevel@tonic-gate if (p_registry->rsm_version > RSM_VERSION) {
1230Sstevel@tonic-gate /* The driver is up-rev than me. Fail attempt to register */
1240Sstevel@tonic-gate return (RSMERR_BAD_DRIVER_VERSION);
1250Sstevel@tonic-gate }
1260Sstevel@tonic-gate
1270Sstevel@tonic-gate /*
1280Sstevel@tonic-gate * RSM_VERSION: Since this is the first version, there cannot be any
1290Sstevel@tonic-gate * down-rev drivers - this will be an issue in the future
1300Sstevel@tonic-gate */
1310Sstevel@tonic-gate if (p_registry->rsm_version != RSM_VERSION)
1320Sstevel@tonic-gate return (RSMERR_BAD_DRIVER_VERSION);
1330Sstevel@tonic-gate
1340Sstevel@tonic-gate mutex_enter(&rsmops_lock);
1350Sstevel@tonic-gate /* First, search that this driver is not already registered */
1360Sstevel@tonic-gate pp_tail = &rsmops_drv_head;
1370Sstevel@tonic-gate while (*pp_tail) {
1380Sstevel@tonic-gate if (strcmp((*pp_tail)->drv.drv_name, p_registry->drv_name)
1390Sstevel@tonic-gate == 0) {
1400Sstevel@tonic-gate mutex_exit(&rsmops_lock);
1410Sstevel@tonic-gate return (RSMERR_DRIVER_NAME_IN_USE);
1420Sstevel@tonic-gate }
1430Sstevel@tonic-gate pp_tail = &((*pp_tail)->next);
1440Sstevel@tonic-gate }
1450Sstevel@tonic-gate
1460Sstevel@tonic-gate p = kmem_alloc(sizeof (rsmops_drv_t), KM_SLEEP);
1470Sstevel@tonic-gate p->drv = *p_registry; /* copy entire rsmops_registry_t structure */
1480Sstevel@tonic-gate p->next = NULL;
1490Sstevel@tonic-gate p->ctrl_cnt = 0;
1500Sstevel@tonic-gate p->ctrl_head = NULL;
1510Sstevel@tonic-gate
1520Sstevel@tonic-gate if (p->drv.rsm_thread_entry_pt) {
1530Sstevel@tonic-gate /* thread entry point is defined - we need to create a thread */
1540Sstevel@tonic-gate extern pri_t minclsyspri;
1550Sstevel@tonic-gate
1560Sstevel@tonic-gate p->ctrl_cnt++; /* bump up the count right now */
1570Sstevel@tonic-gate p->thread_id = thread_create(NULL, 0, rsmops_thread_entry,
1580Sstevel@tonic-gate p, 0, &p0, TS_RUN, minclsyspri);
1590Sstevel@tonic-gate rsmops_threads_started++;
1600Sstevel@tonic-gate } else
1610Sstevel@tonic-gate p->thread_id = NULL;
1620Sstevel@tonic-gate
1630Sstevel@tonic-gate *pp_tail = p;
1640Sstevel@tonic-gate mutex_exit(&rsmops_lock);
1650Sstevel@tonic-gate return (RSM_SUCCESS);
1660Sstevel@tonic-gate }
1670Sstevel@tonic-gate
1680Sstevel@tonic-gate /*
1690Sstevel@tonic-gate * This is expected to be called from the driver's fini function
1700Sstevel@tonic-gate * if this function returns EBUSY, the driver is supposed to fail
1710Sstevel@tonic-gate * its own fini operation
1720Sstevel@tonic-gate */
1730Sstevel@tonic-gate int
rsm_unregister_driver(rsmops_registry_t * p_registry)1740Sstevel@tonic-gate rsm_unregister_driver(rsmops_registry_t *p_registry)
1750Sstevel@tonic-gate {
1760Sstevel@tonic-gate rsmops_drv_t **pp_tail;
1770Sstevel@tonic-gate rsmops_drv_t *p;
1780Sstevel@tonic-gate
1790Sstevel@tonic-gate mutex_enter(&rsmops_lock);
1800Sstevel@tonic-gate
1810Sstevel@tonic-gate /* Search for the driver */
1820Sstevel@tonic-gate pp_tail = &rsmops_drv_head;
1830Sstevel@tonic-gate while (*pp_tail) {
1840Sstevel@tonic-gate if (strcmp((*pp_tail)->drv.drv_name, p_registry->drv_name)) {
1850Sstevel@tonic-gate pp_tail = &((*pp_tail)->next);
1860Sstevel@tonic-gate continue;
1870Sstevel@tonic-gate }
1880Sstevel@tonic-gate /* check ref count - if somebody is using it, return EBUSY */
1890Sstevel@tonic-gate if ((*pp_tail)->ctrl_cnt) {
1900Sstevel@tonic-gate mutex_exit(&rsmops_lock);
1910Sstevel@tonic-gate return (RSMERR_CTLRS_REGISTERED);
1920Sstevel@tonic-gate }
1930Sstevel@tonic-gate /* Nobody is using it - we can allow the unregister to happen */
1940Sstevel@tonic-gate p = *pp_tail;
1950Sstevel@tonic-gate
1960Sstevel@tonic-gate /* Stomp the guy out of our linked list */
1970Sstevel@tonic-gate *pp_tail = (*pp_tail)->next;
1980Sstevel@tonic-gate
1990Sstevel@tonic-gate /* release the memory */
2000Sstevel@tonic-gate kmem_free(p, sizeof (rsmops_drv_t));
2010Sstevel@tonic-gate
2020Sstevel@tonic-gate mutex_exit(&rsmops_lock);
2030Sstevel@tonic-gate return (RSM_SUCCESS);
2040Sstevel@tonic-gate }
2050Sstevel@tonic-gate
2060Sstevel@tonic-gate /* Could not find the guy */
2070Sstevel@tonic-gate mutex_exit(&rsmops_lock);
2080Sstevel@tonic-gate return (RSMERR_DRIVER_NOT_REGISTERED);
2090Sstevel@tonic-gate }
2100Sstevel@tonic-gate
2110Sstevel@tonic-gate /* Should be called holding the rsmops_lock mutex */
2120Sstevel@tonic-gate static rsmops_drv_t *
find_rsmpi_driver(const char * name)2130Sstevel@tonic-gate find_rsmpi_driver(const char *name)
2140Sstevel@tonic-gate {
2150Sstevel@tonic-gate rsmops_drv_t *p_rsmops_list;
2160Sstevel@tonic-gate
2170Sstevel@tonic-gate ASSERT(MUTEX_HELD(&rsmops_lock));
2180Sstevel@tonic-gate /* the name is of the form "sci", "wci" etc */
2190Sstevel@tonic-gate
2200Sstevel@tonic-gate for (p_rsmops_list = rsmops_drv_head; p_rsmops_list != NULL;
2210Sstevel@tonic-gate p_rsmops_list = p_rsmops_list->next) {
2220Sstevel@tonic-gate
2230Sstevel@tonic-gate if (strcmp(name, p_rsmops_list->drv.drv_name) == 0) {
2240Sstevel@tonic-gate return (p_rsmops_list);
2250Sstevel@tonic-gate }
2260Sstevel@tonic-gate }
2270Sstevel@tonic-gate return (NULL);
2280Sstevel@tonic-gate }
2290Sstevel@tonic-gate
2300Sstevel@tonic-gate
2310Sstevel@tonic-gate /* Should be called holding the rsmops_lock mutex */
2320Sstevel@tonic-gate static rsmops_ctrl_t *
find_rsmpi_controller(const char * name,uint_t number)2330Sstevel@tonic-gate find_rsmpi_controller(const char *name, uint_t number)
2340Sstevel@tonic-gate {
2350Sstevel@tonic-gate rsmops_drv_t *p_drv;
2360Sstevel@tonic-gate rsmops_ctrl_t *p;
2370Sstevel@tonic-gate
2380Sstevel@tonic-gate ASSERT(MUTEX_HELD(&rsmops_lock));
2390Sstevel@tonic-gate
2400Sstevel@tonic-gate if ((p_drv = find_rsmpi_driver(name)) == NULL)
2410Sstevel@tonic-gate return (NULL);
2420Sstevel@tonic-gate
2430Sstevel@tonic-gate for (p = p_drv->ctrl_head; p != NULL; p = p->next) {
2440Sstevel@tonic-gate ASSERT(p->p_drv == p_drv);
2450Sstevel@tonic-gate if (p->number == number)
2460Sstevel@tonic-gate return (p);
2470Sstevel@tonic-gate }
2480Sstevel@tonic-gate return (NULL);
2490Sstevel@tonic-gate }
2500Sstevel@tonic-gate
2510Sstevel@tonic-gate /* Should be called holding the rsmops_lock mutex */
2520Sstevel@tonic-gate static rsmops_ctrl_t *
find_rsmpi_controller_handle(rsm_controller_handle_t cntlr_handle)2530Sstevel@tonic-gate find_rsmpi_controller_handle(rsm_controller_handle_t cntlr_handle)
2540Sstevel@tonic-gate {
2550Sstevel@tonic-gate rsmops_drv_t *p_drv;
2560Sstevel@tonic-gate rsmops_ctrl_t *p;
2570Sstevel@tonic-gate
2580Sstevel@tonic-gate ASSERT(MUTEX_HELD(&rsmops_lock));
2590Sstevel@tonic-gate
2600Sstevel@tonic-gate for (p_drv = rsmops_drv_head; p_drv != NULL; p_drv = p_drv->next) {
2610Sstevel@tonic-gate for (p = p_drv->ctrl_head; p != NULL; p = p->next) {
2620Sstevel@tonic-gate if (p->handle == cntlr_handle)
2630Sstevel@tonic-gate return (p);
2640Sstevel@tonic-gate }
2650Sstevel@tonic-gate }
2660Sstevel@tonic-gate
2670Sstevel@tonic-gate return (NULL);
2680Sstevel@tonic-gate }
2690Sstevel@tonic-gate
2700Sstevel@tonic-gate static vnode_t *
2710Sstevel@tonic-gate rsmops_device_open(const char *major_name, const minor_t minor_num);
2720Sstevel@tonic-gate
2730Sstevel@tonic-gate int
rsm_get_controller(const char * name,uint_t number,rsm_controller_object_t * controller,uint_t version)2740Sstevel@tonic-gate rsm_get_controller(const char *name, uint_t number,
2750Sstevel@tonic-gate rsm_controller_object_t *controller, uint_t version)
2760Sstevel@tonic-gate {
2770Sstevel@tonic-gate rsmops_ctrl_t *p_ctrl;
2780Sstevel@tonic-gate rsmops_drv_t *p_drv;
2790Sstevel@tonic-gate vnode_t *vp;
2800Sstevel@tonic-gate int error;
2810Sstevel@tonic-gate int (*rsm_get_controller_handler)
2820Sstevel@tonic-gate (const char *name, uint_t number,
2830Sstevel@tonic-gate rsm_controller_object_t *pcontroller, uint_t version);
2840Sstevel@tonic-gate
2850Sstevel@tonic-gate mutex_enter(&rsmops_lock);
2860Sstevel@tonic-gate
2870Sstevel@tonic-gate /* check if the controller is already registered */
2880Sstevel@tonic-gate if ((p_ctrl = find_rsmpi_controller(name, number)) == NULL) {
2890Sstevel@tonic-gate /*
2900Sstevel@tonic-gate * controller is not registered. We should try to load it
2910Sstevel@tonic-gate * First check if the driver is registered
2920Sstevel@tonic-gate */
2930Sstevel@tonic-gate if ((p_drv = find_rsmpi_driver(name)) == NULL) {
2940Sstevel@tonic-gate /* Cannot find the driver. Try to load him */
2950Sstevel@tonic-gate mutex_exit(&rsmops_lock);
2960Sstevel@tonic-gate if ((error = modload("drv", (char *)name)) == -1) {
2970Sstevel@tonic-gate return (RSMERR_CTLR_NOT_PRESENT);
2980Sstevel@tonic-gate }
2990Sstevel@tonic-gate mutex_enter(&rsmops_lock);
3000Sstevel@tonic-gate if ((p_drv = find_rsmpi_driver(name)) == NULL) {
3010Sstevel@tonic-gate mutex_exit(&rsmops_lock);
3020Sstevel@tonic-gate /*
3030Sstevel@tonic-gate * Cannot find yet - maybe the driver we loaded
3040Sstevel@tonic-gate * was not a RSMPI driver at all. We'll just
3050Sstevel@tonic-gate * fail this call.
3060Sstevel@tonic-gate */
3070Sstevel@tonic-gate return (RSMERR_CTLR_NOT_PRESENT);
3080Sstevel@tonic-gate }
3090Sstevel@tonic-gate }
3100Sstevel@tonic-gate ASSERT(p_drv);
3110Sstevel@tonic-gate p_ctrl = find_rsmpi_controller(name, number);
3120Sstevel@tonic-gate if (p_ctrl == NULL) {
3130Sstevel@tonic-gate /*
3140Sstevel@tonic-gate * controller is not registered.
3150Sstevel@tonic-gate * try to do a VOP_OPEN to force it to get registered
3160Sstevel@tonic-gate */
3170Sstevel@tonic-gate mutex_exit(&rsmops_lock);
3180Sstevel@tonic-gate vp = rsmops_device_open(name, number);
3190Sstevel@tonic-gate mutex_enter(&rsmops_lock);
3200Sstevel@tonic-gate if (vp != NULL) {
3210Sstevel@tonic-gate (void) VOP_CLOSE(vp, FREAD|FWRITE, 0, 0,
3225331Samw CRED(), NULL);
3230Sstevel@tonic-gate VN_RELE(vp);
3240Sstevel@tonic-gate }
3250Sstevel@tonic-gate p_ctrl = find_rsmpi_controller(name, number);
3260Sstevel@tonic-gate if (p_ctrl == NULL) {
3270Sstevel@tonic-gate mutex_exit(&rsmops_lock);
3280Sstevel@tonic-gate return (RSMERR_CTLR_NOT_PRESENT);
3290Sstevel@tonic-gate }
3300Sstevel@tonic-gate }
3310Sstevel@tonic-gate ASSERT(p_ctrl);
3320Sstevel@tonic-gate } else {
3330Sstevel@tonic-gate p_drv = p_ctrl->p_drv;
3340Sstevel@tonic-gate }
3350Sstevel@tonic-gate ASSERT(p_drv);
3360Sstevel@tonic-gate ASSERT(p_drv == p_ctrl->p_drv);
3370Sstevel@tonic-gate
3380Sstevel@tonic-gate rsm_get_controller_handler = p_drv->drv.rsm_get_controller_handler;
3390Sstevel@tonic-gate /*
3400Sstevel@tonic-gate * Increase the refcnt right now, so that attempts to deregister
3410Sstevel@tonic-gate * while we are using this entry will fail
3420Sstevel@tonic-gate */
3430Sstevel@tonic-gate p_ctrl->refcnt++;
3440Sstevel@tonic-gate mutex_exit(&rsmops_lock);
3450Sstevel@tonic-gate
3460Sstevel@tonic-gate error = (*rsm_get_controller_handler)(name, number, controller,
3470Sstevel@tonic-gate version);
3480Sstevel@tonic-gate if (error != RSM_SUCCESS) {
3490Sstevel@tonic-gate /* We failed - drop the refcnt back */
3500Sstevel@tonic-gate mutex_enter(&rsmops_lock);
3510Sstevel@tonic-gate /*
3520Sstevel@tonic-gate * Even though we had released the global lock, we can
3530Sstevel@tonic-gate * guarantee that p_ctrl is still meaningful (and has not
3540Sstevel@tonic-gate * been deregistered, freed whatever) because we were holding
3550Sstevel@tonic-gate * refcnt on it. So, it is okay to just use p_ctrl here
3560Sstevel@tonic-gate * after re-acquiring the global lock
3570Sstevel@tonic-gate */
3580Sstevel@tonic-gate p_ctrl->refcnt--;
3590Sstevel@tonic-gate mutex_exit(&rsmops_lock);
3600Sstevel@tonic-gate } else {
3610Sstevel@tonic-gate /*
3620Sstevel@tonic-gate * Initialize the controller handle field
3630Sstevel@tonic-gate */
3640Sstevel@tonic-gate mutex_enter(&rsmops_lock);
3650Sstevel@tonic-gate if ((p_ctrl = find_rsmpi_controller(name, number)) == NULL) {
3660Sstevel@tonic-gate mutex_exit(&rsmops_lock);
3670Sstevel@tonic-gate return (RSMERR_CTLR_NOT_PRESENT);
3680Sstevel@tonic-gate }
3690Sstevel@tonic-gate
3700Sstevel@tonic-gate p_ctrl->handle = controller->handle;
3710Sstevel@tonic-gate mutex_exit(&rsmops_lock);
3720Sstevel@tonic-gate }
3730Sstevel@tonic-gate return (error);
3740Sstevel@tonic-gate }
3750Sstevel@tonic-gate
3760Sstevel@tonic-gate int
rsm_release_controller(const char * name,uint_t number,rsm_controller_object_t * controller)3770Sstevel@tonic-gate rsm_release_controller(const char *name, uint_t number,
3780Sstevel@tonic-gate rsm_controller_object_t *controller)
3790Sstevel@tonic-gate {
3800Sstevel@tonic-gate rsmops_ctrl_t *p_ctrl;
3810Sstevel@tonic-gate rsmops_drv_t *p_drv;
3820Sstevel@tonic-gate int error;
3830Sstevel@tonic-gate int (*releaser)(const char *name, uint_t number,
3840Sstevel@tonic-gate rsm_controller_object_t *controller);
3850Sstevel@tonic-gate
3860Sstevel@tonic-gate mutex_enter(&rsmops_lock);
3870Sstevel@tonic-gate
3880Sstevel@tonic-gate if ((p_ctrl = find_rsmpi_controller(name, number)) == NULL) {
3890Sstevel@tonic-gate mutex_exit(&rsmops_lock);
3900Sstevel@tonic-gate return (RSMERR_CTLR_NOT_PRESENT);
3910Sstevel@tonic-gate }
3920Sstevel@tonic-gate p_drv = find_rsmpi_driver(name);
3930Sstevel@tonic-gate ASSERT(p_drv); /* If we found controller, there MUST be a driver */
3940Sstevel@tonic-gate
3950Sstevel@tonic-gate /* Found the appropriate driver. Forward the call to it */
3960Sstevel@tonic-gate releaser = p_drv->drv.rsm_release_controller_handler;
3970Sstevel@tonic-gate mutex_exit(&rsmops_lock);
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate error = (*releaser)(name, number, controller);
4000Sstevel@tonic-gate if (error == RSM_SUCCESS) {
4010Sstevel@tonic-gate mutex_enter(&rsmops_lock);
4020Sstevel@tonic-gate p_ctrl->refcnt--;
4030Sstevel@tonic-gate mutex_exit(&rsmops_lock);
4040Sstevel@tonic-gate }
4050Sstevel@tonic-gate return (error);
4060Sstevel@tonic-gate }
4070Sstevel@tonic-gate
4080Sstevel@tonic-gate /* This is expected to be called from the driver's attach function */
4090Sstevel@tonic-gate int
rsm_register_controller(const char * name,uint_t number,rsm_controller_attr_t * attrp)4100Sstevel@tonic-gate rsm_register_controller(const char *name, uint_t number,
4110Sstevel@tonic-gate rsm_controller_attr_t *attrp)
4120Sstevel@tonic-gate {
4130Sstevel@tonic-gate rsmops_drv_t *p_drv;
4140Sstevel@tonic-gate rsmops_ctrl_t *p_ctrl;
4150Sstevel@tonic-gate
4160Sstevel@tonic-gate if (strlen(name) > MAX_DRVNAME)
4170Sstevel@tonic-gate return (RSMERR_NAME_TOO_LONG);
4180Sstevel@tonic-gate
4190Sstevel@tonic-gate mutex_enter(&rsmops_lock);
4200Sstevel@tonic-gate
4210Sstevel@tonic-gate /* Check if the driver is registered with us */
4220Sstevel@tonic-gate p_drv = find_rsmpi_driver(name);
4230Sstevel@tonic-gate if (p_drv == NULL) {
4240Sstevel@tonic-gate /*
4250Sstevel@tonic-gate * Hey! Driver is not registered, but we are getting a
4260Sstevel@tonic-gate * controller ??
4270Sstevel@tonic-gate */
4280Sstevel@tonic-gate mutex_exit(&rsmops_lock);
4290Sstevel@tonic-gate return (RSMERR_DRIVER_NOT_REGISTERED);
4300Sstevel@tonic-gate }
4310Sstevel@tonic-gate
4320Sstevel@tonic-gate /* Check if the controller is already registered with us */
4330Sstevel@tonic-gate p_ctrl = find_rsmpi_controller(name, number);
4340Sstevel@tonic-gate if (p_ctrl) {
4350Sstevel@tonic-gate /* already registered */
4360Sstevel@tonic-gate mutex_exit(&rsmops_lock);
4370Sstevel@tonic-gate return (RSMERR_CTLR_ALREADY_REGISTERED);
4380Sstevel@tonic-gate }
4390Sstevel@tonic-gate
4400Sstevel@tonic-gate /* WAIT: sanity check - verify that the dip matches up to name,number */
4410Sstevel@tonic-gate
4420Sstevel@tonic-gate p_ctrl = kmem_alloc(sizeof (rsmops_ctrl_t), KM_SLEEP);
4430Sstevel@tonic-gate
4440Sstevel@tonic-gate /* bump up controller count on the driver */
4450Sstevel@tonic-gate p_drv->ctrl_cnt++;
4460Sstevel@tonic-gate
4470Sstevel@tonic-gate p_ctrl->p_drv = p_drv; /* setup the back pointer */
4480Sstevel@tonic-gate p_ctrl->number = number;
4490Sstevel@tonic-gate p_ctrl->refcnt = 0;
4500Sstevel@tonic-gate p_ctrl->attrp = attrp;
4510Sstevel@tonic-gate p_ctrl->handle = NULL;
4520Sstevel@tonic-gate
4530Sstevel@tonic-gate /* Now link to head of list */
4540Sstevel@tonic-gate p_ctrl->next = p_drv->ctrl_head;
4550Sstevel@tonic-gate p_drv->ctrl_head = p_ctrl;
4560Sstevel@tonic-gate
4570Sstevel@tonic-gate mutex_exit(&rsmops_lock);
4580Sstevel@tonic-gate
4590Sstevel@tonic-gate return (RSM_SUCCESS);
4600Sstevel@tonic-gate }
4610Sstevel@tonic-gate
4620Sstevel@tonic-gate /*
4630Sstevel@tonic-gate * This is expected to be called from the driver's detach function
4640Sstevel@tonic-gate * if this function returns EBUSY, the driver is supposed to fail
4650Sstevel@tonic-gate * his own detach operation
4660Sstevel@tonic-gate */
4670Sstevel@tonic-gate int
rsm_unregister_controller(const char * name,uint_t number)4680Sstevel@tonic-gate rsm_unregister_controller(const char *name, uint_t number)
4690Sstevel@tonic-gate {
4700Sstevel@tonic-gate rsmops_drv_t *p_drv;
4710Sstevel@tonic-gate rsmops_ctrl_t **p_prev;
4720Sstevel@tonic-gate rsmops_ctrl_t *found;
4730Sstevel@tonic-gate
4740Sstevel@tonic-gate mutex_enter(&rsmops_lock);
4750Sstevel@tonic-gate
4760Sstevel@tonic-gate /* Check if the driver is registered with us */
4770Sstevel@tonic-gate p_drv = find_rsmpi_driver(name);
4780Sstevel@tonic-gate if (p_drv == NULL) {
4790Sstevel@tonic-gate /* Hey! Driver is not registered */
4800Sstevel@tonic-gate mutex_exit(&rsmops_lock);
4810Sstevel@tonic-gate return (RSMERR_DRIVER_NOT_REGISTERED);
4820Sstevel@tonic-gate }
4830Sstevel@tonic-gate
4840Sstevel@tonic-gate /* Search for the controller in the list */
4850Sstevel@tonic-gate for (p_prev = &p_drv->ctrl_head; *p_prev; p_prev = &((*p_prev)->next)) {
4860Sstevel@tonic-gate if ((*p_prev)->number == number) {
4870Sstevel@tonic-gate /* Found the controller. Check if it is busy */
4880Sstevel@tonic-gate found = *p_prev;
4890Sstevel@tonic-gate
4900Sstevel@tonic-gate if (found->refcnt) {
4910Sstevel@tonic-gate /* Controller is busy - handles outstanding */
4920Sstevel@tonic-gate mutex_exit(&rsmops_lock);
4930Sstevel@tonic-gate return (RSMERR_CTLR_IN_USE);
4940Sstevel@tonic-gate }
4950Sstevel@tonic-gate /* unlink it out */
4960Sstevel@tonic-gate *p_prev = found->next;
4970Sstevel@tonic-gate /* bump down controller count on the driver */
4980Sstevel@tonic-gate p_drv->ctrl_cnt--;
4990Sstevel@tonic-gate
5000Sstevel@tonic-gate mutex_exit(&rsmops_lock);
5010Sstevel@tonic-gate kmem_free(found, sizeof (rsmops_ctrl_t));
5020Sstevel@tonic-gate return (RSM_SUCCESS);
5030Sstevel@tonic-gate }
5040Sstevel@tonic-gate }
5050Sstevel@tonic-gate mutex_exit(&rsmops_lock);
5060Sstevel@tonic-gate /* Could not find the right controller */
5070Sstevel@tonic-gate return (RSMERR_CTLR_NOT_REGISTERED);
5080Sstevel@tonic-gate }
5090Sstevel@tonic-gate
5100Sstevel@tonic-gate
5110Sstevel@tonic-gate /*
5120Sstevel@tonic-gate * This opens and closes the appropriate device with minor number -
5130Sstevel@tonic-gate * hopefully, it will cause the driver to attach and register a controller
5140Sstevel@tonic-gate * with us
5150Sstevel@tonic-gate */
5160Sstevel@tonic-gate static vnode_t *
rsmops_device_open(const char * major_name,const minor_t minor_num)5170Sstevel@tonic-gate rsmops_device_open(const char *major_name, const minor_t minor_num)
5180Sstevel@tonic-gate {
5190Sstevel@tonic-gate major_t maj;
5200Sstevel@tonic-gate vnode_t *vp;
5210Sstevel@tonic-gate int ret;
5220Sstevel@tonic-gate
5230Sstevel@tonic-gate if (minor_num == (minor_t)-1) {
5240Sstevel@tonic-gate return (NULL);
5250Sstevel@tonic-gate }
5260Sstevel@tonic-gate
5270Sstevel@tonic-gate maj = ddi_name_to_major((char *)major_name);
5280Sstevel@tonic-gate if (maj == (major_t)-1) {
5290Sstevel@tonic-gate return (NULL);
5300Sstevel@tonic-gate }
5310Sstevel@tonic-gate
5320Sstevel@tonic-gate vp = makespecvp(makedevice(maj, minor_num), VCHR);
5330Sstevel@tonic-gate
5345331Samw ret = VOP_OPEN(&vp, FREAD|FWRITE, CRED(), NULL);
5350Sstevel@tonic-gate if (ret == 0) {
5360Sstevel@tonic-gate return (vp);
5370Sstevel@tonic-gate } else {
5380Sstevel@tonic-gate VN_RELE(vp);
5390Sstevel@tonic-gate return (NULL);
5400Sstevel@tonic-gate }
5410Sstevel@tonic-gate }
5420Sstevel@tonic-gate
5430Sstevel@tonic-gate /*
5440Sstevel@tonic-gate * Attributes for controller identified by the handle are returned
5450Sstevel@tonic-gate * via *attrp. Modifications of attributes is prohibited by client!
5460Sstevel@tonic-gate */
5470Sstevel@tonic-gate int
rsm_get_controller_attr(rsm_controller_handle_t handle,rsm_controller_attr_t ** attrp)5480Sstevel@tonic-gate rsm_get_controller_attr(rsm_controller_handle_t handle,
5490Sstevel@tonic-gate rsm_controller_attr_t **attrp)
5500Sstevel@tonic-gate {
5510Sstevel@tonic-gate
5520Sstevel@tonic-gate rsmops_ctrl_t *p_ctrl;
5530Sstevel@tonic-gate
5540Sstevel@tonic-gate if (handle == NULL)
5550Sstevel@tonic-gate return (RSMERR_BAD_CTLR_HNDL);
5560Sstevel@tonic-gate
5570Sstevel@tonic-gate mutex_enter(&rsmops_lock);
5580Sstevel@tonic-gate
5590Sstevel@tonic-gate /* find controller */
5600Sstevel@tonic-gate if ((p_ctrl = find_rsmpi_controller_handle(handle)) == NULL) {
5610Sstevel@tonic-gate /* can't supply attributes for invalid controller */
5620Sstevel@tonic-gate mutex_exit(&rsmops_lock);
5630Sstevel@tonic-gate return (RSMERR_BAD_CTLR_HNDL);
5640Sstevel@tonic-gate }
5650Sstevel@tonic-gate *attrp = p_ctrl->attrp;
5660Sstevel@tonic-gate mutex_exit(&rsmops_lock);
5670Sstevel@tonic-gate
5680Sstevel@tonic-gate return (RSM_SUCCESS);
5690Sstevel@tonic-gate }
570