1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda/*
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda * CDDL HEADER START
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda *
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda * The contents of this file are subject to the terms of the
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda * Common Development and Distribution License (the "License").
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda * You may not use this file except in compliance with the License.
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda *
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda * or http://www.opensolaris.org/os/licensing.
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda * See the License for the specific language governing permissions
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda * and limitations under the License.
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda *
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda * When distributing Covered Code, include this CDDL HEADER in each
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda * If applicable, add the following below this CDDL HEADER, with the
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda * fields enclosed by brackets "[]" replaced with your own identifying
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda * information: Portions Copyright [yyyy] [name of copyright owner]
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda *
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda * CDDL HEADER END
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda */
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda/*
323a81d93e2f58a7d62f6e523f9fddbc029d3d0bjwadams * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda * Use is subject to license terms.
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda */
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda#include <sys/types.h>
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda#include <sys/door.h>
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda#include <sys/note.h>
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda#include <sys/drctl.h>
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda#include <sys/drctl_impl.h>
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda#include <sys/ddi.h>
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda#include <sys/sunddi.h>
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda#include <sys/dr_util.h>
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaedastatic door_handle_t drctl_dh; /* Door for upcalls */
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaedaint
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaedai_drctl_ioctl(int cmd, intptr_t arg)
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda{
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda int rv;
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda drctl_setup_t setup_rqst;
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda switch (cmd) {
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda case DRCTL_IOCTL_CONNECT_SERVER:
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda if (ddi_copyin((caddr_t)arg,
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda &setup_rqst, sizeof (setup_rqst), 0) != 0) {
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda cmn_err(CE_WARN, "i_drctl_ioctl: ddi_copyin failed "
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda "for DRCTL_IOCTL_CONNECT_SERVER");
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda rv = EFAULT;
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda break;
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda }
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda drctl_dh = door_ki_lookup(setup_rqst.did);
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda rv = 0;
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda break;
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda default:
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda rv = EIO;
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda }
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda return (rv);
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda}
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaedaint
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaedai_drctl_send(void *msg, size_t size, void **obufp, size_t *osize)
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda{
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda int up_err;
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda int rv = 0;
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda door_arg_t door_args;
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda door_handle_t dh = drctl_dh;
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda static const char me[] = "i_drctl_send";
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaedaretry:
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda if (dh)
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda door_ki_hold(dh);
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda else
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda return (EIO);
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda door_args.data_ptr = (char *)msg;
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda door_args.data_size = size;
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda door_args.desc_ptr = NULL;
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda door_args.desc_num = 0;
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda /*
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda * We don't know the size of the message the daemon
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda * will pass back to us. By setting rbuf to NULL,
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda * we force the door code to allocate a buf of the
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda * appropriate size. We must set rsize > 0, however,
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda * else the door code acts as if no response was
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda * expected and doesn't pass the data to us.
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda */
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda door_args.rbuf = NULL;
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda door_args.rsize = 1;
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda DR_DBG_CTL("%s: msg %p size %ld obufp %p osize %p\n",
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda me, msg, size, (void *)obufp, (void *)osize);
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda
323a81d93e2f58a7d62f6e523f9fddbc029d3d0bjwadams up_err = door_ki_upcall_limited(dh, &door_args, NULL, SIZE_MAX, 0);
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda if (up_err == 0) {
0c86d1bb954dd114dc697724f09481f790a39f71rsmaeda if (door_args.rbuf == NULL)
0c86d1bb954dd114dc697724f09481f790a39f71rsmaeda goto done;
0c86d1bb954dd114dc697724f09481f790a39f71rsmaeda
0c86d1bb954dd114dc697724f09481f790a39f71rsmaeda DR_DBG_CTL("%s: rbuf %p rsize %ld\n", me,
0c86d1bb954dd114dc697724f09481f790a39f71rsmaeda (void *)door_args.rbuf, door_args.rsize);
0c86d1bb954dd114dc697724f09481f790a39f71rsmaeda
0c86d1bb954dd114dc697724f09481f790a39f71rsmaeda if (obufp != NULL) {
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda *obufp = door_args.rbuf;
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda *osize = door_args.rsize;
99c7e85592b5d673f1469b2767f876710004dc23James Marks - Sun Microsystems DR_DBG_KMEM("%s: (door) alloc addr %p size %ld\n",
99c7e85592b5d673f1469b2767f876710004dc23James Marks - Sun Microsystems __func__,
99c7e85592b5d673f1469b2767f876710004dc23James Marks - Sun Microsystems (void *)(door_args.rbuf), door_args.rsize);
0c86d1bb954dd114dc697724f09481f790a39f71rsmaeda } else {
0c86d1bb954dd114dc697724f09481f790a39f71rsmaeda /*
0c86d1bb954dd114dc697724f09481f790a39f71rsmaeda * No output buffer pointer was passed in,
0c86d1bb954dd114dc697724f09481f790a39f71rsmaeda * so the response buffer allocated by the
0c86d1bb954dd114dc697724f09481f790a39f71rsmaeda * door code must be deallocated.
0c86d1bb954dd114dc697724f09481f790a39f71rsmaeda */
99c7e85592b5d673f1469b2767f876710004dc23James Marks - Sun Microsystems DR_DBG_KMEM("%s: free addr %p size %ld\n", __func__,
99c7e85592b5d673f1469b2767f876710004dc23James Marks - Sun Microsystems (void *)(door_args.rbuf), door_args.rsize);
0c86d1bb954dd114dc697724f09481f790a39f71rsmaeda kmem_free(door_args.rbuf, door_args.rsize);
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda }
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda } else {
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda switch (up_err) {
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda case EINTR:
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda DR_DBG_CTL("%s: door call returned EINTR\n", me);
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda _NOTE(FALLTHROUGH)
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda case EAGAIN:
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda /*
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda * Server process may be forking, try again.
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda */
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda door_ki_rele(dh);
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda delay(hz);
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda goto retry;
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda case EBADF:
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda case EINVAL:
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda drctl_dh = NULL;
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda DR_DBG_CTL(
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda "%s: door call failed with %d\n", me, up_err);
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda rv = EIO;
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda break;
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda default:
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda DR_DBG_CTL("%s: unexpected return "
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda "code %d from door_ki_upcall\n", me, up_err);
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda rv = EIO;
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda break;
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda }
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda }
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda
0c86d1bb954dd114dc697724f09481f790a39f71rsmaedadone:
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda door_ki_rele(dh);
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda return (rv);
1d4b38e0077763e7c9b20768eacb841957e787bcrsmaeda}