17697SMichael.Christensen@Sun.COM /*
27697SMichael.Christensen@Sun.COM * CDDL HEADER START
37697SMichael.Christensen@Sun.COM *
47697SMichael.Christensen@Sun.COM * The contents of this file are subject to the terms of the
57697SMichael.Christensen@Sun.COM * Common Development and Distribution License (the "License").
67697SMichael.Christensen@Sun.COM * You may not use this file except in compliance with the License.
77697SMichael.Christensen@Sun.COM *
87697SMichael.Christensen@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97697SMichael.Christensen@Sun.COM * or http://www.opensolaris.org/os/licensing.
107697SMichael.Christensen@Sun.COM * See the License for the specific language governing permissions
117697SMichael.Christensen@Sun.COM * and limitations under the License.
127697SMichael.Christensen@Sun.COM *
137697SMichael.Christensen@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
147697SMichael.Christensen@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157697SMichael.Christensen@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
167697SMichael.Christensen@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
177697SMichael.Christensen@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
187697SMichael.Christensen@Sun.COM *
197697SMichael.Christensen@Sun.COM * CDDL HEADER END
207697SMichael.Christensen@Sun.COM */
217697SMichael.Christensen@Sun.COM
227697SMichael.Christensen@Sun.COM /*
2311102SGavin.Maltby@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
247697SMichael.Christensen@Sun.COM * Use is subject to license terms.
257697SMichael.Christensen@Sun.COM */
267697SMichael.Christensen@Sun.COM
277697SMichael.Christensen@Sun.COM /*
287697SMichael.Christensen@Sun.COM * LDOMs Domain Services Device Driver
297697SMichael.Christensen@Sun.COM */
307697SMichael.Christensen@Sun.COM #include <sys/types.h>
317697SMichael.Christensen@Sun.COM #include <sys/file.h>
327697SMichael.Christensen@Sun.COM #include <sys/errno.h>
337697SMichael.Christensen@Sun.COM #include <sys/open.h>
347697SMichael.Christensen@Sun.COM #include <sys/cred.h>
357697SMichael.Christensen@Sun.COM #include <sys/uio.h>
367697SMichael.Christensen@Sun.COM #include <sys/stat.h>
377697SMichael.Christensen@Sun.COM #include <sys/ksynch.h>
387697SMichael.Christensen@Sun.COM #include <sys/modctl.h>
397697SMichael.Christensen@Sun.COM #include <sys/conf.h>
407697SMichael.Christensen@Sun.COM #include <sys/devops.h>
417697SMichael.Christensen@Sun.COM #include <sys/debug.h>
427697SMichael.Christensen@Sun.COM #include <sys/cmn_err.h>
437697SMichael.Christensen@Sun.COM #include <sys/ddi.h>
447697SMichael.Christensen@Sun.COM #include <sys/sunddi.h>
457697SMichael.Christensen@Sun.COM #include <sys/taskq.h>
467697SMichael.Christensen@Sun.COM #include <sys/disp.h>
477697SMichael.Christensen@Sun.COM #include <sys/note.h>
487697SMichael.Christensen@Sun.COM #include <sys/mach_descrip.h>
497697SMichael.Christensen@Sun.COM #include <sys/mdesc.h>
507697SMichael.Christensen@Sun.COM #include <sys/mdeg.h>
517697SMichael.Christensen@Sun.COM #include <sys/ldc.h>
527697SMichael.Christensen@Sun.COM #include <sys/ds.h>
537697SMichael.Christensen@Sun.COM #include <sys/ds_impl.h>
547697SMichael.Christensen@Sun.COM #include <sys/vlds.h>
557697SMichael.Christensen@Sun.COM #include <sys/bitmap.h>
567697SMichael.Christensen@Sun.COM #include <sys/sysevent.h>
577697SMichael.Christensen@Sun.COM
587697SMichael.Christensen@Sun.COM static dev_info_t *vlds_devi;
597697SMichael.Christensen@Sun.COM
607697SMichael.Christensen@Sun.COM
617697SMichael.Christensen@Sun.COM typedef struct vlds_state {
627697SMichael.Christensen@Sun.COM dev_info_t *dip;
637697SMichael.Christensen@Sun.COM int instance;
647697SMichael.Christensen@Sun.COM evchan_t *evchan;
657697SMichael.Christensen@Sun.COM } vlds_state_t;
667697SMichael.Christensen@Sun.COM
677697SMichael.Christensen@Sun.COM static void *vlds_statep;
687697SMichael.Christensen@Sun.COM
697697SMichael.Christensen@Sun.COM typedef struct vlds_recv_hdr {
707697SMichael.Christensen@Sun.COM struct vlds_recv_hdr *next; /* next in recv list */
717697SMichael.Christensen@Sun.COM void *data; /* the data itself */
727697SMichael.Christensen@Sun.COM size_t datasz; /* size of the data */
737697SMichael.Christensen@Sun.COM } vlds_recv_hdr_t;
747697SMichael.Christensen@Sun.COM
757697SMichael.Christensen@Sun.COM typedef struct vlds_svc_info {
767697SMichael.Christensen@Sun.COM int state; /* driver svc info state VLDS_RECV* */
777697SMichael.Christensen@Sun.COM vlds_recv_hdr_t *recv_headp; /* ptr to head of recv queue */
787697SMichael.Christensen@Sun.COM vlds_recv_hdr_t *recv_tailp; /* ptr to tail of recv queue */
797697SMichael.Christensen@Sun.COM size_t recv_size; /* no. of bytes in recv queue */
807813SMichael.Christensen@Sun.COM uint_t recv_cnt; /* no of messages in recv queue */
817697SMichael.Christensen@Sun.COM kmutex_t recv_lock; /* lock for recv queue */
827697SMichael.Christensen@Sun.COM kcondvar_t recv_cv; /* condition variable for recv queue */
837697SMichael.Christensen@Sun.COM int recv_nreaders; /* no of currently waiting readers */
847697SMichael.Christensen@Sun.COM } vlds_svc_info_t;
857697SMichael.Christensen@Sun.COM
867697SMichael.Christensen@Sun.COM #define VLDS_RECV_OK 1
877697SMichael.Christensen@Sun.COM #define VLDS_RECV_UNREG_PENDING 2
887813SMichael.Christensen@Sun.COM #define VLDS_RECV_OVERFLOW 3
897697SMichael.Christensen@Sun.COM
907697SMichael.Christensen@Sun.COM static int vlds_ports_inited = 0;
917697SMichael.Christensen@Sun.COM
927697SMichael.Christensen@Sun.COM static uint_t vlds_flags_to_svc(uint64_t flags);
937697SMichael.Christensen@Sun.COM
947697SMichael.Christensen@Sun.COM
957697SMichael.Christensen@Sun.COM #define VLDS_NAME "vlds"
967697SMichael.Christensen@Sun.COM static int vlds_open(dev_t *devp, int flag, int otyp, cred_t *credp);
977697SMichael.Christensen@Sun.COM static int vlds_close(dev_t dev, int flag, int otyp, cred_t *credp);
987697SMichael.Christensen@Sun.COM static int vlds_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
997697SMichael.Christensen@Sun.COM int *rvalp);
1007697SMichael.Christensen@Sun.COM static int vlds_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
1017697SMichael.Christensen@Sun.COM void **resultp);
1027697SMichael.Christensen@Sun.COM static int vlds_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
1037697SMichael.Christensen@Sun.COM static int vlds_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
1047697SMichael.Christensen@Sun.COM
1057697SMichael.Christensen@Sun.COM /* mdeg register functions */
1068172SMichael.Christensen@Sun.COM static void vlds_mdeg_init(void);
1078172SMichael.Christensen@Sun.COM static int vlds_mdeg_cb(void *cb_argp, mdeg_result_t *resp);
1088172SMichael.Christensen@Sun.COM static int vlds_mdeg_register(void);
1098172SMichael.Christensen@Sun.COM static int vlds_mdeg_unregister(void);
1108172SMichael.Christensen@Sun.COM static int vlds_add_mdeg_port(md_t *mdp, mde_cookie_t node);
1117697SMichael.Christensen@Sun.COM
1127697SMichael.Christensen@Sun.COM /* driver utilities */
1137697SMichael.Christensen@Sun.COM static void vlds_user_reg_cb(ds_cb_arg_t arg, ds_ver_t *ver, ds_svc_hdl_t hdl);
1147697SMichael.Christensen@Sun.COM static void vlds_user_unreg_cb(ds_cb_arg_t arg);
1157697SMichael.Christensen@Sun.COM static void vlds_user_data_cb(ds_cb_arg_t arg, void *buf, size_t buflen);
1167697SMichael.Christensen@Sun.COM static void vlds_recvq_init(vlds_svc_info_t *dpsp);
1177697SMichael.Christensen@Sun.COM static void vlds_recvq_destroy(vlds_svc_info_t *dpsp);
1187697SMichael.Christensen@Sun.COM static int vlds_recvq_get_data(vlds_svc_info_t *dpsp, void *buf, size_t buflen,
1197697SMichael.Christensen@Sun.COM size_t *msglenp, int mode);
1207697SMichael.Christensen@Sun.COM static void vlds_recvq_drain(vlds_svc_info_t *dpsp);
1217697SMichael.Christensen@Sun.COM static int vlds_recvq_put_data(vlds_svc_info_t *dpsp, void *buf, size_t buflen);
1227697SMichael.Christensen@Sun.COM static int vlds_recv_msg(ds_svc_hdl_t hdl, void *buf, size_t buflen,
1237697SMichael.Christensen@Sun.COM size_t *msglenp, int mode);
1247697SMichael.Christensen@Sun.COM
1257697SMichael.Christensen@Sun.COM /*
1267697SMichael.Christensen@Sun.COM * DS driver Ops Vector
1277697SMichael.Christensen@Sun.COM */
1287697SMichael.Christensen@Sun.COM static struct cb_ops vlds_cb_ops = {
1297697SMichael.Christensen@Sun.COM vlds_open, /* cb_open */
1307697SMichael.Christensen@Sun.COM vlds_close, /* cb_close */
1317697SMichael.Christensen@Sun.COM nodev, /* cb_strategy */
1327697SMichael.Christensen@Sun.COM nodev, /* cb_print */
1337697SMichael.Christensen@Sun.COM nodev, /* cb_dump */
1347697SMichael.Christensen@Sun.COM nodev, /* cb_read */
1357697SMichael.Christensen@Sun.COM nodev, /* cb_write */
1367697SMichael.Christensen@Sun.COM vlds_ioctl, /* cb_ioctl */
1377697SMichael.Christensen@Sun.COM nodev, /* cb_devmap */
1387697SMichael.Christensen@Sun.COM nodev, /* cb_mmap */
1397697SMichael.Christensen@Sun.COM nodev, /* cb_segmap */
1407697SMichael.Christensen@Sun.COM nochpoll, /* cb_chpoll */
1417697SMichael.Christensen@Sun.COM ddi_prop_op, /* cb_prop_op */
1427697SMichael.Christensen@Sun.COM (struct streamtab *)NULL, /* cb_str */
1437697SMichael.Christensen@Sun.COM D_MP | D_64BIT, /* cb_flag */
1447697SMichael.Christensen@Sun.COM CB_REV, /* cb_rev */
1457697SMichael.Christensen@Sun.COM nodev, /* cb_aread */
1467697SMichael.Christensen@Sun.COM nodev /* cb_awrite */
1477697SMichael.Christensen@Sun.COM };
1487697SMichael.Christensen@Sun.COM
1497697SMichael.Christensen@Sun.COM static struct dev_ops vlds_dev_ops = {
1507697SMichael.Christensen@Sun.COM DEVO_REV, /* devo_rev */
1517697SMichael.Christensen@Sun.COM 0, /* devo_refcnt */
1527697SMichael.Christensen@Sun.COM vlds_getinfo, /* devo_getinfo */
1537697SMichael.Christensen@Sun.COM nulldev, /* devo_identify */
1547697SMichael.Christensen@Sun.COM nulldev, /* devo_probe */
1557697SMichael.Christensen@Sun.COM vlds_attach, /* devo_attach */
1567697SMichael.Christensen@Sun.COM vlds_detach, /* devo_detach */
1577697SMichael.Christensen@Sun.COM nodev, /* devo_reset */
1587697SMichael.Christensen@Sun.COM &vlds_cb_ops, /* devo_cb_ops */
1597697SMichael.Christensen@Sun.COM (struct bus_ops *)NULL, /* devo_bus_ops */
1607697SMichael.Christensen@Sun.COM nulldev /* devo_power */
1617697SMichael.Christensen@Sun.COM };
1627697SMichael.Christensen@Sun.COM
1637697SMichael.Christensen@Sun.COM static struct modldrv modldrv = {
1647697SMichael.Christensen@Sun.COM &mod_driverops,
1657697SMichael.Christensen@Sun.COM "Domain Services Driver 1.0",
1667697SMichael.Christensen@Sun.COM &vlds_dev_ops
1677697SMichael.Christensen@Sun.COM };
1687697SMichael.Christensen@Sun.COM
1697697SMichael.Christensen@Sun.COM static struct modlinkage modlinkage = {
1707697SMichael.Christensen@Sun.COM MODREV_1,
1717697SMichael.Christensen@Sun.COM (void *)&modldrv,
1727697SMichael.Christensen@Sun.COM NULL
1737697SMichael.Christensen@Sun.COM };
1747697SMichael.Christensen@Sun.COM
1757697SMichael.Christensen@Sun.COM /*
1767697SMichael.Christensen@Sun.COM * Callback ops for user-land services.
1777697SMichael.Christensen@Sun.COM */
1787697SMichael.Christensen@Sun.COM static ds_clnt_ops_t ds_user_ops = {
1797697SMichael.Christensen@Sun.COM vlds_user_reg_cb, /* register */
1807697SMichael.Christensen@Sun.COM vlds_user_unreg_cb, /* unregister */
1817697SMichael.Christensen@Sun.COM vlds_user_data_cb, /* data */
1827697SMichael.Christensen@Sun.COM NULL /* ds_ucap_init will fill in */
1837697SMichael.Christensen@Sun.COM };
1847697SMichael.Christensen@Sun.COM
1857813SMichael.Christensen@Sun.COM static size_t vlds_recvq_maxsize = DS_STREAM_MTU * 8;
1867813SMichael.Christensen@Sun.COM static uint_t vlds_recvq_maxmsg = 16;
1877813SMichael.Christensen@Sun.COM
1887697SMichael.Christensen@Sun.COM #define VLDS_MINOR_MAX SHRT_MAX
1897697SMichael.Christensen@Sun.COM
1907697SMichael.Christensen@Sun.COM /* Definitions for binding handle array */
1917697SMichael.Christensen@Sun.COM static ulong_t vlds_bitmap_initial = 1; /* index 0 indicates error */
1927697SMichael.Christensen@Sun.COM static ulong_t *vlds_minor_bitmap = &vlds_bitmap_initial;
1937697SMichael.Christensen@Sun.COM static size_t vlds_minor_bits = BT_NBIPUL;
1947697SMichael.Christensen@Sun.COM static kmutex_t vlds_minor_mutex;
1957697SMichael.Christensen@Sun.COM
1967697SMichael.Christensen@Sun.COM /*
1977697SMichael.Christensen@Sun.COM * Following vlds_minor_* routines map a binding handle to a minor number.
1987697SMichael.Christensen@Sun.COM * Has to be called w/ locks held.
1997697SMichael.Christensen@Sun.COM */
2007697SMichael.Christensen@Sun.COM static ulong_t *
vlds_minor_alloc(void)2017697SMichael.Christensen@Sun.COM vlds_minor_alloc(void)
2027697SMichael.Christensen@Sun.COM {
2037697SMichael.Christensen@Sun.COM ulong_t *bhst = vlds_minor_bitmap;
2047697SMichael.Christensen@Sun.COM
2057697SMichael.Christensen@Sun.COM /* Increase bitmap by one BT_NBIPUL */
2067697SMichael.Christensen@Sun.COM if (vlds_minor_bits + BT_NBIPUL > VLDS_MINOR_MAX) {
2077697SMichael.Christensen@Sun.COM return ((ulong_t *)NULL);
2087697SMichael.Christensen@Sun.COM }
2097697SMichael.Christensen@Sun.COM vlds_minor_bitmap = kmem_zalloc(
2107697SMichael.Christensen@Sun.COM BT_SIZEOFMAP(vlds_minor_bits + BT_NBIPUL), KM_SLEEP);
2117697SMichael.Christensen@Sun.COM bcopy(bhst, vlds_minor_bitmap, BT_SIZEOFMAP(vlds_minor_bits));
2127697SMichael.Christensen@Sun.COM if (bhst != &vlds_bitmap_initial)
2137697SMichael.Christensen@Sun.COM kmem_free(bhst, BT_SIZEOFMAP(vlds_minor_bits));
2147697SMichael.Christensen@Sun.COM vlds_minor_bits += BT_NBIPUL;
2157697SMichael.Christensen@Sun.COM
2167697SMichael.Christensen@Sun.COM return (vlds_minor_bitmap);
2177697SMichael.Christensen@Sun.COM }
2187697SMichael.Christensen@Sun.COM
2197697SMichael.Christensen@Sun.COM static void
vlds_minor_free(ulong_t * bitmap)2207697SMichael.Christensen@Sun.COM vlds_minor_free(ulong_t *bitmap)
2217697SMichael.Christensen@Sun.COM {
2227697SMichael.Christensen@Sun.COM if (bitmap != &vlds_bitmap_initial)
2237697SMichael.Christensen@Sun.COM kmem_free(bitmap, BT_SIZEOFMAP(vlds_minor_bits));
2247697SMichael.Christensen@Sun.COM }
2257697SMichael.Christensen@Sun.COM
2267697SMichael.Christensen@Sun.COM static index_t
vlds_minor_get(void)2277697SMichael.Christensen@Sun.COM vlds_minor_get(void)
2287697SMichael.Christensen@Sun.COM {
2297697SMichael.Christensen@Sun.COM index_t idx;
2307697SMichael.Christensen@Sun.COM ulong_t *bhst;
2317697SMichael.Christensen@Sun.COM
2327697SMichael.Christensen@Sun.COM /* Search for an available index */
2337697SMichael.Christensen@Sun.COM mutex_enter(&vlds_minor_mutex);
2347697SMichael.Christensen@Sun.COM if ((idx = bt_availbit(vlds_minor_bitmap,
2357697SMichael.Christensen@Sun.COM vlds_minor_bits)) == -1) {
2367697SMichael.Christensen@Sun.COM /* All busy - allocate additional binding handle bitmap space */
2377697SMichael.Christensen@Sun.COM if ((bhst = vlds_minor_alloc()) == NULL) {
2387697SMichael.Christensen@Sun.COM /* Reached our maximum of id's == SHRT_MAX */
2397697SMichael.Christensen@Sun.COM mutex_exit(&vlds_minor_mutex);
2407697SMichael.Christensen@Sun.COM return (0);
2417697SMichael.Christensen@Sun.COM } else {
2427697SMichael.Christensen@Sun.COM vlds_minor_bitmap = bhst;
2437697SMichael.Christensen@Sun.COM }
2447697SMichael.Christensen@Sun.COM idx = bt_availbit(vlds_minor_bitmap, vlds_minor_bits);
2457697SMichael.Christensen@Sun.COM }
2467697SMichael.Christensen@Sun.COM BT_SET(vlds_minor_bitmap, idx);
2477697SMichael.Christensen@Sun.COM mutex_exit(&vlds_minor_mutex);
2487697SMichael.Christensen@Sun.COM return (idx);
2497697SMichael.Christensen@Sun.COM }
2507697SMichael.Christensen@Sun.COM
2517697SMichael.Christensen@Sun.COM static void
vlds_minor_rele(index_t idx)2527697SMichael.Christensen@Sun.COM vlds_minor_rele(index_t idx)
2537697SMichael.Christensen@Sun.COM {
2547697SMichael.Christensen@Sun.COM mutex_enter(&vlds_minor_mutex);
2557697SMichael.Christensen@Sun.COM ASSERT(BT_TEST(vlds_minor_bitmap, idx) == 1);
2567697SMichael.Christensen@Sun.COM BT_CLEAR(vlds_minor_bitmap, idx);
2577697SMichael.Christensen@Sun.COM mutex_exit(&vlds_minor_mutex);
2587697SMichael.Christensen@Sun.COM }
2597697SMichael.Christensen@Sun.COM
2607697SMichael.Christensen@Sun.COM static void
vlds_minor_init(void)2617697SMichael.Christensen@Sun.COM vlds_minor_init(void)
2627697SMichael.Christensen@Sun.COM {
2637697SMichael.Christensen@Sun.COM mutex_init(&vlds_minor_mutex, NULL, MUTEX_DEFAULT, NULL);
2647697SMichael.Christensen@Sun.COM }
2657697SMichael.Christensen@Sun.COM
2667697SMichael.Christensen@Sun.COM int
_init(void)2677697SMichael.Christensen@Sun.COM _init(void)
2687697SMichael.Christensen@Sun.COM {
2697697SMichael.Christensen@Sun.COM int s;
2707697SMichael.Christensen@Sun.COM
2717697SMichael.Christensen@Sun.COM if ((s = ddi_soft_state_init(&vlds_statep, sizeof (vlds_state_t), 0))
2727697SMichael.Christensen@Sun.COM != 0)
2737697SMichael.Christensen@Sun.COM return (s);
2747697SMichael.Christensen@Sun.COM
2757697SMichael.Christensen@Sun.COM if ((s = mod_install(&modlinkage)) != 0) {
2767697SMichael.Christensen@Sun.COM ddi_soft_state_fini(&vlds_statep);
2777697SMichael.Christensen@Sun.COM return (s);
2787697SMichael.Christensen@Sun.COM }
2797697SMichael.Christensen@Sun.COM
2808172SMichael.Christensen@Sun.COM vlds_mdeg_init();
2817697SMichael.Christensen@Sun.COM
2827697SMichael.Christensen@Sun.COM return (s);
2837697SMichael.Christensen@Sun.COM }
2847697SMichael.Christensen@Sun.COM
2857697SMichael.Christensen@Sun.COM int
_fini(void)2867697SMichael.Christensen@Sun.COM _fini(void)
2877697SMichael.Christensen@Sun.COM {
2887697SMichael.Christensen@Sun.COM int s;
2897697SMichael.Christensen@Sun.COM
2907697SMichael.Christensen@Sun.COM if ((s = mod_remove(&modlinkage)) != 0)
2917697SMichael.Christensen@Sun.COM return (s);
2927697SMichael.Christensen@Sun.COM
2937697SMichael.Christensen@Sun.COM ddi_soft_state_fini(&vlds_statep);
2947697SMichael.Christensen@Sun.COM
2957697SMichael.Christensen@Sun.COM return (s);
2967697SMichael.Christensen@Sun.COM }
2977697SMichael.Christensen@Sun.COM
2987697SMichael.Christensen@Sun.COM int
_info(struct modinfo * modinfop)2997697SMichael.Christensen@Sun.COM _info(struct modinfo *modinfop)
3007697SMichael.Christensen@Sun.COM {
3017697SMichael.Christensen@Sun.COM return (mod_info(&modlinkage, modinfop));
3027697SMichael.Christensen@Sun.COM }
3037697SMichael.Christensen@Sun.COM
3047697SMichael.Christensen@Sun.COM
3057697SMichael.Christensen@Sun.COM
3067697SMichael.Christensen@Sun.COM /*ARGSUSED*/
3077697SMichael.Christensen@Sun.COM static int
vlds_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** resultp)3087697SMichael.Christensen@Sun.COM vlds_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp)
3097697SMichael.Christensen@Sun.COM {
3107697SMichael.Christensen@Sun.COM switch (cmd) {
3117697SMichael.Christensen@Sun.COM case DDI_INFO_DEVT2DEVINFO:
3127697SMichael.Christensen@Sun.COM *resultp = vlds_devi;
3137697SMichael.Christensen@Sun.COM return (DDI_SUCCESS);
3147697SMichael.Christensen@Sun.COM case DDI_INFO_DEVT2INSTANCE:
3157697SMichael.Christensen@Sun.COM *resultp = 0;
3167697SMichael.Christensen@Sun.COM return (DDI_SUCCESS);
3177697SMichael.Christensen@Sun.COM }
3187697SMichael.Christensen@Sun.COM return (DDI_FAILURE);
3197697SMichael.Christensen@Sun.COM }
3207697SMichael.Christensen@Sun.COM
3217697SMichael.Christensen@Sun.COM
3227697SMichael.Christensen@Sun.COM static int
vlds_attach(dev_info_t * devi,ddi_attach_cmd_t cmd)3237697SMichael.Christensen@Sun.COM vlds_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
3247697SMichael.Christensen@Sun.COM {
3257697SMichael.Christensen@Sun.COM if (cmd != DDI_ATTACH) {
3267697SMichael.Christensen@Sun.COM return (DDI_FAILURE);
3277697SMichael.Christensen@Sun.COM }
3287697SMichael.Christensen@Sun.COM
3297697SMichael.Christensen@Sun.COM if (ddi_create_minor_node(devi, VLDS_NAME, S_IFCHR,
3307697SMichael.Christensen@Sun.COM 0, DDI_PSEUDO, NULL) == DDI_FAILURE) {
3317697SMichael.Christensen@Sun.COM ddi_remove_minor_node(devi, NULL);
3327697SMichael.Christensen@Sun.COM return (DDI_FAILURE);
3337697SMichael.Christensen@Sun.COM }
3347697SMichael.Christensen@Sun.COM vlds_devi = devi;
3357697SMichael.Christensen@Sun.COM
3367697SMichael.Christensen@Sun.COM vlds_minor_init();
3377697SMichael.Christensen@Sun.COM
338*11185SSean.McEnroe@Sun.COM (void) vlds_mdeg_register();
339*11185SSean.McEnroe@Sun.COM
3407697SMichael.Christensen@Sun.COM return (DDI_SUCCESS);
3417697SMichael.Christensen@Sun.COM }
3427697SMichael.Christensen@Sun.COM
3437697SMichael.Christensen@Sun.COM
3447697SMichael.Christensen@Sun.COM /*ARGSUSED*/
3457697SMichael.Christensen@Sun.COM static int
vlds_detach(dev_info_t * devi,ddi_detach_cmd_t cmd)3467697SMichael.Christensen@Sun.COM vlds_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
3477697SMichael.Christensen@Sun.COM {
3487697SMichael.Christensen@Sun.COM if (cmd != DDI_DETACH) {
3497697SMichael.Christensen@Sun.COM return (DDI_FAILURE);
3507697SMichael.Christensen@Sun.COM }
3517697SMichael.Christensen@Sun.COM
3527697SMichael.Christensen@Sun.COM vlds_minor_free(vlds_minor_bitmap);
3537697SMichael.Christensen@Sun.COM ddi_remove_minor_node(devi, NULL);
354*11185SSean.McEnroe@Sun.COM (void) vlds_mdeg_unregister();
3557697SMichael.Christensen@Sun.COM return (DDI_SUCCESS);
3567697SMichael.Christensen@Sun.COM }
3577697SMichael.Christensen@Sun.COM
3587697SMichael.Christensen@Sun.COM
3597697SMichael.Christensen@Sun.COM /*ARGSUSED*/
3607697SMichael.Christensen@Sun.COM static int
vlds_open(dev_t * devp,int flag,int otyp,cred_t * credp)3617697SMichael.Christensen@Sun.COM vlds_open(dev_t *devp, int flag, int otyp, cred_t *credp)
3627697SMichael.Christensen@Sun.COM {
3637697SMichael.Christensen@Sun.COM int minor;
3647697SMichael.Christensen@Sun.COM
3657697SMichael.Christensen@Sun.COM if (otyp != OTYP_CHR)
3667697SMichael.Christensen@Sun.COM return (EINVAL);
3677697SMichael.Christensen@Sun.COM
3687697SMichael.Christensen@Sun.COM if (getminor(*devp) != 0)
3697697SMichael.Christensen@Sun.COM return (ENXIO);
3707697SMichael.Christensen@Sun.COM
3717697SMichael.Christensen@Sun.COM minor = vlds_minor_get();
3727697SMichael.Christensen@Sun.COM if (minor == 0)
3737697SMichael.Christensen@Sun.COM /* All minors are busy */
3747697SMichael.Christensen@Sun.COM return (EBUSY);
3757697SMichael.Christensen@Sun.COM
3767697SMichael.Christensen@Sun.COM if (ddi_soft_state_zalloc(vlds_statep, minor) != DDI_SUCCESS) {
3777697SMichael.Christensen@Sun.COM vlds_minor_rele(minor);
3787697SMichael.Christensen@Sun.COM return (ENOMEM);
3797697SMichael.Christensen@Sun.COM }
3807697SMichael.Christensen@Sun.COM
3817697SMichael.Christensen@Sun.COM *devp = makedevice(getmajor(*devp), minor);
3827697SMichael.Christensen@Sun.COM
3837697SMichael.Christensen@Sun.COM return (0);
3847697SMichael.Christensen@Sun.COM }
3857697SMichael.Christensen@Sun.COM
3867697SMichael.Christensen@Sun.COM
3877697SMichael.Christensen@Sun.COM /*ARGSUSED*/
3887697SMichael.Christensen@Sun.COM static int
vlds_close(dev_t dev,int flag,int otyp,cred_t * credp)3897697SMichael.Christensen@Sun.COM vlds_close(dev_t dev, int flag, int otyp, cred_t *credp)
3907697SMichael.Christensen@Sun.COM {
3917697SMichael.Christensen@Sun.COM int minor = (int)getminor(dev);
3927697SMichael.Christensen@Sun.COM vlds_state_t *sp;
3937697SMichael.Christensen@Sun.COM
3947697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "vlds_close");
3957697SMichael.Christensen@Sun.COM
3967697SMichael.Christensen@Sun.COM /*
3977697SMichael.Christensen@Sun.COM * Unregister all handles associated with this process.
3987697SMichael.Christensen@Sun.COM */
3997697SMichael.Christensen@Sun.COM ds_unreg_all(minor);
4007697SMichael.Christensen@Sun.COM
4017697SMichael.Christensen@Sun.COM if (otyp != OTYP_CHR)
4027697SMichael.Christensen@Sun.COM return (EINVAL);
4037697SMichael.Christensen@Sun.COM
4047697SMichael.Christensen@Sun.COM sp = ddi_get_soft_state(vlds_statep, minor);
4057697SMichael.Christensen@Sun.COM if (sp == NULL) {
4067697SMichael.Christensen@Sun.COM return (ENXIO);
4077697SMichael.Christensen@Sun.COM }
4087697SMichael.Christensen@Sun.COM
4097697SMichael.Christensen@Sun.COM if (sp->evchan) {
41011102SGavin.Maltby@Sun.COM (void) sysevent_evc_unbind(sp->evchan);
4117697SMichael.Christensen@Sun.COM sp->evchan = NULL;
4127697SMichael.Christensen@Sun.COM }
4137697SMichael.Christensen@Sun.COM
4147697SMichael.Christensen@Sun.COM ddi_soft_state_free(vlds_statep, minor);
4157697SMichael.Christensen@Sun.COM vlds_minor_rele(minor);
4167697SMichael.Christensen@Sun.COM
4177697SMichael.Christensen@Sun.COM return (0);
4187697SMichael.Christensen@Sun.COM }
4197697SMichael.Christensen@Sun.COM
4207697SMichael.Christensen@Sun.COM int
vlds_init_sysevent(vlds_state_t * sp,uint32_t flags)4217697SMichael.Christensen@Sun.COM vlds_init_sysevent(vlds_state_t *sp, uint32_t flags)
4227697SMichael.Christensen@Sun.COM {
4237697SMichael.Christensen@Sun.COM char evchan_name[MAX_CHNAME_LEN];
4247697SMichael.Christensen@Sun.COM int rv;
4257697SMichael.Christensen@Sun.COM
4267697SMichael.Christensen@Sun.COM if (flags & DSSF_ANYCB_VALID) {
4277697SMichael.Christensen@Sun.COM if (sp->evchan) {
4287697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: sysevent already bound",
4297697SMichael.Christensen@Sun.COM __func__);
4307697SMichael.Christensen@Sun.COM return (0);
4317697SMichael.Christensen@Sun.COM }
4327697SMichael.Christensen@Sun.COM (void) sprintf(evchan_name, VLDS_SYSEV_CHAN_FMT, ddi_get_pid());
4337697SMichael.Christensen@Sun.COM if ((rv = sysevent_evc_bind(evchan_name, &sp->evchan,
4347697SMichael.Christensen@Sun.COM EVCH_CREAT|EVCH_HOLD_PEND)) != 0) {
4357697SMichael.Christensen@Sun.COM cmn_err(CE_WARN, "%s: can't bind to '%s' (%d)",
4367697SMichael.Christensen@Sun.COM __func__, evchan_name, rv);
4377697SMichael.Christensen@Sun.COM return (rv);
4387697SMichael.Christensen@Sun.COM }
4397697SMichael.Christensen@Sun.COM
4407697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: sysevent bind to '%s' successful",
4417697SMichael.Christensen@Sun.COM __func__, evchan_name);
4427697SMichael.Christensen@Sun.COM }
4437697SMichael.Christensen@Sun.COM return (0);
4447697SMichael.Christensen@Sun.COM }
4457697SMichael.Christensen@Sun.COM
4467697SMichael.Christensen@Sun.COM #define ARGTOPTR(x) ((void *)((uintptr_t)(x)))
4477697SMichael.Christensen@Sun.COM #define ARGTOUINT(x) ((uint_t)(x))
4487697SMichael.Christensen@Sun.COM #define ARGTOINT(x) ((int)(x))
4497697SMichael.Christensen@Sun.COM
4507697SMichael.Christensen@Sun.COM static int
vlds_get_string(vlds_string_t * strp,char ** rstrp,int mode)4517697SMichael.Christensen@Sun.COM vlds_get_string(vlds_string_t *strp, char **rstrp, int mode)
4527697SMichael.Christensen@Sun.COM {
4537697SMichael.Christensen@Sun.COM char *str;
4547697SMichael.Christensen@Sun.COM uint_t len = strp->vlds_strlen;
4557697SMichael.Christensen@Sun.COM uint_t slen;
4567697SMichael.Christensen@Sun.COM
4577697SMichael.Christensen@Sun.COM if (len == 0) {
4587697SMichael.Christensen@Sun.COM *rstrp = NULL;
4597697SMichael.Christensen@Sun.COM return (0);
4607697SMichael.Christensen@Sun.COM }
4617697SMichael.Christensen@Sun.COM if (len > MAXNAMELEN) {
4627697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: invalid string length: %d", __func__,
4637697SMichael.Christensen@Sun.COM len);
4647697SMichael.Christensen@Sun.COM return (EINVAL);
4657697SMichael.Christensen@Sun.COM }
4667697SMichael.Christensen@Sun.COM str = DS_MALLOC(len);
4677697SMichael.Christensen@Sun.COM if (ddi_copyin(ARGTOPTR(strp->vlds_strp), str, len, mode) != 0) {
4687697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: ddi copyin failed (%p)", __func__,
4697697SMichael.Christensen@Sun.COM ARGTOPTR(strp->vlds_strp));
4707697SMichael.Christensen@Sun.COM DS_FREE(str, len);
4717697SMichael.Christensen@Sun.COM return (EFAULT);
4727697SMichael.Christensen@Sun.COM }
4737697SMichael.Christensen@Sun.COM slen = strlen(str) + 1;
4747697SMichael.Christensen@Sun.COM if (slen != len) {
4757697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: invalid string len: %d != len: %d",
4767697SMichael.Christensen@Sun.COM __func__, slen, len);
4777697SMichael.Christensen@Sun.COM DS_FREE(str, len);
4787697SMichael.Christensen@Sun.COM return (EINVAL);
4797697SMichael.Christensen@Sun.COM }
4807697SMichael.Christensen@Sun.COM *rstrp = str;
4817697SMichael.Christensen@Sun.COM return (0);
4827697SMichael.Christensen@Sun.COM }
4837697SMichael.Christensen@Sun.COM
4847697SMichael.Christensen@Sun.COM static int
vlds_put_string(char * str,vlds_string_t * strp,int mode)4857697SMichael.Christensen@Sun.COM vlds_put_string(char *str, vlds_string_t *strp, int mode)
4867697SMichael.Christensen@Sun.COM {
4877697SMichael.Christensen@Sun.COM uint_t len;
4887697SMichael.Christensen@Sun.COM char *tstr = NULL;
4897697SMichael.Christensen@Sun.COM int rv;
4907697SMichael.Christensen@Sun.COM
4917697SMichael.Christensen@Sun.COM if (str == NULL) {
4927697SMichael.Christensen@Sun.COM str = "";
4937697SMichael.Christensen@Sun.COM }
4947697SMichael.Christensen@Sun.COM len = strlen(str) + 1;
4957697SMichael.Christensen@Sun.COM
4967697SMichael.Christensen@Sun.COM /*
4977697SMichael.Christensen@Sun.COM * If string is longer than user buffer, return a
4987697SMichael.Christensen@Sun.COM * truncated, null-terminated string.
4997697SMichael.Christensen@Sun.COM */
5007697SMichael.Christensen@Sun.COM if (len > strp->vlds_strlen) {
5017697SMichael.Christensen@Sun.COM len = strp->vlds_strlen;
5027697SMichael.Christensen@Sun.COM if (len > 0) {
5037697SMichael.Christensen@Sun.COM tstr = DS_MALLOC(len);
5047697SMichael.Christensen@Sun.COM (void) memcpy(tstr, str, len - 1);
5057697SMichael.Christensen@Sun.COM tstr[len - 1] = '\0';
5067697SMichael.Christensen@Sun.COM str = tstr;
5077697SMichael.Christensen@Sun.COM }
5087697SMichael.Christensen@Sun.COM }
5097697SMichael.Christensen@Sun.COM rv = ddi_copyout(str, ARGTOPTR(strp->vlds_strp), len, mode);
5107697SMichael.Christensen@Sun.COM if (tstr) {
5117697SMichael.Christensen@Sun.COM DS_FREE(tstr, len);
5127697SMichael.Christensen@Sun.COM }
5137697SMichael.Christensen@Sun.COM if (rv) {
5147697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: copyout (%p) failed", __func__,
5157697SMichael.Christensen@Sun.COM ARGTOPTR(strp->vlds_strp));
5167697SMichael.Christensen@Sun.COM return (EFAULT);
5177697SMichael.Christensen@Sun.COM }
5187697SMichael.Christensen@Sun.COM return (0);
5197697SMichael.Christensen@Sun.COM }
5207697SMichael.Christensen@Sun.COM
5217697SMichael.Christensen@Sun.COM static int
vlds_get_ucap(vlds_cap_t * capp,ds_capability_t * ucap,int mode)5227697SMichael.Christensen@Sun.COM vlds_get_ucap(vlds_cap_t *capp, ds_capability_t *ucap, int mode)
5237697SMichael.Christensen@Sun.COM {
5247697SMichael.Christensen@Sun.COM char *servp;
5257697SMichael.Christensen@Sun.COM vlds_ver_t *dsvp;
5267697SMichael.Christensen@Sun.COM vlds_cap_t vlds_cap;
5277697SMichael.Christensen@Sun.COM uint_t n;
5287697SMichael.Christensen@Sun.COM uint_t nver;
5297697SMichael.Christensen@Sun.COM int i;
5307697SMichael.Christensen@Sun.COM int rv;
5317697SMichael.Christensen@Sun.COM
5327697SMichael.Christensen@Sun.COM if (ddi_copyin(capp, &vlds_cap, sizeof (vlds_cap), mode) != 0) {
5337697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: cap copyin failed (%p)", __func__,
5347697SMichael.Christensen@Sun.COM (void *)capp);
5357697SMichael.Christensen@Sun.COM return (EFAULT);
5367697SMichael.Christensen@Sun.COM }
5377697SMichael.Christensen@Sun.COM
5387697SMichael.Christensen@Sun.COM nver = ARGTOUINT(vlds_cap.vlds_nver);
5397697SMichael.Christensen@Sun.COM
5407697SMichael.Christensen@Sun.COM if (nver > VLDS_MAX_VERS) {
5417697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: vlds_nver (%d) invalid", __func__,
5427697SMichael.Christensen@Sun.COM nver);
5437697SMichael.Christensen@Sun.COM return (EINVAL);
5447697SMichael.Christensen@Sun.COM }
5457697SMichael.Christensen@Sun.COM
5467697SMichael.Christensen@Sun.COM if ((rv = vlds_get_string(&vlds_cap.vlds_service, &servp, mode)) != 0) {
5477697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: vlds_get_string vlds_service failed "
5487697SMichael.Christensen@Sun.COM "(%d)", __func__, rv);
5497697SMichael.Christensen@Sun.COM return (rv);
5507697SMichael.Christensen@Sun.COM } else if (servp == NULL) {
5517697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: vlds_get_string vlds_service is NULL",
5527697SMichael.Christensen@Sun.COM __func__);
5537697SMichael.Christensen@Sun.COM return (EINVAL);
5547697SMichael.Christensen@Sun.COM }
5557697SMichael.Christensen@Sun.COM
5567697SMichael.Christensen@Sun.COM n = nver * sizeof (vlds_ver_t);
5577697SMichael.Christensen@Sun.COM dsvp = DS_MALLOC(n);
5587697SMichael.Christensen@Sun.COM
5597697SMichael.Christensen@Sun.COM if (ddi_copyin(ARGTOPTR(vlds_cap.vlds_versp), dsvp, n, mode) != 0) {
5607697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: copyin of vers (%p, %d) failed",
5617697SMichael.Christensen@Sun.COM __func__, ARGTOPTR(vlds_cap.vlds_versp), n);
5627697SMichael.Christensen@Sun.COM DS_FREE(servp, strlen(servp) + 1);
5637697SMichael.Christensen@Sun.COM DS_FREE(dsvp, n);
5647697SMichael.Christensen@Sun.COM return (EFAULT);
5657697SMichael.Christensen@Sun.COM }
5667697SMichael.Christensen@Sun.COM
5677697SMichael.Christensen@Sun.COM ucap->svc_id = servp;
5687697SMichael.Christensen@Sun.COM ucap->vers = DS_MALLOC(nver * sizeof (ds_ver_t));
5697697SMichael.Christensen@Sun.COM for (i = 0; i < nver; i++) {
5707697SMichael.Christensen@Sun.COM ucap->vers[i].major = dsvp[i].vlds_major;
5717697SMichael.Christensen@Sun.COM ucap->vers[i].minor = dsvp[i].vlds_minor;
5727697SMichael.Christensen@Sun.COM }
5737697SMichael.Christensen@Sun.COM ucap->nvers = nver;
5747697SMichael.Christensen@Sun.COM DS_FREE(dsvp, n);
5757697SMichael.Christensen@Sun.COM return (0);
5767697SMichael.Christensen@Sun.COM }
5777697SMichael.Christensen@Sun.COM
5787697SMichael.Christensen@Sun.COM static void
vlds_free_ucap(ds_capability_t * ucap)5797697SMichael.Christensen@Sun.COM vlds_free_ucap(ds_capability_t *ucap)
5807697SMichael.Christensen@Sun.COM {
5817697SMichael.Christensen@Sun.COM kmem_free(ucap->svc_id, strlen(ucap->svc_id) + 1);
5827697SMichael.Christensen@Sun.COM kmem_free(ucap->vers, ucap->nvers * sizeof (ds_ver_t));
5837697SMichael.Christensen@Sun.COM }
5847697SMichael.Christensen@Sun.COM
5857697SMichael.Christensen@Sun.COM /*ARGSUSED*/
5867697SMichael.Christensen@Sun.COM static int
vlds_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)5877697SMichael.Christensen@Sun.COM vlds_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
5887697SMichael.Christensen@Sun.COM int *rvalp)
5897697SMichael.Christensen@Sun.COM {
5907697SMichael.Christensen@Sun.COM vlds_state_t *sp;
5917697SMichael.Christensen@Sun.COM ds_svc_hdl_t hdl;
5927697SMichael.Christensen@Sun.COM ds_domain_hdl_t dhdl;
5937697SMichael.Christensen@Sun.COM char *servicep;
5947697SMichael.Christensen@Sun.COM int rv;
5957697SMichael.Christensen@Sun.COM int minor = (int)getminor(dev);
5967697SMichael.Christensen@Sun.COM
5977697SMichael.Christensen@Sun.COM if ((sp = ddi_get_soft_state(vlds_statep, minor)) == NULL)
5987697SMichael.Christensen@Sun.COM return (ENXIO);
5997697SMichael.Christensen@Sun.COM
6007697SMichael.Christensen@Sun.COM switch (cmd) {
6017697SMichael.Christensen@Sun.COM
6027697SMichael.Christensen@Sun.COM case VLDS_SVC_REG:
6037697SMichael.Christensen@Sun.COM {
6047697SMichael.Christensen@Sun.COM vlds_svc_reg_arg_t vlds_arg;
6057697SMichael.Christensen@Sun.COM ds_capability_t ucap;
6067697SMichael.Christensen@Sun.COM uint64_t hdl_arg;
6077697SMichael.Christensen@Sun.COM uint_t flags;
6087697SMichael.Christensen@Sun.COM
6097697SMichael.Christensen@Sun.COM if (ddi_copyin((void *)arg, &vlds_arg, sizeof (vlds_arg),
6107697SMichael.Christensen@Sun.COM mode) != 0) {
6117697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: SVC REG arg copyin failed",
6127697SMichael.Christensen@Sun.COM __func__);
6137697SMichael.Christensen@Sun.COM return (EFAULT);
6147697SMichael.Christensen@Sun.COM }
6157697SMichael.Christensen@Sun.COM
6167697SMichael.Christensen@Sun.COM if ((rv = vlds_get_ucap(ARGTOPTR(vlds_arg.vlds_capp), &ucap,
6177697SMichael.Christensen@Sun.COM mode)) != 0) {
6187697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: SVC REG get_ucap failed (%d)",
6197697SMichael.Christensen@Sun.COM __func__, rv);
6207697SMichael.Christensen@Sun.COM return (rv);
6217697SMichael.Christensen@Sun.COM }
6227697SMichael.Christensen@Sun.COM
6237697SMichael.Christensen@Sun.COM flags = vlds_flags_to_svc(vlds_arg.vlds_reg_flags);
6247697SMichael.Christensen@Sun.COM if ((rv = vlds_init_sysevent(sp, flags)) != 0) {
6257697SMichael.Christensen@Sun.COM vlds_free_ucap(&ucap);
6267697SMichael.Christensen@Sun.COM return (rv);
6277697SMichael.Christensen@Sun.COM }
6287697SMichael.Christensen@Sun.COM
6297697SMichael.Christensen@Sun.COM rv = ds_ucap_init(&ucap, &ds_user_ops,
6307697SMichael.Christensen@Sun.COM vlds_flags_to_svc(vlds_arg.vlds_reg_flags) | DSSF_ISUSER,
6317697SMichael.Christensen@Sun.COM minor, &hdl);
6327697SMichael.Christensen@Sun.COM
6337697SMichael.Christensen@Sun.COM vlds_free_ucap(&ucap);
6347697SMichael.Christensen@Sun.COM
6357697SMichael.Christensen@Sun.COM if (rv) {
6367697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: SVC REG ds_ucap_init failed "
6377697SMichael.Christensen@Sun.COM "(%d)", __func__, rv);
6387697SMichael.Christensen@Sun.COM return (rv);
6397697SMichael.Christensen@Sun.COM }
6407697SMichael.Christensen@Sun.COM
6417697SMichael.Christensen@Sun.COM hdl_arg = hdl;
6427697SMichael.Christensen@Sun.COM if (ddi_copyout(&hdl_arg, ARGTOPTR(vlds_arg.vlds_hdlp),
6437697SMichael.Christensen@Sun.COM sizeof (hdl_arg), mode) != 0) {
6447697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: SVC REG copyout failed",
6457697SMichael.Christensen@Sun.COM __func__);
6467697SMichael.Christensen@Sun.COM return (EFAULT);
6477697SMichael.Christensen@Sun.COM }
6487697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: SVC REG succeeded: hdl: %lx",
6497697SMichael.Christensen@Sun.COM __func__, hdl);
6507697SMichael.Christensen@Sun.COM break;
6517697SMichael.Christensen@Sun.COM }
6527697SMichael.Christensen@Sun.COM
6537697SMichael.Christensen@Sun.COM case VLDS_UNREG_HDL:
6547697SMichael.Christensen@Sun.COM {
6557697SMichael.Christensen@Sun.COM vlds_unreg_hdl_arg_t vlds_arg;
6567697SMichael.Christensen@Sun.COM
6577697SMichael.Christensen@Sun.COM if (ddi_copyin((void *)arg, &vlds_arg, sizeof (vlds_arg),
6587697SMichael.Christensen@Sun.COM mode) != 0) {
6597697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: UNREG_HDL arg copyin failed",
6607697SMichael.Christensen@Sun.COM __func__);
6617697SMichael.Christensen@Sun.COM return (EFAULT);
6627697SMichael.Christensen@Sun.COM }
6637697SMichael.Christensen@Sun.COM
6647697SMichael.Christensen@Sun.COM hdl = vlds_arg.vlds_hdl;
6657697SMichael.Christensen@Sun.COM
6667697SMichael.Christensen@Sun.COM if ((rv = ds_is_my_hdl(hdl, minor)) != 0) {
6677697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: UNREG_HDL ds_is_my_hdl "
6687697SMichael.Christensen@Sun.COM " hdl: %lx inst: %d failed (%d)", __func__,
6697697SMichael.Christensen@Sun.COM hdl, rv, minor);
6707697SMichael.Christensen@Sun.COM return (rv);
6717697SMichael.Christensen@Sun.COM }
6727697SMichael.Christensen@Sun.COM
6737697SMichael.Christensen@Sun.COM if ((rv = ds_unreg_hdl(hdl)) != 0) {
6747697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: UNREG_HDL ds_cap_unreg "
6757697SMichael.Christensen@Sun.COM " hdl: %lx failed (%d)", __func__, hdl, rv);
6767697SMichael.Christensen@Sun.COM return (rv);
6777697SMichael.Christensen@Sun.COM }
6787697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: UNREG_HDL hdl: %lx succeeded",
6797697SMichael.Christensen@Sun.COM __func__, hdl);
6807697SMichael.Christensen@Sun.COM break;
6817697SMichael.Christensen@Sun.COM }
6827697SMichael.Christensen@Sun.COM
6837697SMichael.Christensen@Sun.COM case VLDS_HDL_LOOKUP:
6847697SMichael.Christensen@Sun.COM {
6857697SMichael.Christensen@Sun.COM vlds_hdl_lookup_arg_t vlds_arg;
6867697SMichael.Christensen@Sun.COM ds_svc_hdl_t *hdlsp;
6877697SMichael.Christensen@Sun.COM uint_t is_client, maxhdls, nhdls;
6887697SMichael.Christensen@Sun.COM uint64_t nhdls_arg;
6897697SMichael.Christensen@Sun.COM
6907697SMichael.Christensen@Sun.COM if (ddi_copyin((void *)arg, &vlds_arg, sizeof (vlds_arg),
6917697SMichael.Christensen@Sun.COM mode) != 0) {
6927697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: HDL_LOOKUP arg copyin failed",
6937697SMichael.Christensen@Sun.COM __func__);
6947697SMichael.Christensen@Sun.COM return (EFAULT);
6957697SMichael.Christensen@Sun.COM }
6967697SMichael.Christensen@Sun.COM
6977697SMichael.Christensen@Sun.COM is_client = ARGTOUINT(vlds_arg.vlds_isclient);
6987697SMichael.Christensen@Sun.COM maxhdls = ARGTOUINT(vlds_arg.vlds_maxhdls);
6997697SMichael.Christensen@Sun.COM if (maxhdls == 0) {
7007697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: HDL_LOOKUP invalid maxhdls "
7017697SMichael.Christensen@Sun.COM "%d", __func__, maxhdls);
7027697SMichael.Christensen@Sun.COM return (EINVAL);
7037697SMichael.Christensen@Sun.COM }
7047697SMichael.Christensen@Sun.COM
7057697SMichael.Christensen@Sun.COM if ((rv = vlds_get_string(&vlds_arg.vlds_service, &servicep,
7067697SMichael.Christensen@Sun.COM mode)) != 0) {
7077697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: HDL_LOOKUP vlds_get_string "
7087697SMichael.Christensen@Sun.COM "(service) failed (%d)", __func__, rv);
7097697SMichael.Christensen@Sun.COM return (EFAULT);
7107697SMichael.Christensen@Sun.COM } else if (servicep == NULL) {
7117697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: HDL_LOOKUP vlds_get_string "
7127697SMichael.Christensen@Sun.COM " service is NULL", __func__);
7137697SMichael.Christensen@Sun.COM return (EINVAL);
7147697SMichael.Christensen@Sun.COM }
7157697SMichael.Christensen@Sun.COM
7167697SMichael.Christensen@Sun.COM if (ARGTOPTR(vlds_arg.vlds_hdlsp) == 0) {
7177697SMichael.Christensen@Sun.COM hdlsp = NULL;
7187697SMichael.Christensen@Sun.COM } else {
7197697SMichael.Christensen@Sun.COM hdlsp = DS_MALLOC(maxhdls * sizeof (*hdlsp));
7207697SMichael.Christensen@Sun.COM }
7217697SMichael.Christensen@Sun.COM
7227697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: HDL_LOOKUP (%s, %d) entered",
7237697SMichael.Christensen@Sun.COM __func__, servicep, is_client);
7247697SMichael.Christensen@Sun.COM rv = ds_hdl_lookup(servicep, is_client, hdlsp, maxhdls, &nhdls);
7257697SMichael.Christensen@Sun.COM
7267697SMichael.Christensen@Sun.COM DS_FREE(servicep, strlen(servicep) + 1);
7277697SMichael.Christensen@Sun.COM if (rv) {
7287697SMichael.Christensen@Sun.COM if (hdlsp) {
7297697SMichael.Christensen@Sun.COM DS_FREE(hdlsp, maxhdls * sizeof (*hdlsp));
7307697SMichael.Christensen@Sun.COM }
7317697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: HDL_LOOKUP failed: (%d)",
7327697SMichael.Christensen@Sun.COM __func__, rv);
7337697SMichael.Christensen@Sun.COM return (rv);
7347697SMichael.Christensen@Sun.COM }
7357697SMichael.Christensen@Sun.COM
7367697SMichael.Christensen@Sun.COM if (hdlsp != NULL && nhdls > 0 &&
7377697SMichael.Christensen@Sun.COM ddi_copyout(hdlsp, ARGTOPTR(vlds_arg.vlds_hdlsp),
7387697SMichael.Christensen@Sun.COM nhdls * sizeof (ds_svc_hdl_t), mode) != 0) {
7397697SMichael.Christensen@Sun.COM if (hdlsp) {
7407697SMichael.Christensen@Sun.COM DS_FREE(hdlsp, maxhdls * sizeof (*hdlsp));
7417697SMichael.Christensen@Sun.COM }
7427697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: HDL_LOOKUP copyout of hdls "
7437697SMichael.Christensen@Sun.COM " failed", __func__);
7447697SMichael.Christensen@Sun.COM return (EFAULT);
7457697SMichael.Christensen@Sun.COM }
7467697SMichael.Christensen@Sun.COM if (hdlsp) {
7477697SMichael.Christensen@Sun.COM DS_FREE(hdlsp, maxhdls * sizeof (*hdlsp));
7487697SMichael.Christensen@Sun.COM }
7497697SMichael.Christensen@Sun.COM
7507697SMichael.Christensen@Sun.COM nhdls_arg = nhdls;
7517697SMichael.Christensen@Sun.COM if (ddi_copyout(&nhdls_arg, ARGTOPTR(vlds_arg.vlds_nhdlsp),
7527697SMichael.Christensen@Sun.COM sizeof (nhdls_arg), mode) != 0) {
7537697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: HDL_LOOKUP copyout of nhdls "
7547697SMichael.Christensen@Sun.COM " failed", __func__);
7557697SMichael.Christensen@Sun.COM return (EFAULT);
7567697SMichael.Christensen@Sun.COM }
7577697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: HDL_LOOKUP succeeded: nhdls: %d",
7587697SMichael.Christensen@Sun.COM __func__, nhdls);
7597697SMichael.Christensen@Sun.COM break;
7607697SMichael.Christensen@Sun.COM }
7617697SMichael.Christensen@Sun.COM
7627697SMichael.Christensen@Sun.COM case VLDS_DMN_LOOKUP:
7637697SMichael.Christensen@Sun.COM {
7647697SMichael.Christensen@Sun.COM vlds_dmn_lookup_arg_t vlds_arg;
7657697SMichael.Christensen@Sun.COM uint64_t dhdl_arg;
7667697SMichael.Christensen@Sun.COM
7677697SMichael.Christensen@Sun.COM if (ddi_copyin((void *)arg, &vlds_arg, sizeof (vlds_arg),
7687697SMichael.Christensen@Sun.COM mode) != 0) {
7697697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: DMN_LOOKUP arg copyin failed",
7707697SMichael.Christensen@Sun.COM __func__);
7717697SMichael.Christensen@Sun.COM return (EFAULT);
7727697SMichael.Christensen@Sun.COM }
7737697SMichael.Christensen@Sun.COM
7747697SMichael.Christensen@Sun.COM hdl = vlds_arg.vlds_hdl;
7757697SMichael.Christensen@Sun.COM
7767697SMichael.Christensen@Sun.COM if ((rv = ds_domain_lookup(hdl, &dhdl)) != 0) {
7777697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: DMN_LOOKUP lookup hdl: 0x%lx "
7787697SMichael.Christensen@Sun.COM "failed (%d)", __func__, hdl, rv);
7797697SMichael.Christensen@Sun.COM return (rv);
7807697SMichael.Christensen@Sun.COM }
7817697SMichael.Christensen@Sun.COM
7827697SMichael.Christensen@Sun.COM dhdl_arg = dhdl;
7837697SMichael.Christensen@Sun.COM
7847697SMichael.Christensen@Sun.COM if (ddi_copyout(&dhdl_arg, ARGTOPTR(vlds_arg.vlds_dhdlp),
7857697SMichael.Christensen@Sun.COM sizeof (dhdl_arg), mode) != 0) {
7867697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: DMN_LOOKUP copyout "
7877697SMichael.Christensen@Sun.COM "failed (%d)", __func__, rv);
7887697SMichael.Christensen@Sun.COM return (rv);
7897697SMichael.Christensen@Sun.COM }
7907697SMichael.Christensen@Sun.COM
7917697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: DMN_LOOKUP hdl: 0x%lx, dhdl: 0x%lx "
7927697SMichael.Christensen@Sun.COM "succeeded", __func__, hdl, dhdl);
7937697SMichael.Christensen@Sun.COM break;
7947697SMichael.Christensen@Sun.COM }
7957697SMichael.Christensen@Sun.COM
7967697SMichael.Christensen@Sun.COM case VLDS_SEND_MSG:
7977697SMichael.Christensen@Sun.COM {
7987697SMichael.Christensen@Sun.COM vlds_send_msg_arg_t vlds_arg;
7997697SMichael.Christensen@Sun.COM size_t buflen;
8007697SMichael.Christensen@Sun.COM char *bufp;
8017697SMichael.Christensen@Sun.COM
8027697SMichael.Christensen@Sun.COM if (ddi_copyin((void *)arg, &vlds_arg, sizeof (vlds_arg),
8037697SMichael.Christensen@Sun.COM mode) != 0) {
8047697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: SEND_MSG arg copyin failed",
8057697SMichael.Christensen@Sun.COM __func__);
8067697SMichael.Christensen@Sun.COM return (EFAULT);
8077697SMichael.Christensen@Sun.COM }
8087697SMichael.Christensen@Sun.COM
8097697SMichael.Christensen@Sun.COM hdl = vlds_arg.vlds_hdl;
8107697SMichael.Christensen@Sun.COM if ((rv = ds_is_my_hdl(hdl, minor)) != 0) {
8117697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: SEND_MSG ds_is_my_hdl "
8127697SMichael.Christensen@Sun.COM " hdl: %lx inst: %d failed (%d)", __func__,
8137697SMichael.Christensen@Sun.COM hdl, rv, minor);
8147697SMichael.Christensen@Sun.COM return (rv);
8157697SMichael.Christensen@Sun.COM }
8167697SMichael.Christensen@Sun.COM
8177697SMichael.Christensen@Sun.COM buflen = ARGTOUINT(vlds_arg.vlds_buflen);
8187697SMichael.Christensen@Sun.COM bufp = DS_MALLOC(buflen);
8197697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: SEND_MSG (hdl: %lx, bufp: %p, "
8207697SMichael.Christensen@Sun.COM "buflen: %ld", __func__, hdl, ARGTOPTR(vlds_arg.vlds_bufp),
8217697SMichael.Christensen@Sun.COM buflen);
8227697SMichael.Christensen@Sun.COM
8237697SMichael.Christensen@Sun.COM if (ddi_copyin(ARGTOPTR(vlds_arg.vlds_bufp), bufp, buflen,
8247697SMichael.Christensen@Sun.COM mode) != 0) {
8257697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: SEND_MSG buf (%p, %ld) "
8267697SMichael.Christensen@Sun.COM "copyin failed", __func__,
8277697SMichael.Christensen@Sun.COM ARGTOPTR(vlds_arg.vlds_bufp), buflen);
8287697SMichael.Christensen@Sun.COM DS_FREE(bufp, buflen);
8297697SMichael.Christensen@Sun.COM return (EFAULT);
8307697SMichael.Christensen@Sun.COM }
8317697SMichael.Christensen@Sun.COM
8327697SMichael.Christensen@Sun.COM if ((rv = ds_cap_send(hdl, bufp, buflen)) != 0) {
8337697SMichael.Christensen@Sun.COM DS_FREE(bufp, buflen);
8347697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: SEND_MSG ds_cap_send failed "
8357697SMichael.Christensen@Sun.COM "(%d)", __func__, rv);
8367697SMichael.Christensen@Sun.COM return (rv);
8377697SMichael.Christensen@Sun.COM }
8387697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: SEND_MSG hdl: %lx, bufp: %p, "
8397697SMichael.Christensen@Sun.COM "buflen: %ld succeeded", __func__, hdl, (void *)bufp,
8407697SMichael.Christensen@Sun.COM buflen);
8417697SMichael.Christensen@Sun.COM DS_DUMP_MSG(DS_DBG_FLAG_VLDS, bufp, buflen);
8427697SMichael.Christensen@Sun.COM DS_FREE(bufp, buflen);
8437697SMichael.Christensen@Sun.COM break;
8447697SMichael.Christensen@Sun.COM }
8457697SMichael.Christensen@Sun.COM
8467697SMichael.Christensen@Sun.COM case VLDS_RECV_MSG:
8477697SMichael.Christensen@Sun.COM {
8487697SMichael.Christensen@Sun.COM vlds_recv_msg_arg_t vlds_arg;
8497697SMichael.Christensen@Sun.COM size_t buflen, msglen;
8507697SMichael.Christensen@Sun.COM uint64_t msglen_arg;
8517697SMichael.Christensen@Sun.COM
8527697SMichael.Christensen@Sun.COM if (ddi_copyin((void *)arg, &vlds_arg, sizeof (vlds_arg),
8537697SMichael.Christensen@Sun.COM mode) != 0) {
8547697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: RECV_MSG arg copyin failed",
8557697SMichael.Christensen@Sun.COM __func__);
8567697SMichael.Christensen@Sun.COM return (EFAULT);
8577697SMichael.Christensen@Sun.COM }
8587697SMichael.Christensen@Sun.COM
8597697SMichael.Christensen@Sun.COM hdl = vlds_arg.vlds_hdl;
8607697SMichael.Christensen@Sun.COM if ((rv = ds_is_my_hdl(hdl, minor)) != 0) {
8617697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: RECV_MSG ds_is_my_hdl "
8627697SMichael.Christensen@Sun.COM " hdl: %lx inst: %d failed (%d)", __func__,
8637697SMichael.Christensen@Sun.COM hdl, rv, minor);
8647697SMichael.Christensen@Sun.COM return (rv);
8657697SMichael.Christensen@Sun.COM }
8667697SMichael.Christensen@Sun.COM
8677697SMichael.Christensen@Sun.COM buflen = ARGTOUINT(vlds_arg.vlds_buflen);
8687697SMichael.Christensen@Sun.COM
8697697SMichael.Christensen@Sun.COM if ((rv = vlds_recv_msg(hdl, ARGTOPTR(vlds_arg.vlds_bufp),
8707697SMichael.Christensen@Sun.COM buflen, &msglen, mode)) != 0 && rv != EFBIG) {
8717697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: RECV_MSG vlds_recv_msg "
8727697SMichael.Christensen@Sun.COM " failed (%d)", __func__, rv);
8737697SMichael.Christensen@Sun.COM return (rv);
8747697SMichael.Christensen@Sun.COM }
8757697SMichael.Christensen@Sun.COM
8767697SMichael.Christensen@Sun.COM msglen_arg = msglen;
8777697SMichael.Christensen@Sun.COM if (ddi_copyout(&msglen_arg, ARGTOPTR(vlds_arg.vlds_msglenp),
8787697SMichael.Christensen@Sun.COM sizeof (msglen_arg), mode) != 0) {
8797697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: RECV_MSG copyout of msglen "
8807697SMichael.Christensen@Sun.COM "failed", __func__);
8817697SMichael.Christensen@Sun.COM return (EFAULT);
8827697SMichael.Christensen@Sun.COM }
8837697SMichael.Christensen@Sun.COM
8847697SMichael.Christensen@Sun.COM if (rv == EFBIG) {
8857697SMichael.Christensen@Sun.COM return (EFBIG);
8867697SMichael.Christensen@Sun.COM }
8877697SMichael.Christensen@Sun.COM
8887697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: RECV_MSG hdl: %lx, "
8897697SMichael.Christensen@Sun.COM "msglen: %ld succeeded", __func__, hdl, buflen);
8907697SMichael.Christensen@Sun.COM break;
8917697SMichael.Christensen@Sun.COM }
8927697SMichael.Christensen@Sun.COM
8937697SMichael.Christensen@Sun.COM case VLDS_HDL_ISREADY:
8947697SMichael.Christensen@Sun.COM {
8957697SMichael.Christensen@Sun.COM vlds_hdl_isready_arg_t vlds_arg;
8967697SMichael.Christensen@Sun.COM ds_svc_hdl_t hdl;
8977697SMichael.Christensen@Sun.COM uint64_t is_ready_arg;
8987697SMichael.Christensen@Sun.COM uint_t is_ready;
8997697SMichael.Christensen@Sun.COM
9007697SMichael.Christensen@Sun.COM if (ddi_copyin((void *)arg, &vlds_arg, sizeof (vlds_arg),
9017697SMichael.Christensen@Sun.COM mode) != 0) {
9027697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: HDL_ISREADY arg copyin "
9037697SMichael.Christensen@Sun.COM "failed", __func__);
9047697SMichael.Christensen@Sun.COM return (EFAULT);
9057697SMichael.Christensen@Sun.COM }
9067697SMichael.Christensen@Sun.COM
9077697SMichael.Christensen@Sun.COM hdl = vlds_arg.vlds_hdl;
9087697SMichael.Christensen@Sun.COM if ((rv = ds_hdl_isready(hdl, &is_ready)) != 0) {
9097697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: HDL_ISREADY ds_hdl_isready "
9107697SMichael.Christensen@Sun.COM "error (%d)", __func__, rv);
9117697SMichael.Christensen@Sun.COM return (rv);
9127697SMichael.Christensen@Sun.COM }
9137697SMichael.Christensen@Sun.COM
9147697SMichael.Christensen@Sun.COM is_ready_arg = is_ready;
9157697SMichael.Christensen@Sun.COM if (ddi_copyout(&is_ready_arg, ARGTOPTR(vlds_arg.vlds_isreadyp),
9167697SMichael.Christensen@Sun.COM sizeof (is_ready_arg), mode) != 0) {
9177697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: HDL_ISREADY copyout of "
9187697SMichael.Christensen@Sun.COM "vlds_isready failed", __func__);
9197697SMichael.Christensen@Sun.COM return (EFAULT);
9207697SMichael.Christensen@Sun.COM }
9217697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: HDL_ISREADY succeeded hdl: %lx, "
9227697SMichael.Christensen@Sun.COM "is_ready: %d", __func__, hdl, is_ready);
9237697SMichael.Christensen@Sun.COM break;
9247697SMichael.Christensen@Sun.COM }
9257697SMichael.Christensen@Sun.COM
9267697SMichael.Christensen@Sun.COM case VLDS_DOM_NAM2HDL:
9277697SMichael.Christensen@Sun.COM {
9287697SMichael.Christensen@Sun.COM vlds_dom_nam2hdl_arg_t vlds_arg;
9297697SMichael.Christensen@Sun.COM char *domain_name;
9307697SMichael.Christensen@Sun.COM uint64_t dhdl_arg;
9317697SMichael.Christensen@Sun.COM ds_domain_hdl_t dhdl;
9327697SMichael.Christensen@Sun.COM
9337697SMichael.Christensen@Sun.COM if (ddi_copyin((void *)arg, &vlds_arg, sizeof (vlds_arg),
9347697SMichael.Christensen@Sun.COM mode) != 0) {
9357697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: DOM_NAM2HDL arg copyin "
9367697SMichael.Christensen@Sun.COM "failed", __func__);
9377697SMichael.Christensen@Sun.COM return (EFAULT);
9387697SMichael.Christensen@Sun.COM }
9397697SMichael.Christensen@Sun.COM
9407697SMichael.Christensen@Sun.COM if ((rv = vlds_get_string(&vlds_arg.vlds_domain_name,
9417697SMichael.Christensen@Sun.COM &domain_name, mode)) != 0) {
9427697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: DOM_NAM2HDL vlds_get_string "
9437697SMichael.Christensen@Sun.COM "domain_name failed (%d)", __func__, rv);
9447697SMichael.Christensen@Sun.COM return (EFAULT);
9457697SMichael.Christensen@Sun.COM } else if (servicep == NULL) {
9467697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: DOM_NAM2HDL vlds_get_string "
9477697SMichael.Christensen@Sun.COM " domain_name is NULL", __func__);
9487697SMichael.Christensen@Sun.COM return (EINVAL);
9497697SMichael.Christensen@Sun.COM }
9507697SMichael.Christensen@Sun.COM
9517697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: DOM_NAM2HDL (%s) entered", __func__,
9527697SMichael.Christensen@Sun.COM domain_name);
9537697SMichael.Christensen@Sun.COM
9547697SMichael.Christensen@Sun.COM if ((rv = ds_dom_name_to_hdl(domain_name, &dhdl)) != 0) {
9557697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: DOM_NAM2HDL name: '%s' "
9567697SMichael.Christensen@Sun.COM "failed: (%d)", __func__, domain_name, rv);
9577697SMichael.Christensen@Sun.COM DS_FREE(domain_name, strlen(domain_name) + 1);
9587697SMichael.Christensen@Sun.COM return (rv);
9597697SMichael.Christensen@Sun.COM }
9607697SMichael.Christensen@Sun.COM
9617697SMichael.Christensen@Sun.COM dhdl_arg = dhdl;
9627697SMichael.Christensen@Sun.COM if (ddi_copyout(&dhdl_arg, ARGTOPTR(vlds_arg.vlds_dhdlp),
9637697SMichael.Christensen@Sun.COM sizeof (dhdl_arg), mode) != 0) {
9647697SMichael.Christensen@Sun.COM DS_FREE(domain_name, strlen(domain_name) + 1);
9657697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: DOM_NAM2HDL copyout of dhdl "
9667697SMichael.Christensen@Sun.COM " failed", __func__);
9677697SMichael.Christensen@Sun.COM return (EFAULT);
9687697SMichael.Christensen@Sun.COM }
9697697SMichael.Christensen@Sun.COM
9707697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: DOM_NAM2HDL succeeded: name: '%s', "
9717697SMichael.Christensen@Sun.COM "dhdl: 0x%lx", __func__, domain_name, dhdl);
9727697SMichael.Christensen@Sun.COM DS_FREE(domain_name, strlen(domain_name) + 1);
9737697SMichael.Christensen@Sun.COM break;
9747697SMichael.Christensen@Sun.COM }
9757697SMichael.Christensen@Sun.COM
9767697SMichael.Christensen@Sun.COM case VLDS_DOM_HDL2NAM:
9777697SMichael.Christensen@Sun.COM {
9787697SMichael.Christensen@Sun.COM vlds_dom_hdl2nam_arg_t vlds_arg;
9797697SMichael.Christensen@Sun.COM ds_domain_hdl_t dhdl;
9807697SMichael.Christensen@Sun.COM char *domain_name;
9817697SMichael.Christensen@Sun.COM
9827697SMichael.Christensen@Sun.COM if (ddi_copyin((void *)arg, &vlds_arg, sizeof (vlds_arg),
9837697SMichael.Christensen@Sun.COM mode) != 0) {
9847697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: DOM_HDL2NAM arg copyin "
9857697SMichael.Christensen@Sun.COM "failed", __func__);
9867697SMichael.Christensen@Sun.COM return (EFAULT);
9877697SMichael.Christensen@Sun.COM }
9887697SMichael.Christensen@Sun.COM
9897697SMichael.Christensen@Sun.COM dhdl = vlds_arg.vlds_dhdl;
9908172SMichael.Christensen@Sun.COM if ((rv = ds_dom_hdl_to_name(dhdl, &domain_name)) != 0) {
9917697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: DOM_HDL2NAM lookup dhdl: %lx "
9927697SMichael.Christensen@Sun.COM "failed (%d)", __func__, dhdl, rv);
9937697SMichael.Christensen@Sun.COM return (rv);
9947697SMichael.Christensen@Sun.COM }
9957697SMichael.Christensen@Sun.COM
9967697SMichael.Christensen@Sun.COM if ((rv = vlds_put_string(domain_name,
9977697SMichael.Christensen@Sun.COM &vlds_arg.vlds_domain_name, mode)) != 0) {
9987697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: DOM_HDL2NAM vlds_put_string "
9997697SMichael.Christensen@Sun.COM "'%s' failed (%d)", __func__, domain_name, rv);
10007697SMichael.Christensen@Sun.COM return (rv);
10017697SMichael.Christensen@Sun.COM }
10027697SMichael.Christensen@Sun.COM
10037697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: DOM_HDL2NAM dhdl: 0x%lx name: '%s'",
10047697SMichael.Christensen@Sun.COM __func__, dhdl, domain_name);
10057697SMichael.Christensen@Sun.COM break;
10067697SMichael.Christensen@Sun.COM }
10077697SMichael.Christensen@Sun.COM
10087697SMichael.Christensen@Sun.COM default:
10097697SMichael.Christensen@Sun.COM return (EINVAL);
10107697SMichael.Christensen@Sun.COM }
10117697SMichael.Christensen@Sun.COM return (0);
10127697SMichael.Christensen@Sun.COM }
10137697SMichael.Christensen@Sun.COM
10147697SMichael.Christensen@Sun.COM static uint_t
vlds_flags_to_svc(uint64_t flags)10157697SMichael.Christensen@Sun.COM vlds_flags_to_svc(uint64_t flags)
10167697SMichael.Christensen@Sun.COM {
10177697SMichael.Christensen@Sun.COM uint_t sflags = 0;
10187697SMichael.Christensen@Sun.COM
10197697SMichael.Christensen@Sun.COM if (flags & VLDS_REG_CLIENT)
10207697SMichael.Christensen@Sun.COM sflags |= DSSF_ISCLIENT;
10217697SMichael.Christensen@Sun.COM if (flags & VLDS_REGCB_VALID)
10227697SMichael.Christensen@Sun.COM sflags |= DSSF_REGCB_VALID;
10237697SMichael.Christensen@Sun.COM if (flags & VLDS_UNREGCB_VALID)
10247697SMichael.Christensen@Sun.COM sflags |= DSSF_UNREGCB_VALID;
10257697SMichael.Christensen@Sun.COM if (flags & VLDS_DATACB_VALID)
10267697SMichael.Christensen@Sun.COM sflags |= DSSF_DATACB_VALID;
10277697SMichael.Christensen@Sun.COM return (sflags);
10287697SMichael.Christensen@Sun.COM }
10297697SMichael.Christensen@Sun.COM
10307697SMichael.Christensen@Sun.COM /*
10317697SMichael.Christensen@Sun.COM * MD registration code.
10327697SMichael.Christensen@Sun.COM * Placed in vlds rather than ds module due to cirular dependency of
10337697SMichael.Christensen@Sun.COM * platsvc module which contains the mdeg code.
10347697SMichael.Christensen@Sun.COM */
10358172SMichael.Christensen@Sun.COM mdeg_handle_t vlds_mdeg_hdl;
10367697SMichael.Christensen@Sun.COM
10377697SMichael.Christensen@Sun.COM /*
10388172SMichael.Christensen@Sun.COM * Look for "virtual-device-service" node among the
10398172SMichael.Christensen@Sun.COM * "virtual-device" nodes.
10407697SMichael.Christensen@Sun.COM */
10418172SMichael.Christensen@Sun.COM static mdeg_prop_spec_t vlds_prop_template[] = {
10428172SMichael.Christensen@Sun.COM { MDET_PROP_STR, "name", VLDS_MD_VIRT_ROOT_NAME },
10438172SMichael.Christensen@Sun.COM { MDET_LIST_END, NULL, NULL }
10447697SMichael.Christensen@Sun.COM };
10457697SMichael.Christensen@Sun.COM
10468172SMichael.Christensen@Sun.COM static mdeg_node_spec_t vlds_node_template =
10478172SMichael.Christensen@Sun.COM { VLDS_MD_VIRT_DEV_NAME, vlds_prop_template };
10487697SMichael.Christensen@Sun.COM
10497697SMichael.Christensen@Sun.COM /*
10507697SMichael.Christensen@Sun.COM * Matching criteria passed to the MDEG to register interest
10517697SMichael.Christensen@Sun.COM * in changes to domain services port nodes identified by their
10527697SMichael.Christensen@Sun.COM * 'id' property.
10537697SMichael.Christensen@Sun.COM */
10548172SMichael.Christensen@Sun.COM static md_prop_match_t vlds_port_prop_match[] = {
10557697SMichael.Christensen@Sun.COM { MDET_PROP_VAL, "id" },
10567697SMichael.Christensen@Sun.COM { MDET_LIST_END, NULL }
10577697SMichael.Christensen@Sun.COM };
10587697SMichael.Christensen@Sun.COM
10598172SMichael.Christensen@Sun.COM static mdeg_node_match_t vlds_port_match = { VLDS_MD_VIRT_PORT_NAME,
10608172SMichael.Christensen@Sun.COM vlds_port_prop_match };
10617697SMichael.Christensen@Sun.COM
10627697SMichael.Christensen@Sun.COM /* mdeg callback */
10637697SMichael.Christensen@Sun.COM static int
vlds_mdeg_cb(void * cb_argp,mdeg_result_t * resp)10648172SMichael.Christensen@Sun.COM vlds_mdeg_cb(void *cb_argp, mdeg_result_t *resp)
10657697SMichael.Christensen@Sun.COM {
10667697SMichael.Christensen@Sun.COM _NOTE(ARGUNUSED(cb_argp))
10677697SMichael.Christensen@Sun.COM int idx;
10687697SMichael.Christensen@Sun.COM uint64_t portno;
10697697SMichael.Christensen@Sun.COM int rv;
10707697SMichael.Christensen@Sun.COM md_t *mdp;
10717697SMichael.Christensen@Sun.COM mde_cookie_t node;
10727697SMichael.Christensen@Sun.COM
10737697SMichael.Christensen@Sun.COM if (resp == NULL) {
10748172SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "vlds_mdeg_cb: no result returned");
10757697SMichael.Christensen@Sun.COM return (MDEG_FAILURE);
10767697SMichael.Christensen@Sun.COM }
10777697SMichael.Christensen@Sun.COM
10787697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: added=%d, removed=%d, matched=%d", __func__,
10797697SMichael.Christensen@Sun.COM resp->added.nelem, resp->removed.nelem, resp->match_prev.nelem);
10807697SMichael.Christensen@Sun.COM
10817697SMichael.Christensen@Sun.COM /* process added ports */
10827697SMichael.Christensen@Sun.COM for (idx = 0; idx < resp->added.nelem; idx++) {
10837697SMichael.Christensen@Sun.COM mdp = resp->added.mdp;
10847697SMichael.Christensen@Sun.COM node = resp->added.mdep[idx];
10857697SMichael.Christensen@Sun.COM
10867697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: processing added node 0x%lx",
10877697SMichael.Christensen@Sun.COM __func__, node);
10887697SMichael.Christensen@Sun.COM
10897697SMichael.Christensen@Sun.COM /* attempt to add a port */
10908172SMichael.Christensen@Sun.COM if ((rv = vlds_add_mdeg_port(mdp, node)) != MDEG_SUCCESS) {
10917697SMichael.Christensen@Sun.COM if (vlds_ports_inited) {
10927697SMichael.Christensen@Sun.COM cmn_err(CE_NOTE, "%s: unable to add port, "
10937697SMichael.Christensen@Sun.COM "err = %d", __func__, rv);
10947697SMichael.Christensen@Sun.COM }
10957697SMichael.Christensen@Sun.COM }
10967697SMichael.Christensen@Sun.COM }
10977697SMichael.Christensen@Sun.COM
10987697SMichael.Christensen@Sun.COM /* process removed ports */
10997697SMichael.Christensen@Sun.COM for (idx = 0; idx < resp->removed.nelem; idx++) {
11007697SMichael.Christensen@Sun.COM mdp = resp->removed.mdp;
11017697SMichael.Christensen@Sun.COM node = resp->removed.mdep[idx];
11027697SMichael.Christensen@Sun.COM
11037697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: processing removed node 0x%lx",
11047697SMichael.Christensen@Sun.COM __func__, node);
11057697SMichael.Christensen@Sun.COM
11067697SMichael.Christensen@Sun.COM /* read in the port's id property */
11077697SMichael.Christensen@Sun.COM if (md_get_prop_val(mdp, node, "id", &portno)) {
11087697SMichael.Christensen@Sun.COM cmn_err(CE_NOTE, "%s: node 0x%lx of removed list "
11097697SMichael.Christensen@Sun.COM "has no 'id' property", __func__, node);
11107697SMichael.Christensen@Sun.COM continue;
11117697SMichael.Christensen@Sun.COM }
11127697SMichael.Christensen@Sun.COM
11137697SMichael.Christensen@Sun.COM /* attempt to remove a port */
11147697SMichael.Christensen@Sun.COM if ((rv = ds_remove_port(portno, 0)) != 0) {
11157697SMichael.Christensen@Sun.COM cmn_err(CE_NOTE, "%s: unable to remove port %lu, "
11167697SMichael.Christensen@Sun.COM " err %d", __func__, portno, rv);
11177697SMichael.Christensen@Sun.COM }
11187697SMichael.Christensen@Sun.COM }
11197697SMichael.Christensen@Sun.COM
11207697SMichael.Christensen@Sun.COM vlds_ports_inited = 1;
11217697SMichael.Christensen@Sun.COM
11227697SMichael.Christensen@Sun.COM return (MDEG_SUCCESS);
11237697SMichael.Christensen@Sun.COM }
11247697SMichael.Christensen@Sun.COM
11257697SMichael.Christensen@Sun.COM /* register callback to mdeg */
11267697SMichael.Christensen@Sun.COM static int
vlds_mdeg_register(void)11278172SMichael.Christensen@Sun.COM vlds_mdeg_register(void)
11287697SMichael.Christensen@Sun.COM {
11297697SMichael.Christensen@Sun.COM int rv;
11307697SMichael.Christensen@Sun.COM
11318172SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "vlds_mdeg_register: entered");
11327697SMichael.Christensen@Sun.COM
11337697SMichael.Christensen@Sun.COM /* perform the registration */
11348172SMichael.Christensen@Sun.COM rv = mdeg_register(&vlds_node_template, &vlds_port_match, vlds_mdeg_cb,
11358172SMichael.Christensen@Sun.COM NULL, &vlds_mdeg_hdl);
11367697SMichael.Christensen@Sun.COM
11377697SMichael.Christensen@Sun.COM if (rv != MDEG_SUCCESS) {
11388172SMichael.Christensen@Sun.COM cmn_err(CE_NOTE, "vlds_mdeg_register: mdeg_register "
11397697SMichael.Christensen@Sun.COM "failed, err = %d", rv);
11407697SMichael.Christensen@Sun.COM return (DDI_FAILURE);
11417697SMichael.Christensen@Sun.COM }
11427697SMichael.Christensen@Sun.COM
11437697SMichael.Christensen@Sun.COM return (DDI_SUCCESS);
11447697SMichael.Christensen@Sun.COM }
11457697SMichael.Christensen@Sun.COM
11467697SMichael.Christensen@Sun.COM /* unregister callback from mdeg */
11477697SMichael.Christensen@Sun.COM static int
vlds_mdeg_unregister(void)11488172SMichael.Christensen@Sun.COM vlds_mdeg_unregister(void)
11497697SMichael.Christensen@Sun.COM {
11508172SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "vlds_mdeg_unregister: hdl=0x%lx", vlds_mdeg_hdl);
11517697SMichael.Christensen@Sun.COM
11528172SMichael.Christensen@Sun.COM return (mdeg_unregister(vlds_mdeg_hdl));
11537697SMichael.Christensen@Sun.COM }
11547697SMichael.Christensen@Sun.COM
11557697SMichael.Christensen@Sun.COM static int
vlds_get_port_channel(md_t * mdp,mde_cookie_t node,uint64_t * ldc_id)11568172SMichael.Christensen@Sun.COM vlds_get_port_channel(md_t *mdp, mde_cookie_t node, uint64_t *ldc_id)
11577697SMichael.Christensen@Sun.COM {
11587697SMichael.Christensen@Sun.COM int num_nodes, nchan;
11597697SMichael.Christensen@Sun.COM size_t listsz;
11607697SMichael.Christensen@Sun.COM mde_cookie_t *listp;
11617697SMichael.Christensen@Sun.COM
11627697SMichael.Christensen@Sun.COM /*
11637697SMichael.Christensen@Sun.COM * Find the channel-endpoint node(s) (which should be under this
11647697SMichael.Christensen@Sun.COM * port node) which contain the channel id(s).
11657697SMichael.Christensen@Sun.COM */
11667697SMichael.Christensen@Sun.COM if ((num_nodes = md_node_count(mdp)) <= 0) {
11677697SMichael.Christensen@Sun.COM cmn_err(CE_NOTE, "%s: invalid number of channel-endpoint nodes "
11687697SMichael.Christensen@Sun.COM "found (%d)", __func__, num_nodes);
11697697SMichael.Christensen@Sun.COM return (-1);
11707697SMichael.Christensen@Sun.COM }
11717697SMichael.Christensen@Sun.COM
11727697SMichael.Christensen@Sun.COM /* allocate space for node list */
11737697SMichael.Christensen@Sun.COM listsz = num_nodes * sizeof (mde_cookie_t);
11747697SMichael.Christensen@Sun.COM listp = kmem_alloc(listsz, KM_SLEEP);
11757697SMichael.Christensen@Sun.COM
11767697SMichael.Christensen@Sun.COM nchan = md_scan_dag(mdp, node, md_find_name(mdp, "channel-endpoint"),
11777697SMichael.Christensen@Sun.COM md_find_name(mdp, "fwd"), listp);
11787697SMichael.Christensen@Sun.COM
11797697SMichael.Christensen@Sun.COM if (nchan <= 0) {
11807697SMichael.Christensen@Sun.COM cmn_err(CE_NOTE, "%s: no channel-endpoint nodes found",
11817697SMichael.Christensen@Sun.COM __func__);
11827697SMichael.Christensen@Sun.COM kmem_free(listp, listsz);
11837697SMichael.Christensen@Sun.COM return (-1);
11847697SMichael.Christensen@Sun.COM }
11857697SMichael.Christensen@Sun.COM
11867697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: %d channel-endpoint nodes found", __func__,
11877697SMichael.Christensen@Sun.COM nchan);
11887697SMichael.Christensen@Sun.COM
11897697SMichael.Christensen@Sun.COM /* use property from first node found */
11907697SMichael.Christensen@Sun.COM if (md_get_prop_val(mdp, listp[0], "id", ldc_id)) {
11917697SMichael.Christensen@Sun.COM cmn_err(CE_NOTE, "%s: channel-endpoint has no 'id' property",
11927697SMichael.Christensen@Sun.COM __func__);
11937697SMichael.Christensen@Sun.COM kmem_free(listp, listsz);
11947697SMichael.Christensen@Sun.COM return (-1);
11957697SMichael.Christensen@Sun.COM }
11967697SMichael.Christensen@Sun.COM
11977697SMichael.Christensen@Sun.COM kmem_free(listp, listsz);
11987697SMichael.Christensen@Sun.COM
11997697SMichael.Christensen@Sun.COM return (0);
12007697SMichael.Christensen@Sun.COM }
12017697SMichael.Christensen@Sun.COM
12027697SMichael.Christensen@Sun.COM /* add a DS services port */
12037697SMichael.Christensen@Sun.COM static int
vlds_add_mdeg_port(md_t * mdp,mde_cookie_t node)12048172SMichael.Christensen@Sun.COM vlds_add_mdeg_port(md_t *mdp, mde_cookie_t node)
12057697SMichael.Christensen@Sun.COM {
12067697SMichael.Christensen@Sun.COM uint64_t portno;
12077697SMichael.Christensen@Sun.COM uint64_t ldc_id;
12087697SMichael.Christensen@Sun.COM int rv;
12097697SMichael.Christensen@Sun.COM uint64_t dhdl;
12107697SMichael.Christensen@Sun.COM char *dom_name;
12117697SMichael.Christensen@Sun.COM
12127697SMichael.Christensen@Sun.COM /* read in the port's id property */
12137697SMichael.Christensen@Sun.COM if (md_get_prop_val(mdp, node, "id", &portno)) {
12147697SMichael.Christensen@Sun.COM cmn_err(CE_NOTE, "%s: node 0x%lx of added list has no "
12157697SMichael.Christensen@Sun.COM "'id' property", __func__, node);
12167697SMichael.Christensen@Sun.COM return (MDEG_FAILURE);
12177697SMichael.Christensen@Sun.COM }
12187697SMichael.Christensen@Sun.COM
12197697SMichael.Christensen@Sun.COM if (portno >= DS_MAX_PORTS) {
12207697SMichael.Christensen@Sun.COM cmn_err(CE_NOTE, "%s: found port number (%lu) "
12217697SMichael.Christensen@Sun.COM "larger than maximum supported number of ports", __func__,
12227697SMichael.Christensen@Sun.COM portno);
12237697SMichael.Christensen@Sun.COM return (MDEG_FAILURE);
12247697SMichael.Christensen@Sun.COM }
12257697SMichael.Christensen@Sun.COM
12267697SMichael.Christensen@Sun.COM /* get all channels for this device (currently only one) */
12278172SMichael.Christensen@Sun.COM if (vlds_get_port_channel(mdp, node, &ldc_id) == -1) {
12287697SMichael.Christensen@Sun.COM return (MDEG_FAILURE);
12297697SMichael.Christensen@Sun.COM }
12307697SMichael.Christensen@Sun.COM
12318172SMichael.Christensen@Sun.COM if (md_get_prop_val(mdp, node, VLDS_MD_REM_DOMAIN_HDL, &dhdl) != 0) {
12328172SMichael.Christensen@Sun.COM cmn_err(CE_NOTE, "!ds%lx: %s no %s property", portno, __func__,
12338172SMichael.Christensen@Sun.COM VLDS_MD_REM_DOMAIN_HDL);
12347697SMichael.Christensen@Sun.COM dhdl = DS_DHDL_INVALID;
12357697SMichael.Christensen@Sun.COM }
12367697SMichael.Christensen@Sun.COM
12378172SMichael.Christensen@Sun.COM if (md_get_prop_str(mdp, node, VLDS_MD_REM_DOMAIN_NAME, &dom_name)
12388172SMichael.Christensen@Sun.COM != 0) {
12398172SMichael.Christensen@Sun.COM cmn_err(CE_NOTE, "!ds%lx: %s no %s property", portno, __func__,
12408172SMichael.Christensen@Sun.COM VLDS_MD_REM_DOMAIN_NAME);
12417697SMichael.Christensen@Sun.COM dom_name = NULL;
12427697SMichael.Christensen@Sun.COM }
12437697SMichael.Christensen@Sun.COM
12447697SMichael.Christensen@Sun.COM rv = ds_add_port(portno, ldc_id, dhdl, dom_name, vlds_ports_inited);
12457697SMichael.Christensen@Sun.COM
12467697SMichael.Christensen@Sun.COM if (rv != 0) {
12477697SMichael.Christensen@Sun.COM if (vlds_ports_inited) {
12487697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "ds%lx: %s LDC chan: %lx "
12497697SMichael.Christensen@Sun.COM "failed err = %d", portno, __func__, ldc_id, rv);
12507697SMichael.Christensen@Sun.COM }
12517697SMichael.Christensen@Sun.COM return (MDEG_FAILURE);
12527697SMichael.Christensen@Sun.COM }
12537697SMichael.Christensen@Sun.COM
12547697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "ds%lx: %s LDC chan: %lx inited", portno,
12557697SMichael.Christensen@Sun.COM __func__, ldc_id);
12567697SMichael.Christensen@Sun.COM
12577697SMichael.Christensen@Sun.COM return (MDEG_SUCCESS);
12587697SMichael.Christensen@Sun.COM }
12597697SMichael.Christensen@Sun.COM
12607697SMichael.Christensen@Sun.COM static void
vlds_mdeg_init(void)12618172SMichael.Christensen@Sun.COM vlds_mdeg_init(void)
12628172SMichael.Christensen@Sun.COM {
12638172SMichael.Christensen@Sun.COM md_t *mdp;
12648172SMichael.Christensen@Sun.COM int num_nodes;
12658172SMichael.Christensen@Sun.COM int listsz;
12668172SMichael.Christensen@Sun.COM mde_cookie_t rootnode;
12678172SMichael.Christensen@Sun.COM mde_cookie_t vldsnode;
12688172SMichael.Christensen@Sun.COM mde_cookie_t *vlds_nodes = NULL;
12698172SMichael.Christensen@Sun.COM int nvlds;
12708172SMichael.Christensen@Sun.COM int i;
12718172SMichael.Christensen@Sun.COM ds_domain_hdl_t dhdl;
12728172SMichael.Christensen@Sun.COM char *dom_name;
12738172SMichael.Christensen@Sun.COM char *svc_name;
12748172SMichael.Christensen@Sun.COM
12758172SMichael.Christensen@Sun.COM if ((mdp = md_get_handle()) == NULL) {
12768172SMichael.Christensen@Sun.COM cmn_err(CE_NOTE, "Unable to initialize machine description");
12778172SMichael.Christensen@Sun.COM return;
12788172SMichael.Christensen@Sun.COM }
12798172SMichael.Christensen@Sun.COM
12808172SMichael.Christensen@Sun.COM num_nodes = md_node_count(mdp);
12818172SMichael.Christensen@Sun.COM ASSERT(num_nodes > 0);
12828172SMichael.Christensen@Sun.COM
12838172SMichael.Christensen@Sun.COM listsz = num_nodes * sizeof (mde_cookie_t);
12848172SMichael.Christensen@Sun.COM
12858172SMichael.Christensen@Sun.COM /* allocate temporary storage for MD scans */
12868172SMichael.Christensen@Sun.COM vlds_nodes = kmem_zalloc(listsz, KM_SLEEP);
12878172SMichael.Christensen@Sun.COM
12888172SMichael.Christensen@Sun.COM rootnode = md_root_node(mdp);
12898172SMichael.Christensen@Sun.COM ASSERT(rootnode != MDE_INVAL_ELEM_COOKIE);
12908172SMichael.Christensen@Sun.COM
12918172SMichael.Christensen@Sun.COM /*
12928172SMichael.Christensen@Sun.COM * Search for Virtual Domain Service node.
12938172SMichael.Christensen@Sun.COM */
12948172SMichael.Christensen@Sun.COM nvlds = md_scan_dag(mdp, rootnode, md_find_name(mdp,
12958172SMichael.Christensen@Sun.COM VLDS_MD_VIRT_DEV_NAME), md_find_name(mdp, "fwd"), vlds_nodes);
12968172SMichael.Christensen@Sun.COM
12978172SMichael.Christensen@Sun.COM if (nvlds <= 0) {
12988172SMichael.Christensen@Sun.COM DS_DBG_MD(CE_NOTE, "No '%s' nodes in MD",
12998172SMichael.Christensen@Sun.COM VLDS_MD_VIRT_DEV_NAME);
13008172SMichael.Christensen@Sun.COM goto done;
13018172SMichael.Christensen@Sun.COM }
13028172SMichael.Christensen@Sun.COM
13038172SMichael.Christensen@Sun.COM for (i = 0; i < nvlds; i++) {
13048172SMichael.Christensen@Sun.COM if (md_get_prop_str(mdp, vlds_nodes[i], "name", &svc_name)) {
13058172SMichael.Christensen@Sun.COM DS_DBG_MD(CE_NOTE, "%s: missing 'name' property for"
13068172SMichael.Christensen@Sun.COM " IO node %d\n", __func__, i);
13078172SMichael.Christensen@Sun.COM continue;
13088172SMichael.Christensen@Sun.COM }
13098172SMichael.Christensen@Sun.COM
13108172SMichael.Christensen@Sun.COM if (strcmp(svc_name, VLDS_MD_VIRT_ROOT_NAME) == 0) {
13118172SMichael.Christensen@Sun.COM vldsnode = vlds_nodes[i];
13128172SMichael.Christensen@Sun.COM break;
13138172SMichael.Christensen@Sun.COM }
13148172SMichael.Christensen@Sun.COM }
13158172SMichael.Christensen@Sun.COM
13168172SMichael.Christensen@Sun.COM if (i >= nvlds) {
13178172SMichael.Christensen@Sun.COM DS_DBG_MD(CE_NOTE, "No '%s' node in MD",
13188172SMichael.Christensen@Sun.COM VLDS_MD_VIRT_ROOT_NAME);
13198172SMichael.Christensen@Sun.COM goto done;
13208172SMichael.Christensen@Sun.COM }
13218172SMichael.Christensen@Sun.COM
13228172SMichael.Christensen@Sun.COM if (md_get_prop_val(mdp, vldsnode, VLDS_MD_DOMAIN_HDL, &dhdl) != 0) {
13238172SMichael.Christensen@Sun.COM DS_DBG_MD(CE_NOTE, "No '%s' property for '%s' node in MD",
13248172SMichael.Christensen@Sun.COM VLDS_MD_DOMAIN_HDL, VLDS_MD_VIRT_ROOT_NAME);
13258172SMichael.Christensen@Sun.COM dhdl = DS_DHDL_INVALID;
13268172SMichael.Christensen@Sun.COM }
13278172SMichael.Christensen@Sun.COM if (md_get_prop_str(mdp, vldsnode, VLDS_MD_DOMAIN_NAME, &dom_name)
13288172SMichael.Christensen@Sun.COM != 0) {
13298172SMichael.Christensen@Sun.COM DS_DBG_MD(CE_NOTE, "No '%s' property for '%s' node in MD",
13308172SMichael.Christensen@Sun.COM VLDS_MD_DOMAIN_NAME, VLDS_MD_VIRT_ROOT_NAME);
13318172SMichael.Christensen@Sun.COM dom_name = NULL;
13328172SMichael.Christensen@Sun.COM }
13338172SMichael.Christensen@Sun.COM DS_DBG_MD(CE_NOTE, "My Domain Hdl: 0x%lx, Name: '%s'", dhdl,
13348172SMichael.Christensen@Sun.COM dom_name == NULL ? "NULL" : dom_name);
13358172SMichael.Christensen@Sun.COM ds_set_my_dom_hdl_name(dhdl, dom_name);
13368172SMichael.Christensen@Sun.COM
13378172SMichael.Christensen@Sun.COM done:
13388172SMichael.Christensen@Sun.COM DS_FREE(vlds_nodes, listsz);
13398172SMichael.Christensen@Sun.COM
13408172SMichael.Christensen@Sun.COM (void) md_fini_handle(mdp);
13418172SMichael.Christensen@Sun.COM }
13428172SMichael.Christensen@Sun.COM
13438172SMichael.Christensen@Sun.COM static void
vlds_user_reg_cb(ds_cb_arg_t arg,ds_ver_t * ver,ds_svc_hdl_t hdl)13447697SMichael.Christensen@Sun.COM vlds_user_reg_cb(ds_cb_arg_t arg, ds_ver_t *ver, ds_svc_hdl_t hdl)
13457697SMichael.Christensen@Sun.COM {
13467697SMichael.Christensen@Sun.COM nvlist_t *nvl = NULL;
13477697SMichael.Christensen@Sun.COM ds_domain_hdl_t dhdl;
13487697SMichael.Christensen@Sun.COM char *servicep;
13497697SMichael.Christensen@Sun.COM uint32_t flags;
13507697SMichael.Christensen@Sun.COM int minor;
13517697SMichael.Christensen@Sun.COM vlds_state_t *sp;
13527697SMichael.Christensen@Sun.COM vlds_svc_info_t *dpsp;
13537697SMichael.Christensen@Sun.COM
13547697SMichael.Christensen@Sun.COM ds_cbarg_get_flags(arg, &flags);
13557697SMichael.Christensen@Sun.COM ASSERT((flags & DSSF_ISUSER) != 0);
13567697SMichael.Christensen@Sun.COM
13577697SMichael.Christensen@Sun.COM if ((flags & DSSF_DATACB_VALID) == 0) {
13587697SMichael.Christensen@Sun.COM /*
13597697SMichael.Christensen@Sun.COM * must allocate and init the svc read queue.
13607697SMichael.Christensen@Sun.COM */
13617697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: hdl: 0x%lx initing recvq", __func__,
13627697SMichael.Christensen@Sun.COM hdl);
13637697SMichael.Christensen@Sun.COM dpsp = DS_MALLOC(sizeof (vlds_svc_info_t));
13647697SMichael.Christensen@Sun.COM vlds_recvq_init(dpsp);
13657697SMichael.Christensen@Sun.COM ds_cbarg_set_drv_per_svc_ptr(arg, dpsp);
13667697SMichael.Christensen@Sun.COM }
13677697SMichael.Christensen@Sun.COM
13687697SMichael.Christensen@Sun.COM if ((flags & DSSF_REGCB_VALID) != 0) {
13697697SMichael.Christensen@Sun.COM ds_cbarg_get_drv_info(arg, &minor);
13707697SMichael.Christensen@Sun.COM sp = ddi_get_soft_state(vlds_statep, minor);
13717697SMichael.Christensen@Sun.COM ASSERT(sp != NULL);
13727697SMichael.Christensen@Sun.COM ASSERT(sp->evchan != NULL);
13737697SMichael.Christensen@Sun.COM ds_cbarg_get_domain(arg, &dhdl);
13747697SMichael.Christensen@Sun.COM ds_cbarg_get_service_id(arg, &servicep);
13757697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: regcb: hdl: 0x%lx, ver%d.%d, "
13767697SMichael.Christensen@Sun.COM " dhdl: 0x%lx", __func__, hdl, ver->major,
13777697SMichael.Christensen@Sun.COM ver->minor, dhdl);
13787697SMichael.Christensen@Sun.COM if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP) ||
13797697SMichael.Christensen@Sun.COM nvlist_add_uint64(nvl, VLDS_HDL, hdl) ||
13807697SMichael.Christensen@Sun.COM nvlist_add_uint16(nvl, VLDS_VER_MAJOR, ver->major) ||
13817697SMichael.Christensen@Sun.COM nvlist_add_uint16(nvl, VLDS_VER_MINOR, ver->minor) ||
13827697SMichael.Christensen@Sun.COM nvlist_add_uint64(nvl, VLDS_DOMAIN_HDL, dhdl) ||
13837697SMichael.Christensen@Sun.COM nvlist_add_string(nvl, VLDS_SERVICE_ID, servicep) ||
13847697SMichael.Christensen@Sun.COM nvlist_add_boolean_value(nvl, VLDS_ISCLIENT,
13857697SMichael.Christensen@Sun.COM (flags & DSSF_ISCLIENT) != 0) ||
13867697SMichael.Christensen@Sun.COM sysevent_evc_publish(sp->evchan, EC_VLDS,
13877697SMichael.Christensen@Sun.COM ESC_VLDS_REGISTER, "sun.com", "kernel", nvl, EVCH_SLEEP)) {
13887697SMichael.Christensen@Sun.COM cmn_err(CE_WARN, "Failed to send REG Callback");
13897697SMichael.Christensen@Sun.COM } else {
13907697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: sysevent_evc_publish "
13917697SMichael.Christensen@Sun.COM "succeeded", __func__);
13927697SMichael.Christensen@Sun.COM }
13937697SMichael.Christensen@Sun.COM nvlist_free(nvl);
13947697SMichael.Christensen@Sun.COM }
13957697SMichael.Christensen@Sun.COM }
13967697SMichael.Christensen@Sun.COM
13977697SMichael.Christensen@Sun.COM static void
vlds_user_unreg_cb(ds_cb_arg_t arg)13987697SMichael.Christensen@Sun.COM vlds_user_unreg_cb(ds_cb_arg_t arg)
13997697SMichael.Christensen@Sun.COM {
14007697SMichael.Christensen@Sun.COM nvlist_t *nvl = NULL;
14017697SMichael.Christensen@Sun.COM int minor;
14027697SMichael.Christensen@Sun.COM ds_svc_hdl_t hdl;
14037697SMichael.Christensen@Sun.COM vlds_state_t *sp;
14047697SMichael.Christensen@Sun.COM void *dpsp;
14057697SMichael.Christensen@Sun.COM uint32_t flags;
14067697SMichael.Christensen@Sun.COM
14077697SMichael.Christensen@Sun.COM ds_cbarg_get_flags(arg, &flags);
14087697SMichael.Christensen@Sun.COM ASSERT((flags & DSSF_ISUSER) != 0);
14097697SMichael.Christensen@Sun.COM
14107697SMichael.Christensen@Sun.COM if ((flags & DSSF_DATACB_VALID) == 0) {
14117697SMichael.Christensen@Sun.COM ds_cbarg_get_drv_per_svc_ptr(arg, &dpsp);
14127697SMichael.Christensen@Sun.COM if (dpsp) {
14137697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: unregcb draining recvq",
14147697SMichael.Christensen@Sun.COM __func__);
14157697SMichael.Christensen@Sun.COM vlds_recvq_drain(dpsp);
14167697SMichael.Christensen@Sun.COM vlds_recvq_destroy(dpsp);
14177697SMichael.Christensen@Sun.COM ds_cbarg_set_drv_per_svc_ptr(arg, NULL);
14187697SMichael.Christensen@Sun.COM }
14197697SMichael.Christensen@Sun.COM }
14207697SMichael.Christensen@Sun.COM
14217697SMichael.Christensen@Sun.COM if ((flags & DSSF_UNREGCB_VALID) != 0) {
14227697SMichael.Christensen@Sun.COM ds_cbarg_get_hdl(arg, &hdl);
14237697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: unregcb hdl: 0x%lx", __func__,
14247697SMichael.Christensen@Sun.COM hdl);
14257697SMichael.Christensen@Sun.COM ds_cbarg_get_drv_info(arg, &minor);
14267697SMichael.Christensen@Sun.COM sp = ddi_get_soft_state(vlds_statep, minor);
14277697SMichael.Christensen@Sun.COM ASSERT(sp != NULL);
14287697SMichael.Christensen@Sun.COM ASSERT(sp->evchan != NULL);
14297697SMichael.Christensen@Sun.COM if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP) ||
14307697SMichael.Christensen@Sun.COM nvlist_add_uint64(nvl, VLDS_HDL, hdl) ||
14317697SMichael.Christensen@Sun.COM sysevent_evc_publish(sp->evchan, EC_VLDS,
14327697SMichael.Christensen@Sun.COM ESC_VLDS_UNREGISTER, "sun.com", "kernel", nvl,
14337697SMichael.Christensen@Sun.COM EVCH_SLEEP)) {
14347697SMichael.Christensen@Sun.COM cmn_err(CE_WARN, "Failed to send UNREG Callback");
14357697SMichael.Christensen@Sun.COM }
14367697SMichael.Christensen@Sun.COM nvlist_free(nvl);
14377697SMichael.Christensen@Sun.COM }
14387697SMichael.Christensen@Sun.COM }
14397697SMichael.Christensen@Sun.COM
14407697SMichael.Christensen@Sun.COM static void
vlds_user_data_cb(ds_cb_arg_t arg,void * buf,size_t buflen)14417697SMichael.Christensen@Sun.COM vlds_user_data_cb(ds_cb_arg_t arg, void *buf, size_t buflen)
14427697SMichael.Christensen@Sun.COM {
14437697SMichael.Christensen@Sun.COM nvlist_t *nvl = NULL;
14447697SMichael.Christensen@Sun.COM ds_svc_hdl_t hdl;
14457697SMichael.Christensen@Sun.COM int minor;
14467697SMichael.Christensen@Sun.COM void *dpsp;
14477697SMichael.Christensen@Sun.COM vlds_state_t *sp;
14487697SMichael.Christensen@Sun.COM uint32_t flags;
14497697SMichael.Christensen@Sun.COM
14507697SMichael.Christensen@Sun.COM ds_cbarg_get_flags(arg, &flags);
14517697SMichael.Christensen@Sun.COM ASSERT((flags & DSSF_ISUSER) != 0);
14527697SMichael.Christensen@Sun.COM
14537697SMichael.Christensen@Sun.COM if ((flags & DSSF_DATACB_VALID) == 0) {
14547697SMichael.Christensen@Sun.COM ds_cbarg_get_drv_per_svc_ptr(arg, &dpsp);
14557697SMichael.Christensen@Sun.COM ASSERT(dpsp != NULL);
14567697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: datacb: to recvq: buflen: %ld",
14577697SMichael.Christensen@Sun.COM __func__, buflen);
14587697SMichael.Christensen@Sun.COM (void) vlds_recvq_put_data(dpsp, buf, buflen);
14597697SMichael.Christensen@Sun.COM } else {
14607697SMichael.Christensen@Sun.COM ds_cbarg_get_hdl(arg, &hdl);
14617697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: datacb: usercb: hdl: 0x%lx, "
14627697SMichael.Christensen@Sun.COM " buflen: %ld", __func__, hdl, buflen);
14637697SMichael.Christensen@Sun.COM ds_cbarg_get_drv_info(arg, &minor);
14647697SMichael.Christensen@Sun.COM sp = ddi_get_soft_state(vlds_statep, minor);
14657697SMichael.Christensen@Sun.COM ASSERT(sp != NULL);
14667697SMichael.Christensen@Sun.COM ASSERT(sp->evchan != NULL);
14677697SMichael.Christensen@Sun.COM if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP) ||
14687697SMichael.Christensen@Sun.COM nvlist_add_uint64(nvl, VLDS_HDL, hdl) ||
14697697SMichael.Christensen@Sun.COM nvlist_add_byte_array(nvl, VLDS_DATA, buf, buflen) ||
14707697SMichael.Christensen@Sun.COM sysevent_evc_publish(sp->evchan, EC_VLDS,
14717697SMichael.Christensen@Sun.COM ESC_VLDS_DATA, "sun.com", "kernel", nvl, EVCH_SLEEP)) {
14727697SMichael.Christensen@Sun.COM cmn_err(CE_WARN, "Failed to send DATA Callback");
14737697SMichael.Christensen@Sun.COM }
14747697SMichael.Christensen@Sun.COM }
14757697SMichael.Christensen@Sun.COM nvlist_free(nvl);
14767697SMichael.Christensen@Sun.COM }
14777697SMichael.Christensen@Sun.COM
14787697SMichael.Christensen@Sun.COM /*
14797697SMichael.Christensen@Sun.COM * Initialize receive queue if request is from user land but
14807697SMichael.Christensen@Sun.COM * data callback is null (implying user will be using ds_recv_msg).
14817697SMichael.Christensen@Sun.COM */
14827697SMichael.Christensen@Sun.COM static void
vlds_recvq_init(vlds_svc_info_t * dpsp)14837697SMichael.Christensen@Sun.COM vlds_recvq_init(vlds_svc_info_t *dpsp)
14847697SMichael.Christensen@Sun.COM {
14857697SMichael.Christensen@Sun.COM dpsp->state = VLDS_RECV_OK;
14867697SMichael.Christensen@Sun.COM mutex_init(&dpsp->recv_lock, NULL, MUTEX_DRIVER, NULL);
14877697SMichael.Christensen@Sun.COM cv_init(&dpsp->recv_cv, NULL, CV_DRIVER, NULL);
14887697SMichael.Christensen@Sun.COM dpsp->recv_headp = NULL;
14897697SMichael.Christensen@Sun.COM dpsp->recv_tailp = NULL;
14907697SMichael.Christensen@Sun.COM dpsp->recv_size = 0;
14917813SMichael.Christensen@Sun.COM dpsp->recv_cnt = 0;
14927697SMichael.Christensen@Sun.COM }
14937697SMichael.Christensen@Sun.COM
14947697SMichael.Christensen@Sun.COM static void
vlds_recvq_destroy(vlds_svc_info_t * dpsp)14957697SMichael.Christensen@Sun.COM vlds_recvq_destroy(vlds_svc_info_t *dpsp)
14967697SMichael.Christensen@Sun.COM {
14977697SMichael.Christensen@Sun.COM ASSERT(dpsp->state == VLDS_RECV_UNREG_PENDING);
14987697SMichael.Christensen@Sun.COM ASSERT(dpsp->recv_size == 0);
14997813SMichael.Christensen@Sun.COM ASSERT(dpsp->recv_cnt == 0);
15007697SMichael.Christensen@Sun.COM ASSERT(dpsp->recv_headp == NULL);
15017697SMichael.Christensen@Sun.COM ASSERT(dpsp->recv_tailp == NULL);
15027697SMichael.Christensen@Sun.COM
15037697SMichael.Christensen@Sun.COM mutex_destroy(&dpsp->recv_lock);
15047697SMichael.Christensen@Sun.COM cv_destroy(&dpsp->recv_cv);
15057697SMichael.Christensen@Sun.COM DS_FREE(dpsp, sizeof (vlds_svc_info_t));
15067697SMichael.Christensen@Sun.COM }
15077697SMichael.Christensen@Sun.COM
15087697SMichael.Christensen@Sun.COM static int
vlds_recvq_get_data(vlds_svc_info_t * dpsp,void * buf,size_t buflen,size_t * msglenp,int mode)15097697SMichael.Christensen@Sun.COM vlds_recvq_get_data(vlds_svc_info_t *dpsp, void *buf, size_t buflen,
15107697SMichael.Christensen@Sun.COM size_t *msglenp, int mode)
15117697SMichael.Christensen@Sun.COM {
15127697SMichael.Christensen@Sun.COM vlds_recv_hdr_t *rhp;
15137697SMichael.Christensen@Sun.COM int rv;
15147697SMichael.Christensen@Sun.COM size_t msglen;
15157697SMichael.Christensen@Sun.COM
15167697SMichael.Christensen@Sun.COM mutex_enter(&dpsp->recv_lock);
15177697SMichael.Christensen@Sun.COM while (dpsp->recv_size == 0) {
15187813SMichael.Christensen@Sun.COM ASSERT(dpsp->recv_cnt == 0);
15197697SMichael.Christensen@Sun.COM if (dpsp->state == VLDS_RECV_UNREG_PENDING)
15207697SMichael.Christensen@Sun.COM break;
15217813SMichael.Christensen@Sun.COM
15227813SMichael.Christensen@Sun.COM if (dpsp->state == VLDS_RECV_OVERFLOW) {
15237813SMichael.Christensen@Sun.COM DS_DBG_RCVQ(CE_NOTE, "%s: user data queue overflow",
15247813SMichael.Christensen@Sun.COM __func__);
15257813SMichael.Christensen@Sun.COM dpsp->state = VLDS_RECV_OK;
15267813SMichael.Christensen@Sun.COM mutex_exit(&dpsp->recv_lock);
15277813SMichael.Christensen@Sun.COM return (ENOBUFS);
15287813SMichael.Christensen@Sun.COM }
15297697SMichael.Christensen@Sun.COM /*
15307697SMichael.Christensen@Sun.COM * Passing in a buflen of 0 allows user to poll for msgs.
15317697SMichael.Christensen@Sun.COM */
15327697SMichael.Christensen@Sun.COM if (buflen == 0) {
15337697SMichael.Christensen@Sun.COM mutex_exit(&dpsp->recv_lock);
15347697SMichael.Christensen@Sun.COM *msglenp = 0;
15357697SMichael.Christensen@Sun.COM return (EFBIG);
15367697SMichael.Christensen@Sun.COM }
15377697SMichael.Christensen@Sun.COM dpsp->recv_nreaders += 1;
15387697SMichael.Christensen@Sun.COM rv = cv_wait_sig(&dpsp->recv_cv, &dpsp->recv_lock);
15397697SMichael.Christensen@Sun.COM dpsp->recv_nreaders -= 1;
15407697SMichael.Christensen@Sun.COM if (rv == 0) {
15417697SMichael.Christensen@Sun.COM DS_DBG_RCVQ(CE_NOTE, "%s: signal EINTR", __func__);
15427697SMichael.Christensen@Sun.COM mutex_exit(&dpsp->recv_lock);
15437697SMichael.Christensen@Sun.COM return (EINTR);
15447697SMichael.Christensen@Sun.COM }
15457697SMichael.Christensen@Sun.COM }
15467697SMichael.Christensen@Sun.COM if (dpsp->state == VLDS_RECV_UNREG_PENDING) {
15477697SMichael.Christensen@Sun.COM DS_DBG_RCVQ(CE_NOTE, "%s: unreg pending", __func__);
15487697SMichael.Christensen@Sun.COM cv_broadcast(&dpsp->recv_cv);
15497697SMichael.Christensen@Sun.COM mutex_exit(&dpsp->recv_lock);
15507697SMichael.Christensen@Sun.COM return (EINVAL);
15517697SMichael.Christensen@Sun.COM }
15527697SMichael.Christensen@Sun.COM ASSERT(dpsp->recv_headp != NULL);
15537697SMichael.Christensen@Sun.COM rhp = dpsp->recv_headp;
15547697SMichael.Christensen@Sun.COM
15557697SMichael.Christensen@Sun.COM /*
15567697SMichael.Christensen@Sun.COM * Don't transfer truncated data, return EFBIG error if user-supplied
15577697SMichael.Christensen@Sun.COM * buffer is too small.
15587697SMichael.Christensen@Sun.COM */
15597697SMichael.Christensen@Sun.COM if (rhp->datasz > buflen) {
15607697SMichael.Christensen@Sun.COM *msglenp = rhp->datasz;
15617697SMichael.Christensen@Sun.COM mutex_exit(&dpsp->recv_lock);
15627697SMichael.Christensen@Sun.COM return (EFBIG);
15637697SMichael.Christensen@Sun.COM }
15647697SMichael.Christensen@Sun.COM if (rhp == dpsp->recv_tailp) {
15657697SMichael.Christensen@Sun.COM dpsp->recv_headp = NULL;
15667697SMichael.Christensen@Sun.COM dpsp->recv_tailp = NULL;
15677697SMichael.Christensen@Sun.COM } else {
15687697SMichael.Christensen@Sun.COM dpsp->recv_headp = rhp->next;
15697697SMichael.Christensen@Sun.COM ASSERT(dpsp->recv_headp != NULL);
15707697SMichael.Christensen@Sun.COM }
15717813SMichael.Christensen@Sun.COM ASSERT(dpsp->recv_cnt > 0);
15727697SMichael.Christensen@Sun.COM dpsp->recv_size -= rhp->datasz;
15737813SMichael.Christensen@Sun.COM dpsp->recv_cnt -= 1;
15747697SMichael.Christensen@Sun.COM mutex_exit(&dpsp->recv_lock);
15757697SMichael.Christensen@Sun.COM
15767697SMichael.Christensen@Sun.COM msglen = rhp->datasz;
15777697SMichael.Christensen@Sun.COM rv = ddi_copyout(rhp->data, buf, msglen, mode);
15787697SMichael.Christensen@Sun.COM
15797697SMichael.Christensen@Sun.COM if (rv == 0) {
15807697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: user data dequeued msglen: %ld",
15817697SMichael.Christensen@Sun.COM __func__, rhp->datasz);
15827697SMichael.Christensen@Sun.COM DS_DUMP_MSG(DS_DBG_FLAG_VLDS, rhp->data, rhp->datasz);
15837697SMichael.Christensen@Sun.COM }
15847697SMichael.Christensen@Sun.COM
15857697SMichael.Christensen@Sun.COM DS_FREE(rhp->data, rhp->datasz);
15867697SMichael.Christensen@Sun.COM DS_FREE(rhp, sizeof (vlds_recv_hdr_t));
15877697SMichael.Christensen@Sun.COM
15887697SMichael.Christensen@Sun.COM if (rv != 0) {
15897697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: copyout failed", __func__);
15907697SMichael.Christensen@Sun.COM return (EFAULT);
15917697SMichael.Christensen@Sun.COM }
15927697SMichael.Christensen@Sun.COM
15937697SMichael.Christensen@Sun.COM *msglenp = msglen;
15947697SMichael.Christensen@Sun.COM return (0);
15957697SMichael.Christensen@Sun.COM }
15967697SMichael.Christensen@Sun.COM
15977697SMichael.Christensen@Sun.COM uint64_t vlds_recv_drain_delay_time = 1 * MILLISEC;
15987697SMichael.Christensen@Sun.COM
15997697SMichael.Christensen@Sun.COM static void
vlds_recvq_drain(vlds_svc_info_t * dpsp)16007697SMichael.Christensen@Sun.COM vlds_recvq_drain(vlds_svc_info_t *dpsp)
16017697SMichael.Christensen@Sun.COM {
16027697SMichael.Christensen@Sun.COM vlds_recv_hdr_t *rhp, *nextp;
16037697SMichael.Christensen@Sun.COM
16047697SMichael.Christensen@Sun.COM mutex_enter(&dpsp->recv_lock);
16057697SMichael.Christensen@Sun.COM dpsp->state = VLDS_RECV_UNREG_PENDING;
16067697SMichael.Christensen@Sun.COM for (rhp = dpsp->recv_tailp; rhp != NULL; rhp = nextp) {
16077697SMichael.Christensen@Sun.COM nextp = rhp->next;
16087697SMichael.Christensen@Sun.COM DS_FREE(rhp->data, rhp->datasz);
16097697SMichael.Christensen@Sun.COM DS_FREE(rhp, sizeof (vlds_recv_hdr_t));
16107697SMichael.Christensen@Sun.COM }
16117697SMichael.Christensen@Sun.COM dpsp->recv_headp = NULL;
16127697SMichael.Christensen@Sun.COM dpsp->recv_tailp = NULL;
16137697SMichael.Christensen@Sun.COM dpsp->recv_size = 0;
16147813SMichael.Christensen@Sun.COM dpsp->recv_cnt = 0;
16157697SMichael.Christensen@Sun.COM
16167697SMichael.Christensen@Sun.COM /*
16177697SMichael.Christensen@Sun.COM * Make sure other readers have exited.
16187697SMichael.Christensen@Sun.COM */
16197697SMichael.Christensen@Sun.COM while (dpsp->recv_nreaders > 0) {
16207697SMichael.Christensen@Sun.COM cv_broadcast(&dpsp->recv_cv);
16217697SMichael.Christensen@Sun.COM mutex_exit(&dpsp->recv_lock);
16227697SMichael.Christensen@Sun.COM delay(vlds_recv_drain_delay_time);
16237697SMichael.Christensen@Sun.COM mutex_enter(&dpsp->recv_lock);
16247697SMichael.Christensen@Sun.COM }
16257697SMichael.Christensen@Sun.COM
16267697SMichael.Christensen@Sun.COM mutex_exit(&dpsp->recv_lock);
16277697SMichael.Christensen@Sun.COM }
16287697SMichael.Christensen@Sun.COM
16297697SMichael.Christensen@Sun.COM static int
vlds_recvq_put_data(vlds_svc_info_t * dpsp,void * buf,size_t buflen)16307697SMichael.Christensen@Sun.COM vlds_recvq_put_data(vlds_svc_info_t *dpsp, void *buf, size_t buflen)
16317697SMichael.Christensen@Sun.COM {
16327697SMichael.Christensen@Sun.COM vlds_recv_hdr_t *rhp;
16337697SMichael.Christensen@Sun.COM
16347697SMichael.Christensen@Sun.COM mutex_enter(&dpsp->recv_lock);
16357697SMichael.Christensen@Sun.COM if (dpsp->state != VLDS_RECV_UNREG_PENDING) {
16367813SMichael.Christensen@Sun.COM /*
16377813SMichael.Christensen@Sun.COM * If we've already encountered an overflow, or there
16387813SMichael.Christensen@Sun.COM * are pending messages and either queue size and
16397813SMichael.Christensen@Sun.COM * message limits will be exceeded with this message,
16407813SMichael.Christensen@Sun.COM * we mark the recvq as overflowed and return an ENOBUFS
16417813SMichael.Christensen@Sun.COM * error. This allows the enqueuing of one big message
16427813SMichael.Christensen@Sun.COM * or several little messages.
16437813SMichael.Christensen@Sun.COM */
16447813SMichael.Christensen@Sun.COM if ((dpsp->state == VLDS_RECV_OVERFLOW) ||
16457813SMichael.Christensen@Sun.COM ((dpsp->recv_cnt != 0) &&
16467813SMichael.Christensen@Sun.COM ((dpsp->recv_size + buflen) > vlds_recvq_maxsize) ||
16477813SMichael.Christensen@Sun.COM ((dpsp->recv_cnt + 1) > vlds_recvq_maxmsg))) {
16487813SMichael.Christensen@Sun.COM DS_DBG_RCVQ(CE_NOTE, "%s: user data queue overflow",
16497813SMichael.Christensen@Sun.COM __func__);
16507813SMichael.Christensen@Sun.COM dpsp->state = VLDS_RECV_OVERFLOW;
16517813SMichael.Christensen@Sun.COM cv_broadcast(&dpsp->recv_cv);
16527813SMichael.Christensen@Sun.COM mutex_exit(&dpsp->recv_lock);
16537813SMichael.Christensen@Sun.COM return (ENOBUFS);
16547813SMichael.Christensen@Sun.COM }
16557813SMichael.Christensen@Sun.COM
16567697SMichael.Christensen@Sun.COM DS_DBG_RCVQ(CE_NOTE, "%s: user data enqueued msglen: %ld",
16577697SMichael.Christensen@Sun.COM __func__, buflen);
16587697SMichael.Christensen@Sun.COM DS_DUMP_MSG(DS_DBG_FLAG_RCVQ, buf, buflen);
16597697SMichael.Christensen@Sun.COM rhp = DS_MALLOC(sizeof (vlds_recv_hdr_t));
16607697SMichael.Christensen@Sun.COM rhp->data = DS_MALLOC(buflen);
16617697SMichael.Christensen@Sun.COM (void) memcpy(rhp->data, buf, buflen);
16627697SMichael.Christensen@Sun.COM rhp->datasz = buflen;
16637697SMichael.Christensen@Sun.COM rhp->next = NULL;
16647697SMichael.Christensen@Sun.COM if (dpsp->recv_headp == NULL) {
16657697SMichael.Christensen@Sun.COM dpsp->recv_headp = rhp;
16667697SMichael.Christensen@Sun.COM dpsp->recv_tailp = rhp;
16677697SMichael.Christensen@Sun.COM } else {
16687697SMichael.Christensen@Sun.COM dpsp->recv_tailp->next = rhp;
16697697SMichael.Christensen@Sun.COM dpsp->recv_tailp = rhp;
16707697SMichael.Christensen@Sun.COM }
16717697SMichael.Christensen@Sun.COM dpsp->recv_size += rhp->datasz;
16727813SMichael.Christensen@Sun.COM dpsp->recv_cnt += 1;
16737697SMichael.Christensen@Sun.COM cv_broadcast(&dpsp->recv_cv);
16747697SMichael.Christensen@Sun.COM }
16757697SMichael.Christensen@Sun.COM mutex_exit(&dpsp->recv_lock);
16767697SMichael.Christensen@Sun.COM return (0);
16777697SMichael.Christensen@Sun.COM }
16787697SMichael.Christensen@Sun.COM
16797697SMichael.Christensen@Sun.COM static int
vlds_recv_msg(ds_svc_hdl_t hdl,void * buf,size_t buflen,size_t * msglenp,int mode)16807697SMichael.Christensen@Sun.COM vlds_recv_msg(ds_svc_hdl_t hdl, void *buf, size_t buflen, size_t *msglenp,
16817697SMichael.Christensen@Sun.COM int mode)
16827697SMichael.Christensen@Sun.COM {
16837697SMichael.Christensen@Sun.COM void *dpsp;
16847697SMichael.Christensen@Sun.COM ds_cb_arg_t cbarg;
16857697SMichael.Christensen@Sun.COM uint32_t flags;
16867697SMichael.Christensen@Sun.COM int rv;
16877697SMichael.Christensen@Sun.COM
16887697SMichael.Christensen@Sun.COM if ((rv = ds_hdl_get_cbarg(hdl, &cbarg)) != 0) {
16897697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: handle %lx not found (%d)", __func__,
16907697SMichael.Christensen@Sun.COM hdl, rv);
16917697SMichael.Christensen@Sun.COM return (rv);
16927697SMichael.Christensen@Sun.COM }
16937697SMichael.Christensen@Sun.COM ds_cbarg_get_flags(cbarg, &flags);
16947697SMichael.Christensen@Sun.COM if ((flags & DSSF_ISUSER) == 0 || (flags & DSSF_DATACB_VALID) != 0) {
16957697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: invalid flags: %x", __func__, flags);
16967697SMichael.Christensen@Sun.COM return (EINVAL);
16977697SMichael.Christensen@Sun.COM }
16987697SMichael.Christensen@Sun.COM ds_cbarg_get_drv_per_svc_ptr(cbarg, &dpsp);
16997697SMichael.Christensen@Sun.COM if (dpsp == NULL) {
17007697SMichael.Christensen@Sun.COM DS_DBG_VLDS(CE_NOTE, "%s: recv on non-ready handle: %x",
17017697SMichael.Christensen@Sun.COM __func__, flags);
17027697SMichael.Christensen@Sun.COM return (ENXIO);
17037697SMichael.Christensen@Sun.COM }
17047697SMichael.Christensen@Sun.COM rv = vlds_recvq_get_data(dpsp, buf, buflen, msglenp, mode);
17057697SMichael.Christensen@Sun.COM return (rv);
17067697SMichael.Christensen@Sun.COM }
1707