17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5da6c28aaSamw * Common Development and Distribution License (the "License"). 6da6c28aaSamw * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*39b361b2SRichard Bean * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <sys/types.h> 277c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 287c478bd9Sstevel@tonic-gate #include <sys/stat.h> 297c478bd9Sstevel@tonic-gate #include <sys/proc.h> 307c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 317c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 327c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 337c478bd9Sstevel@tonic-gate #include <sys/file.h> 347c478bd9Sstevel@tonic-gate #include <sys/rsm/rsm_common.h> 357c478bd9Sstevel@tonic-gate #include <sys/rsm/rsmpi.h> 367c478bd9Sstevel@tonic-gate #include <sys/rsm/rsmpi_driver.h> 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate /* lint -w2 */ 397c478bd9Sstevel@tonic-gate static struct modlmisc modlmisc = { 40*39b361b2SRichard Bean &mod_miscops, "RSMOPS module", 417c478bd9Sstevel@tonic-gate }; 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 447c478bd9Sstevel@tonic-gate MODREV_1, (void *)&modlmisc, NULL 457c478bd9Sstevel@tonic-gate }; 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate static kmutex_t rsmops_lock; 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate static rsmops_drv_t *rsmops_drv_head = NULL; 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate static int rsmops_threads_started = 0; 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate int 547c478bd9Sstevel@tonic-gate _init(void) 557c478bd9Sstevel@tonic-gate { 567c478bd9Sstevel@tonic-gate int err; 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate mutex_init(&rsmops_lock, NULL, MUTEX_DEFAULT, NULL); 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate if ((err = mod_install(&modlinkage)) != 0) 617c478bd9Sstevel@tonic-gate mutex_destroy(&rsmops_lock); 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate return (err); 647c478bd9Sstevel@tonic-gate } 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate int 677c478bd9Sstevel@tonic-gate _fini(void) 687c478bd9Sstevel@tonic-gate { 697c478bd9Sstevel@tonic-gate int err; 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate mutex_enter(&rsmops_lock); 727c478bd9Sstevel@tonic-gate if (rsmops_drv_head) { 737c478bd9Sstevel@tonic-gate /* Somebody is still registered with us - we cannot unload */ 747c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 757c478bd9Sstevel@tonic-gate return (EBUSY); 767c478bd9Sstevel@tonic-gate } 777c478bd9Sstevel@tonic-gate if (rsmops_threads_started) { 787c478bd9Sstevel@tonic-gate /* 797c478bd9Sstevel@tonic-gate * Some threads have been started. We do not have any 807c478bd9Sstevel@tonic-gate * well-supported way of checking whether they have all 817c478bd9Sstevel@tonic-gate * exited. For now, fail attempt to unload if we have 827c478bd9Sstevel@tonic-gate * ever started any threads. This is overkill, but ... 837c478bd9Sstevel@tonic-gate */ 847c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 857c478bd9Sstevel@tonic-gate return (EBUSY); 867c478bd9Sstevel@tonic-gate } 877c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate if ((err = mod_remove(&modlinkage)) == 0) 907c478bd9Sstevel@tonic-gate mutex_destroy(&rsmops_lock); 917c478bd9Sstevel@tonic-gate return (err); 927c478bd9Sstevel@tonic-gate } 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate int 957c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 967c478bd9Sstevel@tonic-gate { 977c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 987c478bd9Sstevel@tonic-gate } 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate static void 1017c478bd9Sstevel@tonic-gate rsmops_thread_entry(rsmops_drv_t *p_drv) 1027c478bd9Sstevel@tonic-gate { 1037c478bd9Sstevel@tonic-gate /* p_drv->ctrl_cnt has already been increased by the time we get here */ 1047c478bd9Sstevel@tonic-gate ASSERT(p_drv->drv.rsm_thread_entry_pt); 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate /* call the driver with the thread */ 1077c478bd9Sstevel@tonic-gate (*(p_drv->drv.rsm_thread_entry_pt))(p_drv->drv.drv_name); 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate /* thread has returned */ 1107c478bd9Sstevel@tonic-gate mutex_enter(&rsmops_lock); 1117c478bd9Sstevel@tonic-gate p_drv->ctrl_cnt--; 1127c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate /* This is expected to be called from the driver's init function */ 1167c478bd9Sstevel@tonic-gate int 1177c478bd9Sstevel@tonic-gate rsm_register_driver(rsmops_registry_t *p_registry) 1187c478bd9Sstevel@tonic-gate { 1197c478bd9Sstevel@tonic-gate rsmops_drv_t **pp_tail; 1207c478bd9Sstevel@tonic-gate rsmops_drv_t *p; 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate if (p_registry->rsm_version > RSM_VERSION) { 1237c478bd9Sstevel@tonic-gate /* The driver is up-rev than me. Fail attempt to register */ 1247c478bd9Sstevel@tonic-gate return (RSMERR_BAD_DRIVER_VERSION); 1257c478bd9Sstevel@tonic-gate } 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate /* 1287c478bd9Sstevel@tonic-gate * RSM_VERSION: Since this is the first version, there cannot be any 1297c478bd9Sstevel@tonic-gate * down-rev drivers - this will be an issue in the future 1307c478bd9Sstevel@tonic-gate */ 1317c478bd9Sstevel@tonic-gate if (p_registry->rsm_version != RSM_VERSION) 1327c478bd9Sstevel@tonic-gate return (RSMERR_BAD_DRIVER_VERSION); 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate mutex_enter(&rsmops_lock); 1357c478bd9Sstevel@tonic-gate /* First, search that this driver is not already registered */ 1367c478bd9Sstevel@tonic-gate pp_tail = &rsmops_drv_head; 1377c478bd9Sstevel@tonic-gate while (*pp_tail) { 1387c478bd9Sstevel@tonic-gate if (strcmp((*pp_tail)->drv.drv_name, p_registry->drv_name) 1397c478bd9Sstevel@tonic-gate == 0) { 1407c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 1417c478bd9Sstevel@tonic-gate return (RSMERR_DRIVER_NAME_IN_USE); 1427c478bd9Sstevel@tonic-gate } 1437c478bd9Sstevel@tonic-gate pp_tail = &((*pp_tail)->next); 1447c478bd9Sstevel@tonic-gate } 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate p = kmem_alloc(sizeof (rsmops_drv_t), KM_SLEEP); 1477c478bd9Sstevel@tonic-gate p->drv = *p_registry; /* copy entire rsmops_registry_t structure */ 1487c478bd9Sstevel@tonic-gate p->next = NULL; 1497c478bd9Sstevel@tonic-gate p->ctrl_cnt = 0; 1507c478bd9Sstevel@tonic-gate p->ctrl_head = NULL; 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate if (p->drv.rsm_thread_entry_pt) { 1537c478bd9Sstevel@tonic-gate /* thread entry point is defined - we need to create a thread */ 1547c478bd9Sstevel@tonic-gate extern pri_t minclsyspri; 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate p->ctrl_cnt++; /* bump up the count right now */ 1577c478bd9Sstevel@tonic-gate p->thread_id = thread_create(NULL, 0, rsmops_thread_entry, 1587c478bd9Sstevel@tonic-gate p, 0, &p0, TS_RUN, minclsyspri); 1597c478bd9Sstevel@tonic-gate rsmops_threads_started++; 1607c478bd9Sstevel@tonic-gate } else 1617c478bd9Sstevel@tonic-gate p->thread_id = NULL; 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate *pp_tail = p; 1647c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 1657c478bd9Sstevel@tonic-gate return (RSM_SUCCESS); 1667c478bd9Sstevel@tonic-gate } 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate /* 1697c478bd9Sstevel@tonic-gate * This is expected to be called from the driver's fini function 1707c478bd9Sstevel@tonic-gate * if this function returns EBUSY, the driver is supposed to fail 1717c478bd9Sstevel@tonic-gate * its own fini operation 1727c478bd9Sstevel@tonic-gate */ 1737c478bd9Sstevel@tonic-gate int 1747c478bd9Sstevel@tonic-gate rsm_unregister_driver(rsmops_registry_t *p_registry) 1757c478bd9Sstevel@tonic-gate { 1767c478bd9Sstevel@tonic-gate rsmops_drv_t **pp_tail; 1777c478bd9Sstevel@tonic-gate rsmops_drv_t *p; 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate mutex_enter(&rsmops_lock); 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate /* Search for the driver */ 1827c478bd9Sstevel@tonic-gate pp_tail = &rsmops_drv_head; 1837c478bd9Sstevel@tonic-gate while (*pp_tail) { 1847c478bd9Sstevel@tonic-gate if (strcmp((*pp_tail)->drv.drv_name, p_registry->drv_name)) { 1857c478bd9Sstevel@tonic-gate pp_tail = &((*pp_tail)->next); 1867c478bd9Sstevel@tonic-gate continue; 1877c478bd9Sstevel@tonic-gate } 1887c478bd9Sstevel@tonic-gate /* check ref count - if somebody is using it, return EBUSY */ 1897c478bd9Sstevel@tonic-gate if ((*pp_tail)->ctrl_cnt) { 1907c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 1917c478bd9Sstevel@tonic-gate return (RSMERR_CTLRS_REGISTERED); 1927c478bd9Sstevel@tonic-gate } 1937c478bd9Sstevel@tonic-gate /* Nobody is using it - we can allow the unregister to happen */ 1947c478bd9Sstevel@tonic-gate p = *pp_tail; 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate /* Stomp the guy out of our linked list */ 1977c478bd9Sstevel@tonic-gate *pp_tail = (*pp_tail)->next; 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate /* release the memory */ 2007c478bd9Sstevel@tonic-gate kmem_free(p, sizeof (rsmops_drv_t)); 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 2037c478bd9Sstevel@tonic-gate return (RSM_SUCCESS); 2047c478bd9Sstevel@tonic-gate } 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate /* Could not find the guy */ 2077c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 2087c478bd9Sstevel@tonic-gate return (RSMERR_DRIVER_NOT_REGISTERED); 2097c478bd9Sstevel@tonic-gate } 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate /* Should be called holding the rsmops_lock mutex */ 2127c478bd9Sstevel@tonic-gate static rsmops_drv_t * 2137c478bd9Sstevel@tonic-gate find_rsmpi_driver(const char *name) 2147c478bd9Sstevel@tonic-gate { 2157c478bd9Sstevel@tonic-gate rsmops_drv_t *p_rsmops_list; 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&rsmops_lock)); 2187c478bd9Sstevel@tonic-gate /* the name is of the form "sci", "wci" etc */ 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate for (p_rsmops_list = rsmops_drv_head; p_rsmops_list != NULL; 2217c478bd9Sstevel@tonic-gate p_rsmops_list = p_rsmops_list->next) { 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate if (strcmp(name, p_rsmops_list->drv.drv_name) == 0) { 2247c478bd9Sstevel@tonic-gate return (p_rsmops_list); 2257c478bd9Sstevel@tonic-gate } 2267c478bd9Sstevel@tonic-gate } 2277c478bd9Sstevel@tonic-gate return (NULL); 2287c478bd9Sstevel@tonic-gate } 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate /* Should be called holding the rsmops_lock mutex */ 2327c478bd9Sstevel@tonic-gate static rsmops_ctrl_t * 2337c478bd9Sstevel@tonic-gate find_rsmpi_controller(const char *name, uint_t number) 2347c478bd9Sstevel@tonic-gate { 2357c478bd9Sstevel@tonic-gate rsmops_drv_t *p_drv; 2367c478bd9Sstevel@tonic-gate rsmops_ctrl_t *p; 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&rsmops_lock)); 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate if ((p_drv = find_rsmpi_driver(name)) == NULL) 2417c478bd9Sstevel@tonic-gate return (NULL); 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate for (p = p_drv->ctrl_head; p != NULL; p = p->next) { 2447c478bd9Sstevel@tonic-gate ASSERT(p->p_drv == p_drv); 2457c478bd9Sstevel@tonic-gate if (p->number == number) 2467c478bd9Sstevel@tonic-gate return (p); 2477c478bd9Sstevel@tonic-gate } 2487c478bd9Sstevel@tonic-gate return (NULL); 2497c478bd9Sstevel@tonic-gate } 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate /* Should be called holding the rsmops_lock mutex */ 2527c478bd9Sstevel@tonic-gate static rsmops_ctrl_t * 2537c478bd9Sstevel@tonic-gate find_rsmpi_controller_handle(rsm_controller_handle_t cntlr_handle) 2547c478bd9Sstevel@tonic-gate { 2557c478bd9Sstevel@tonic-gate rsmops_drv_t *p_drv; 2567c478bd9Sstevel@tonic-gate rsmops_ctrl_t *p; 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&rsmops_lock)); 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate for (p_drv = rsmops_drv_head; p_drv != NULL; p_drv = p_drv->next) { 2617c478bd9Sstevel@tonic-gate for (p = p_drv->ctrl_head; p != NULL; p = p->next) { 2627c478bd9Sstevel@tonic-gate if (p->handle == cntlr_handle) 2637c478bd9Sstevel@tonic-gate return (p); 2647c478bd9Sstevel@tonic-gate } 2657c478bd9Sstevel@tonic-gate } 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate return (NULL); 2687c478bd9Sstevel@tonic-gate } 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate static vnode_t * 2717c478bd9Sstevel@tonic-gate rsmops_device_open(const char *major_name, const minor_t minor_num); 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate int 2747c478bd9Sstevel@tonic-gate rsm_get_controller(const char *name, uint_t number, 2757c478bd9Sstevel@tonic-gate rsm_controller_object_t *controller, uint_t version) 2767c478bd9Sstevel@tonic-gate { 2777c478bd9Sstevel@tonic-gate rsmops_ctrl_t *p_ctrl; 2787c478bd9Sstevel@tonic-gate rsmops_drv_t *p_drv; 2797c478bd9Sstevel@tonic-gate vnode_t *vp; 2807c478bd9Sstevel@tonic-gate int error; 2817c478bd9Sstevel@tonic-gate int (*rsm_get_controller_handler) 2827c478bd9Sstevel@tonic-gate (const char *name, uint_t number, 2837c478bd9Sstevel@tonic-gate rsm_controller_object_t *pcontroller, uint_t version); 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate mutex_enter(&rsmops_lock); 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate /* check if the controller is already registered */ 2887c478bd9Sstevel@tonic-gate if ((p_ctrl = find_rsmpi_controller(name, number)) == NULL) { 2897c478bd9Sstevel@tonic-gate /* 2907c478bd9Sstevel@tonic-gate * controller is not registered. We should try to load it 2917c478bd9Sstevel@tonic-gate * First check if the driver is registered 2927c478bd9Sstevel@tonic-gate */ 2937c478bd9Sstevel@tonic-gate if ((p_drv = find_rsmpi_driver(name)) == NULL) { 2947c478bd9Sstevel@tonic-gate /* Cannot find the driver. Try to load him */ 2957c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 2967c478bd9Sstevel@tonic-gate if ((error = modload("drv", (char *)name)) == -1) { 2977c478bd9Sstevel@tonic-gate return (RSMERR_CTLR_NOT_PRESENT); 2987c478bd9Sstevel@tonic-gate } 2997c478bd9Sstevel@tonic-gate mutex_enter(&rsmops_lock); 3007c478bd9Sstevel@tonic-gate if ((p_drv = find_rsmpi_driver(name)) == NULL) { 3017c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 3027c478bd9Sstevel@tonic-gate /* 3037c478bd9Sstevel@tonic-gate * Cannot find yet - maybe the driver we loaded 3047c478bd9Sstevel@tonic-gate * was not a RSMPI driver at all. We'll just 3057c478bd9Sstevel@tonic-gate * fail this call. 3067c478bd9Sstevel@tonic-gate */ 3077c478bd9Sstevel@tonic-gate return (RSMERR_CTLR_NOT_PRESENT); 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate ASSERT(p_drv); 3117c478bd9Sstevel@tonic-gate p_ctrl = find_rsmpi_controller(name, number); 3127c478bd9Sstevel@tonic-gate if (p_ctrl == NULL) { 3137c478bd9Sstevel@tonic-gate /* 3147c478bd9Sstevel@tonic-gate * controller is not registered. 3157c478bd9Sstevel@tonic-gate * try to do a VOP_OPEN to force it to get registered 3167c478bd9Sstevel@tonic-gate */ 3177c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 3187c478bd9Sstevel@tonic-gate vp = rsmops_device_open(name, number); 3197c478bd9Sstevel@tonic-gate mutex_enter(&rsmops_lock); 3207c478bd9Sstevel@tonic-gate if (vp != NULL) { 3217c478bd9Sstevel@tonic-gate (void) VOP_CLOSE(vp, FREAD|FWRITE, 0, 0, 322da6c28aaSamw CRED(), NULL); 3237c478bd9Sstevel@tonic-gate VN_RELE(vp); 3247c478bd9Sstevel@tonic-gate } 3257c478bd9Sstevel@tonic-gate p_ctrl = find_rsmpi_controller(name, number); 3267c478bd9Sstevel@tonic-gate if (p_ctrl == NULL) { 3277c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 3287c478bd9Sstevel@tonic-gate return (RSMERR_CTLR_NOT_PRESENT); 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate } 3317c478bd9Sstevel@tonic-gate ASSERT(p_ctrl); 3327c478bd9Sstevel@tonic-gate } else { 3337c478bd9Sstevel@tonic-gate p_drv = p_ctrl->p_drv; 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate ASSERT(p_drv); 3367c478bd9Sstevel@tonic-gate ASSERT(p_drv == p_ctrl->p_drv); 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate rsm_get_controller_handler = p_drv->drv.rsm_get_controller_handler; 3397c478bd9Sstevel@tonic-gate /* 3407c478bd9Sstevel@tonic-gate * Increase the refcnt right now, so that attempts to deregister 3417c478bd9Sstevel@tonic-gate * while we are using this entry will fail 3427c478bd9Sstevel@tonic-gate */ 3437c478bd9Sstevel@tonic-gate p_ctrl->refcnt++; 3447c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate error = (*rsm_get_controller_handler)(name, number, controller, 3477c478bd9Sstevel@tonic-gate version); 3487c478bd9Sstevel@tonic-gate if (error != RSM_SUCCESS) { 3497c478bd9Sstevel@tonic-gate /* We failed - drop the refcnt back */ 3507c478bd9Sstevel@tonic-gate mutex_enter(&rsmops_lock); 3517c478bd9Sstevel@tonic-gate /* 3527c478bd9Sstevel@tonic-gate * Even though we had released the global lock, we can 3537c478bd9Sstevel@tonic-gate * guarantee that p_ctrl is still meaningful (and has not 3547c478bd9Sstevel@tonic-gate * been deregistered, freed whatever) because we were holding 3557c478bd9Sstevel@tonic-gate * refcnt on it. So, it is okay to just use p_ctrl here 3567c478bd9Sstevel@tonic-gate * after re-acquiring the global lock 3577c478bd9Sstevel@tonic-gate */ 3587c478bd9Sstevel@tonic-gate p_ctrl->refcnt--; 3597c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 3607c478bd9Sstevel@tonic-gate } else { 3617c478bd9Sstevel@tonic-gate /* 3627c478bd9Sstevel@tonic-gate * Initialize the controller handle field 3637c478bd9Sstevel@tonic-gate */ 3647c478bd9Sstevel@tonic-gate mutex_enter(&rsmops_lock); 3657c478bd9Sstevel@tonic-gate if ((p_ctrl = find_rsmpi_controller(name, number)) == NULL) { 3667c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 3677c478bd9Sstevel@tonic-gate return (RSMERR_CTLR_NOT_PRESENT); 3687c478bd9Sstevel@tonic-gate } 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate p_ctrl->handle = controller->handle; 3717c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 3727c478bd9Sstevel@tonic-gate } 3737c478bd9Sstevel@tonic-gate return (error); 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate int 3777c478bd9Sstevel@tonic-gate rsm_release_controller(const char *name, uint_t number, 3787c478bd9Sstevel@tonic-gate rsm_controller_object_t *controller) 3797c478bd9Sstevel@tonic-gate { 3807c478bd9Sstevel@tonic-gate rsmops_ctrl_t *p_ctrl; 3817c478bd9Sstevel@tonic-gate rsmops_drv_t *p_drv; 3827c478bd9Sstevel@tonic-gate int error; 3837c478bd9Sstevel@tonic-gate int (*releaser)(const char *name, uint_t number, 3847c478bd9Sstevel@tonic-gate rsm_controller_object_t *controller); 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate mutex_enter(&rsmops_lock); 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate if ((p_ctrl = find_rsmpi_controller(name, number)) == NULL) { 3897c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 3907c478bd9Sstevel@tonic-gate return (RSMERR_CTLR_NOT_PRESENT); 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate p_drv = find_rsmpi_driver(name); 3937c478bd9Sstevel@tonic-gate ASSERT(p_drv); /* If we found controller, there MUST be a driver */ 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate /* Found the appropriate driver. Forward the call to it */ 3967c478bd9Sstevel@tonic-gate releaser = p_drv->drv.rsm_release_controller_handler; 3977c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate error = (*releaser)(name, number, controller); 4007c478bd9Sstevel@tonic-gate if (error == RSM_SUCCESS) { 4017c478bd9Sstevel@tonic-gate mutex_enter(&rsmops_lock); 4027c478bd9Sstevel@tonic-gate p_ctrl->refcnt--; 4037c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 4047c478bd9Sstevel@tonic-gate } 4057c478bd9Sstevel@tonic-gate return (error); 4067c478bd9Sstevel@tonic-gate } 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate /* This is expected to be called from the driver's attach function */ 4097c478bd9Sstevel@tonic-gate int 4107c478bd9Sstevel@tonic-gate rsm_register_controller(const char *name, uint_t number, 4117c478bd9Sstevel@tonic-gate rsm_controller_attr_t *attrp) 4127c478bd9Sstevel@tonic-gate { 4137c478bd9Sstevel@tonic-gate rsmops_drv_t *p_drv; 4147c478bd9Sstevel@tonic-gate rsmops_ctrl_t *p_ctrl; 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate if (strlen(name) > MAX_DRVNAME) 4177c478bd9Sstevel@tonic-gate return (RSMERR_NAME_TOO_LONG); 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate mutex_enter(&rsmops_lock); 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate /* Check if the driver is registered with us */ 4227c478bd9Sstevel@tonic-gate p_drv = find_rsmpi_driver(name); 4237c478bd9Sstevel@tonic-gate if (p_drv == NULL) { 4247c478bd9Sstevel@tonic-gate /* 4257c478bd9Sstevel@tonic-gate * Hey! Driver is not registered, but we are getting a 4267c478bd9Sstevel@tonic-gate * controller ?? 4277c478bd9Sstevel@tonic-gate */ 4287c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 4297c478bd9Sstevel@tonic-gate return (RSMERR_DRIVER_NOT_REGISTERED); 4307c478bd9Sstevel@tonic-gate } 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate /* Check if the controller is already registered with us */ 4337c478bd9Sstevel@tonic-gate p_ctrl = find_rsmpi_controller(name, number); 4347c478bd9Sstevel@tonic-gate if (p_ctrl) { 4357c478bd9Sstevel@tonic-gate /* already registered */ 4367c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 4377c478bd9Sstevel@tonic-gate return (RSMERR_CTLR_ALREADY_REGISTERED); 4387c478bd9Sstevel@tonic-gate } 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate /* WAIT: sanity check - verify that the dip matches up to name,number */ 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate p_ctrl = kmem_alloc(sizeof (rsmops_ctrl_t), KM_SLEEP); 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate /* bump up controller count on the driver */ 4457c478bd9Sstevel@tonic-gate p_drv->ctrl_cnt++; 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate p_ctrl->p_drv = p_drv; /* setup the back pointer */ 4487c478bd9Sstevel@tonic-gate p_ctrl->number = number; 4497c478bd9Sstevel@tonic-gate p_ctrl->refcnt = 0; 4507c478bd9Sstevel@tonic-gate p_ctrl->attrp = attrp; 4517c478bd9Sstevel@tonic-gate p_ctrl->handle = NULL; 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate /* Now link to head of list */ 4547c478bd9Sstevel@tonic-gate p_ctrl->next = p_drv->ctrl_head; 4557c478bd9Sstevel@tonic-gate p_drv->ctrl_head = p_ctrl; 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 4587c478bd9Sstevel@tonic-gate 4597c478bd9Sstevel@tonic-gate return (RSM_SUCCESS); 4607c478bd9Sstevel@tonic-gate } 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate /* 4637c478bd9Sstevel@tonic-gate * This is expected to be called from the driver's detach function 4647c478bd9Sstevel@tonic-gate * if this function returns EBUSY, the driver is supposed to fail 4657c478bd9Sstevel@tonic-gate * his own detach operation 4667c478bd9Sstevel@tonic-gate */ 4677c478bd9Sstevel@tonic-gate int 4687c478bd9Sstevel@tonic-gate rsm_unregister_controller(const char *name, uint_t number) 4697c478bd9Sstevel@tonic-gate { 4707c478bd9Sstevel@tonic-gate rsmops_drv_t *p_drv; 4717c478bd9Sstevel@tonic-gate rsmops_ctrl_t **p_prev; 4727c478bd9Sstevel@tonic-gate rsmops_ctrl_t *found; 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate mutex_enter(&rsmops_lock); 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate /* Check if the driver is registered with us */ 4777c478bd9Sstevel@tonic-gate p_drv = find_rsmpi_driver(name); 4787c478bd9Sstevel@tonic-gate if (p_drv == NULL) { 4797c478bd9Sstevel@tonic-gate /* Hey! Driver is not registered */ 4807c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 4817c478bd9Sstevel@tonic-gate return (RSMERR_DRIVER_NOT_REGISTERED); 4827c478bd9Sstevel@tonic-gate } 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate /* Search for the controller in the list */ 4857c478bd9Sstevel@tonic-gate for (p_prev = &p_drv->ctrl_head; *p_prev; p_prev = &((*p_prev)->next)) { 4867c478bd9Sstevel@tonic-gate if ((*p_prev)->number == number) { 4877c478bd9Sstevel@tonic-gate /* Found the controller. Check if it is busy */ 4887c478bd9Sstevel@tonic-gate found = *p_prev; 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate if (found->refcnt) { 4917c478bd9Sstevel@tonic-gate /* Controller is busy - handles outstanding */ 4927c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 4937c478bd9Sstevel@tonic-gate return (RSMERR_CTLR_IN_USE); 4947c478bd9Sstevel@tonic-gate } 4957c478bd9Sstevel@tonic-gate /* unlink it out */ 4967c478bd9Sstevel@tonic-gate *p_prev = found->next; 4977c478bd9Sstevel@tonic-gate /* bump down controller count on the driver */ 4987c478bd9Sstevel@tonic-gate p_drv->ctrl_cnt--; 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 5017c478bd9Sstevel@tonic-gate kmem_free(found, sizeof (rsmops_ctrl_t)); 5027c478bd9Sstevel@tonic-gate return (RSM_SUCCESS); 5037c478bd9Sstevel@tonic-gate } 5047c478bd9Sstevel@tonic-gate } 5057c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 5067c478bd9Sstevel@tonic-gate /* Could not find the right controller */ 5077c478bd9Sstevel@tonic-gate return (RSMERR_CTLR_NOT_REGISTERED); 5087c478bd9Sstevel@tonic-gate } 5097c478bd9Sstevel@tonic-gate 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate /* 5127c478bd9Sstevel@tonic-gate * This opens and closes the appropriate device with minor number - 5137c478bd9Sstevel@tonic-gate * hopefully, it will cause the driver to attach and register a controller 5147c478bd9Sstevel@tonic-gate * with us 5157c478bd9Sstevel@tonic-gate */ 5167c478bd9Sstevel@tonic-gate static vnode_t * 5177c478bd9Sstevel@tonic-gate rsmops_device_open(const char *major_name, const minor_t minor_num) 5187c478bd9Sstevel@tonic-gate { 5197c478bd9Sstevel@tonic-gate major_t maj; 5207c478bd9Sstevel@tonic-gate vnode_t *vp; 5217c478bd9Sstevel@tonic-gate int ret; 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate if (minor_num == (minor_t)-1) { 5247c478bd9Sstevel@tonic-gate return (NULL); 5257c478bd9Sstevel@tonic-gate } 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate maj = ddi_name_to_major((char *)major_name); 5287c478bd9Sstevel@tonic-gate if (maj == (major_t)-1) { 5297c478bd9Sstevel@tonic-gate return (NULL); 5307c478bd9Sstevel@tonic-gate } 5317c478bd9Sstevel@tonic-gate 5327c478bd9Sstevel@tonic-gate vp = makespecvp(makedevice(maj, minor_num), VCHR); 5337c478bd9Sstevel@tonic-gate 534da6c28aaSamw ret = VOP_OPEN(&vp, FREAD|FWRITE, CRED(), NULL); 5357c478bd9Sstevel@tonic-gate if (ret == 0) { 5367c478bd9Sstevel@tonic-gate return (vp); 5377c478bd9Sstevel@tonic-gate } else { 5387c478bd9Sstevel@tonic-gate VN_RELE(vp); 5397c478bd9Sstevel@tonic-gate return (NULL); 5407c478bd9Sstevel@tonic-gate } 5417c478bd9Sstevel@tonic-gate } 5427c478bd9Sstevel@tonic-gate 5437c478bd9Sstevel@tonic-gate /* 5447c478bd9Sstevel@tonic-gate * Attributes for controller identified by the handle are returned 5457c478bd9Sstevel@tonic-gate * via *attrp. Modifications of attributes is prohibited by client! 5467c478bd9Sstevel@tonic-gate */ 5477c478bd9Sstevel@tonic-gate int 5487c478bd9Sstevel@tonic-gate rsm_get_controller_attr(rsm_controller_handle_t handle, 5497c478bd9Sstevel@tonic-gate rsm_controller_attr_t **attrp) 5507c478bd9Sstevel@tonic-gate { 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate rsmops_ctrl_t *p_ctrl; 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate if (handle == NULL) 5557c478bd9Sstevel@tonic-gate return (RSMERR_BAD_CTLR_HNDL); 5567c478bd9Sstevel@tonic-gate 5577c478bd9Sstevel@tonic-gate mutex_enter(&rsmops_lock); 5587c478bd9Sstevel@tonic-gate 5597c478bd9Sstevel@tonic-gate /* find controller */ 5607c478bd9Sstevel@tonic-gate if ((p_ctrl = find_rsmpi_controller_handle(handle)) == NULL) { 5617c478bd9Sstevel@tonic-gate /* can't supply attributes for invalid controller */ 5627c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 5637c478bd9Sstevel@tonic-gate return (RSMERR_BAD_CTLR_HNDL); 5647c478bd9Sstevel@tonic-gate } 5657c478bd9Sstevel@tonic-gate *attrp = p_ctrl->attrp; 5667c478bd9Sstevel@tonic-gate mutex_exit(&rsmops_lock); 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate return (RSM_SUCCESS); 5697c478bd9Sstevel@tonic-gate } 570