12309Srsmaeda /* 22309Srsmaeda * CDDL HEADER START 32309Srsmaeda * 42309Srsmaeda * The contents of this file are subject to the terms of the 52309Srsmaeda * Common Development and Distribution License (the "License"). 62309Srsmaeda * You may not use this file except in compliance with the License. 72309Srsmaeda * 82309Srsmaeda * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 92309Srsmaeda * or http://www.opensolaris.org/os/licensing. 102309Srsmaeda * See the License for the specific language governing permissions 112309Srsmaeda * and limitations under the License. 122309Srsmaeda * 132309Srsmaeda * When distributing Covered Code, include this CDDL HEADER in each 142309Srsmaeda * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 152309Srsmaeda * If applicable, add the following below this CDDL HEADER, with the 162309Srsmaeda * fields enclosed by brackets "[]" replaced with your own identifying 172309Srsmaeda * information: Portions Copyright [yyyy] [name of copyright owner] 182309Srsmaeda * 192309Srsmaeda * CDDL HEADER END 202309Srsmaeda */ 212309Srsmaeda 222309Srsmaeda /* 23*6997Sjwadams * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 242309Srsmaeda * Use is subject to license terms. 252309Srsmaeda */ 262309Srsmaeda 272309Srsmaeda #pragma ident "%Z%%M% %I% %E% SMI" 282309Srsmaeda 292309Srsmaeda #include <sys/types.h> 302309Srsmaeda #include <sys/door.h> 312309Srsmaeda #include <sys/note.h> 322309Srsmaeda #include <sys/drctl.h> 332309Srsmaeda #include <sys/drctl_impl.h> 342309Srsmaeda #include <sys/ddi.h> 352309Srsmaeda #include <sys/sunddi.h> 362309Srsmaeda #include <sys/dr_util.h> 372309Srsmaeda 382309Srsmaeda static door_handle_t drctl_dh; /* Door for upcalls */ 392309Srsmaeda 402309Srsmaeda 412309Srsmaeda int 422309Srsmaeda i_drctl_ioctl(int cmd, intptr_t arg) 432309Srsmaeda { 442309Srsmaeda int rv; 452309Srsmaeda drctl_setup_t setup_rqst; 462309Srsmaeda 472309Srsmaeda switch (cmd) { 482309Srsmaeda case DRCTL_IOCTL_CONNECT_SERVER: 492309Srsmaeda if (ddi_copyin((caddr_t)arg, 502309Srsmaeda &setup_rqst, sizeof (setup_rqst), 0) != 0) { 512309Srsmaeda cmn_err(CE_WARN, "i_drctl_ioctl: ddi_copyin failed " 522309Srsmaeda "for DRCTL_IOCTL_CONNECT_SERVER"); 532309Srsmaeda rv = EFAULT; 542309Srsmaeda break; 552309Srsmaeda } 562309Srsmaeda 572309Srsmaeda drctl_dh = door_ki_lookup(setup_rqst.did); 582309Srsmaeda rv = 0; 592309Srsmaeda break; 602309Srsmaeda 612309Srsmaeda default: 622309Srsmaeda rv = EIO; 632309Srsmaeda } 642309Srsmaeda 652309Srsmaeda return (rv); 662309Srsmaeda } 672309Srsmaeda 682309Srsmaeda int 692309Srsmaeda i_drctl_send(void *msg, size_t size, void **obufp, size_t *osize) 702309Srsmaeda { 712309Srsmaeda int up_err; 722309Srsmaeda int rv = 0; 732309Srsmaeda door_arg_t door_args; 742309Srsmaeda door_handle_t dh = drctl_dh; 752309Srsmaeda static const char me[] = "i_drctl_send"; 762309Srsmaeda 772309Srsmaeda retry: 782309Srsmaeda if (dh) 792309Srsmaeda door_ki_hold(dh); 802309Srsmaeda else 812309Srsmaeda return (EIO); 822309Srsmaeda 832309Srsmaeda door_args.data_ptr = (char *)msg; 842309Srsmaeda door_args.data_size = size; 852309Srsmaeda door_args.desc_ptr = NULL; 862309Srsmaeda door_args.desc_num = 0; 872309Srsmaeda 882309Srsmaeda /* 892309Srsmaeda * We don't know the size of the message the daemon 902309Srsmaeda * will pass back to us. By setting rbuf to NULL, 912309Srsmaeda * we force the door code to allocate a buf of the 922309Srsmaeda * appropriate size. We must set rsize > 0, however, 932309Srsmaeda * else the door code acts as if no response was 942309Srsmaeda * expected and doesn't pass the data to us. 952309Srsmaeda */ 962309Srsmaeda door_args.rbuf = NULL; 972309Srsmaeda door_args.rsize = 1; 982309Srsmaeda DR_DBG_CTL("%s: msg %p size %ld obufp %p osize %p\n", 992309Srsmaeda me, msg, size, (void *)obufp, (void *)osize); 1002309Srsmaeda 101*6997Sjwadams up_err = door_ki_upcall_limited(dh, &door_args, NULL, SIZE_MAX, 0); 1022309Srsmaeda if (up_err == 0) { 1033414Srsmaeda if (door_args.rbuf == NULL) 1043414Srsmaeda goto done; 1053414Srsmaeda 1063414Srsmaeda DR_DBG_CTL("%s: rbuf %p rsize %ld\n", me, 1073414Srsmaeda (void *)door_args.rbuf, door_args.rsize); 1083414Srsmaeda 1093414Srsmaeda if (obufp != NULL) { 1102309Srsmaeda *obufp = door_args.rbuf; 1112309Srsmaeda *osize = door_args.rsize; 1123414Srsmaeda } else { 1133414Srsmaeda /* 1143414Srsmaeda * No output buffer pointer was passed in, 1153414Srsmaeda * so the response buffer allocated by the 1163414Srsmaeda * door code must be deallocated. 1173414Srsmaeda */ 1183414Srsmaeda kmem_free(door_args.rbuf, door_args.rsize); 1192309Srsmaeda } 1202309Srsmaeda } else { 1212309Srsmaeda switch (up_err) { 1222309Srsmaeda case EINTR: 1232309Srsmaeda DR_DBG_CTL("%s: door call returned EINTR\n", me); 1242309Srsmaeda _NOTE(FALLTHROUGH) 1252309Srsmaeda case EAGAIN: 1262309Srsmaeda /* 1272309Srsmaeda * Server process may be forking, try again. 1282309Srsmaeda */ 1292309Srsmaeda door_ki_rele(dh); 1302309Srsmaeda delay(hz); 1312309Srsmaeda goto retry; 1322309Srsmaeda case EBADF: 1332309Srsmaeda case EINVAL: 1342309Srsmaeda drctl_dh = NULL; 1352309Srsmaeda DR_DBG_CTL( 1362309Srsmaeda "%s: door call failed with %d\n", me, up_err); 1372309Srsmaeda rv = EIO; 1382309Srsmaeda break; 1392309Srsmaeda default: 1402309Srsmaeda DR_DBG_CTL("%s: unexpected return " 1412309Srsmaeda "code %d from door_ki_upcall\n", me, up_err); 1422309Srsmaeda rv = EIO; 1432309Srsmaeda break; 1442309Srsmaeda } 1452309Srsmaeda } 1462309Srsmaeda 1473414Srsmaeda done: 1482309Srsmaeda door_ki_rele(dh); 1492309Srsmaeda return (rv); 1502309Srsmaeda } 151