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