11d4b38e0Srsmaeda /* 21d4b38e0Srsmaeda * CDDL HEADER START 31d4b38e0Srsmaeda * 41d4b38e0Srsmaeda * The contents of this file are subject to the terms of the 51d4b38e0Srsmaeda * Common Development and Distribution License (the "License"). 61d4b38e0Srsmaeda * You may not use this file except in compliance with the License. 71d4b38e0Srsmaeda * 81d4b38e0Srsmaeda * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91d4b38e0Srsmaeda * or http://www.opensolaris.org/os/licensing. 101d4b38e0Srsmaeda * See the License for the specific language governing permissions 111d4b38e0Srsmaeda * and limitations under the License. 121d4b38e0Srsmaeda * 131d4b38e0Srsmaeda * When distributing Covered Code, include this CDDL HEADER in each 141d4b38e0Srsmaeda * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151d4b38e0Srsmaeda * If applicable, add the following below this CDDL HEADER, with the 161d4b38e0Srsmaeda * fields enclosed by brackets "[]" replaced with your own identifying 171d4b38e0Srsmaeda * information: Portions Copyright [yyyy] [name of copyright owner] 181d4b38e0Srsmaeda * 191d4b38e0Srsmaeda * CDDL HEADER END 201d4b38e0Srsmaeda */ 211d4b38e0Srsmaeda 221d4b38e0Srsmaeda /* 23323a81d9Sjwadams * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 241d4b38e0Srsmaeda * Use is subject to license terms. 251d4b38e0Srsmaeda */ 261d4b38e0Srsmaeda 271d4b38e0Srsmaeda #include <sys/types.h> 281d4b38e0Srsmaeda #include <sys/door.h> 291d4b38e0Srsmaeda #include <sys/note.h> 301d4b38e0Srsmaeda #include <sys/drctl.h> 311d4b38e0Srsmaeda #include <sys/drctl_impl.h> 321d4b38e0Srsmaeda #include <sys/ddi.h> 331d4b38e0Srsmaeda #include <sys/sunddi.h> 341d4b38e0Srsmaeda #include <sys/dr_util.h> 351d4b38e0Srsmaeda 361d4b38e0Srsmaeda static door_handle_t drctl_dh; /* Door for upcalls */ 371d4b38e0Srsmaeda 381d4b38e0Srsmaeda 391d4b38e0Srsmaeda int 401d4b38e0Srsmaeda i_drctl_ioctl(int cmd, intptr_t arg) 411d4b38e0Srsmaeda { 421d4b38e0Srsmaeda int rv; 431d4b38e0Srsmaeda drctl_setup_t setup_rqst; 441d4b38e0Srsmaeda 451d4b38e0Srsmaeda switch (cmd) { 461d4b38e0Srsmaeda case DRCTL_IOCTL_CONNECT_SERVER: 471d4b38e0Srsmaeda if (ddi_copyin((caddr_t)arg, 481d4b38e0Srsmaeda &setup_rqst, sizeof (setup_rqst), 0) != 0) { 491d4b38e0Srsmaeda cmn_err(CE_WARN, "i_drctl_ioctl: ddi_copyin failed " 501d4b38e0Srsmaeda "for DRCTL_IOCTL_CONNECT_SERVER"); 511d4b38e0Srsmaeda rv = EFAULT; 521d4b38e0Srsmaeda break; 531d4b38e0Srsmaeda } 541d4b38e0Srsmaeda 551d4b38e0Srsmaeda drctl_dh = door_ki_lookup(setup_rqst.did); 561d4b38e0Srsmaeda rv = 0; 571d4b38e0Srsmaeda break; 581d4b38e0Srsmaeda 591d4b38e0Srsmaeda default: 601d4b38e0Srsmaeda rv = EIO; 611d4b38e0Srsmaeda } 621d4b38e0Srsmaeda 631d4b38e0Srsmaeda return (rv); 641d4b38e0Srsmaeda } 651d4b38e0Srsmaeda 661d4b38e0Srsmaeda int 671d4b38e0Srsmaeda i_drctl_send(void *msg, size_t size, void **obufp, size_t *osize) 681d4b38e0Srsmaeda { 691d4b38e0Srsmaeda int up_err; 701d4b38e0Srsmaeda int rv = 0; 711d4b38e0Srsmaeda door_arg_t door_args; 721d4b38e0Srsmaeda door_handle_t dh = drctl_dh; 731d4b38e0Srsmaeda static const char me[] = "i_drctl_send"; 741d4b38e0Srsmaeda 751d4b38e0Srsmaeda retry: 761d4b38e0Srsmaeda if (dh) 771d4b38e0Srsmaeda door_ki_hold(dh); 781d4b38e0Srsmaeda else 791d4b38e0Srsmaeda return (EIO); 801d4b38e0Srsmaeda 811d4b38e0Srsmaeda door_args.data_ptr = (char *)msg; 821d4b38e0Srsmaeda door_args.data_size = size; 831d4b38e0Srsmaeda door_args.desc_ptr = NULL; 841d4b38e0Srsmaeda door_args.desc_num = 0; 851d4b38e0Srsmaeda 861d4b38e0Srsmaeda /* 871d4b38e0Srsmaeda * We don't know the size of the message the daemon 881d4b38e0Srsmaeda * will pass back to us. By setting rbuf to NULL, 891d4b38e0Srsmaeda * we force the door code to allocate a buf of the 901d4b38e0Srsmaeda * appropriate size. We must set rsize > 0, however, 911d4b38e0Srsmaeda * else the door code acts as if no response was 921d4b38e0Srsmaeda * expected and doesn't pass the data to us. 931d4b38e0Srsmaeda */ 941d4b38e0Srsmaeda door_args.rbuf = NULL; 951d4b38e0Srsmaeda door_args.rsize = 1; 961d4b38e0Srsmaeda DR_DBG_CTL("%s: msg %p size %ld obufp %p osize %p\n", 971d4b38e0Srsmaeda me, msg, size, (void *)obufp, (void *)osize); 981d4b38e0Srsmaeda 99323a81d9Sjwadams up_err = door_ki_upcall_limited(dh, &door_args, NULL, SIZE_MAX, 0); 1001d4b38e0Srsmaeda if (up_err == 0) { 1010c86d1bbSrsmaeda if (door_args.rbuf == NULL) 1020c86d1bbSrsmaeda goto done; 1030c86d1bbSrsmaeda 1040c86d1bbSrsmaeda DR_DBG_CTL("%s: rbuf %p rsize %ld\n", me, 1050c86d1bbSrsmaeda (void *)door_args.rbuf, door_args.rsize); 1060c86d1bbSrsmaeda 1070c86d1bbSrsmaeda if (obufp != NULL) { 1081d4b38e0Srsmaeda *obufp = door_args.rbuf; 1091d4b38e0Srsmaeda *osize = door_args.rsize; 110*99c7e855SJames Marks - Sun Microsystems DR_DBG_KMEM("%s: (door) alloc addr %p size %ld\n", 111*99c7e855SJames Marks - Sun Microsystems __func__, 112*99c7e855SJames Marks - Sun Microsystems (void *)(door_args.rbuf), door_args.rsize); 1130c86d1bbSrsmaeda } else { 1140c86d1bbSrsmaeda /* 1150c86d1bbSrsmaeda * No output buffer pointer was passed in, 1160c86d1bbSrsmaeda * so the response buffer allocated by the 1170c86d1bbSrsmaeda * door code must be deallocated. 1180c86d1bbSrsmaeda */ 119*99c7e855SJames Marks - Sun Microsystems DR_DBG_KMEM("%s: free addr %p size %ld\n", __func__, 120*99c7e855SJames Marks - Sun Microsystems (void *)(door_args.rbuf), door_args.rsize); 1210c86d1bbSrsmaeda kmem_free(door_args.rbuf, door_args.rsize); 1221d4b38e0Srsmaeda } 1231d4b38e0Srsmaeda } else { 1241d4b38e0Srsmaeda switch (up_err) { 1251d4b38e0Srsmaeda case EINTR: 1261d4b38e0Srsmaeda DR_DBG_CTL("%s: door call returned EINTR\n", me); 1271d4b38e0Srsmaeda _NOTE(FALLTHROUGH) 1281d4b38e0Srsmaeda case EAGAIN: 1291d4b38e0Srsmaeda /* 1301d4b38e0Srsmaeda * Server process may be forking, try again. 1311d4b38e0Srsmaeda */ 1321d4b38e0Srsmaeda door_ki_rele(dh); 1331d4b38e0Srsmaeda delay(hz); 1341d4b38e0Srsmaeda goto retry; 1351d4b38e0Srsmaeda case EBADF: 1361d4b38e0Srsmaeda case EINVAL: 1371d4b38e0Srsmaeda drctl_dh = NULL; 1381d4b38e0Srsmaeda DR_DBG_CTL( 1391d4b38e0Srsmaeda "%s: door call failed with %d\n", me, up_err); 1401d4b38e0Srsmaeda rv = EIO; 1411d4b38e0Srsmaeda break; 1421d4b38e0Srsmaeda default: 1431d4b38e0Srsmaeda DR_DBG_CTL("%s: unexpected return " 1441d4b38e0Srsmaeda "code %d from door_ki_upcall\n", me, up_err); 1451d4b38e0Srsmaeda rv = EIO; 1461d4b38e0Srsmaeda break; 1471d4b38e0Srsmaeda } 1481d4b38e0Srsmaeda } 1491d4b38e0Srsmaeda 1500c86d1bbSrsmaeda done: 1511d4b38e0Srsmaeda door_ki_rele(dh); 1521d4b38e0Srsmaeda return (rv); 1531d4b38e0Srsmaeda } 154