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
i_drctl_ioctl(int cmd,intptr_t arg)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
i_drctl_send(void * msg,size_t size,void ** obufp,size_t * osize)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