xref: /illumos-gate/usr/src/lib/librsm/common/rsmlib.c (revision 7f7322febbcfe774b7270abc3b191c094bfcc517)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 
23 /*
24  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  */
27 
28 #pragma ident	"%Z%%M%	%I%	%E% SMI"
29 
30 #include "c_synonyms.h"
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <stdarg.h>
35 #include <string.h>
36 #include <strings.h>
37 #include <ctype.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <sys/mman.h>
41 #include <sys/uio.h>
42 #include <sys/sysmacros.h>
43 #include <sys/resource.h>
44 #include <errno.h>
45 #include <assert.h>
46 #include <fcntl.h>
47 #include <dlfcn.h>
48 #include <sched.h>
49 #include <stropts.h>
50 #include <poll.h>
51 
52 #include <rsmapi.h>
53 #include <sys/rsm/rsmndi.h>
54 #include <rsmlib_in.h>
55 #include <sys/rsm/rsm.h>
56 
57 #ifdef __STDC__
58 
59 #pragma weak rsm_get_controller = _rsm_get_controller
60 #pragma weak rsm_get_controller_attr = _rsm_get_controller_attr
61 #pragma weak rsm_release_controller = _rsm_release_controller
62 #pragma weak rsm_get_interconnect_topology = _rsm_get_interconnect_topology
63 #pragma weak rsm_free_interconnect_topology = _rsm_free_interconnect_topology
64 #pragma weak rsm_memseg_export_create = _rsm_memseg_export_create
65 #pragma weak rsm_memseg_export_destroy = _rsm_memseg_export_destroy
66 #pragma weak rsm_memseg_export_rebind = _rsm_memseg_export_rebind
67 #pragma weak rsm_memseg_export_publish = _rsm_memseg_export_publish
68 #pragma weak rsm_memseg_export_unpublish = _rsm_memseg_export_unpublish
69 #pragma weak rsm_memseg_export_republish = _rsm_memseg_export_republish
70 #pragma weak rsm_memseg_import_connect = _rsm_memseg_import_connect
71 #pragma weak rsm_memseg_import_disconnect = _rsm_memseg_import_disconnect
72 #pragma weak rsm_memseg_import_get8 = _rsm_memseg_import_get8
73 #pragma weak rsm_memseg_import_get16 = _rsm_memseg_import_get16
74 #pragma weak rsm_memseg_import_get32 = _rsm_memseg_import_get32
75 #pragma weak rsm_memseg_import_get64 = _rsm_memseg_import_get64
76 #pragma weak rsm_memseg_import_get = _rsm_memseg_import_get
77 #pragma weak rsm_memseg_import_getv = _rsm_memseg_import_getv
78 #pragma weak rsm_memseg_import_put8 = _rsm_memseg_import_put8
79 #pragma weak rsm_memseg_import_put16 = _rsm_memseg_import_put16
80 #pragma weak rsm_memseg_import_put32 = _rsm_memseg_import_put32
81 #pragma weak rsm_memseg_import_put64 = _rsm_memseg_import_put64
82 #pragma weak rsm_memseg_import_put = _rsm_memseg_import_put
83 #pragma weak rsm_memseg_import_putv = _rsm_memseg_import_putv
84 #pragma weak rsm_memseg_import_map = _rsm_memseg_import_map
85 #pragma weak rsm_memseg_import_unmap = _rsm_memseg_import_unmap
86 #pragma weak rsm_memseg_import_init_barrier = _rsm_memseg_import_init_barrier
87 #pragma weak rsm_memseg_import_open_barrier = _rsm_memseg_import_open_barrier
88 #pragma weak rsm_memseg_import_close_barrier = _rsm_memseg_import_close_barrier
89 #pragma weak rsm_memseg_import_order_barrier = _rsm_memseg_import_order_barrier
90 #pragma weak rsm_memseg_import_destroy_barrier = \
91 				_rsm_memseg_import_destroy_barrier
92 #pragma weak rsm_memseg_import_get_mode = _rsm_memseg_import_get_mode
93 #pragma weak rsm_memseg_import_set_mode = _rsm_memseg_import_set_mode
94 #pragma weak rsm_create_localmemory_handle = _rsm_create_localmemory_handle
95 #pragma weak rsm_free_localmemory_handle = _rsm_free_localmemory_handle
96 #pragma weak rsm_intr_signal_post = _rsm_intr_signal_post
97 #pragma weak rsm_intr_signal_wait = _rsm_intr_signal_wait
98 #pragma weak rsm_intr_signal_wait_pollfd = _rsm_intr_signal_wait_pollfd
99 #pragma weak rsm_memseg_get_pollfd = _rsm_memseg_get_pollfd
100 #pragma weak rsm_memseg_release_pollfd = _rsm_memseg_release_pollfd
101 #pragma weak rsm_get_segmentid_range = _rsm_get_segmentid_range
102 
103 #endif /* __STDC__ */
104 
105 /* lint -w2 */
106 extern void __rsmloopback_init_ops(rsm_segops_t *);
107 extern void __rsmdefault_setops(rsm_segops_t *);
108 
109 typedef void (*rsm_access_func_t)(void *, void *, rsm_access_size_t);
110 
111 #ifdef DEBUG
112 
113 #define	RSMLOG_BUF_SIZE 256
114 FILE *rsmlog_fd = NULL;
115 static mutex_t rsmlog_lock;
116 int rsmlibdbg_category = RSM_LIBRARY;
117 int rsmlibdbg_level = RSM_ERR;
118 void dbg_printf(int category, int level, char *fmt, ...);
119 
120 #endif /* DEBUG */
121 
122 rsm_node_id_t rsm_local_nodeid = 0;
123 
124 static rsm_controller_t *controller_list = NULL;
125 
126 static rsm_segops_t loopback_ops;
127 
128 #define	MAX_STRLEN	80
129 
130 #define	RSM_IOTYPE_PUTGET	1
131 #define	RSM_IOTYPE_SCATGATH	2
132 
133 #define	RSMFILE_BUFSIZE		256
134 
135 #pragma init(_rsm_librsm_init)
136 
137 static mutex_t _rsm_lock;
138 
139 static int _rsm_fd = -1;
140 static rsm_gnum_t *bar_va, bar_fixed = 0;
141 static rsm_pollfd_table_t pollfd_table;
142 
143 static int _rsm_get_hwaddr(rsmapi_controller_handle_t handle,
144 rsm_node_id_t, rsm_addr_t *hwaddrp);
145 static int _rsm_get_nodeid(rsmapi_controller_handle_t,
146 rsm_addr_t, rsm_node_id_t *);
147 static int __rsm_import_implicit_map(rsmseg_handle_t *, int);
148 static int __rsm_intr_signal_wait_common(struct pollfd [], minor_t [],
149     nfds_t, int, int *);
150 
151 static	rsm_lib_funcs_t lib_functions = {
152 	RSM_LIB_FUNCS_VERSION,
153 	_rsm_get_hwaddr,
154 	_rsm_get_nodeid
155 };
156 
157 int _rsm_get_interconnect_topology(rsm_topology_t **);
158 void _rsm_free_interconnect_topology(rsm_topology_t *);
159 int _rsm_memseg_import_open_barrier(rsmapi_barrier_t *);
160 int _rsm_memseg_import_close_barrier(rsmapi_barrier_t *);
161 int _rsm_memseg_import_unmap(rsm_memseg_import_handle_t);
162 
163 rsm_topology_t *tp;
164 
165 
166 
167 /*
168  * service module function templates:
169  */
170 
171 /*
172  * The _rsm_librsm_init function is called the first time an application
173  * references the RSMAPI library
174  */
175 int
176 _rsm_librsm_init()
177 {
178 	rsm_ioctlmsg_t 		msg;
179 	int e, tmpfd;
180 	int i;
181 	char logname[MAXNAMELEN];
182 
183 	mutex_init(&_rsm_lock, USYNC_THREAD, NULL);
184 
185 #ifdef DEBUG
186 	mutex_init(&rsmlog_lock, USYNC_THREAD, NULL);
187 	sprintf(logname, "%s.%d", TRACELOG, getpid());
188 	rsmlog_fd = fopen(logname, "w+");
189 	if (rsmlog_fd == NULL) {
190 		fprintf(stderr, "Log file open failed\n");
191 		return (errno);
192 	}
193 
194 #endif /* DEBUG */
195 
196 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
197 	    "_rsm_librsm_init: enter\n"));
198 
199 	/* initialize the pollfd_table */
200 	mutex_init(&pollfd_table.lock, USYNC_THREAD, NULL);
201 
202 	for (i = 0; i < RSM_MAX_BUCKETS; i++) {
203 		pollfd_table.buckets[i] = NULL;
204 	}
205 
206 	/* open /dev/rsm and mmap barrier generation pages */
207 	mutex_lock(&_rsm_lock);
208 	_rsm_fd = open(DEVRSM, O_RDONLY);
209 	if (_rsm_fd < 0) {
210 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
211 		    "unable to open /dev/rsm\n"));
212 		mutex_unlock(&_rsm_lock);
213 		return (errno);
214 	}
215 
216 	/*
217 	 * DUP the opened file descriptor to something greater than
218 	 * STDERR_FILENO so that we never use the STDIN_FILENO,
219 	 * STDOUT_FILENO or STDERR_FILENO.
220 	 */
221 	tmpfd = fcntl(_rsm_fd, F_DUPFD, 3);
222 	if (tmpfd < 0) {
223 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
224 		    "F_DUPFD failed\n"));
225 	} else {
226 		(void) close(_rsm_fd);
227 		_rsm_fd = tmpfd;
228 	}
229 
230 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
231 	    "_rsm_fd is %d\n", _rsm_fd));
232 
233 	if (fcntl(_rsm_fd, F_SETFD, FD_CLOEXEC) < 0) {
234 	    DBPRINTF((RSM_LIBRARY, RSM_ERR,
235 		"F_SETFD failed\n"));
236 	}
237 
238 	/* get mapping generation number page info */
239 	if (ioctl(_rsm_fd, RSM_IOCTL_BAR_INFO, &msg) < 0) {
240 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
241 		    "RSM_IOCTL_BAR_INFO failed\n"));
242 		mutex_unlock(&_rsm_lock);
243 		return (errno);
244 	}
245 
246 	/*
247 	 * bar_va is mapped to the mapping generation number page
248 	 * in order to support close barrier
249 	 */
250 	/* LINTED */
251 	bar_va = (rsm_gnum_t *)mmap(NULL, msg.len,
252 	    PROT_READ, MAP_SHARED, _rsm_fd, msg.off);
253 	if (bar_va == (rsm_gnum_t *)MAP_FAILED) {
254 		bar_va = NULL;
255 		mutex_unlock(&_rsm_lock);
256 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
257 		    "unable to map barrier page\n"));
258 		return (RSMERR_MAP_FAILED);
259 	}
260 
261 	mutex_unlock(&_rsm_lock);
262 
263 	/* get local nodeid */
264 	e = rsm_get_interconnect_topology(&tp);
265 	if (e != RSM_SUCCESS) {
266 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
267 		    "unable to obtain topology data\n"));
268 		return (e);
269 	} else
270 	    rsm_local_nodeid = tp->topology_hdr.local_nodeid;
271 
272 	rsm_free_interconnect_topology(tp);
273 
274 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
275 	    "_rsm_librsm_init: exit\n"));
276 
277 	return (RSM_SUCCESS);
278 }
279 
280 static int
281 _rsm_loopbackload(caddr_t name, int unit, rsm_controller_t **chdl)
282 {
283 	rsm_controller_t *p;
284 	rsm_ioctlmsg_t msg;
285 
286 	DBPRINTF((RSM_LIBRARY|RSM_LOOPBACK, RSM_DEBUG_VERBOSE,
287 	    "_rsm_loopbackload: enter\n"));
288 	/*
289 	 * For now do this, but we should open some file and read the
290 	 * list of supported controllers and there numbers.
291 	 */
292 
293 	p = (rsm_controller_t *)malloc(sizeof (*p) + strlen(name) + 1);
294 	if (!p) {
295 		DBPRINTF((RSM_LIBRARY|RSM_LOOPBACK, RSM_ERR,
296 		    "not enough memory\n"));
297 		return (RSMERR_INSUFFICIENT_MEM);
298 	}
299 
300 	msg.cname = name;
301 	msg.cname_len = strlen(name) +1;
302 	msg.cnum = unit;
303 	msg.arg = (caddr_t)&p->cntr_attr;
304 	if (ioctl(_rsm_fd, RSM_IOCTL_ATTR, &msg) < 0) {
305 		int error = errno;
306 		free((void *)p);
307 		DBPRINTF((RSM_LIBRARY|RSM_LOOPBACK, RSM_ERR,
308 		    "RSM_IOCTL_ATTR failed\n"));
309 		return (error);
310 	}
311 
312 	__rsmloopback_init_ops(&loopback_ops);
313 	__rsmdefault_setops(&loopback_ops);
314 	p->cntr_segops = &loopback_ops;
315 
316 	/*
317 	 * Should add this entry into list
318 	 */
319 	p->cntr_fd = _rsm_fd;
320 	p->cntr_name = strcpy((char *)(p+1), name);
321 	p->cntr_unit = unit;
322 	p->cntr_refcnt = 1;
323 
324 
325 	mutex_init(&p->cntr_lock, USYNC_THREAD, NULL);
326 	cond_init(&p->cntr_cv, USYNC_THREAD, NULL);
327 	p->cntr_rqlist = NULL;
328 	p->cntr_segops->rsm_get_lib_attr(&p->cntr_lib_attr);
329 	p->cntr_next = controller_list;
330 	controller_list = p;
331 
332 	*chdl = p;
333 
334 	DBPRINTF((RSM_LIBRARY|RSM_LOOPBACK, RSM_DEBUG_VERBOSE,
335 	    "_rsm_loopbackload: exit\n"));
336 	return (RSM_SUCCESS);
337 
338 }
339 
340 static int
341 _rsm_modload(caddr_t name, int unit, rsmapi_controller_handle_t *controller)
342 {
343 	int error = RSM_SUCCESS;
344 	char clib[MAX_STRLEN];
345 	rsm_controller_t *p = NULL;
346 	void *dlh;
347 	rsm_attach_entry_t fptr;
348 	rsm_ioctlmsg_t msg;
349 
350 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
351 	    "_rsm_modload: enter\n"));
352 
353 	(void) sprintf(clib, "%s.so", name);
354 
355 	/* found entry, try to load library */
356 	dlh = dlopen(clib, RTLD_LAZY);
357 	if (dlh == NULL) {
358 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
359 		    "unable to find plugin library\n"));
360 		error = RSMERR_CTLR_NOT_PRESENT;
361 		goto skiplib;
362 	}
363 
364 	(void) sprintf(clib, "%s_opendevice", name);
365 
366 	fptr = (rsm_attach_entry_t)dlsym(dlh, clib); /* lint !e611 */
367 	if (fptr != NULL) {
368 		/* allocate new lib structure */
369 		/* get ops handler, attr and ops */
370 		p = (rsm_controller_t *)malloc(sizeof (*p) + strlen(name) + 1);
371 		if (p != NULL) {
372 			error = fptr(unit, &p->cntr_segops);
373 		} else {
374 			error = RSMERR_INSUFFICIENT_MEM;
375 			DBPRINTF((RSM_LIBRARY, RSM_ERR,
376 			    "not enough memory\n"));
377 		}
378 	} else {
379 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
380 		    "can't find symbol %s\n", clib));
381 		error = RSMERR_CTLR_NOT_PRESENT;
382 		(void) dlclose(dlh);
383 	}
384 
385 skiplib:
386 	if ((error != RSM_SUCCESS) || (p == NULL)) {
387 		if (p != NULL)
388 			free((void *)p);
389 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
390 		    "_rsm_modload error %d\n", error));
391 		return (error);
392 	}
393 
394 	/* check the version number */
395 	if (p->cntr_segops->rsm_version != RSM_LIB_VERSION) {
396 		/* bad version number */
397 		DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
398 		    "wrong version; "
399 		    "found %d, expected %d\n",
400 		    p->cntr_segops->rsm_version, RSM_LIB_VERSION));
401 		free(p);
402 		return (RSMERR_BAD_LIBRARY_VERSION);
403 	} else {
404 		/* pass the fuctions to NDI library */
405 		if ((p->cntr_segops->rsm_register_lib_funcs == NULL) ||
406 		    (p->cntr_segops->rsm_register_lib_funcs(
407 		    &lib_functions) != RSM_SUCCESS)) {
408 			DBPRINTF((RSM_LIBRARY, RSM_ERR,
409 			    "RSMNDI library not registering lib functions\n"));
410 		}
411 
412 		/* get controller attributes */
413 		msg.cnum = unit;
414 		msg.cname = name;
415 		msg.cname_len = strlen(name) +1;
416 		msg.arg = (caddr_t)&p->cntr_attr;
417 		if (ioctl(_rsm_fd, RSM_IOCTL_ATTR, &msg) < 0) {
418 			error = errno;
419 			free((void *)p);
420 			DBPRINTF((RSM_LIBRARY, RSM_ERR,
421 			    "RSM_IOCTL_ATTR failed\n"));
422 			return (error);
423 		}
424 
425 		/* set controller access functions */
426 		__rsmdefault_setops(p->cntr_segops);
427 
428 		mutex_init(&p->cntr_lock, USYNC_THREAD, NULL);
429 		cond_init(&p->cntr_cv, USYNC_THREAD, NULL);
430 		p->cntr_rqlist = NULL;
431 		p->cntr_segops->rsm_get_lib_attr(&p->cntr_lib_attr);
432 		/* insert into list of controllers */
433 		p->cntr_name = strcpy((char *)(p+1), name);
434 		p->cntr_fd = _rsm_fd;
435 		p->cntr_unit = unit;
436 		p->cntr_refcnt = 1;	/* first reference */
437 		p->cntr_next = controller_list;
438 		controller_list = p;
439 		*controller = (rsmapi_controller_handle_t)p;
440 		errno = RSM_SUCCESS;
441 	}
442 
443 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
444 	    "_rsm_modload: exit\n"));
445 	return (error);
446 }
447 
448 /*
449  * inserts a given segment handle into the pollfd table, this is called
450  * when rsm_memseg_get_pollfd() is called the first time on a segment handle.
451  * Returns RSM_SUCCESS if successful otherwise the error code is returned
452  */
453 static int
454 _rsm_insert_pollfd_table(int segfd, minor_t segrnum)
455 {
456 	int i;
457 	int hash;
458 	rsm_pollfd_chunk_t *chunk;
459 
460 	hash = RSM_POLLFD_HASH(segfd);
461 
462 	mutex_lock(&pollfd_table.lock);
463 
464 	chunk = pollfd_table.buckets[hash];
465 	while (chunk) {
466 		if (chunk->nfree > 0)
467 			break;
468 		chunk = chunk->next;
469 	}
470 
471 	if (!chunk) { /* couldn't find a free chunk - allocate a new one */
472 		chunk = malloc(sizeof (rsm_pollfd_chunk_t));
473 		if (!chunk) {
474 			mutex_unlock(&pollfd_table.lock);
475 			return (RSMERR_INSUFFICIENT_MEM);
476 		}
477 		chunk->nfree = RSM_POLLFD_PER_CHUNK - 1;
478 		chunk->fdarray[0].fd = segfd;
479 		chunk->fdarray[0].segrnum = segrnum;
480 		for (i = 1; i < RSM_POLLFD_PER_CHUNK; i++) {
481 			chunk->fdarray[i].fd = -1;
482 			chunk->fdarray[i].segrnum = 0;
483 		}
484 		/* insert this into the hash table */
485 		chunk->next = pollfd_table.buckets[hash];
486 		pollfd_table.buckets[hash] = chunk;
487 		DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
488 		    "rsm_insert_pollfd: new chunk(%p) @ %d for %d:%d\n",
489 		    chunk, hash, segfd, segrnum));
490 	} else { /* a chunk with free slot was found */
491 		for (i = 0; i < RSM_POLLFD_PER_CHUNK; i++) {
492 			if (chunk->fdarray[i].fd == -1) {
493 				chunk->fdarray[i].fd = segfd;
494 				chunk->fdarray[i].segrnum = segrnum;
495 				chunk->nfree--;
496 				break;
497 			}
498 		}
499 		DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
500 		    "rsm_insert_pollfd: inserted @ %d for %d:%d chunk(%p)\n",
501 		    hash, segfd, segrnum, chunk));
502 		assert(i < RSM_POLLFD_PER_CHUNK);
503 	}
504 
505 	mutex_unlock(&pollfd_table.lock);
506 	return (RSM_SUCCESS);
507 }
508 
509 /*
510  * Given a file descriptor returns the corresponding segment handles
511  * resource number, if the fd is not found returns 0. 0 is not a valid
512  * minor number for a rsmapi segment since it is used for the barrier
513  * resource.
514  */
515 static minor_t
516 _rsm_lookup_pollfd_table(int segfd)
517 {
518 	int i;
519 	rsm_pollfd_chunk_t	*chunk;
520 
521 	if (segfd < 0)
522 		return (0);
523 
524 	mutex_lock(&pollfd_table.lock);
525 
526 	chunk = pollfd_table.buckets[RSM_POLLFD_HASH(segfd)];
527 	while (chunk) {
528 		assert(chunk->nfree < RSM_POLLFD_PER_CHUNK);
529 
530 		for (i = 0; i < RSM_POLLFD_PER_CHUNK; i++) {
531 			if (chunk->fdarray[i].fd == segfd) {
532 				mutex_unlock(&pollfd_table.lock);
533 				DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
534 				    "rsm_lookup_pollfd: found(%d) rnum(%d)\n",
535 				    segfd, chunk->fdarray[i].segrnum));
536 				return (chunk->fdarray[i].segrnum);
537 			}
538 		}
539 		chunk = chunk->next;
540 	}
541 
542 	mutex_unlock(&pollfd_table.lock);
543 
544 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
545 	    "rsm_lookup_pollfd: not found(%d)\n", segfd));
546 
547 	return (0);
548 }
549 
550 /*
551  * Remove the entry corresponding to the given file descriptor from the
552  * pollfd table.
553  */
554 static void
555 _rsm_remove_pollfd_table(int segfd)
556 {
557 	int i;
558 	int hash;
559 	rsm_pollfd_chunk_t	*chunk;
560 	rsm_pollfd_chunk_t	*prev_chunk;
561 
562 	if (segfd < 0)
563 		return;
564 
565 	hash = RSM_POLLFD_HASH(segfd);
566 
567 	mutex_lock(&pollfd_table.lock);
568 
569 	prev_chunk = chunk = pollfd_table.buckets[hash];
570 	while (chunk) {
571 		assert(chunk->nfree < RSM_POLLFD_PER_CHUNK);
572 
573 		for (i = 0; i < RSM_POLLFD_PER_CHUNK; i++) {
574 			if (chunk->fdarray[i].fd == segfd) {
575 				DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
576 				    "rsm_remove_pollfd: %d:%d\n",
577 				    chunk->fdarray[i].fd,
578 				    chunk->fdarray[i].segrnum));
579 				chunk->fdarray[i].fd = -1;
580 				chunk->fdarray[i].segrnum = 0;
581 				chunk->nfree++;
582 				if (chunk->nfree == RSM_POLLFD_PER_CHUNK) {
583 					/* chunk is empty free it */
584 					if (prev_chunk == chunk) {
585 						pollfd_table.buckets[hash] =
586 						    chunk->next;
587 					} else {
588 						prev_chunk->next = chunk->next;
589 					}
590 					DBPRINTF((RSM_LIBRARY,
591 					    RSM_DEBUG_VERBOSE,
592 					    "rsm_remove_pollfd:free(%p)\n",
593 					    chunk));
594 					free(chunk);
595 					mutex_unlock(&pollfd_table.lock);
596 					return;
597 				}
598 			}
599 		}
600 		prev_chunk = chunk;
601 		chunk = chunk->next;
602 	}
603 
604 	mutex_unlock(&pollfd_table.lock);
605 }
606 
607 int
608 _rsm_get_controller(char *name, rsmapi_controller_handle_t *chdl)
609 {
610 	rsm_controller_t *p;
611 	char	cntr_name[MAXNAMELEN];	/* cntr_name=<cntr_type><unit> */
612 	char	*cntr_type;
613 	int	unit = 0;
614 	int	i, e;
615 
616 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
617 	    "rsm_get_controller: enter\n"));
618 	/*
619 	 * Lookup controller name and return ops vector and controller
620 	 * structure
621 	 */
622 
623 	if (!chdl) {
624 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
625 		    "Invalid controller handle\n"));
626 		return (RSMERR_BAD_CTLR_HNDL);
627 	}
628 	if (!name) {
629 		/* use loopback if null */
630 		cntr_type = LOOPBACK;
631 	} else {
632 		(void) strcpy(cntr_name, name);
633 		/* scan from the end till a non-digit is found */
634 		for (i = strlen(cntr_name) - 1; i >= 0; i--) {
635 			if (! isdigit((int)cntr_name[i]))
636 				break;
637 		}
638 		i++;
639 		unit = atoi((char *)cntr_name+i);
640 		cntr_name[i] = '\0';	/* null terminate the cntr_type part */
641 		cntr_type = (char *)cntr_name;
642 		DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
643 		    "cntr_type=%s, instance=%d\n",
644 		    cntr_type, unit));
645 	}
646 
647 	/* protect the controller_list by locking the device/library */
648 	mutex_lock(&_rsm_lock);
649 
650 	for (p = controller_list; p; p = p->cntr_next) {
651 		if (!strcasecmp(p->cntr_name, cntr_type) &&
652 		    !strcasecmp(cntr_type, LOOPBACK)) {
653 			p->cntr_refcnt++;
654 			*chdl = (rsmapi_controller_handle_t)p;
655 			mutex_unlock(&_rsm_lock);
656 			DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
657 			    "rsm_get_controller: exit\n"));
658 			return (RSM_SUCCESS);
659 		} else if (!strcasecmp(p->cntr_name, cntr_type) &&
660 		    (p->cntr_unit == unit)) {
661 			p->cntr_refcnt++;
662 			*chdl = (rsmapi_controller_handle_t)p;
663 			mutex_unlock(&_rsm_lock);
664 			DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
665 			    "rsm_get_controller: exit\n"));
666 			return (RSM_SUCCESS);
667 		}
668 	}
669 
670 
671 	if (!strcasecmp(cntr_type, LOOPBACK)) {
672 		e = _rsm_loopbackload(cntr_type, unit,
673 		    (rsm_controller_t **)chdl);
674 	} else {
675 		e = _rsm_modload(cntr_type, unit, chdl);
676 	}
677 
678 	mutex_unlock(&_rsm_lock);
679 
680 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
681 	    " rsm_get_controller: exit\n"));
682 	return (e);
683 }
684 
685 int
686 _rsm_release_controller(rsmapi_controller_handle_t cntr_handle)
687 {
688 	int			e = RSM_SUCCESS;
689 	rsm_controller_t	*chdl = (rsm_controller_t *)cntr_handle;
690 	rsm_controller_t	*curr, *prev;
691 
692 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
693 	    "rsm_release_controller: enter\n"));
694 
695 	mutex_lock(&_rsm_lock);
696 
697 	if (chdl->cntr_refcnt == 0) {
698 		mutex_unlock(&_rsm_lock);
699 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
700 		    "controller reference count is zero\n"));
701 		return (RSMERR_BAD_CTLR_HNDL);
702 	}
703 
704 	chdl->cntr_refcnt--;
705 
706 	if (chdl->cntr_refcnt > 0) {
707 		mutex_unlock(&_rsm_lock);
708 		DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
709 		    "rsm_release_controller: exit\n"));
710 		return (RSM_SUCCESS);
711 	}
712 
713 	e = chdl->cntr_segops->rsm_closedevice(cntr_handle);
714 
715 	/*
716 	 * remove the controller in any case from the controller list
717 	 */
718 
719 	prev = curr = controller_list;
720 	while (curr != NULL) {
721 		if (curr == chdl) {
722 			if (curr == prev) {
723 				controller_list = curr->cntr_next;
724 			} else {
725 				prev->cntr_next = curr->cntr_next;
726 			}
727 			free(curr);
728 			break;
729 		}
730 		prev = curr;
731 		curr = curr->cntr_next;
732 	}
733 	mutex_unlock(&_rsm_lock);
734 
735 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
736 	    "rsm_release_controller: exit\n"));
737 
738 	return (e);
739 }
740 
741 int _rsm_get_controller_attr(rsmapi_controller_handle_t chandle,
742     rsmapi_controller_attr_t *attr)
743 {
744 	rsm_controller_t *p;
745 
746 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
747 	    "rsm_get_controller_attr: enter\n"));
748 
749 	if (!chandle) {
750 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
751 		    "invalid controller handle\n"));
752 		return (RSMERR_BAD_CTLR_HNDL);
753 	}
754 
755 	if (!attr) {
756 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
757 		    "invalid attribute pointer\n"));
758 		return (RSMERR_BAD_ADDR);
759 	}
760 
761 	p = (rsm_controller_t *)chandle;
762 
763 	mutex_lock(&_rsm_lock);
764 	if (p->cntr_refcnt == 0) {
765 		mutex_unlock(&_rsm_lock);
766 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
767 		    "cntr refcnt is 0\n"));
768 		return (RSMERR_CTLR_NOT_PRESENT);
769 	}
770 
771 	/* copy only the user part of the attr structure */
772 	attr->attr_direct_access_sizes =
773 	    p->cntr_attr.attr_direct_access_sizes;
774 	attr->attr_atomic_sizes =
775 	    p->cntr_attr.attr_atomic_sizes;
776 	attr->attr_page_size =
777 	    p->cntr_attr.attr_page_size;
778 	attr->attr_max_export_segment_size =
779 	    p->cntr_attr.attr_max_export_segment_size;
780 	attr->attr_tot_export_segment_size =
781 	    p->cntr_attr.attr_tot_export_segment_size;
782 	attr->attr_max_export_segments =
783 	    p->cntr_attr.attr_max_export_segments;
784 	attr->attr_max_import_map_size =
785 	    p->cntr_attr.attr_max_import_map_size;
786 	attr->attr_tot_import_map_size =
787 	    p->cntr_attr.attr_tot_import_map_size;
788 	attr->attr_max_import_segments =
789 	    p->cntr_attr.attr_max_import_segments;
790 
791 	mutex_unlock(&_rsm_lock);
792 
793 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
794 	    "rsm_get_controller_attr: exit\n"));
795 
796 	return (RSM_SUCCESS);
797 }
798 
799 
800 
801 /*
802  * Create a segment handle for the virtual address range specified
803  * by vaddr and size
804  */
805 int
806 _rsm_memseg_export_create(rsmapi_controller_handle_t controller,
807     rsm_memseg_export_handle_t *memseg,
808     void *vaddr,
809     size_t length,
810     uint_t flags)
811 {
812 
813 	rsm_controller_t *chdl = (rsm_controller_t *)controller;
814 	rsmseg_handle_t *p;
815 	rsm_ioctlmsg_t msg;
816 	int e;
817 #ifndef	_LP64
818 	int tmpfd;
819 #endif
820 
821 	DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
822 	    "rsm_memseg_export_create: enter\n"));
823 
824 	if (!controller) {
825 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
826 		    "invalid controller handle\n"));
827 		return (RSMERR_BAD_CTLR_HNDL);
828 	}
829 	if (!memseg) {
830 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
831 		    "invalid segment handle\n"));
832 		return (RSMERR_BAD_SEG_HNDL);
833 	}
834 
835 	*memseg = 0;
836 
837 	/*
838 	 * Check vaddr and size alignment, both must be mmu page size
839 	 * aligned
840 	 */
841 	if (!vaddr) {
842 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
843 		    "invalid arguments\n"));
844 		return (RSMERR_BAD_ADDR);
845 	}
846 
847 	if (!length) {
848 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
849 		    "invalid arguments\n"));
850 		return (RSMERR_BAD_LENGTH);
851 	}
852 
853 	if (((size_t)vaddr & (PAGESIZE - 1)) ||
854 		(length & (PAGESIZE - 1))) {
855 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
856 		    "invalid mem alignment for vaddr or length\n"));
857 		return (RSMERR_BAD_MEM_ALIGNMENT);
858 	}
859 
860 	/*
861 	 * The following check does not apply for loopback controller
862 	 * since for the loopback adapter, the attr_max_export_segment_size
863 	 * is always 0.
864 	 */
865 	if (strcasecmp(chdl->cntr_name, LOOPBACK)) {
866 		if (length > chdl->cntr_attr.attr_max_export_segment_size) {
867 			DBPRINTF((RSM_LIBRARY, RSM_ERR,
868 			    "length exceeds controller limits\n"));
869 			DBPRINTF((RSM_LIBRARY, RSM_ERR,
870 			    "controller limits %d\n",
871 			    chdl->cntr_attr.attr_max_export_segment_size));
872 			return (RSMERR_BAD_LENGTH);
873 		}
874 	}
875 
876 	p = (rsmseg_handle_t *)malloc(sizeof (*p));
877 	if (p == NULL) {
878 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
879 		    "not enough memory\n"));
880 		return (RSMERR_INSUFFICIENT_MEM);
881 	}
882 
883 	p->rsmseg_fd = open(DEVRSM, O_RDWR);
884 	if (p->rsmseg_fd < 0) {
885 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
886 		    "unable to open device /dev/rsm\n"));
887 		free((void *)p);
888 		return (RSMERR_INSUFFICIENT_RESOURCES);
889 	}
890 
891 #ifndef	_LP64
892 	/*
893 	 * libc can't handle fd's greater than 255,  in order to
894 	 * insure that these values remain available make /dev/rsm
895 	 * fd > 255. Note: not needed for LP64
896 	 */
897 	tmpfd = fcntl(p->rsmseg_fd, F_DUPFD, 256);
898 	e = errno;
899 	if (tmpfd < 0) {
900 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
901 		    "F_DUPFD failed\n"));
902 	} else {
903 		(void) close(p->rsmseg_fd);
904 		p->rsmseg_fd = tmpfd;
905 	}
906 #endif	/*	_LP64	*/
907 
908 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE, ""
909 	    "rsmseg_fd is %d\n", p->rsmseg_fd));
910 
911 	if (fcntl(p->rsmseg_fd, F_SETFD, FD_CLOEXEC) < 0) {
912 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
913 		    "F_SETFD failed\n"));
914 	}
915 
916 	p->rsmseg_state = EXPORT_CREATE;
917 	p->rsmseg_size = length;
918 	/* increment controller handle */
919 	p->rsmseg_controller = chdl;
920 
921 	/* try to bind user address range */
922 	msg.cnum = chdl->cntr_unit;
923 	msg.cname = chdl->cntr_name;
924 	msg.cname_len = strlen(chdl->cntr_name) +1;
925 	msg.vaddr = vaddr;
926 	msg.len = length;
927 	msg.perm = flags;
928 	msg.off = 0;
929 	e = RSM_IOCTL_BIND;
930 
931 	/* Try to bind */
932 	if (ioctl(p->rsmseg_fd, e, &msg) < 0) {
933 		e = errno;
934 		(void) close(p->rsmseg_fd);
935 		free((void *)p);
936 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
937 		    "RSM_IOCTL_BIND failed\n"));
938 		return (e);
939 	}
940 	/* OK */
941 	p->rsmseg_type = RSM_EXPORT_SEG;
942 	p->rsmseg_vaddr = vaddr;
943 	p->rsmseg_size = length;
944 	p->rsmseg_state = EXPORT_BIND;
945 	p->rsmseg_pollfd_refcnt = 0;
946 	p->rsmseg_rnum = msg.rnum;
947 
948 	mutex_init(&p->rsmseg_lock, USYNC_THREAD, NULL);
949 
950 	*memseg = (rsm_memseg_export_handle_t)p;
951 
952 	DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
953 	    "rsm_memseg_export_create: exit\n"));
954 
955 	return (RSM_SUCCESS);
956 }
957 
958 int
959 _rsm_memseg_export_destroy(rsm_memseg_export_handle_t memseg)
960 {
961 	rsmseg_handle_t *seg;
962 
963 	DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
964 	    "rsm_memseg_export_destroy: enter\n"));
965 
966 	if (!memseg) {
967 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
968 		    "invalid segment handle\n"));
969 		return (RSMERR_BAD_SEG_HNDL);
970 	}
971 
972 	seg = (rsmseg_handle_t *)memseg;
973 
974 	mutex_lock(&seg->rsmseg_lock);
975 	if (seg->rsmseg_pollfd_refcnt) {
976 		mutex_unlock(&seg->rsmseg_lock);
977 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
978 		    "segment reference count not zero\n"));
979 		return (RSMERR_POLLFD_IN_USE);
980 	}
981 	else
982 		seg->rsmseg_state = EXPORT_BIND;
983 
984 	mutex_unlock(&seg->rsmseg_lock);
985 
986 	(void) close(seg->rsmseg_fd);
987 	mutex_destroy(&seg->rsmseg_lock);
988 	free((void *)seg);
989 
990 	DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
991 	    "rsm_memseg_export_destroy: exit\n"));
992 
993 	return (RSM_SUCCESS);
994 }
995 
996 int
997 _rsm_memseg_export_rebind(rsm_memseg_export_handle_t memseg, void *vaddr,
998     offset_t off, size_t length)
999 {
1000 	rsm_ioctlmsg_t msg;
1001 	rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
1002 
1003 	DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
1004 	    "rsm_memseg_export_rebind: enter\n"));
1005 
1006 	off = off;
1007 
1008 	if (!seg) {
1009 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1010 		    "invalid segment handle\n"));
1011 		return (RSMERR_BAD_SEG_HNDL);
1012 	}
1013 	if (!vaddr) {
1014 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1015 		    "invalid vaddr\n"));
1016 		return (RSMERR_BAD_ADDR);
1017 	}
1018 
1019 	/*
1020 	 * Same as bind except it's ok to have elimint in list.
1021 	 * Call into driver to remove any existing mappings.
1022 	 */
1023 	msg.vaddr = vaddr;
1024 	msg.len = length;
1025 	msg.off = 0;
1026 
1027 	mutex_lock(&seg->rsmseg_lock);
1028 	if (ioctl(seg->rsmseg_fd, RSM_IOCTL_REBIND, &msg) < 0) {
1029 		mutex_unlock(&seg->rsmseg_lock);
1030 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1031 		    "RSM_IOCTL_REBIND failed\n"));
1032 		return (errno);
1033 	}
1034 
1035 	mutex_unlock(&seg->rsmseg_lock);
1036 
1037 	DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
1038 	    "rsm_memseg_export_rebind: exit\n"));
1039 
1040 	return (RSM_SUCCESS);
1041 }
1042 
1043 int
1044 _rsm_memseg_export_publish(rsm_memseg_export_handle_t memseg,
1045     rsm_memseg_id_t *seg_id,
1046     rsmapi_access_entry_t access_list[],
1047     uint_t access_list_length)
1048 
1049 {
1050 	rsm_ioctlmsg_t msg;
1051 	rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
1052 
1053 	DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
1054 	    "rsm_memseg_export_publish: enter\n"));
1055 
1056 	if (seg_id == NULL) {
1057 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1058 		    "invalid segment id\n"));
1059 		return (RSMERR_BAD_SEGID);
1060 	}
1061 
1062 	if (!seg) {
1063 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1064 		    "invalid segment handle\n"));
1065 		return (RSMERR_BAD_SEG_HNDL);
1066 	}
1067 
1068 	if (access_list_length > 0 && !access_list) {
1069 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1070 		    "invalid access control list\n"));
1071 		return (RSMERR_BAD_ACL);
1072 	}
1073 
1074 	mutex_lock(&seg->rsmseg_lock);
1075 	if (seg->rsmseg_state != EXPORT_BIND) {
1076 		mutex_unlock(&seg->rsmseg_lock);
1077 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1078 		    "invalid segment state\n"));
1079 		return (RSMERR_SEG_ALREADY_PUBLISHED);
1080 	}
1081 
1082 	/*
1083 	 * seg id < RSM_DLPI_END and in the RSM_USER_APP_ID range
1084 	 * are reserved for internal use.
1085 	 */
1086 	if ((*seg_id > 0) &&
1087 	    ((*seg_id <= RSM_DLPI_ID_END) ||
1088 	    BETWEEN (*seg_id, RSM_USER_APP_ID_BASE, RSM_USER_APP_ID_END))) {
1089 		mutex_unlock(&seg->rsmseg_lock);
1090 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1091 		    "invalid segment id\n"));
1092 		return (RSMERR_RESERVED_SEGID);
1093 	}
1094 
1095 	msg.key = *seg_id;
1096 	msg.acl = access_list;
1097 	msg.acl_len = access_list_length;
1098 
1099 	if (ioctl(seg->rsmseg_fd, RSM_IOCTL_PUBLISH, &msg) < 0) {
1100 		mutex_unlock(&seg->rsmseg_lock);
1101 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1102 		    "RSM_IOCTL_PUBLISH failed\n"));
1103 		return (errno);
1104 	}
1105 
1106 	seg->rsmseg_keyid = msg.key;
1107 	seg->rsmseg_state = EXPORT_PUBLISH;
1108 	mutex_unlock(&seg->rsmseg_lock);
1109 
1110 	if (*seg_id == 0)
1111 		*seg_id = msg.key;
1112 
1113 	DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
1114 	    "rsm_memseg_export_publish: exit\n"));
1115 
1116 	return (RSM_SUCCESS);
1117 
1118 }
1119 
1120 int
1121 _rsm_memseg_export_unpublish(rsm_memseg_export_handle_t memseg)
1122 {
1123 	rsm_ioctlmsg_t msg;
1124 	rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
1125 
1126 	DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
1127 	    "rsm_memseg_export_unpublish: enter\n"));
1128 
1129 	if (!seg) {
1130 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1131 		    "invalid arguments\n"));
1132 		return (RSMERR_BAD_SEG_HNDL);
1133 	}
1134 
1135 	mutex_lock(&seg->rsmseg_lock);
1136 	if (seg->rsmseg_state != EXPORT_PUBLISH) {
1137 		mutex_unlock(&seg->rsmseg_lock);
1138 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1139 		    "segment not published %d\n",
1140 			seg->rsmseg_keyid));
1141 		return (RSMERR_SEG_NOT_PUBLISHED);
1142 	}
1143 
1144 	msg.key = seg->rsmseg_keyid;
1145 	if (ioctl(seg->rsmseg_fd, RSM_IOCTL_UNPUBLISH, &msg) < 0) {
1146 		mutex_unlock(&seg->rsmseg_lock);
1147 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1148 		    "RSM_IOCTL_UNPUBLISH failed\n"));
1149 		return (errno);
1150 	}
1151 
1152 	seg->rsmseg_state = EXPORT_BIND;
1153 	mutex_unlock(&seg->rsmseg_lock);
1154 
1155 	DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
1156 	    "rsm_memseg_export_unpublish: exit\n"));
1157 
1158 	return (RSM_SUCCESS);
1159 }
1160 
1161 
1162 int
1163 _rsm_memseg_export_republish(rsm_memseg_export_handle_t memseg,
1164     rsmapi_access_entry_t access_list[],
1165     uint_t access_list_length)
1166 {
1167 	rsm_ioctlmsg_t msg;
1168 	rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
1169 
1170 	DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
1171 	    "rsm_memseg_export_republish: enter\n"));
1172 
1173 	if (!seg) {
1174 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1175 		    "invalid segment or segment state\n"));
1176 		return (RSMERR_BAD_SEG_HNDL);
1177 	}
1178 
1179 	mutex_lock(&seg->rsmseg_lock);
1180 	if (seg->rsmseg_state != EXPORT_PUBLISH) {
1181 		mutex_unlock(&seg->rsmseg_lock);
1182 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1183 		    "segment not published\n"));
1184 		return (RSMERR_SEG_NOT_PUBLISHED);
1185 	}
1186 
1187 	if (access_list_length > 0 && !access_list) {
1188 		mutex_unlock(&seg->rsmseg_lock);
1189 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1190 		    "invalid access control list\n"));
1191 		return (RSMERR_BAD_ACL);
1192 	}
1193 
1194 	msg.key = seg->rsmseg_keyid;
1195 	msg.acl = access_list;
1196 	msg.acl_len = access_list_length;
1197 
1198 	if (ioctl(seg->rsmseg_fd, RSM_IOCTL_REPUBLISH, &msg) < 0) {
1199 		mutex_unlock(&seg->rsmseg_lock);
1200 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1201 		    "RSM_IOCTL_REPUBLISH failed\n"));
1202 		return (errno);
1203 	}
1204 	mutex_unlock(&seg->rsmseg_lock);
1205 
1206 	DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
1207 	    "rsm_memseg_export_republish: exit\n"));
1208 
1209 	return (RSM_SUCCESS);
1210 }
1211 
1212 
1213 	/*
1214 	 * import side memory segment operations:
1215 	 */
1216 int
1217 _rsm_memseg_import_connect(rsmapi_controller_handle_t controller,
1218     rsm_node_id_t node_id,
1219     rsm_memseg_id_t segment_id,
1220     rsm_permission_t perm,
1221     rsm_memseg_import_handle_t *im_memseg)
1222 {
1223 	rsm_ioctlmsg_t msg;
1224 	rsmseg_handle_t *p;
1225 	rsm_controller_t *cntr = (rsm_controller_t *)controller;
1226 #ifndef	_LP64		/* added for fd > 255 fix */
1227 	int tmpfd;
1228 #endif
1229 	int e;
1230 
1231 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1232 	    "rsm_memseg_import_connect: enter\n"));
1233 
1234 	if (!cntr) {
1235 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1236 		    "invalid controller handle\n"));
1237 		return (RSMERR_BAD_CTLR_HNDL);
1238 	}
1239 
1240 	*im_memseg = 0;
1241 
1242 	p = (rsmseg_handle_t *)malloc(sizeof (*p));
1243 	if (!p) {
1244 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1245 		    "not enough memory\n"));
1246 		return (RSMERR_INSUFFICIENT_MEM);
1247 	}
1248 
1249 	if (perm & ~RSM_PERM_RDWR) {
1250 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1251 		    "invalid permissions\n"));
1252 		return (RSMERR_PERM_DENIED);
1253 	}
1254 
1255 	/*
1256 	 * Get size, va from driver
1257 	 */
1258 	msg.cnum = cntr->cntr_unit;
1259 	msg.cname = cntr->cntr_name;
1260 	msg.cname_len = strlen(cntr->cntr_name) +1;
1261 	msg.nodeid = node_id;
1262 	msg.key = segment_id;
1263 	msg.perm = perm;
1264 
1265 	p->rsmseg_fd = open(DEVRSM, O_RDWR);
1266 	if (p->rsmseg_fd < 0) {
1267 		    DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1268 			"unable to open /dev/rsm"));
1269 		free((void *)p);
1270 		return (RSMERR_INSUFFICIENT_RESOURCES);
1271 	}
1272 
1273 #ifndef	_LP64
1274 	/*
1275 	 * libc can't handle fd's greater than 255,  in order to
1276 	 * insure that these values remain available make /dev/rsm
1277 	 * fd > 255. Note: not needed for LP64
1278 	 */
1279 	tmpfd = fcntl(p->rsmseg_fd, F_DUPFD, 256); /* make fd > 255 */
1280 	e = errno;
1281 	if (tmpfd < 0) {
1282 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1283 		    "F_DUPFD failed\n"));
1284 	} else {
1285 		(void) close(p->rsmseg_fd);
1286 		p->rsmseg_fd = tmpfd;
1287 	}
1288 #endif	/* _LP64 */
1289 
1290 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
1291 	    "rsmseg_fd is %d\n", p->rsmseg_fd));
1292 
1293 	if (fcntl(p->rsmseg_fd, F_SETFD, FD_CLOEXEC) < 0) {
1294 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1295 		    "F_SETFD failed\n"));
1296 	}
1297 	if (ioctl(p->rsmseg_fd, RSM_IOCTL_CONNECT, &msg) < 0) {
1298 		e = errno;
1299 		(void) close(p->rsmseg_fd);
1300 		free((void *)p);
1301 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1302 		    "RSM_IOCTL_CONNECT failed\n"));
1303 		return (e);
1304 	}
1305 
1306 	/*
1307 	 * We connected ok.
1308 	 */
1309 	p->rsmseg_type = RSM_IMPORT_SEG;
1310 	p->rsmseg_state = IMPORT_CONNECT;
1311 	p->rsmseg_keyid = segment_id;
1312 	p->rsmseg_nodeid = node_id;
1313 	p->rsmseg_size = msg.len;
1314 	p->rsmseg_perm = perm;
1315 	p->rsmseg_controller = cntr;
1316 	p->rsmseg_barrier = NULL;
1317 	p->rsmseg_barmode = RSM_BARRIER_MODE_IMPLICIT;
1318 	p->rsmseg_bar = (bar_va ? bar_va + msg.off : &bar_fixed);
1319 	p->rsmseg_gnum = msg.gnum;
1320 	p->rsmseg_pollfd_refcnt = 0;
1321 	p->rsmseg_maplen = 0;    /* initialized, set in import_map */
1322 	p->rsmseg_mapoffset = 0;
1323 	p->rsmseg_flags = 0;
1324 	p->rsmseg_rnum = msg.rnum;
1325 	mutex_init(&p->rsmseg_lock, USYNC_THREAD, NULL);
1326 
1327 	p->rsmseg_ops = cntr->cntr_segops;
1328 
1329 	/*
1330 	 * XXX: Based on permission and controller direct_access attribute
1331 	 * we fix the segment ops vector
1332 	 */
1333 
1334 	p->rsmseg_vaddr = 0; /* defer mapping till using maps or trys to rw */
1335 
1336 	*im_memseg = (rsm_memseg_import_handle_t)p;
1337 
1338 	e =  p->rsmseg_ops->rsm_memseg_import_connect(controller,
1339 	    node_id, segment_id, perm, im_memseg);
1340 
1341 	if (e != RSM_SUCCESS) {
1342 		(void) close(p->rsmseg_fd);
1343 		mutex_destroy(&p->rsmseg_lock);
1344 		free((void *)p);
1345 	}
1346 
1347 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1348 	    "rsm_memseg_import_connect: exit\n"));
1349 
1350 	return (e);
1351 }
1352 
1353 
1354 int
1355 _rsm_memseg_import_disconnect(rsm_memseg_import_handle_t im_memseg)
1356 {
1357 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1358 	int e;
1359 
1360 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1361 	    "rsm_memseg_import_disconnect: enter\n"));
1362 
1363 	if (!seg) {
1364 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1365 		    "invalid segment handle\n"));
1366 		return (RSMERR_BAD_SEG_HNDL);
1367 	}
1368 
1369 	if (seg->rsmseg_state != IMPORT_CONNECT) {
1370 		if (seg->rsmseg_flags & RSM_IMPLICIT_MAP) {
1371 			e = rsm_memseg_import_unmap(im_memseg);
1372 			if (e != RSM_SUCCESS) {
1373 				DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1374 				    "unmap failure\n"));
1375 				return (e);
1376 			}
1377 		} else {
1378 			DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1379 			    "segment busy\n"));
1380 			return (RSMERR_SEG_STILL_MAPPED);
1381 		}
1382 	}
1383 
1384 	mutex_lock(&seg->rsmseg_lock);
1385 	if (seg->rsmseg_pollfd_refcnt) {
1386 		mutex_unlock(&seg->rsmseg_lock);
1387 		DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1388 		    "segment reference count not zero\n"));
1389 		return (RSMERR_POLLFD_IN_USE);
1390 	}
1391 	mutex_unlock(&seg->rsmseg_lock);
1392 
1393 	e =  seg->rsmseg_ops->rsm_memseg_import_disconnect(im_memseg);
1394 
1395 	if (e == RSM_SUCCESS) {
1396 		(void) close(seg->rsmseg_fd);
1397 		mutex_destroy(&seg->rsmseg_lock);
1398 		free((void *)seg);
1399 	}
1400 
1401 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1402 	    "rsm_memseg_import_disconnect: exit\n"));
1403 
1404 	return (e);
1405 }
1406 
1407 /*
1408  * import side memory segment operations (read access functions):
1409  */
1410 
1411 static int
1412 __rsm_import_verify_access(rsmseg_handle_t *seg,
1413     off_t offset,
1414     caddr_t datap,
1415     size_t len,
1416     rsm_permission_t perm,
1417     rsm_access_size_t das)
1418 {
1419 	int	error;
1420 
1421 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1422 	    " __rsm_import_verify_access: enter\n"));
1423 
1424 	if (!seg) {
1425 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1426 		    "invalid segment handle\n"));
1427 		return (RSMERR_BAD_SEG_HNDL);
1428 	}
1429 	if (!datap) {
1430 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1431 		    "invalid data pointer\n"));
1432 		return (RSMERR_BAD_ADDR);
1433 	}
1434 
1435 	/*
1436 	 * Check alignment of pointer
1437 	 */
1438 	if ((uintptr_t)datap & (das - 1)) {
1439 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1440 		    "invalid alignment of data pointer\n"));
1441 		return (RSMERR_BAD_MEM_ALIGNMENT);
1442 	}
1443 
1444 	if (offset & (das - 1)) {
1445 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1446 		    "invalid offset\n"));
1447 		return (RSMERR_BAD_MEM_ALIGNMENT);
1448 	}
1449 
1450 	/* make sure that the import seg is connected */
1451 	if (seg->rsmseg_state != IMPORT_CONNECT &&
1452 	    seg->rsmseg_state != IMPORT_MAP) {
1453 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1454 		    "incorrect segment state\n"));
1455 		return (RSMERR_BAD_SEG_HNDL);
1456 	}
1457 
1458 	/* do an implicit map if required */
1459 	if (seg->rsmseg_state == IMPORT_CONNECT) {
1460 		error = __rsm_import_implicit_map(seg, RSM_IOTYPE_PUTGET);
1461 		if (error != RSM_SUCCESS) {
1462 			DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1463 			    "implicit map failure\n"));
1464 			return (error);
1465 		}
1466 	}
1467 
1468 	if ((seg->rsmseg_perm & perm) != perm) {
1469 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1470 		    "invalid permissions\n"));
1471 		return (RSMERR_PERM_DENIED);
1472 	}
1473 
1474 	if (seg->rsmseg_state == IMPORT_MAP) {
1475 		if ((offset < seg->rsmseg_mapoffset) ||
1476 		    (offset + len > seg->rsmseg_mapoffset +
1477 		    seg->rsmseg_maplen)) {
1478 			DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1479 			    "incorrect offset+length\n"));
1480 			return (RSMERR_BAD_OFFSET);
1481 		}
1482 	} else { /* IMPORT_CONNECT */
1483 		if ((len + offset) > seg->rsmseg_size) {
1484 			DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1485 			    "incorrect offset+length\n"));
1486 			return (RSMERR_BAD_LENGTH);
1487 		}
1488 	}
1489 
1490 	if ((seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) &&
1491 	    (seg->rsmseg_barrier == NULL)) {
1492 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1493 		    "invalid barrier\n"));
1494 		return (RSMERR_BARRIER_UNINITIALIZED);
1495 	}
1496 
1497 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1498 	    " __rsm_import_verify_access: exit\n"));
1499 
1500 	return (RSM_SUCCESS);
1501 }
1502 
1503 static int
1504 __rsm_import_implicit_map(rsmseg_handle_t *seg, int iotype)
1505 {
1506 	caddr_t va;
1507 	int flag = MAP_SHARED;
1508 	int prot = PROT_READ|PROT_WRITE;
1509 	int mapping_reqd = 0;
1510 
1511 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1512 	    " __rsm_import_implicit_map: enter\n"));
1513 
1514 	if (iotype == RSM_IOTYPE_PUTGET)
1515 		mapping_reqd = seg->rsmseg_controller->cntr_lib_attr->
1516 		    rsm_putget_map_reqd;
1517 	else if (iotype == RSM_IOTYPE_SCATGATH)
1518 		mapping_reqd = seg->rsmseg_controller->cntr_lib_attr->
1519 		    rsm_scatgath_map_reqd;
1520 
1521 
1522 	if (mapping_reqd) {
1523 		va = mmap(NULL, seg->rsmseg_size, prot,
1524 		    flag, seg->rsmseg_fd, 0);
1525 
1526 		if (va == MAP_FAILED) {
1527 			DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1528 			    "implicit map failed\n"));
1529 			if (errno == ENOMEM || errno == ENXIO ||
1530 			    errno == EOVERFLOW)
1531 				return (RSMERR_BAD_LENGTH);
1532 			else if (errno == ENODEV)
1533 				return (RSMERR_CONN_ABORTED);
1534 			else if (errno == EAGAIN)
1535 				return (RSMERR_INSUFFICIENT_RESOURCES);
1536 			else if (errno == ENOTSUP)
1537 				return (RSMERR_MAP_FAILED);
1538 			else if (errno == EACCES)
1539 				return (RSMERR_BAD_PERMS);
1540 			else
1541 				return (RSMERR_MAP_FAILED);
1542 		}
1543 		seg->rsmseg_vaddr = va;
1544 		seg->rsmseg_maplen = seg->rsmseg_size;
1545 		seg->rsmseg_mapoffset = 0;
1546 		seg->rsmseg_state = IMPORT_MAP;
1547 		seg->rsmseg_flags |= RSM_IMPLICIT_MAP;
1548 	}
1549 
1550 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1551 	    " __rsm_import_implicit_map: exit\n"));
1552 
1553 	return (RSM_SUCCESS);
1554 }
1555 
1556 int
1557 _rsm_memseg_import_get8(rsm_memseg_import_handle_t im_memseg,
1558     off_t offset,
1559     uint8_t *datap,
1560     ulong_t rep_cnt)
1561 {
1562 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1563 	int e;
1564 
1565 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1566 	    "rsm_memseg_import_get8: enter\n"));
1567 
1568 	e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt,
1569 	    RSM_PERM_READ,
1570 	    RSM_DAS8);
1571 	if (e == RSM_SUCCESS) {
1572 		rsm_segops_t *ops = seg->rsmseg_ops;
1573 		rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1574 
1575 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1576 			/* generation number snapshot */
1577 			bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1578 		}
1579 
1580 		e = ops->rsm_memseg_import_get8(im_memseg, offset, datap,
1581 		    rep_cnt, 0);
1582 
1583 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1584 			/* check the generation number for force disconnects */
1585 			if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1586 				return (RSMERR_CONN_ABORTED);
1587 			}
1588 		}
1589 	}
1590 
1591 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1592 	    "rsm_memseg_import_get8: exit\n"));
1593 
1594 	return (e);
1595 }
1596 
1597 int
1598 _rsm_memseg_import_get16(rsm_memseg_import_handle_t im_memseg,
1599     off_t offset,
1600     uint16_t *datap,
1601     ulong_t rep_cnt)
1602 {
1603 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1604 	int e;
1605 
1606 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1607 	    "rsm_memseg_import_get16: enter\n"));
1608 
1609 	e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt*2,
1610 	    RSM_PERM_READ,
1611 	    RSM_DAS16);
1612 	if (e == RSM_SUCCESS) {
1613 		rsm_segops_t *ops = seg->rsmseg_ops;
1614 		rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1615 
1616 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1617 			/* generation number snapshot */
1618 			bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1619 		}
1620 
1621 		e = ops->rsm_memseg_import_get16(im_memseg, offset, datap,
1622 		    rep_cnt, 0);
1623 
1624 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1625 			/* check the generation number for force disconnects */
1626 			if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1627 				return (RSMERR_CONN_ABORTED);
1628 			}
1629 		}
1630 
1631 	}
1632 
1633 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1634 	    "rsm_memseg_import_get16: exit\n"));
1635 
1636 	return (e);
1637 }
1638 
1639 int
1640 _rsm_memseg_import_get32(rsm_memseg_import_handle_t im_memseg,
1641     off_t offset,
1642     uint32_t *datap,
1643     ulong_t rep_cnt)
1644 {
1645 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1646 	int e;
1647 
1648 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1649 	    "rsm_memseg_import_get32: enter\n"));
1650 
1651 	e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt*4,
1652 	    RSM_PERM_READ,
1653 	    RSM_DAS32);
1654 	if (e == RSM_SUCCESS) {
1655 		rsm_segops_t *ops = seg->rsmseg_ops;
1656 		rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1657 
1658 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1659 			/* generation number snapshot */
1660 			bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1661 		}
1662 
1663 		e = ops->rsm_memseg_import_get32(im_memseg, offset, datap,
1664 		    rep_cnt, 0);
1665 
1666 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1667 			/* check the generation number for force disconnects */
1668 			if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1669 				return (RSMERR_CONN_ABORTED);
1670 			}
1671 		}
1672 	}
1673 
1674 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1675 	    "rsm_memseg_import_get32: exit\n"));
1676 
1677 	return (e);
1678 }
1679 
1680 int
1681 _rsm_memseg_import_get64(rsm_memseg_import_handle_t im_memseg,
1682     off_t offset,
1683     uint64_t *datap,
1684     ulong_t rep_cnt)
1685 {
1686 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1687 	int e;
1688 
1689 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1690 	    "rsm_memseg_import_get64: enter\n"));
1691 
1692 	e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt*8,
1693 	    RSM_PERM_READ,
1694 	    RSM_DAS64);
1695 	if (e == RSM_SUCCESS) {
1696 		rsm_segops_t *ops = seg->rsmseg_ops;
1697 		rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1698 
1699 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1700 			/* generation number snapshot */
1701 			bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1702 		}
1703 
1704 		e = ops->rsm_memseg_import_get64(im_memseg, offset, datap,
1705 		    rep_cnt, 0);
1706 
1707 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1708 			/* check the generation number for force disconnects */
1709 			if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1710 				return (RSMERR_CONN_ABORTED);
1711 			}
1712 		}
1713 	}
1714 
1715 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1716 	    "rsm_memseg_import_get64: exit\n"));
1717 
1718 	return (e);
1719 }
1720 
1721 int
1722 _rsm_memseg_import_get(rsm_memseg_import_handle_t im_memseg,
1723     off_t offset,
1724     void *dst_addr,
1725     size_t length)
1726 {
1727 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1728 	int e;
1729 
1730 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1731 	    "rsm_memseg_import_get: enter\n"));
1732 
1733 	e = __rsm_import_verify_access(seg, offset, (caddr_t)dst_addr, length,
1734 	    RSM_PERM_READ,
1735 	    RSM_DAS8);
1736 	if (e == RSM_SUCCESS) {
1737 		rsm_segops_t *ops = seg->rsmseg_ops;
1738 		rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1739 
1740 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1741 			/* generation number snapshot */
1742 			bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1743 		}
1744 
1745 		e = ops->rsm_memseg_import_get(im_memseg, offset, dst_addr,
1746 		    length);
1747 
1748 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1749 			/* check the generation number for force disconnects */
1750 			if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1751 				return (RSMERR_CONN_ABORTED);
1752 			}
1753 		}
1754 	}
1755 
1756 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1757 	    "rsm_memseg_import_get: exit\n"));
1758 
1759 	return (e);
1760 }
1761 
1762 
1763 int
1764 _rsm_memseg_import_getv(rsm_scat_gath_t *sg_io)
1765 {
1766 	rsm_controller_t *cntrl;
1767 	rsmseg_handle_t *seg;
1768 	uint_t save_sg_io_flags;
1769 
1770 	int e;
1771 
1772 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1773 	    "rsm_memseg_import_getv: enter\n"));
1774 
1775 	if (sg_io == NULL) {
1776 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1777 		    "invalid sg_io structure\n"));
1778 		return (RSMERR_BAD_SGIO);
1779 	}
1780 
1781 	seg = (rsmseg_handle_t *)sg_io->remote_handle;
1782 	if (seg == NULL) {
1783 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1784 		    "invalid remote segment handle in sg_io\n"));
1785 		return (RSMERR_BAD_SEG_HNDL);
1786 	}
1787 
1788 	cntrl = (rsm_controller_t *)seg->rsmseg_controller;
1789 	if (cntrl == NULL) {
1790 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1791 		    "invalid controller handle\n"));
1792 		return (RSMERR_BAD_SEG_HNDL);
1793 	}
1794 
1795 	if ((sg_io->io_request_count > RSM_MAX_SGIOREQS) ||
1796 	    (sg_io->io_request_count == 0)) {
1797 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1798 		    "io_request_count value incorrect\n"));
1799 		return (RSMERR_BAD_SGIO);
1800 	}
1801 
1802 	if (seg->rsmseg_state == IMPORT_CONNECT) {
1803 		e = __rsm_import_implicit_map(seg, RSM_IOTYPE_SCATGATH);
1804 		if (e != RSM_SUCCESS) {
1805 			DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1806 			    "implicit map failure\n"));
1807 			return (e);
1808 		}
1809 	}
1810 
1811 	/*
1812 	 * Copy the flags field of the sg_io structure in a local
1813 	 * variable.
1814 	 * This is required since the flags field can be
1815 	 * changed by the plugin library routine to indicate that
1816 	 * the signal post was done.
1817 	 * This change in the flags field of the sg_io structure
1818 	 * should not be reflected to the user. Hence once the flags
1819 	 * field has been used for the purpose of determining whether
1820 	 * the plugin executed a signal post, it must be restored to
1821 	 * its original value which is stored in the local variable.
1822 	 */
1823 	save_sg_io_flags = sg_io->flags;
1824 
1825 	e = cntrl->cntr_segops->rsm_memseg_import_getv(sg_io);
1826 
1827 	/*
1828 	 * At this point, if an implicit signal post was requested by
1829 	 * the user, there could be two possibilities that arise:
1830 	 * 1. the plugin routine has already executed the implicit
1831 	 *    signal post either successfully or unsuccessfully
1832 	 * 2. the plugin does not have the capability of doing an
1833 	 *    implicit signal post and hence the signal post needs
1834 	 *    to be done here.
1835 	 * The above two cases can be idenfied by the flags
1836 	 * field within the sg_io structure as follows:
1837 	 * In case 1, the RSM_IMPLICIT_SIGPOST bit is reset to 0 by the
1838 	 * plugin, indicating that the signal post was done.
1839 	 * In case 2, the bit remains set to a 1 as originally given
1840 	 * by the user, and hence a signal post needs to be done here.
1841 	 */
1842 	if (sg_io->flags & RSM_IMPLICIT_SIGPOST &&
1843 	    e == RSM_SUCCESS) {
1844 		/* Do the implicit signal post */
1845 
1846 		/*
1847 		 * The value of the second argument to this call
1848 		 * depends on the value of the sg_io->flags field.
1849 		 * If the RSM_SIGPOST_NO_ACCUMULATE flag has been
1850 		 * ored into the sg_io->flags field, this indicates
1851 		 * that the rsm_intr_signal_post is to be done with
1852 		 * the flags argument set to RSM_SIGPOST_NO_ACCUMULATE
1853 		 * Else, the flags argument is set to 0. These
1854 		 * semantics can be achieved simply by masking off
1855 		 * all other bits in the sg_io->flags field except the
1856 		 * RSM_SIGPOST_NO_ACCUMULATE bit and using the result
1857 		 * as the flags argument for the rsm_intr_signal_post.
1858 		 */
1859 
1860 		int sigpost_flags = sg_io->flags & RSM_SIGPOST_NO_ACCUMULATE;
1861 		e = rsm_intr_signal_post(seg, sigpost_flags);
1862 	}
1863 
1864 	/* Restore the flags field within the users scatter gather structure */
1865 	sg_io->flags = save_sg_io_flags;
1866 
1867 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1868 	    "rsm_memseg_import_getv: exit\n"));
1869 
1870 	return (e);
1871 
1872 }
1873 
1874 	/*
1875 	 * import side memory segment operations (write access functions):
1876 	 */
1877 
1878 int
1879 _rsm_memseg_import_put8(rsm_memseg_import_handle_t im_memseg,
1880     off_t offset,
1881     uint8_t *datap,
1882     ulong_t rep_cnt)
1883 {
1884 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1885 	int e;
1886 
1887 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1888 	    "rsm_memseg_import_put8: enter\n"));
1889 
1890 	/* addr of data will always pass the alignment check, avoids	*/
1891 	/* need for a special case in verify_access for PUTs		*/
1892 	e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt,
1893 	    RSM_PERM_WRITE,
1894 	    RSM_DAS8);
1895 	if (e == RSM_SUCCESS) {
1896 		rsm_segops_t *ops = seg->rsmseg_ops;
1897 		rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1898 
1899 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1900 			/* generation number snapshot */
1901 			bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1902 		}
1903 
1904 		e = ops->rsm_memseg_import_put8(im_memseg, offset, datap,
1905 		    rep_cnt, 0);
1906 
1907 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1908 			/* check the generation number for force disconnects */
1909 			if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1910 				return (RSMERR_CONN_ABORTED);
1911 			}
1912 		}
1913 	}
1914 
1915 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1916 	    "rsm_memseg_import_put8: exit\n"));
1917 
1918 	return (e);
1919 }
1920 
1921 int
1922 _rsm_memseg_import_put16(rsm_memseg_import_handle_t im_memseg,
1923     off_t offset,
1924     uint16_t *datap,
1925     ulong_t rep_cnt)
1926 {
1927 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1928 	int e;
1929 
1930 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1931 	    "rsm_memseg_import_put16: enter\n"));
1932 
1933 	/* addr of data will always pass the alignment check, avoids	*/
1934 	/* need for a special case in verify_access for PUTs		*/
1935 	e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt*2,
1936 	    RSM_PERM_WRITE,
1937 	    RSM_DAS16);
1938 	if (e == RSM_SUCCESS) {
1939 		rsm_segops_t *ops = seg->rsmseg_ops;
1940 		rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1941 
1942 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1943 			/* generation number snapshot */
1944 			bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1945 		}
1946 
1947 		e = ops->rsm_memseg_import_put16(im_memseg, offset, datap,
1948 		    rep_cnt, 0);
1949 
1950 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1951 			/* check the generation number for force disconnects */
1952 			if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1953 				return (RSMERR_CONN_ABORTED);
1954 			}
1955 		}
1956 
1957 	}
1958 
1959 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1960 	    "rsm_memseg_import_put16: exit\n"));
1961 
1962 	return (e);
1963 }
1964 
1965 int
1966 _rsm_memseg_import_put32(rsm_memseg_import_handle_t im_memseg,
1967     off_t offset,
1968     uint32_t *datap,
1969     ulong_t rep_cnt)
1970 {
1971 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1972 	int e;
1973 
1974 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1975 	    "rsm_memseg_import_put32: enter\n"));
1976 
1977 	/* addr of data will always pass the alignment check, avoids	*/
1978 	/* need for a special case in verify_access for PUTs		*/
1979 	e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt*4,
1980 	    RSM_PERM_WRITE,
1981 	    RSM_DAS32);
1982 	if (e == RSM_SUCCESS) {
1983 		rsm_segops_t *ops = seg->rsmseg_ops;
1984 		rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1985 
1986 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1987 			/* generation number snapshot */
1988 			bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1989 		}
1990 
1991 		e = ops->rsm_memseg_import_put32(im_memseg, offset, datap,
1992 		    rep_cnt, 0);
1993 
1994 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1995 			/* check the generation number for force disconnects */
1996 			if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1997 				return (RSMERR_CONN_ABORTED);
1998 			}
1999 		}
2000 	}
2001 
2002 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2003 	    "rsm_memseg_import_put32: exit\n"));
2004 
2005 	return (e);
2006 }
2007 
2008 int
2009 _rsm_memseg_import_put64(rsm_memseg_import_handle_t im_memseg,
2010     off_t offset,
2011     uint64_t *datap,
2012     ulong_t rep_cnt)
2013 {
2014 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
2015 	int		e;
2016 
2017 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2018 	    "rsm_memseg_import_put64: enter\n"));
2019 
2020 	/* addr of data will always pass the alignment check, avoids	*/
2021 	/* need for a special case in verify_access for PUTs		*/
2022 	e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt*8,
2023 	    RSM_PERM_WRITE,
2024 	    RSM_DAS64);
2025 	if (e == RSM_SUCCESS) {
2026 		rsm_segops_t *ops = seg->rsmseg_ops;
2027 		rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
2028 
2029 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
2030 			/* generation number snapshot */
2031 			bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
2032 		}
2033 
2034 		e = ops->rsm_memseg_import_put64(im_memseg, offset, datap,
2035 		    rep_cnt, 0);
2036 
2037 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
2038 			/* check the generation number for force disconnects */
2039 			if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
2040 				return (RSMERR_CONN_ABORTED);
2041 			}
2042 		}
2043 	}
2044 
2045 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2046 	    "rsm_memseg_import_put64: exit\n"));
2047 
2048 	return (e);
2049 }
2050 
2051 int
2052 _rsm_memseg_import_put(rsm_memseg_import_handle_t im_memseg,
2053     off_t offset,
2054     void *src_addr,
2055     size_t length)
2056 {
2057 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
2058 	int e;
2059 
2060 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2061 	    "rsm_memseg_import_put: enter\n"));
2062 
2063 	e = __rsm_import_verify_access(seg, offset, (caddr_t)src_addr, length,
2064 	    RSM_PERM_WRITE,
2065 	    RSM_DAS8);
2066 	if (e == RSM_SUCCESS) {
2067 		rsm_segops_t *ops = seg->rsmseg_ops;
2068 		rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
2069 
2070 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
2071 			/* generation number snapshot */
2072 			bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
2073 		}
2074 
2075 		e = ops->rsm_memseg_import_put(im_memseg, offset, src_addr,
2076 		    length);
2077 
2078 		if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
2079 			/* check the generation number for force disconnects */
2080 			if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
2081 				return (RSMERR_CONN_ABORTED);
2082 			}
2083 		}
2084 
2085 	}
2086 
2087 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2088 	    "rsm_memseg_import_put: exit\n"));
2089 	return (e);
2090 }
2091 
2092 
2093 int
2094 _rsm_memseg_import_putv(rsm_scat_gath_t *sg_io)
2095 {
2096 	rsm_controller_t *cntrl;
2097 	rsmseg_handle_t *seg;
2098 	uint_t save_sg_io_flags;
2099 
2100 	int e;
2101 
2102 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2103 	    "rsm_memseg_import_putv: enter\n"));
2104 
2105 
2106 	if (sg_io == NULL) {
2107 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2108 		    "invalid sg_io structure\n"));
2109 		return (RSMERR_BAD_SGIO);
2110 	}
2111 
2112 	seg = (rsmseg_handle_t *)sg_io->remote_handle;
2113 	if (seg == NULL) {
2114 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2115 		    "invalid remote segment handle in sg_io\n"));
2116 		return (RSMERR_BAD_SEG_HNDL);
2117 	}
2118 
2119 	cntrl = (rsm_controller_t *)seg->rsmseg_controller;
2120 	if (cntrl == NULL) {
2121 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2122 		    "invalid controller handle\n"));
2123 		return (RSMERR_BAD_SEG_HNDL);
2124 	}
2125 
2126 	if ((sg_io->io_request_count > RSM_MAX_SGIOREQS) ||
2127 	    (sg_io->io_request_count == 0)) {
2128 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2129 		    "io_request_count value incorrect\n"));
2130 		return (RSMERR_BAD_SGIO);
2131 	}
2132 
2133 	/* do an implicit map if required */
2134 	if (seg->rsmseg_state == IMPORT_CONNECT) {
2135 		e = __rsm_import_implicit_map(seg, RSM_IOTYPE_SCATGATH);
2136 		if (e != RSM_SUCCESS) {
2137 			DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2138 			    "implicit map failed\n"));
2139 			return (e);
2140 		}
2141 	}
2142 
2143 	/*
2144 	 * Copy the flags field of the sg_io structure in a local
2145 	 * variable.
2146 	 * This is required since the flags field can be
2147 	 * changed by the plugin library routine to indicate that
2148 	 * the signal post was done.
2149 	 * This change in the flags field of the sg_io structure
2150 	 * should not be reflected to the user. Hence once the flags
2151 	 * field has been used for the purpose of determining whether
2152 	 * the plugin executed a signal post, it must be restored to
2153 	 * its original value which is stored in the local variable.
2154 	 */
2155 	save_sg_io_flags = sg_io->flags;
2156 
2157 	e = cntrl->cntr_segops->rsm_memseg_import_putv(sg_io);
2158 
2159 	/*
2160 	 * At this point, if an implicit signal post was requested by
2161 	 * the user, there could be two possibilities that arise:
2162 	 * 1. the plugin routine has already executed the implicit
2163 	 *    signal post either successfully or unsuccessfully
2164 	 * 2. the plugin does not have the capability of doing an
2165 	 *    implicit signal post and hence the signal post needs
2166 	 *    to be done here.
2167 	 * The above two cases can be idenfied by the flags
2168 	 * field within the sg_io structure as follows:
2169 	 * In case 1, the RSM_IMPLICIT_SIGPOST bit is reset to 0 by the
2170 	 * plugin, indicating that the signal post was done.
2171 	 * In case 2, the bit remains set to a 1 as originally given
2172 	 * by the user, and hence a signal post needs to be done here.
2173 	 */
2174 	if (sg_io->flags & RSM_IMPLICIT_SIGPOST &&
2175 		e == RSM_SUCCESS) {
2176 		/* Do the implicit signal post */
2177 
2178 		/*
2179 		 * The value of the second argument to this call
2180 		 * depends on the value of the sg_io->flags field.
2181 		 * If the RSM_SIGPOST_NO_ACCUMULATE flag has been
2182 		 * ored into the sg_io->flags field, this indicates
2183 		 * that the rsm_intr_signal_post is to be done with
2184 		 * the flags argument set to RSM_SIGPOST_NO_ACCUMULATE
2185 		 * Else, the flags argument is set to 0. These
2186 		 * semantics can be achieved simply by masking off
2187 		 * all other bits in the sg_io->flags field except the
2188 		 * RSM_SIGPOST_NO_ACCUMULATE bit and using the result
2189 		 * as the flags argument for the rsm_intr_signal_post.
2190 		 */
2191 
2192 		int sigpost_flags = sg_io->flags & RSM_SIGPOST_NO_ACCUMULATE;
2193 		e = rsm_intr_signal_post(seg, sigpost_flags);
2194 
2195 	}
2196 
2197 	/* Restore the flags field within the users scatter gather structure */
2198 	sg_io->flags = save_sg_io_flags;
2199 
2200 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2201 	    "rsm_memseg_import_putv: exit\n"));
2202 
2203 	return (e);
2204 }
2205 
2206 
2207 	/*
2208 	 * import side memory segment operations (mapping):
2209 	 */
2210 int
2211 _rsm_memseg_import_map(rsm_memseg_import_handle_t im_memseg,
2212     void **address,
2213     rsm_attribute_t attr,
2214     rsm_permission_t perm,
2215     off_t offset,
2216     size_t length)
2217 {
2218 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
2219 	int flag = MAP_SHARED;
2220 	int prot;
2221 	caddr_t va;
2222 
2223 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2224 	    "rsm_memseg_import_map: enter\n"));
2225 
2226 	if (!seg) {
2227 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2228 		    "invalid segment\n"));
2229 		return (RSMERR_BAD_SEG_HNDL);
2230 	}
2231 	if (!address) {
2232 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2233 		    "invalid address\n"));
2234 		return (RSMERR_BAD_ADDR);
2235 	}
2236 
2237 	/*
2238 	 * Only one map per segment handle!
2239 	 * XXX need to take a lock here
2240 	 */
2241 	mutex_lock(&seg->rsmseg_lock);
2242 
2243 	if (seg->rsmseg_state == IMPORT_MAP) {
2244 		mutex_unlock(&seg->rsmseg_lock);
2245 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2246 		    "segment already mapped\n"));
2247 		return (RSMERR_SEG_ALREADY_MAPPED);
2248 	}
2249 
2250 	/* Only import segments allowed to map */
2251 	if (seg->rsmseg_state != IMPORT_CONNECT) {
2252 		mutex_unlock(&seg->rsmseg_lock);
2253 		return (RSMERR_BAD_SEG_HNDL);
2254 	}
2255 
2256 	/* check for permissions */
2257 	if (perm > RSM_PERM_RDWR) {
2258 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2259 		    "bad permissions when mapping\n"));
2260 		mutex_unlock(&seg->rsmseg_lock);
2261 		return (RSMERR_BAD_PERMS);
2262 	}
2263 
2264 	if (length == 0) {
2265 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2266 		    "mapping with length 0\n"));
2267 		mutex_unlock(&seg->rsmseg_lock);
2268 		return (RSMERR_BAD_LENGTH);
2269 	}
2270 
2271 	if (offset + length > seg->rsmseg_size) {
2272 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2273 		    "map length + offset exceed segment size\n"));
2274 		mutex_unlock(&seg->rsmseg_lock);
2275 		return (RSMERR_BAD_LENGTH);
2276 	}
2277 
2278 	if ((size_t)offset & (PAGESIZE - 1)) {
2279 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
2280 		    "bad mem alignment\n"));
2281 		return (RSMERR_BAD_MEM_ALIGNMENT);
2282 	}
2283 
2284 	if (attr & RSM_MAP_FIXED) {
2285 		if ((uintptr_t)(*address) & (PAGESIZE - 1)) {
2286 			DBPRINTF((RSM_LIBRARY, RSM_ERR,
2287 			    "bad mem alignment\n"));
2288 			return (RSMERR_BAD_MEM_ALIGNMENT);
2289 		}
2290 		flag |= MAP_FIXED;
2291 	}
2292 
2293 	prot = PROT_NONE;
2294 	if (perm & RSM_PERM_READ)
2295 		prot |= PROT_READ;
2296 	if (perm & RSM_PERM_WRITE)
2297 		prot |= PROT_WRITE;
2298 
2299 	va = mmap(*address, length, prot, flag, seg->rsmseg_fd, offset);
2300 	if (va == MAP_FAILED) {
2301 		int e = errno;
2302 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2303 		    "error %d during map\n", e));
2304 
2305 		mutex_unlock(&seg->rsmseg_lock);
2306 		if (e == ENXIO || e == EOVERFLOW ||
2307 		    e == ENOMEM)
2308 			return (RSMERR_BAD_LENGTH);
2309 		else if (e == ENODEV)
2310 			return (RSMERR_CONN_ABORTED);
2311 		else if (e == EAGAIN)
2312 			return (RSMERR_INSUFFICIENT_RESOURCES);
2313 		else if (e == ENOTSUP)
2314 			return (RSMERR_MAP_FAILED);
2315 		else if (e == EACCES)
2316 			return (RSMERR_BAD_PERMS);
2317 		else
2318 			return (RSMERR_MAP_FAILED);
2319 	}
2320 	*address = va;
2321 
2322 	/*
2323 	 * Fix segment ops vector to handle direct access.
2324 	 */
2325 	/*
2326 	 * XXX: Set this only for full segment mapping. Keep a list
2327 	 * of mappings to use for access functions
2328 	 */
2329 	seg->rsmseg_vaddr = va;
2330 	seg->rsmseg_maplen = length;
2331 	seg->rsmseg_mapoffset = offset;
2332 	seg->rsmseg_state = IMPORT_MAP;
2333 
2334 	mutex_unlock(&seg->rsmseg_lock);
2335 
2336 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2337 	    "rsm_memseg_import_map: exit\n"));
2338 
2339 	return (RSM_SUCCESS);
2340 }
2341 
2342 int
2343 _rsm_memseg_import_unmap(rsm_memseg_import_handle_t im_memseg)
2344 {
2345 	/*
2346 	 * Until we fix the rsm driver to catch unload, we unload
2347 	 * the whole segment.
2348 	 */
2349 
2350 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
2351 
2352 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2353 	    "rsm_memseg_import_unmap: enter\n"));
2354 
2355 	if (!seg) {
2356 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2357 		    "invalid segment or segment state\n"));
2358 		return (RSMERR_BAD_SEG_HNDL);
2359 	}
2360 
2361 	mutex_lock(&seg->rsmseg_lock);
2362 	if (seg->rsmseg_state != IMPORT_MAP) {
2363 		mutex_unlock(&seg->rsmseg_lock);
2364 		return (RSMERR_SEG_NOT_MAPPED);
2365 	}
2366 
2367 	seg->rsmseg_mapoffset = 0;   /* reset the offset */
2368 	seg->rsmseg_state = IMPORT_CONNECT;
2369 	seg->rsmseg_flags &= ~RSM_IMPLICIT_MAP;
2370 	(void) munmap(seg->rsmseg_vaddr, seg->rsmseg_maplen);
2371 
2372 	mutex_unlock(&seg->rsmseg_lock);
2373 
2374 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2375 	    "rsm_memseg_import_unmap: exit\n"));
2376 
2377 	return (RSM_SUCCESS);
2378 }
2379 
2380 
2381 	/*
2382 	 * import side memory segment operations (barriers):
2383 	 */
2384 int
2385 _rsm_memseg_import_init_barrier(rsm_memseg_import_handle_t im_memseg,
2386     rsm_barrier_type_t type,
2387     rsmapi_barrier_t *barrier)
2388 {
2389 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
2390 	rsmbar_handle_t *bar;
2391 
2392 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2393 	    "rsm_memseg_import_init_barrier: enter\n"));
2394 
2395 	if (!seg) {
2396 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2397 		    "invalid segment or barrier\n"));
2398 		return (RSMERR_BAD_SEG_HNDL);
2399 	}
2400 	if (!barrier) {
2401 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2402 		    "invalid barrier pointer\n"));
2403 		return (RSMERR_BAD_BARRIER_PTR);
2404 	}
2405 
2406 	bar = (rsmbar_handle_t *)barrier;
2407 	bar->rsmbar_seg = seg;
2408 
2409 	seg->rsmseg_barrier = barrier;  /* used in put/get fns */
2410 
2411 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2412 	    "rsm_memseg_import_init_barrier: exit\n"));
2413 
2414 	return (seg->rsmseg_ops->rsm_memseg_import_init_barrier(im_memseg,
2415 	    type, (rsm_barrier_handle_t)barrier));
2416 }
2417 
2418 int
2419 _rsm_memseg_import_open_barrier(rsmapi_barrier_t *barrier)
2420 {
2421 	rsmbar_handle_t *bar = (rsmbar_handle_t *)barrier;
2422 	rsm_segops_t *ops;
2423 
2424 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2425 	    "rsm_memseg_import_open_barrier: enter\n"));
2426 
2427 	if (!bar) {
2428 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2429 		    "invalid barrier\n"));
2430 		return (RSMERR_BAD_BARRIER_PTR);
2431 	}
2432 	if (!bar->rsmbar_seg) {
2433 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2434 		    "uninitialized barrier\n"));
2435 		return (RSMERR_BARRIER_UNINITIALIZED);
2436 	}
2437 
2438 	/* generation number snapshot */
2439 	bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum; /* bar[0] */
2440 
2441 	ops = bar->rsmbar_seg->rsmseg_ops;
2442 
2443 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2444 	    "rsm_memseg_import_open_barrier: exit\n"));
2445 
2446 	return (ops->rsm_memseg_import_open_barrier(
2447 	    (rsm_barrier_handle_t)barrier));
2448 }
2449 
2450 int
2451 _rsm_memseg_import_order_barrier(rsmapi_barrier_t *barrier)
2452 {
2453 	rsmbar_handle_t *bar = (rsmbar_handle_t *)barrier;
2454 	rsm_segops_t *ops;
2455 
2456 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2457 	    "rsm_memseg_import_order_barrier: enter\n"));
2458 
2459 	if (!bar) {
2460 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2461 		    "invalid barrier\n"));
2462 		return (RSMERR_BAD_BARRIER_PTR);
2463 	}
2464 	if (!bar->rsmbar_seg) {
2465 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2466 		    "uninitialized barrier\n"));
2467 		return (RSMERR_BARRIER_UNINITIALIZED);
2468 	}
2469 
2470 	ops = bar->rsmbar_seg->rsmseg_ops;
2471 
2472 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2473 	    "rsm_memseg_import_order_barrier: exit\n"));
2474 
2475 	return (ops->rsm_memseg_import_order_barrier(
2476 	    (rsm_barrier_handle_t)barrier));
2477 }
2478 
2479 int
2480 _rsm_memseg_import_close_barrier(rsmapi_barrier_t *barrier)
2481 {
2482 	rsmbar_handle_t *bar = (rsmbar_handle_t *)barrier;
2483 	rsm_segops_t *ops;
2484 
2485 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2486 	    "rsm_memseg_import_close_barrier: enter\n"));
2487 
2488 	if (!bar) {
2489 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2490 		    "invalid barrier\n"));
2491 		return (RSMERR_BAD_BARRIER_PTR);
2492 	}
2493 	if (!bar->rsmbar_seg) {
2494 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2495 		    "uninitialized barrier\n"));
2496 		return (RSMERR_BARRIER_UNINITIALIZED);
2497 	}
2498 
2499 	/* generation number snapshot */
2500 	if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
2501 		return (RSMERR_CONN_ABORTED);
2502 	}
2503 
2504 	ops = bar->rsmbar_seg->rsmseg_ops;
2505 
2506 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2507 	    "rsm_memseg_import_close_barrier: exit\n"));
2508 
2509 	return (ops->rsm_memseg_import_close_barrier(
2510 	    (rsm_barrier_handle_t)barrier));
2511 }
2512 
2513 int
2514 _rsm_memseg_import_destroy_barrier(rsmapi_barrier_t *barrier)
2515 {
2516 	rsmbar_handle_t *bar = (rsmbar_handle_t *)barrier;
2517 	rsm_segops_t *ops;
2518 
2519 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2520 	    "rsm_memseg_import_destroy_barrier: enter\n"));
2521 
2522 	if (!bar) {
2523 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2524 		    "invalid barrier\n"));
2525 		return (RSMERR_BAD_BARRIER_PTR);
2526 	}
2527 	if (!bar->rsmbar_seg) {
2528 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2529 		    "uninitialized barrier\n"));
2530 		return (RSMERR_BARRIER_UNINITIALIZED);
2531 	}
2532 
2533 	bar->rsmbar_seg->rsmseg_barrier = NULL;
2534 
2535 	ops = bar->rsmbar_seg->rsmseg_ops;
2536 
2537 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2538 	    "rsm_memseg_import_destroy_barrier: exit\n"));
2539 
2540 	return (ops->rsm_memseg_import_destroy_barrier
2541 	    ((rsm_barrier_handle_t)barrier));
2542 }
2543 
2544 int
2545 _rsm_memseg_import_get_mode(rsm_memseg_import_handle_t im_memseg,
2546     rsm_barrier_mode_t *mode)
2547 {
2548 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
2549 
2550 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2551 	    "rsm_memseg_import_get_mode: enter\n"));
2552 
2553 	if (seg) {
2554 		*mode = seg->rsmseg_barmode;
2555 		DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2556 		    "rsm_memseg_import_get_mode: exit\n"));
2557 
2558 		return (seg->rsmseg_ops->rsm_memseg_import_get_mode(im_memseg,
2559 		    mode));
2560 	}
2561 
2562 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2563 	    "invalid arguments \n"));
2564 
2565 	return (RSMERR_BAD_SEG_HNDL);
2566 
2567 }
2568 
2569 int
2570 _rsm_memseg_import_set_mode(rsm_memseg_import_handle_t im_memseg,
2571     rsm_barrier_mode_t mode)
2572 {
2573 	rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
2574 
2575 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2576 	    "rsm_memseg_import_set_mode: enter\n"));
2577 	if (seg) {
2578 		if ((mode == RSM_BARRIER_MODE_IMPLICIT ||
2579 		    mode == RSM_BARRIER_MODE_EXPLICIT)) {
2580 			seg->rsmseg_barmode = mode;
2581 			DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2582 			    "rsm_memseg_import_set_mode: exit\n"));
2583 
2584 			return (seg->rsmseg_ops->rsm_memseg_import_set_mode(
2585 			    im_memseg,
2586 			    mode));
2587 		} else {
2588 			DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2589 			    "bad barrier mode\n"));
2590 			return (RSMERR_BAD_MODE);
2591 		}
2592 	}
2593 
2594 	DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2595 	    "invalid arguments\n"));
2596 
2597 	return (RSMERR_BAD_SEG_HNDL);
2598 }
2599 
2600 int
2601 _rsm_intr_signal_post(void *memseg, uint_t flags)
2602 {
2603 	rsm_ioctlmsg_t msg;
2604 	rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
2605 
2606 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2607 	    "rsm_intr_signal_post: enter\n"));
2608 
2609 	flags = flags;
2610 
2611 	if (!seg) {
2612 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
2613 		    "invalid segment handle\n"));
2614 		return (RSMERR_BAD_SEG_HNDL);
2615 	}
2616 
2617 	if (ioctl(seg->rsmseg_fd, RSM_IOCTL_RING_BELL, &msg) < 0) {
2618 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
2619 		    "RSM_IOCTL_RING_BELL failed\n"));
2620 		return (errno);
2621 	}
2622 
2623 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2624 	    "rsm_intr_signal_post: exit\n"));
2625 
2626 	return (RSM_SUCCESS);
2627 }
2628 
2629 int
2630 _rsm_intr_signal_wait(void *memseg, int timeout)
2631 {
2632 	rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
2633 	struct pollfd fds;
2634 	minor_t	rnum;
2635 
2636 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2637 	    "rsm_intr_signal_wait: enter\n"));
2638 
2639 	if (!seg) {
2640 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
2641 		    "invalid segment\n"));
2642 		return (RSMERR_BAD_SEG_HNDL);
2643 	}
2644 
2645 	fds.fd = seg->rsmseg_fd;
2646 	fds.events = POLLRDNORM;
2647 
2648 	rnum = seg->rsmseg_rnum;
2649 
2650 	return (__rsm_intr_signal_wait_common(&fds, &rnum, 1, timeout, NULL));
2651 }
2652 
2653 int
2654 _rsm_intr_signal_wait_pollfd(struct pollfd fds[], nfds_t nfds, int timeout,
2655 	int *numfdsp)
2656 {
2657 	return (__rsm_intr_signal_wait_common(fds, NULL, nfds, timeout,
2658 	    numfdsp));
2659 }
2660 
2661 /*
2662  * This is the generic wait routine, it takes the following arguments
2663  *	- pollfd array
2664  *	- rnums array corresponding to the pollfd if known, if this is
2665  *	NULL then the fds are looked up from the pollfd_table.
2666  *	- number of fds in pollfd array,
2667  *	- timeout
2668  *	- pointer to a location where the number of fds with successful
2669  *	events is returned.
2670  */
2671 static int
2672 __rsm_intr_signal_wait_common(struct pollfd fds[], minor_t rnums[],
2673     nfds_t nfds, int timeout, int *numfdsp)
2674 {
2675 	int	i;
2676 	int	numsegs = 0;
2677 	int	numfd;
2678 	int	fds_processed = 0;
2679 	minor_t	segrnum;
2680 	rsm_poll_event_t	event_arr[RSM_MAX_POLLFDS];
2681 	rsm_poll_event_t	*event_list = NULL;
2682 	rsm_poll_event_t	*events;
2683 	rsm_consume_event_msg_t msg;
2684 
2685 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE, "wait_common enter\n"));
2686 
2687 	if (numfdsp) {
2688 		*numfdsp = 0;
2689 	}
2690 
2691 	numfd = poll(fds, nfds, timeout);
2692 
2693 	switch (numfd) {
2694 	case -1: /* poll returned error - map to RSMERR_... */
2695 		DBPRINTF((RSM_LIBRARY, RSM_ERR, "signal wait pollfd err\n"));
2696 		switch (errno) {
2697 		case EAGAIN:
2698 			return (RSMERR_INSUFFICIENT_RESOURCES);
2699 		case EFAULT:
2700 			return (RSMERR_BAD_ADDR);
2701 		case EINTR:
2702 			return (RSMERR_INTERRUPTED);
2703 		case EINVAL:
2704 		default:
2705 			return (RSMERR_BAD_ARGS_ERRORS);
2706 		}
2707 	case 0: /* timedout - return from here */
2708 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
2709 		    "signal wait timed out\n"));
2710 		return (RSMERR_TIMEOUT);
2711 	default:
2712 		break;
2713 	}
2714 
2715 	if (numfd <= RSM_MAX_POLLFDS) {
2716 		/* use the event array on the stack */
2717 		events = (rsm_poll_event_t *)event_arr;
2718 	} else {
2719 		/*
2720 		 * actual number of fds corresponding to rsmapi segments might
2721 		 * be < numfd, don't want to scan the list to figure that out
2722 		 * lets just allocate on the heap
2723 		 */
2724 		event_list = (rsm_poll_event_t *)malloc(
2725 			sizeof (rsm_poll_event_t)*numfd);
2726 		if (!event_list) {
2727 			/*
2728 			 * return with error even if poll might have succeeded
2729 			 * since the application can retry and the events will
2730 			 * still be available.
2731 			 */
2732 			return (RSMERR_INSUFFICIENT_MEM);
2733 		}
2734 		events = event_list;
2735 	}
2736 
2737 	/*
2738 	 * process the fds for events and if it corresponds to an rsmapi
2739 	 * segment consume the event
2740 	 */
2741 	for (i = 0; i < nfds; i++) {
2742 		if (fds[i].revents == POLLRDNORM) {
2743 			/*
2744 			 * poll returned an event and if its POLLRDNORM, it
2745 			 * might correspond to an rsmapi segment
2746 			 */
2747 			if (rnums) { /* resource num is passed in */
2748 				segrnum = rnums[i];
2749 			} else { /* lookup pollfd table to get resource num */
2750 				segrnum = _rsm_lookup_pollfd_table(fds[i].fd);
2751 			}
2752 			if (segrnum) {
2753 				events[numsegs].rnum = segrnum;
2754 				events[numsegs].revent = 0;
2755 				events[numsegs].fdsidx = i; /* fdlist index */
2756 				numsegs++;
2757 			}
2758 		}
2759 
2760 		if ((fds[i].revents) && (++fds_processed == numfd)) {
2761 			/*
2762 			 * only "numfd" events have revents field set, once we
2763 			 * process that many break out of the loop
2764 			 */
2765 			break;
2766 		}
2767 	}
2768 
2769 	if (numsegs == 0) { /* No events for rsmapi segs in the fdlist */
2770 		if (event_list) {
2771 			free(event_list);
2772 		}
2773 		if (numfdsp) {
2774 			*numfdsp = numfd;
2775 		}
2776 		DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2777 		    "wait_common exit: no rsmapi segs\n"));
2778 		return (RSM_SUCCESS);
2779 	}
2780 
2781 	msg.seglist = (caddr_t)events;
2782 	msg.numents = numsegs;
2783 
2784 	if (ioctl(_rsm_fd, RSM_IOCTL_CONSUMEEVENT, &msg) < 0) {
2785 		int error = errno;
2786 		if (event_list) {
2787 			free(event_list);
2788 		}
2789 		DBPRINTF((RSM_LIBRARY|RSM_LOOPBACK, RSM_ERR,
2790 		    "RSM_IOCTL_CONSUMEEVENT failed(%d)\n", error));
2791 		return (error);
2792 	}
2793 
2794 	/* count the number of segs for which consumeevent was successful */
2795 	numfd -= numsegs;
2796 
2797 	for (i = 0; i < numsegs; i++) {
2798 		if (events[i].revent != 0) {
2799 			fds[events[i].fdsidx].revents = POLLRDNORM;
2800 			numfd++;
2801 		} else { /* failed to consume event so set revents to 0 */
2802 			fds[events[i].fdsidx].revents = 0;
2803 		}
2804 	}
2805 
2806 	if (event_list) {
2807 		free(event_list);
2808 	}
2809 
2810 	if (numfd > 0) {
2811 		if (numfdsp) {
2812 			*numfdsp = numfd;
2813 		}
2814 		DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2815 		    "wait_common exit\n"));
2816 		return (RSM_SUCCESS);
2817 	} else {
2818 		DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2819 		    "wait_common exit\n"));
2820 		return (RSMERR_TIMEOUT);
2821 	}
2822 }
2823 
2824 /*
2825  * This function provides the data (file descriptor and event) for
2826  * the specified pollfd struct.  The pollfd struct may then be
2827  * subsequently used with the poll system call to wait for an event
2828  * signalled by rsm_intr_signal_post.  The memory segment must be
2829  * currently published for a successful return with a valid pollfd.
2830  * A reference count for the descriptor is incremented.
2831  */
2832 int
2833 _rsm_memseg_get_pollfd(void *memseg,
2834 			struct pollfd *poll_fd)
2835 {
2836 	int	i;
2837 	int	err = RSM_SUCCESS;
2838 	rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
2839 
2840 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2841 	    "rsm_memseg_get_pollfd: enter\n"));
2842 
2843 	if (!seg) {
2844 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
2845 		    "invalid segment\n"));
2846 		return (RSMERR_BAD_SEG_HNDL);
2847 	}
2848 
2849 	mutex_lock(&seg->rsmseg_lock);
2850 
2851 	poll_fd->fd = seg->rsmseg_fd;
2852 	poll_fd->events = POLLRDNORM;
2853 	seg->rsmseg_pollfd_refcnt++;
2854 	if (seg->rsmseg_pollfd_refcnt == 1) {
2855 		/* insert the segment into the pollfd table */
2856 		err = _rsm_insert_pollfd_table(seg->rsmseg_fd,
2857 		    seg->rsmseg_rnum);
2858 	}
2859 
2860 	mutex_unlock(&seg->rsmseg_lock);
2861 
2862 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2863 	    "rsm_memseg_get_pollfd: exit(%d)\n", err));
2864 
2865 	return (err);
2866 }
2867 
2868 /*
2869  * This function decrements the segment pollfd reference count.
2870  * A segment unpublish or destroy operation will fail if the reference count is
2871  * non zero.
2872  */
2873 int
2874 _rsm_memseg_release_pollfd(void * memseg)
2875 {
2876 	int	i;
2877 	rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
2878 
2879 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2880 	    "rsm_memseg_release_pollfd: enter\n"));
2881 
2882 	if (!seg) {
2883 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
2884 		    "invalid segment handle\n"));
2885 		return (RSMERR_BAD_SEG_HNDL);
2886 	}
2887 
2888 	mutex_lock(&seg->rsmseg_lock);
2889 
2890 	if (seg->rsmseg_pollfd_refcnt) {
2891 		seg->rsmseg_pollfd_refcnt--;
2892 		if (seg->rsmseg_pollfd_refcnt == 0) {
2893 			/* last reference removed - update the pollfd_table */
2894 			_rsm_remove_pollfd_table(seg->rsmseg_fd);
2895 		}
2896 	}
2897 
2898 	mutex_unlock(&seg->rsmseg_lock);
2899 
2900 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2901 	    "rsm_memseg_release_pollfd: exit\n"));
2902 
2903 	return (RSM_SUCCESS);
2904 }
2905 
2906 /*
2907  * The interconnect topology data is obtained from the Kernel Agent
2908  * and stored in a memory buffer allocated by this function.  A pointer
2909  * to the buffer is stored in the location specified by the caller in
2910  * the function argument.  It is the callers responsibility to
2911  * call rsm_free_interconnect_topolgy() to free the allocated memory.
2912  */
2913 int
2914 _rsm_get_interconnect_topology(rsm_topology_t **topology_data)
2915 {
2916 	uint32_t		topology_data_size;
2917 	rsm_topology_t		*topology_ptr;
2918 	int			error;
2919 
2920 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2921 	    "rsm_get_interconnect_topology: enter\n"));
2922 
2923 	if (topology_data == NULL)
2924 		return (RSMERR_BAD_TOPOLOGY_PTR);
2925 
2926 	*topology_data = NULL;
2927 
2928 again:
2929 	/* obtain the size of the topology data */
2930 	if (ioctl(_rsm_fd, RSM_IOCTL_TOPOLOGY_SIZE, &topology_data_size) < 0) {
2931 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
2932 		    "RSM_IOCTL_TOPOLOGY_SIZE failed\n"));
2933 		return (errno);
2934 	}
2935 
2936 	/* allocate double-word aligned memory to hold the topology data */
2937 	topology_ptr = (rsm_topology_t *)memalign(8, topology_data_size);
2938 	if (topology_ptr == NULL) {
2939 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
2940 		    "not enough memory\n"));
2941 		return (RSMERR_INSUFFICIENT_MEM);
2942 	}
2943 
2944 	/*
2945 	 * Request the topology data.
2946 	 * Pass in the size to be used as a check in case
2947 	 * the data has grown since the size was obtained - if
2948 	 * it has, the errno value will be E2BIG.
2949 	 */
2950 	topology_ptr->topology_hdr.local_nodeid =
2951 	    (rsm_node_id_t)topology_data_size;
2952 	if (ioctl(_rsm_fd, RSM_IOCTL_TOPOLOGY_DATA, topology_ptr) < 0) {
2953 		error = errno;
2954 		free((void *)topology_ptr);
2955 		if (error == E2BIG)
2956 			goto again;
2957 		else {
2958 			DBPRINTF((RSM_LIBRARY, RSM_ERR,
2959 			    "RSM_IOCTL_TOPOLOGY_DATA failed\n"));
2960 			return (error);
2961 		}
2962 	} else
2963 		*topology_data = topology_ptr;
2964 
2965 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2966 	    " rsm_get_interconnect_topology: exit\n"));
2967 
2968 	return (RSM_SUCCESS);
2969 }
2970 
2971 
2972 void
2973 _rsm_free_interconnect_topology(rsm_topology_t *topology_ptr)
2974 {
2975 
2976 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2977 	    "rsm_free_interconnect_topology: enter\n"));
2978 
2979 	if (topology_ptr) {
2980 		free((void *)topology_ptr);
2981 	}
2982 
2983 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2984 	    "rsm_free_interconnect_topology: exit\n"));
2985 }
2986 
2987 int
2988 _rsm_create_localmemory_handle(rsmapi_controller_handle_t cntrl_handle,
2989 				rsm_localmemory_handle_t *local_hndl_p,
2990 				caddr_t local_vaddr, size_t len)
2991 {
2992 	int e;
2993 	rsm_controller_t *cntrl = (rsm_controller_t *)cntrl_handle;
2994 
2995 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2996 	    "rsm_create_localmemory_handle: enter\n"));
2997 
2998 	if ((size_t)local_vaddr & (PAGESIZE - 1)) {
2999 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
3000 		    "invalid arguments\n"));
3001 		return (RSMERR_BAD_ADDR);
3002 	}
3003 
3004 	if (!cntrl_handle) {
3005 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
3006 		    "invalid controller handle\n"));
3007 		return (RSMERR_BAD_CTLR_HNDL);
3008 	}
3009 	if (!local_hndl_p) {
3010 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
3011 		    "invalid local memory handle pointer\n"));
3012 		return (RSMERR_BAD_LOCALMEM_HNDL);
3013 	}
3014 	if (len == 0) {
3015 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
3016 		    "invalid length\n"));
3017 		return (RSMERR_BAD_LENGTH);
3018 	}
3019 
3020 	e = cntrl->cntr_segops->rsm_create_localmemory_handle(
3021 	    cntrl_handle,
3022 	    local_hndl_p,
3023 	    local_vaddr,
3024 	    len);
3025 
3026 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
3027 	    "rsm_create_localmemory_handle: exit\n"));
3028 
3029 	return (e);
3030 }
3031 
3032 int
3033 _rsm_free_localmemory_handle(rsmapi_controller_handle_t cntrl_handle,
3034     rsm_localmemory_handle_t local_handle)
3035 {
3036 	int e;
3037 
3038 	rsm_controller_t *cntrl = (rsm_controller_t *)cntrl_handle;
3039 
3040 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
3041 	    "rsm_free_localmemory_handle: enter\n"));
3042 
3043 
3044 	if (!cntrl_handle) {
3045 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
3046 		    "invalid controller handle\n"));
3047 		return (RSMERR_BAD_CTLR_HNDL);
3048 	}
3049 
3050 	if (!local_handle) {
3051 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
3052 		    "invalid localmemory handle\n"));
3053 		return (RSMERR_BAD_LOCALMEM_HNDL);
3054 	}
3055 
3056 	e = cntrl->cntr_segops->rsm_free_localmemory_handle(local_handle);
3057 
3058 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
3059 	    "rsm_free_localmemory_handle: exit\n"));
3060 
3061 	return (e);
3062 }
3063 
3064 int
3065 _rsm_get_segmentid_range(const char *appid, rsm_memseg_id_t *baseid,
3066 	uint32_t *length)
3067 {
3068 	char    buf[RSMFILE_BUFSIZE];
3069 	char	*s;
3070 	char	*fieldv[4];
3071 	int	fieldc = 0;
3072 	int	found = 0;
3073 	int	err = RSMERR_BAD_APPID;
3074 	FILE    *fp;
3075 
3076 	if (appid == NULL || baseid == NULL || length == NULL)
3077 		return (RSMERR_BAD_ADDR);
3078 
3079 	if ((fp = fopen(RSMSEGIDFILE, "r")) == NULL) {
3080 		DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
3081 		    "cannot open <%s>\n", RSMSEGIDFILE));
3082 		return (RSMERR_BAD_CONF);
3083 	}
3084 
3085 	while (s = fgets(buf, RSMFILE_BUFSIZE, fp)) {
3086 		fieldc = 0;
3087 		while (isspace(*s))	/* skip the leading spaces */
3088 			s++;
3089 
3090 		if (*s == '#') {	/* comment line - skip it */
3091 			continue;
3092 		}
3093 
3094 		/*
3095 		 * parse the reserved segid file and
3096 		 * set the pointers appropriately.
3097 		 * fieldv[0] :  keyword
3098 		 * fieldv[1] :  application identifier
3099 		 * fieldv[2] :  baseid
3100 		 * fieldv[3] :  length
3101 		 */
3102 		while ((*s != '\n') && (*s != '\0') && (fieldc < 4)) {
3103 
3104 			while (isspace(*s)) /* skip the leading spaces */
3105 				s++;
3106 
3107 			fieldv[fieldc++] = s;
3108 
3109 			if (fieldc == 4) {
3110 				if (fieldv[3][strlen(fieldv[3])-1] == '\n')
3111 					fieldv[3][strlen(fieldv[3])-1] = '\0';
3112 				break;
3113 			}
3114 
3115 			while (*s && !isspace(*s))
3116 				++s;	/* move to the next white space */
3117 
3118 			if (*s)
3119 				*s++ = '\0';
3120 		}
3121 
3122 		if (fieldc < 4) {	/* some fields are missing */
3123 			err = RSMERR_BAD_CONF;
3124 			break;
3125 		}
3126 
3127 		if (strcasecmp(fieldv[1], appid) == 0) { /* found a match */
3128 			if (strcasecmp(fieldv[0], RSMSEG_RESERVED) == 0) {
3129 				errno = 0;
3130 				*baseid = strtol(fieldv[2], (char **)NULL, 16);
3131 				if (errno != 0) {
3132 					err = RSMERR_BAD_CONF;
3133 					break;
3134 				}
3135 
3136 				errno = 0;
3137 				*length = (int)strtol(fieldv[3],
3138 				    (char **)NULL, 10);
3139 				if (errno != 0) {
3140 					err = RSMERR_BAD_CONF;
3141 					break;
3142 				}
3143 
3144 				found = 1;
3145 			} else {	/* error in format */
3146 				err = RSMERR_BAD_CONF;
3147 			}
3148 			break;
3149 		}
3150 	}
3151 
3152 	(void) fclose(fp);
3153 
3154 	if (found)
3155 		return (RSM_SUCCESS);
3156 
3157 	return (err);
3158 }
3159 
3160 static 	int
3161 _rsm_get_hwaddr(rsmapi_controller_handle_t handle, rsm_node_id_t nodeid,
3162     rsm_addr_t *hwaddrp)
3163 {
3164 	rsm_ioctlmsg_t	msg = {0};
3165 	rsm_controller_t *ctrlp;
3166 
3167 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
3168 	    "_rsm_get_hwaddr: enter\n"));
3169 
3170 	ctrlp = (rsm_controller_t *)handle;
3171 
3172 	if (ctrlp == NULL) {
3173 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
3174 		    "invalid controller handle\n"));
3175 		return (RSMERR_BAD_CTLR_HNDL);
3176 	}
3177 
3178 	msg.cname = ctrlp->cntr_name;
3179 	msg.cname_len = strlen(ctrlp->cntr_name) +1;
3180 	msg.cnum = ctrlp->cntr_unit;
3181 	msg.nodeid = nodeid;
3182 
3183 	if (ioctl(_rsm_fd, RSM_IOCTL_MAP_TO_ADDR, &msg) < 0) {
3184 		int error = errno;
3185 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
3186 		    "RSM_IOCTL_MAP_TO_ADDR failed\n"));
3187 		return (error);
3188 	}
3189 
3190 	*hwaddrp = msg.hwaddr;
3191 
3192 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
3193 	    "_rsm_get_hwaddr: exit\n"));
3194 
3195 	return (RSM_SUCCESS);
3196 
3197 }
3198 
3199 static	int
3200 _rsm_get_nodeid(rsmapi_controller_handle_t handle, rsm_addr_t hwaddr,
3201     rsm_node_id_t *nodeidp)
3202 {
3203 
3204 	rsm_ioctlmsg_t	msg = {0};
3205 	rsm_controller_t *ctrlp;
3206 
3207 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
3208 	    "_rsm_get_nodeid: enter\n"));
3209 
3210 	ctrlp = (rsm_controller_t *)handle;
3211 
3212 	if (ctrlp == NULL) {
3213 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
3214 		    "invalid arguments\n"));
3215 		return (RSMERR_BAD_CTLR_HNDL);
3216 	}
3217 
3218 	msg.cname = ctrlp->cntr_name;
3219 	msg.cname_len = strlen(ctrlp->cntr_name) +1;
3220 	msg.cnum = ctrlp->cntr_unit;
3221 	msg.hwaddr = hwaddr;
3222 
3223 	if (ioctl(_rsm_fd, RSM_IOCTL_MAP_TO_NODEID, &msg) < 0) {
3224 		int error = errno;
3225 		DBPRINTF((RSM_LIBRARY, RSM_ERR,
3226 		    "RSM_IOCTL_MAP_TO_NODEID failed\n"));
3227 		return (error);
3228 	}
3229 
3230 	*nodeidp = msg.nodeid;
3231 
3232 	DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
3233 	    "_rsm_get_nodeid: exit\n"));
3234 
3235 	return (RSM_SUCCESS);
3236 
3237 }
3238 
3239 #ifdef DEBUG
3240 void
3241 dbg_printf(int msg_category, int msg_level, char *fmt, ...)
3242 {
3243 	if ((msg_category & rsmlibdbg_category) &&
3244 	    (msg_level <= rsmlibdbg_level)) {
3245 		va_list arg_list;
3246 		va_start(arg_list, fmt);
3247 		mutex_lock(&rsmlog_lock);
3248 		fprintf(rsmlog_fd,
3249 			"Thread %d ", thr_self());
3250 		vfprintf(rsmlog_fd, fmt, arg_list);
3251 		fflush(rsmlog_fd);
3252 		mutex_unlock(&rsmlog_lock);
3253 		va_end(arg_list);
3254 	}
3255 }
3256 #endif /* DEBUG */
3257