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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <sys/types.h>
27 #include <sys/ksynch.h>
28 #include <sys/errno.h>
29 #include <sys/file.h>
30 #include <sys/open.h>
31 #include <sys/cred.h>
32 #include <sys/kmem.h>
33 #include <sys/ddi.h>
34
35 #include <sys/ncall/ncall.h>
36
37 #define __NSC_GEN__
38 #include "nsc_dev.h"
39 #include "nsc_ncallio.h"
40 #include "../nsctl.h"
41
42
43 extern nsc_mem_t *_nsc_local_mem;
44
45 extern void _nsc_init_ncio(void);
46 extern void _nsc_deinit_ncio(void);
47
48 static nsc_io_t *nsc_ncio_io;
49 static kmutex_t nsc_ncio_lock;
50 static nsc_ncio_dev_t *nsc_ncio_top;
51
52
53 /*
54 * ncall-io io provider - client side.
55 */
56
57
58 static int
nsc_ncio_split(char * node_and_path,char ** pathp)59 nsc_ncio_split(char *node_and_path, char **pathp)
60 {
61 char *cp;
62 int i, snode;
63
64 snode = 0;
65 for (cp = node_and_path; *cp && *cp != ':'; cp++) {
66 i = *cp - '0';
67 if (i < 0 || i > 9)
68 break;
69
70 snode = (10 * snode) + i;
71 }
72
73 if (*cp != ':') {
74 cmn_err(CE_WARN,
75 "ncio: failed to convert %s to node and path",
76 node_and_path);
77 return (-1);
78 }
79
80 *pathp = cp + 1;
81 return (snode);
82 }
83
84
85 /*
86 * nsc_ncio_open()
87 *
88 * The pathname that is used with the NSC_NCALL io provider should be
89 * of the form "<node>:<pathname>", where <node> is the decimal ncall
90 * nodeid of the server machine and <pathname> is the pathname of the
91 * device on the server node.
92 */
93
94 /* ARGSUSED */
95 static int
nsc_ncio_open(char * node_and_path,int flag,blind_t * cdp,void * iodev)96 nsc_ncio_open(char *node_and_path, int flag, blind_t *cdp, void *iodev)
97 {
98 nsc_ncio_dev_t *ncp, *new;
99 char *path = NULL;
100 uint64_t phash;
101 int snode;
102
103 snode = nsc_ncio_split(node_and_path, &path);
104 if (snode < 0)
105 return (EINVAL);
106
107 new = nsc_kmem_zalloc(sizeof (*new), KM_SLEEP, _nsc_local_mem);
108 phash = nsc_strhash(path);
109
110 if (new) {
111 (void) strncpy(new->path, path, sizeof (new->path));
112 new->phash = phash;
113 new->snode = snode;
114 }
115
116 mutex_enter(&nsc_ncio_lock);
117
118 for (ncp = nsc_ncio_top; ncp; ncp = ncp->next)
119 if (ncp->phash == phash && strcmp(path, ncp->path) == 0)
120 break;
121
122 if (ncp == NULL && new != NULL) {
123 ncp = new;
124 new = NULL;
125 ncp->next = nsc_ncio_top;
126 nsc_ncio_top = ncp;
127 }
128
129 if (ncp != NULL)
130 ncp->ref++;
131
132 mutex_exit(&nsc_ncio_lock);
133
134 if (new)
135 nsc_kmem_free(new, sizeof (*new));
136
137 if (!ncp)
138 return (ENOMEM);
139
140 *cdp = (blind_t)ncp;
141 return (0);
142 }
143
144
145 static int
nsc_ncio_close(nsc_ncio_dev_t * ncp)146 nsc_ncio_close(nsc_ncio_dev_t *ncp)
147 {
148 nsc_ncio_dev_t **ncpp;
149 int found, free;
150
151 if (ncp == NULL)
152 return (EINVAL);
153
154 found = 0;
155 free = 0;
156
157 mutex_enter(&nsc_ncio_lock);
158
159 for (ncpp = &nsc_ncio_top; *ncpp; ncpp = &((*ncpp)->next)) {
160 if (*ncpp == ncp) {
161 found = 1;
162 break;
163 }
164 }
165
166 if (!found) {
167 mutex_exit(&nsc_ncio_lock);
168 return (ENODEV);
169 }
170
171 ncp->ref--;
172 if (ncp->ref == 0) {
173 *ncpp = ncp->next;
174 free = 1;
175 }
176
177 mutex_exit(&nsc_ncio_lock);
178
179 if (free)
180 nsc_kmem_free(ncp, sizeof (*ncp));
181
182 return (0);
183 }
184
185
186 /* ARGSUSED1 */
187 static nsc_buf_t *
nsc_ncio_alloch(void (* d_cb)(),void (* r_cb)(),void (* w_cb)())188 nsc_ncio_alloch(void (*d_cb)(), void (*r_cb)(), void (*w_cb)())
189 {
190 nsc_ncio_buf_t *h;
191
192 if ((h = nsc_kmem_zalloc(sizeof (*h), KM_SLEEP,
193 _nsc_local_mem)) == NULL)
194 return (NULL);
195
196 h->disc = d_cb;
197 h->bufh.sb_flag = NSC_HALLOCATED;
198
199 return (&h->bufh);
200 }
201
202
203 static int
nsc_ncio_freeh(nsc_ncio_buf_t * h)204 nsc_ncio_freeh(nsc_ncio_buf_t *h)
205 {
206 nsc_kmem_free(h, sizeof (*h));
207 return (0);
208 }
209
210
211 static int
nsc_ncio_rwb(nsc_ncio_buf_t * h,nsc_off_t pos,nsc_size_t len,int flag,const int rwflag)212 nsc_ncio_rwb(nsc_ncio_buf_t *h, nsc_off_t pos, nsc_size_t len,
213 int flag, const int rwflag)
214 {
215 nsc_ncio_rw_t *rw;
216 ncall_t *ncall;
217 int ncall_flag;
218 int ncall_proc;
219 int ncall_len;
220 int rc, err;
221
222 if (h->bufh.sb_flag & NSC_ABUF)
223 return (EIO);
224
225 if (pos < h->bufh.sb_pos ||
226 (pos + len) > (h->bufh.sb_pos + h->bufh.sb_len)) {
227 return (EINVAL);
228 }
229
230 if (!len)
231 return (0);
232
233 if (rwflag == NSC_READ && (flag & NSC_RDAHEAD))
234 return (0);
235
236 /* CONSTCOND */
237 if (sizeof (*rw) > NCALL_DATA_SZ) {
238 /* CONSTCOND */
239 ASSERT(sizeof (*rw) <= NCALL_DATA_SZ);
240 return (ENXIO);
241 }
242
243 if (rwflag == NSC_READ) {
244 ncall_flag = NCALL_RDATA;
245 ncall_proc = NSC_NCIO_READ;
246 ncall_len = sizeof (*rw) - sizeof (rw->rw_data);
247 } else {
248 ncall_flag = 0;
249 ncall_proc = NSC_NCIO_WRITE;
250 ncall_len = sizeof (*rw);
251 }
252
253 rw = &h->rw;
254
255 if (rwflag == 0) {
256 /* zero */
257 bzero(rw->rw_data, sizeof (rw->rw_data));
258 }
259
260 if (h->disc)
261 (*h->disc)(h);
262
263 rc = ncall_alloc(rw->rw_snode, 0, 0, &ncall);
264 if (rc != 0) {
265 return (rc);
266 }
267
268 rw->rw_pos = (uint64_t)pos;
269 rw->rw_len = (uint64_t)len;
270 rc = ncall_put_data(ncall, rw, ncall_len);
271 if (rc != 0) {
272 return (rc);
273 }
274
275 rc = ncall_send(ncall, ncall_flag, ncall_proc);
276 if (rc != 0) {
277 return (rc);
278 }
279
280 rc = ncall_read_reply(ncall, 1, &err);
281 if (rc != 0 || err != 0) {
282 return (rc ? rc : err);
283 }
284
285 if (rwflag == NSC_READ) {
286 rc = ncall_get_data(ncall, rw, sizeof (*rw));
287 if (rc != 0) {
288 return (rc);
289 }
290 }
291
292 ncall_free(ncall);
293 return (0);
294 }
295
296
297 static int
nsc_ncio_read(nsc_ncio_buf_t * h,nsc_off_t pos,nsc_size_t len,int flag)298 nsc_ncio_read(nsc_ncio_buf_t *h, nsc_off_t pos, nsc_size_t len, int flag)
299 {
300 return (nsc_ncio_rwb(h, pos, len, flag, NSC_READ));
301 }
302
303
304 static int
nsc_ncio_write(nsc_ncio_buf_t * h,nsc_off_t pos,nsc_size_t len,int flag)305 nsc_ncio_write(nsc_ncio_buf_t *h, nsc_off_t pos, nsc_size_t len, int flag)
306 {
307 return (nsc_ncio_rwb(h, pos, len, flag, NSC_WRITE));
308 }
309
310
311 static int
nsc_ncio_zero(nsc_ncio_buf_t * h,nsc_off_t pos,nsc_size_t len,int flag)312 nsc_ncio_zero(nsc_ncio_buf_t *h, nsc_off_t pos, nsc_size_t len, int flag)
313 {
314 return (nsc_ncio_rwb(h, pos, len, flag, 0));
315 }
316
317
318 static void
nsc_wait_ncio(nsc_ncio_buf_t * h)319 nsc_wait_ncio(nsc_ncio_buf_t *h)
320 {
321 nsc_iodev_t *iodev = h->bufh.sb_fd->sf_iodev;
322 void (*fn)() = h->disc;
323 nsc_ncio_buf_t *hp;
324
325 mutex_enter(&iodev->si_lock);
326
327 h->next = iodev->si_active;
328 iodev->si_active = h;
329
330 /* CONSTCOND */
331
332 while (1) {
333 for (hp = h->next; hp; hp = hp->next) {
334 if ((h->bufh.sb_pos + h->bufh.sb_len) >
335 hp->bufh.sb_pos &&
336 h->bufh.sb_pos <
337 (hp->bufh.sb_pos + hp->bufh.sb_len)) {
338 /* found overlapping io in progress */
339 break;
340 }
341 }
342
343 if (!hp)
344 break;
345
346 if (fn) {
347 (*fn)(h);
348 fn = NULL;
349 }
350
351 cv_wait(&iodev->si_cv, &iodev->si_lock);
352 }
353
354 mutex_exit(&iodev->si_lock);
355 }
356
357
358 static int
nsc_ncio_freeb(nsc_ncio_buf_t * h)359 nsc_ncio_freeb(nsc_ncio_buf_t *h)
360 {
361 nsc_ncio_buf_t **hpp, *hp;
362 nsc_iodev_t *iodev;
363 int wake = 0;
364
365 if ((h->bufh.sb_flag & NSC_HACTIVE) &&
366 h->bufh.sb_fd && !(h->bufh.sb_flag & NSC_ABUF)) {
367 iodev = h->bufh.sb_fd->sf_iodev;
368
369 mutex_enter(&iodev->si_lock);
370
371 for (hpp = (nsc_ncio_buf_t **)&iodev->si_active;
372 *hpp; hpp = &hp->next) {
373 if ((hp = *hpp) == h) {
374 *hpp = h->next;
375 break;
376 }
377
378 if ((h->bufh.sb_pos + h->bufh.sb_len) >
379 hp->bufh.sb_pos &&
380 h->bufh.sb_pos <
381 (hp->bufh.sb_pos + hp->bufh.sb_len)) {
382 wake = 1;
383 }
384 }
385
386 if (wake)
387 cv_broadcast(&iodev->si_cv);
388
389 mutex_exit(&iodev->si_lock);
390 }
391
392 /* clear flags, preserve NSC_HALLOCATED */
393 h->bufh.sb_flag &= NSC_HALLOCATED;
394
395 if ((h->bufh.sb_flag & NSC_HALLOCATED) == 0)
396 (void) nsc_ncio_freeh(h);
397
398 return (0);
399 }
400
401
402 static int
nsc_ncio_allocb(nsc_ncio_dev_t * ncp,nsc_off_t pos,nsc_size_t len,int flag,nsc_ncio_buf_t ** hp)403 nsc_ncio_allocb(nsc_ncio_dev_t *ncp, nsc_off_t pos, nsc_size_t len,
404 int flag, nsc_ncio_buf_t **hp)
405 {
406 nsc_ncio_buf_t *h = *hp;
407 int rc;
408
409 if (h == NULL) {
410 cmn_err(CE_WARN, "nsc_ncio_allocb: NULL handle!");
411 return (EIO);
412 }
413
414 if (FBA_SIZE(len) > NSC_NCIO_MAXDATA) {
415 /* too large */
416 return (ENXIO);
417 }
418
419 if ((blind_t)ncp == NSC_ANON_CD) {
420 flag &= ~(NSC_READ | NSC_WRITE | NSC_RDAHEAD);
421 }
422
423 if (h->disc)
424 (*h->disc)(h);
425
426 h->bufh.sb_pos = pos;
427 h->bufh.sb_len = len;
428 h->bufh.sb_error = 0;
429 h->bufh.sb_flag |= flag | NSC_HACTIVE;
430 h->bufh.sb_vec = &h->vec[0];
431
432 if (!((blind_t)ncp == NSC_ANON_CD)) {
433 (void) strncpy(h->rw.rw_path, ncp->path,
434 sizeof (h->rw.rw_path));
435 h->rw.rw_snode = ncp->snode;
436 }
437
438 h->vec[0].sv_len = FBA_SIZE(len);
439 h->vec[0].sv_addr = (uchar_t *)&h->rw.rw_data[0];
440 h->vec[0].sv_vme = 0;
441
442 h->vec[1].sv_len = 0;
443 h->vec[1].sv_addr = 0;
444 h->vec[1].sv_vme = 0;
445
446 if ((flag & NSC_RDAHEAD) || ((blind_t)ncp == NSC_ANON_CD))
447 return (NSC_DONE);
448
449 nsc_wait_ncio(h);
450
451 if (flag & NSC_READ) {
452 if ((rc = nsc_ncio_read(h, pos, len, flag)) != 0) {
453 (void) nsc_ncio_freeb(h);
454 return (rc);
455 }
456 }
457
458 return (NSC_DONE);
459 }
460
461
462 static int
nsc_ncio_partsize(nsc_ncio_dev_t * ncp,nsc_size_t * rvalp)463 nsc_ncio_partsize(nsc_ncio_dev_t *ncp, nsc_size_t *rvalp)
464 {
465 *rvalp = (nsc_size_t)ncp->partsize;
466 return (0);
467 }
468
469
470 /* ARGSUSED */
471 static int
nsc_ncio_maxfbas(nsc_ncio_dev_t * ncp,int flag,nsc_size_t * ptr)472 nsc_ncio_maxfbas(nsc_ncio_dev_t *ncp, int flag, nsc_size_t *ptr)
473 {
474 if (flag == NSC_CACHEBLK)
475 *ptr = 1;
476 else
477 *ptr = FBA_NUM(NSC_NCIO_MAXDATA);
478
479 return (0);
480 }
481
482
483 static int
nsc_ncio_attach(nsc_ncio_dev_t * ncp)484 nsc_ncio_attach(nsc_ncio_dev_t *ncp)
485 {
486 nsc_ncio_size_t *size;
487 ncall_t *ncall;
488 int sizeh, sizel;
489 int rc, err;
490
491 /* CONSTCOND */
492 if (sizeof (*size) > NCALL_DATA_SZ) {
493 /* CONSTCOND */
494 ASSERT(sizeof (*size) <= NCALL_DATA_SZ);
495 return (ENXIO);
496 }
497
498 size = kmem_zalloc(sizeof (*size), KM_SLEEP);
499 (void) strncpy(size->path, ncp->path, sizeof (size->path));
500
501 rc = ncall_alloc(ncp->snode, 0, 0, &ncall);
502 if (rc != 0) {
503 kmem_free(size, sizeof (*size));
504 return (rc);
505 }
506
507 rc = ncall_put_data(ncall, size, sizeof (*size));
508 kmem_free(size, sizeof (*size));
509 size = NULL;
510 if (rc != 0)
511 return (rc);
512
513 rc = ncall_send(ncall, 0, NSC_NCIO_PARTSIZE);
514 if (rc != 0)
515 return (0);
516
517 rc = ncall_read_reply(ncall, 3, &err, &sizeh, &sizel);
518 if (rc != 0 || err != 0)
519 return (rc ? rc : err);
520
521 ncall_free(ncall);
522
523 ncp->partsize = (uint64_t)(((uint64_t)sizeh << 32) | (uint64_t)sizel);
524 return (0);
525 }
526
527
528 static nsc_def_t nsc_ncio_def[] = {
529 { "Open", (uintptr_t)nsc_ncio_open, 0 },
530 { "Close", (uintptr_t)nsc_ncio_close, 0 },
531 { "Attach", (uintptr_t)nsc_ncio_attach, 0 },
532 { "AllocHandle", (uintptr_t)nsc_ncio_alloch, 0 },
533 { "FreeHandle", (uintptr_t)nsc_ncio_freeh, 0 },
534 { "AllocBuf", (uintptr_t)nsc_ncio_allocb, 0 },
535 { "FreeBuf", (uintptr_t)nsc_ncio_freeb, 0 },
536 { "Read", (uintptr_t)nsc_ncio_read, 0 },
537 { "Write", (uintptr_t)nsc_ncio_write, 0 },
538 { "Zero", (uintptr_t)nsc_ncio_zero, 0 },
539 { "PartSize", (uintptr_t)nsc_ncio_partsize, 0 },
540 { "MaxFbas", (uintptr_t)nsc_ncio_maxfbas, 0 },
541 { "Provide", NSC_NCALL, 0 },
542 { 0, 0, 0 }
543 };
544
545
546 /*
547 * ncall-io io provider - server side.
548 */
549
550 /* ARGSUSED1 */
551 static void
nsc_rncio_partsize(ncall_t * ncall,int * ap)552 nsc_rncio_partsize(ncall_t *ncall, int *ap)
553 {
554 nsc_ncio_size_t *size;
555 nsc_size_t partsize;
556 int sizeh, sizel;
557 nsc_fd_t *fd;
558 int rc;
559
560 size = kmem_alloc(sizeof (*size), KM_SLEEP);
561 rc = ncall_get_data(ncall, size, sizeof (*size));
562 if (rc != 0) {
563 ncall_reply(ncall, EFAULT, 0, 0);
564 kmem_free(size, sizeof (*size));
565 return;
566 }
567
568 fd = nsc_open(size->path, NSC_CACHE | NSC_DEVICE | NSC_READ,
569 NULL, NULL, &rc);
570 kmem_free(size, sizeof (*size));
571 size = NULL;
572 if (fd == NULL) {
573 ncall_reply(ncall, rc, 0, 0);
574 return;
575 }
576
577 rc = nsc_reserve(fd, NSC_PCATCH);
578 if (rc != 0) {
579 (void) nsc_close(fd);
580 ncall_reply(ncall, rc, 0, 0);
581 return;
582 }
583
584 sizeh = sizel = 0;
585 rc = nsc_partsize(fd, &partsize);
586 sizel = (int)(partsize & 0xffffffff);
587 /* CONSTCOND */
588 if (sizeof (nsc_size_t) > sizeof (int)) {
589 sizeh = (int)((partsize & 0xffffffff00000000) >> 32);
590 }
591
592 nsc_release(fd);
593 (void) nsc_close(fd);
594
595 ncall_reply(ncall, rc, sizeh, sizel);
596 }
597
598
599 static int
nsc_rncio_copy(char * data,nsc_buf_t * bufp,const int read)600 nsc_rncio_copy(char *data, nsc_buf_t *bufp, const int read)
601 {
602 nsc_vec_t *vec;
603 char *datap;
604 uint64_t tocopy; /* bytes */
605 int thischunk; /* bytes */
606 int rc;
607
608 rc = 0;
609 datap = data;
610 vec = bufp->sb_vec;
611
612 tocopy = FBA_SIZE(bufp->sb_len);
613
614 while (tocopy > 0) {
615 if (vec->sv_len == 0 || vec->sv_addr == 0) {
616 rc = ENOSPC;
617 break;
618 }
619
620 thischunk = (int)min((nsc_size_t)vec->sv_len, tocopy);
621
622 if (read) {
623 bcopy(vec->sv_addr, datap, thischunk);
624 } else {
625 bcopy(datap, vec->sv_addr, thischunk);
626 }
627
628 tocopy -= thischunk;
629 if (thischunk == vec->sv_len)
630 vec++;
631 }
632
633 return (rc);
634 }
635
636
637 /* ARGSUSED */
638 static void
nsc_rncio_io(ncall_t * ncall,int * ap,const int read)639 nsc_rncio_io(ncall_t *ncall, int *ap, const int read)
640 {
641 nsc_ncio_rw_t *rw;
642 nsc_buf_t *bufp;
643 nsc_fd_t *fd;
644 nsc_size_t len;
645 nsc_off_t pos;
646 int ioflag;
647 int rc;
648
649 rw = kmem_alloc(sizeof (*rw), KM_SLEEP);
650 rc = ncall_get_data(ncall, rw, sizeof (*rw));
651 if (rc != 0) {
652 ncall_reply(ncall, EFAULT);
653 kmem_free(rw, sizeof (*rw));
654 return;
655 }
656
657 ioflag = (read ? NSC_READ : NSC_WRITE);
658 pos = (nsc_off_t)rw->rw_pos;
659 len = (nsc_size_t)rw->rw_len;
660
661 fd = nsc_open(rw->rw_path, NSC_CACHE | NSC_DEVICE | NSC_READ | ioflag,
662 NULL, NULL, &rc);
663 if (fd == NULL) {
664 ncall_reply(ncall, rc);
665 kmem_free(rw, sizeof (*rw));
666 return;
667 }
668
669 rc = nsc_reserve(fd, NSC_PCATCH);
670 if (rc != 0) {
671 ncall_reply(ncall, rc);
672 (void) nsc_close(fd);
673 kmem_free(rw, sizeof (*rw));
674 return;
675 }
676
677 bufp = NULL;
678 rc = nsc_alloc_buf(fd, pos, len, NSC_NOCACHE | ioflag, &bufp);
679 if (rc > 0) {
680 ncall_reply(ncall, rc);
681 if (bufp != NULL) {
682 (void) nsc_free_buf(bufp);
683 }
684 nsc_release(fd);
685 (void) nsc_close(fd);
686 kmem_free(rw, sizeof (*rw));
687 return;
688 }
689
690 rc = nsc_rncio_copy(&rw->rw_data[0], bufp, read);
691 if (rc == 0) {
692 if (read) {
693 /* store reply data */
694 rc = ncall_put_data(ncall, rw, sizeof (*rw));
695 } else {
696 /* write new data */
697 rc = nsc_write(bufp, pos, len, 0);
698 }
699 }
700
701 ncall_reply(ncall, rc);
702
703 (void) nsc_free_buf(bufp);
704 nsc_release(fd);
705 (void) nsc_close(fd);
706 kmem_free(rw, sizeof (*rw));
707 }
708
709
710 static void
nsc_rncio_read(ncall_t * ncall,int * ap)711 nsc_rncio_read(ncall_t *ncall, int *ap)
712 {
713 nsc_rncio_io(ncall, ap, TRUE);
714 }
715
716
717 static void
nsc_rncio_write(ncall_t * ncall,int * ap)718 nsc_rncio_write(ncall_t *ncall, int *ap)
719 {
720 nsc_rncio_io(ncall, ap, FALSE);
721 }
722
723
724 /*
725 * ncall-io io provider - setup.
726 */
727
728 void
_nsc_init_ncio(void)729 _nsc_init_ncio(void)
730 {
731 mutex_init(&nsc_ncio_lock, NULL, MUTEX_DRIVER, NULL);
732
733 ncall_register_svc(NSC_NCIO_PARTSIZE, nsc_rncio_partsize);
734 ncall_register_svc(NSC_NCIO_WRITE, nsc_rncio_write);
735 ncall_register_svc(NSC_NCIO_READ, nsc_rncio_read);
736
737 nsc_ncio_io = nsc_register_io("ncall-io",
738 NSC_NCALL_ID | NSC_REFCNT, nsc_ncio_def);
739
740 if (!nsc_ncio_io)
741 cmn_err(CE_WARN, "_nsc_ncio_init: register io failed - ncall");
742 }
743
744
745 void
_nsc_deinit_ncio(void)746 _nsc_deinit_ncio(void)
747 {
748 if (nsc_ncio_io)
749 (void) nsc_unregister_io(nsc_ncio_io, 0);
750
751 ncall_unregister_svc(NSC_NCIO_PARTSIZE);
752 ncall_unregister_svc(NSC_NCIO_WRITE);
753 ncall_unregister_svc(NSC_NCIO_READ);
754
755 nsc_ncio_io = NULL;
756 mutex_destroy(&nsc_ncio_lock);
757 }
758