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