NetBSD/sys/compat/mach/mach_iokit.c
manu bb7e6443cb Remove all our real devices from the IOKit registry, as they won't be
usefull. Emulate only IOHIDSystem, IOFramebuffer and friends in the
registry.

ioreg is able to display the tree and dump the properties.
2003-11-01 18:41:25 +00:00

1237 lines
37 KiB
C

/* $NetBSD: mach_iokit.c,v 1.24 2003/11/01 18:41:25 manu Exp $ */
/*-
* Copyright (c) 2003 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Emmanuel Dreyfus.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "opt_compat_darwin.h"
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: mach_iokit.c,v 1.24 2003/11/01 18:41:25 manu Exp $");
#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/signal.h>
#include <sys/mount.h>
#include <sys/proc.h>
#include <sys/device.h>
#include <uvm/uvm_extern.h>
#include <uvm/uvm_map.h>
#include <compat/mach/mach_types.h>
#include <compat/mach/mach_message.h>
#include <compat/mach/mach_port.h>
#include <compat/mach/mach_errno.h>
#include <compat/mach/mach_iokit.h>
#ifdef COMPAT_DARWIN
#include <compat/darwin/darwin_iokit.h>
#endif
struct mach_iokit_devclass mach_ioroot_devclass = {
"(unknwon)",
{ NULL },
"<dict ID=\"0\"></dict>",
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
"Root",
NULL,
};
struct mach_iokit_devclass *mach_iokit_devclasses[] = {
&mach_ioroot_devclass,
#ifdef COMPAT_DARWIN
DARWIN_IOKIT_DEVCLASSES
#endif
NULL,
};
static int mach_fill_child_iterator(struct mach_device_iterator *, int, int,
struct mach_iokit_devclass *);
static int mach_fill_parent_iterator(struct mach_device_iterator *, int, int,
struct mach_iokit_devclass *);
int
mach_io_service_get_matching_services(args)
struct mach_trap_args *args;
{
mach_io_service_get_matching_services_request_t *req = args->smsg;
mach_io_service_get_matching_services_reply_t *rep = args->rmsg;
size_t *msglen = args->rsize;
struct lwp *l = args->l;
struct mach_port *mp;
struct mach_right *mr;
struct mach_iokit_devclass *mid;
struct mach_device_iterator *mdi;
size_t size;
int i;
mp = mach_port_get();
mp->mp_flags |= MACH_MP_INKERNEL;
mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
mp->mp_data = NULL;
i = 0;
while ((mid = mach_iokit_devclasses[i++]) != NULL) {
if (memcmp(req->req_string, mid->mid_string,
strlen(mid->mid_string)) == 0) {
mp->mp_datatype = MACH_MP_DEVICE_ITERATOR;
size = sizeof(*mdi)
+ sizeof(struct mach_device_iterator *);
mdi = malloc(size, M_EMULDATA, M_WAITOK);
mdi->mdi_devices[0] = mid;
mdi->mdi_devices[1] = NULL;
mdi->mdi_current = 0;
mp->mp_data = mdi;
break;
}
}
if (mp->mp_data == NULL)
return mach_iokit_error(args, MACH_IOKIT_ENOENT);
rep->rep_msgh.msgh_bits =
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE) |
MACH_MSGH_BITS_COMPLEX;
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
rep->rep_body.msgh_descriptor_count = 1;
rep->rep_match.name = (mach_port_t)mr->mr_name;
rep->rep_match.disposition = 0x11; /* XXX */
rep->rep_trailer.msgh_trailer_size = 8;
*msglen = sizeof(*rep);
return 0;
}
int
mach_io_iterator_next(args)
struct mach_trap_args *args;
{
mach_io_iterator_next_request_t *req = args->smsg;
mach_io_iterator_next_reply_t *rep = args->rmsg;
size_t *msglen = args->rsize;
struct lwp *l = args->l;
struct mach_port *mp;
struct mach_right *mr;
struct mach_device_iterator *mdi;
mach_port_t mn;
mn = req->req_msgh.msgh_remote_port;
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
return mach_iokit_error(args, MACH_IOKIT_EPERM);
if (mr->mr_port->mp_datatype != MACH_MP_DEVICE_ITERATOR)
return mach_iokit_error(args, MACH_IOKIT_EINVAL);
mdi = mr->mr_port->mp_data;
/* Is there something coming next? */
if (mdi->mdi_devices[mdi->mdi_current] == NULL)
return mach_iokit_error(args, MACH_IOKIT_EINVAL);
mp = mach_port_get();
mp->mp_flags |= MACH_MP_INKERNEL;
mp->mp_datatype = MACH_MP_IOKIT_DEVCLASS;
mp->mp_data = mdi->mdi_devices[mdi->mdi_current++];
mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
rep->rep_msgh.msgh_bits =
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE) |
MACH_MSGH_BITS_COMPLEX;
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
rep->rep_body.msgh_descriptor_count = 1;
rep->rep_object.name = (mach_port_t)mr->mr_name;
rep->rep_object.disposition = 0x11; /* XXX */
rep->rep_trailer.msgh_trailer_size = 8;
*msglen = sizeof(*rep);
return 0;
}
int
mach_io_service_open(args)
struct mach_trap_args *args;
{
mach_io_service_open_request_t *req = args->smsg;
mach_io_service_open_reply_t *rep = args->rmsg;
size_t *msglen = args->rsize;
struct lwp *l = args->l;
struct mach_port *mp;
struct mach_right *mr;
mach_port_t mn;
mn = req->req_msgh.msgh_remote_port;
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
return mach_iokit_error(args, MACH_IOKIT_EPERM);
mp = mach_port_get();
mp->mp_flags |= MACH_MP_INKERNEL;
if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) {
mp->mp_datatype = MACH_MP_IOKIT_DEVCLASS;
mp->mp_data = mr->mr_port->mp_data;
}
mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
rep->rep_msgh.msgh_bits =
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE) |
MACH_MSGH_BITS_COMPLEX;
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
rep->rep_body.msgh_descriptor_count = 1;
rep->rep_connect.name = (mach_port_t)mr->mr_name;
rep->rep_connect.disposition = 0x11; /* XXX */
rep->rep_trailer.msgh_trailer_size = 8;
*msglen = sizeof(*rep);
return 0;
}
int
mach_io_connect_method_scalari_scalaro(args)
struct mach_trap_args *args;
{
mach_io_connect_method_scalari_scalaro_request_t *req = args->smsg;
struct lwp *l = args->l;
mach_port_t mn;
struct mach_right *mr;
struct mach_iokit_devclass *mid;
mn = req->req_msgh.msgh_remote_port;
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
return mach_iokit_error(args, MACH_IOKIT_EPERM);
if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) {
mid = mr->mr_port->mp_data;
if (mid->mid_connect_method_scalari_scalaro == NULL)
printf("no connect_method_scalari_scalaro method "
"for darwin_iokit_class %s\n", mid->mid_name);
else
return (mid->mid_connect_method_scalari_scalaro)(args);
}
return mach_iokit_error(args, MACH_IOKIT_ENODEV);
}
int
mach_io_connect_get_service(args)
struct mach_trap_args *args;
{
mach_io_connect_get_service_request_t *req = args->smsg;
mach_io_connect_get_service_reply_t *rep = args->rmsg;
size_t *msglen = args->rsize;
struct lwp *l = args->l;
struct mach_port *mp;
struct mach_right *mr;
mach_port_t mn;
mn = req->req_msgh.msgh_remote_port;
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
return mach_iokit_error(args, MACH_IOKIT_EPERM);
mp = mach_port_get();
mp->mp_flags |= MACH_MP_INKERNEL;
if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) {
mp->mp_datatype = MACH_MP_IOKIT_DEVCLASS;
mp->mp_data = mr->mr_port->mp_data;
}
mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
/*
* XXX Bump the refcount to workaround an emulation bug
* that causes Windowserver to release the port too early.
*/
mr->mr_refcount++;
rep->rep_msgh.msgh_bits =
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE) |
MACH_MSGH_BITS_COMPLEX;
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
rep->rep_body.msgh_descriptor_count = 1;
rep->rep_service.name = (mach_port_t)mr->mr_name;
rep->rep_service.disposition = 0x11; /* XXX */
rep->rep_trailer.msgh_trailer_size = 8;
*msglen = sizeof(*rep);
return 0;
}
int
mach_io_registry_entry_create_iterator(args)
struct mach_trap_args *args;
{
mach_io_registry_entry_create_iterator_request_t *req = args->smsg;
mach_io_registry_entry_create_iterator_reply_t *rep = args->rmsg;
size_t *msglen = args->rsize;
struct lwp *l = args->l;
struct mach_port *mp;
mach_port_t mn;
struct mach_right *mr;
struct mach_iokit_devclass *mid;
struct mach_device_iterator *mdi;
struct mach_iokit_devclass **midp;
int maxdev, index;
size_t size;
mn = req->req_msgh.msgh_remote_port;
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
return mach_iokit_error(args, MACH_IOKIT_EPERM);
if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS)
return mach_iokit_error(args, MACH_IOKIT_EINVAL);
mid = (struct mach_iokit_devclass *)mr->mr_port->mp_data;
mp = mach_port_get();
mp->mp_flags |= (MACH_MP_INKERNEL | MACH_MP_DATA_ALLOCATED);
mp->mp_datatype = MACH_MP_DEVICE_ITERATOR;
maxdev = sizeof(mach_iokit_devclasses);
size = sizeof(*mdi) + (maxdev * sizeof(struct mach_iokit_devclass *));
mdi = malloc(size, M_EMULDATA, M_WAITOK);
mp->mp_data = mdi;
if (req->req_options & MACH_IOKIT_PARENT_ITERATOR)
index = mach_fill_parent_iterator(mdi, maxdev, 0, mid);
else
index = mach_fill_child_iterator(mdi, maxdev, 0, mid);
/* XXX This is untested */
if (req->req_options & MACH_IOKIT_RECURSIVE_ITERATOR) {
for (midp = mdi->mdi_devices; *midp != NULL; midp++) {
if (req->req_options & MACH_IOKIT_PARENT_ITERATOR)
index = mach_fill_parent_iterator(mdi,
maxdev, index, *midp);
else
index = mach_fill_child_iterator(mdi,
maxdev, index, *midp);
}
}
mdi->mdi_current = 0;
mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
#ifdef DEBUG_MACH
printf("io_registry_entry_create_iterator\n");
#endif
rep->rep_msgh.msgh_bits =
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE) |
MACH_MSGH_BITS_COMPLEX;
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
rep->rep_body.msgh_descriptor_count = 1;
rep->rep_iterator.name = (mach_port_t)mr->mr_name;
rep->rep_iterator.disposition = 0x11; /* XXX */
rep->rep_trailer.msgh_trailer_size = 8;
*msglen = sizeof(*rep);
return 0;
}
int
mach_io_object_conforms_to(args)
struct mach_trap_args *args;
{
mach_io_object_conforms_to_request_t *req = args->smsg;
mach_io_object_conforms_to_reply_t *rep = args->rmsg;
size_t *msglen = args->rsize;
rep->rep_msgh.msgh_bits =
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE);
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
rep->rep_conforms = 1; /* XXX */
rep->rep_trailer.msgh_trailer_size = 8;
*msglen = sizeof(*rep);
return 0;
}
int
mach_io_service_add_interest_notification(args)
struct mach_trap_args *args;
{
mach_io_service_add_interest_notification_request_t *req = args->smsg;
mach_io_service_add_interest_notification_reply_t *rep = args->rmsg;
size_t *msglen = args->rsize;
struct lwp *l = args->l;
struct mach_port *mp;
struct mach_right *mr;
mp = mach_port_get();
mp->mp_flags |= MACH_MP_INKERNEL;
mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
rep->rep_msgh.msgh_bits =
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE) |
MACH_MSGH_BITS_COMPLEX;
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
rep->rep_body.msgh_descriptor_count = 1;
rep->rep_notification.name = (mach_port_t)mr->mr_name;
rep->rep_notification.disposition = 0x11; /* XXX */
rep->rep_trailer.msgh_trailer_size = 8;
*msglen = sizeof(*rep);
return 0;
}
int
mach_io_connect_set_notification_port(args)
struct mach_trap_args *args;
{
mach_io_connect_set_notification_port_request_t *req = args->smsg;
mach_io_connect_set_notification_port_reply_t *rep = args->rmsg;
struct lwp *l = args->l;
size_t *msglen = args->rsize;
mach_port_t mnn, mn;
struct mach_right *mrn;
struct mach_right *mr;
struct mach_iokit_devclass *mid;
#ifdef DEBUG_DARWIN
printf("mach_io_connect_set_notification_port\n");
#endif
mnn = req->req_port.name;
if ((mrn = mach_right_check(mnn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
return mach_msg_error(args, EINVAL);
mn = req->req_msgh.msgh_remote_port;
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
return mach_msg_error(args, EINVAL);
if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS)
return mach_msg_error(args, EINVAL);
#ifdef DEBUG_DARWIN
printf("notification on right %p, name %x\n", mrn, mrn->mr_name);
#endif
mid = (struct mach_iokit_devclass *)mr->mr_port->mp_data;
mid->mid_notify = mrn;
rep->rep_msgh.msgh_bits =
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE);
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
rep->rep_trailer.msgh_trailer_size = 8;
*msglen = sizeof(*rep);
return 0;
}
int
mach_io_registry_get_root_entry(args)
struct mach_trap_args *args;
{
mach_io_registry_get_root_entry_request_t *req = args->smsg;
mach_io_registry_get_root_entry_reply_t *rep = args->rmsg;
size_t *msglen = args->rsize;
struct lwp *l = args->l;
struct mach_port *mp;
struct mach_right *mr;
mp = mach_port_get();
mp->mp_flags |= MACH_MP_INKERNEL;
mp->mp_datatype = MACH_MP_IOKIT_DEVCLASS;
mp->mp_data = &mach_ioroot_devclass;
mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
rep->rep_msgh.msgh_bits =
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE) |
MACH_MSGH_BITS_COMPLEX;
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
rep->rep_body.msgh_descriptor_count = 1;
rep->rep_root.name = (mach_port_t)mr->mr_name;
rep->rep_root.disposition = 0x11; /* XXX */
rep->rep_trailer.msgh_trailer_size = 8;
*msglen = sizeof(*rep);
return 0;
}
int
mach_io_registry_entry_get_child_iterator(args)
struct mach_trap_args *args;
{
mach_io_registry_entry_get_child_iterator_request_t *req = args->smsg;
mach_io_registry_entry_get_child_iterator_reply_t *rep = args->rmsg;
size_t *msglen = args->rsize;
struct lwp *l = args->l;
struct mach_port *mp;
struct mach_right *mr;
mach_port_t mn;
struct mach_iokit_devclass *mid;
struct mach_device_iterator *mdi;
int maxdev;
size_t size;
mn = req->req_msgh.msgh_remote_port;
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
return mach_iokit_error(args, MACH_IOKIT_EPERM);
if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS)
return mach_iokit_error(args, MACH_IOKIT_EINVAL);
mid = (struct mach_iokit_devclass *)mr->mr_port->mp_data;
mp = mach_port_get();
mp->mp_flags |= (MACH_MP_INKERNEL | MACH_MP_DATA_ALLOCATED);
mp->mp_datatype = MACH_MP_DEVICE_ITERATOR;
maxdev = sizeof(mach_iokit_devclasses);
size = sizeof(*mdi) + (maxdev * sizeof(struct mach_iokit_devclass *));
mdi = malloc(size, M_EMULDATA, M_WAITOK);
mp->mp_data = mdi;
(void)mach_fill_child_iterator(mdi, maxdev, 0, mid);
mdi->mdi_current = 0;
mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
rep->rep_msgh.msgh_bits =
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE) |
MACH_MSGH_BITS_COMPLEX;
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
rep->rep_body.msgh_descriptor_count = 1;
rep->rep_iterator.name = (mach_port_t)mr->mr_name;
rep->rep_iterator.disposition = 0x11; /* XXX */
rep->rep_trailer.msgh_trailer_size = 8;
*msglen = sizeof(*rep);
return 0;
}
int
mach_io_registry_entry_get_name_in_plane(args)
struct mach_trap_args *args;
{
mach_io_registry_entry_get_name_in_plane_request_t *req = args->smsg;
mach_io_registry_entry_get_name_in_plane_reply_t *rep = args->rmsg;
size_t *msglen = args->rsize;
struct lwp *l = args->l;
struct mach_right *mr;
mach_port_t mn;
struct mach_iokit_devclass *mid;
mn = req->req_msgh.msgh_remote_port;
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
return mach_iokit_error(args, MACH_IOKIT_EPERM);
if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS)
return mach_iokit_error(args, MACH_IOKIT_EINVAL);
mid = mr->mr_port->mp_data;
rep->rep_msgh.msgh_bits =
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE);
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
rep->rep_namecount = strlen(mid->mid_name);
if (rep->rep_namecount >= 128)
rep->rep_namecount = 128;
memcpy(&rep->rep_name, mid->mid_name, rep->rep_namecount);
rep->rep_trailer.msgh_trailer_size = 8;
*msglen = sizeof(*rep);
return 0;
}
int
mach_io_object_get_class(args)
struct mach_trap_args *args;
{
mach_io_object_get_class_request_t *req = args->smsg;
mach_io_object_get_class_reply_t *rep = args->rmsg;
size_t *msglen = args->rsize;
char classname[] = "unknownClass";
rep->rep_msgh.msgh_bits =
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE);
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
/* XXX Just return a dummy name for now */
rep->rep_namecount = strlen(classname);
if (rep->rep_namecount >= 128)
rep->rep_namecount = 128;
memcpy(&rep->rep_name, classname, rep->rep_namecount);
rep->rep_trailer.msgh_trailer_size = 8;
*msglen = sizeof(*rep);
return 0;
}
int
mach_io_registry_entry_get_location_in_plane(args)
struct mach_trap_args *args;
{
mach_io_registry_entry_get_location_in_plane_request_t *req =
args->smsg;
mach_io_registry_entry_get_location_in_plane_reply_t *rep = args->rmsg;
size_t *msglen = args->rsize;
char location[] = "";
rep->rep_msgh.msgh_bits =
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE);
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
/* XXX Just return a dummy name for now */
rep->rep_locationcount = sizeof(location);
memcpy(&rep->rep_location, location, sizeof(location));
rep->rep_trailer.msgh_trailer_size = 8;
*msglen = sizeof(*rep);
return 0;
}
int
mach_io_registry_entry_get_properties(args)
struct mach_trap_args *args;
{
mach_io_registry_entry_get_properties_request_t *req = args->smsg;
mach_io_registry_entry_get_properties_reply_t *rep = args->rmsg;
size_t *msglen = args->rsize;
struct lwp *l = args->l;
int error;
vaddr_t va;
size_t size;
mach_port_t mn;
struct mach_right *mr;
struct mach_iokit_devclass *mid;
mn = req->req_msgh.msgh_remote_port;
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
return mach_iokit_error(args, MACH_IOKIT_EPERM);
if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS)
return mach_iokit_error(args, MACH_IOKIT_EINVAL);
mid = mr->mr_port->mp_data;
if (mid->mid_properties == NULL)
return mach_iokit_error(args, MACH_IOKIT_EINVAL);
size = strlen(mid->mid_properties) + 1; /* Include trailing zero */
va = vm_map_min(&l->l_proc->p_vmspace->vm_map);
if ((error = uvm_map(&l->l_proc->p_vmspace->vm_map, &va,
round_page(size), NULL, UVM_UNKNOWN_OFFSET, 0,
UVM_MAPFLAG(UVM_PROT_RW, UVM_PROT_ALL,
UVM_INH_COPY, UVM_ADV_NORMAL, UVM_FLAG_COPYONW))) != 0)
return mach_msg_error(args, error);
#ifdef DEBUG_MACH
printf("pid %d.%d: copyout iokit properties at %p\n",
l->l_proc->p_pid, l->l_lid, (void *)va);
#endif
if ((error = copyout(mid->mid_properties, (void *)va, size)) != 0) {
#ifdef DEBUG_MACH
printf("pid %d.%d: copyout iokit properties failed\n",
l->l_proc->p_pid, l->l_lid);
#endif
}
rep->rep_msgh.msgh_bits =
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE) |
MACH_MSGH_BITS_COMPLEX;
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
rep->rep_body.msgh_descriptor_count = 1;
rep->rep_properties.address = (void *)va;
rep->rep_properties.size = size;
rep->rep_properties.deallocate = 0; /* XXX */
rep->rep_properties.copy = 2; /* XXX */
rep->rep_properties.pad1 = 1; /* XXX */
rep->rep_properties.type = 1; /* XXX */
rep->rep_count = size;
rep->rep_trailer.msgh_trailer_size = 8;
*msglen = sizeof(*rep);
return 0;
}
int
mach_io_registry_entry_get_property(args)
struct mach_trap_args *args;
{
mach_io_registry_entry_get_property_request_t *req = args->smsg;
mach_io_registry_entry_get_property_reply_t *rep = args->rmsg;
size_t *msglen = args->rsize;
struct lwp *l = args->l;
int error;
vaddr_t va;
size_t size;
size_t len;
mach_port_t mn;
struct mach_right *mr;
struct mach_iokit_devclass *mid;
struct mach_iokit_property *mip;
#ifdef DEBUG_MACH
/*
* We do not handle non zero offset and multiple names,
* but it seems that Darwin binaries just fold random values
* in theses fields. We have yet to see a real use of
* non null offset / multiple names.
*/
if (req->req_property_nameoffset != 0) {
printf("pid %d.%d: mach_io_registry_entry_get_property "
"offset = %d (ignoring)\n", l->l_proc->p_pid, l->l_lid,
req->req_property_nameoffset);
}
if (req->req_property_namecount != 1) {
printf("pid %d.%d: mach_io_registry_entry_get_property "
"count = %d (ignoring)\n", l->l_proc->p_pid, l->l_lid,
req->req_property_namecount);
}
#endif
/* Find the port */
mn = req->req_msgh.msgh_remote_port;
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
return mach_iokit_error(args, MACH_IOKIT_EPERM);
/* Find the devclass information */
if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS)
return mach_iokit_error(args, MACH_IOKIT_EINVAL);
mid = mr->mr_port->mp_data;
if (mid->mid_properties_array == NULL)
return mach_iokit_error(args, MACH_IOKIT_EINVAL);
/* Lookup the property name */
for (mip = mid->mid_properties_array; mip->mip_name; mip++) {
len = strlen(mip->mip_name);
if (memcmp(mip->mip_name, req->req_propery_name, len) == 0)
break;
}
if (mip->mip_value == NULL)
return mach_iokit_error(args, MACH_IOKIT_ENOENT);
/* And copyout its associated value */
va = vm_map_min(&l->l_proc->p_vmspace->vm_map);
size = strlen(mip->mip_value) + 1; /* Include trailing zero */
if ((error = uvm_map(&l->l_proc->p_vmspace->vm_map, &va,
round_page(size), NULL, UVM_UNKNOWN_OFFSET, 0,
UVM_MAPFLAG(UVM_PROT_RW, UVM_PROT_ALL,
UVM_INH_COPY, UVM_ADV_NORMAL, UVM_FLAG_COPYONW))) != 0)
return mach_msg_error(args, error);
#ifdef DEBUG_MACH
printf("pid %d.%d: copyout iokit property at %p\n",
l->l_proc->p_pid, l->l_lid, (void *)va);
#endif
if ((error = copyout(mip->mip_value, (void *)va, size)) != 0) {
#ifdef DEBUG_MACH
printf("pid %d.%d: copyout iokit property failed\n",
l->l_proc->p_pid, l->l_lid);
#endif
}
rep->rep_msgh.msgh_bits =
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE) |
MACH_MSGH_BITS_COMPLEX;
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
rep->rep_body.msgh_descriptor_count = 1;
rep->rep_properties.address = (void *)va;
rep->rep_properties.size = size;
rep->rep_properties.deallocate = 0; /* XXX */
rep->rep_properties.copy = 2; /* XXX */
rep->rep_properties.pad1 = 0; /* XXX */
rep->rep_properties.type = 0; /* XXX */
rep->rep_properties_count = size;
rep->rep_trailer.msgh_trailer_size = 8;
*msglen = sizeof(*rep);
return 0;
}
int
mach_io_registry_entry_get_path(args)
struct mach_trap_args *args;
{
mach_io_registry_entry_get_path_request_t *req = args->smsg;
mach_io_registry_entry_get_path_reply_t *rep = args->rmsg;
size_t *msglen = args->rsize;
char location[] = ":/GossamerPE/pci@80000000/AppleGracklePCI/"
"ATY,264LT-G@11/.Display_Video_ATI_mach64-01018002/"
"display0/AppleBacklightDisplay";
char *cp;
size_t len, plen;
/* XXX Just return a dummy name for now */
len = req->req_count + strlen(location) - 1;
/* Sanity check for len */
if (len > 512)
return mach_iokit_error(args, MACH_IOKIT_EINVAL);
plen = (len & ~0x3UL) + 4; /* Round to an int */
rep->rep_msgh.msgh_bits =
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE);
rep->rep_msgh.msgh_size = sizeof(*rep) +
(plen - 512) - sizeof(rep->rep_trailer);
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
rep->rep_retval = 0;
rep->rep_count = len;
cp = &rep->rep_path[0];
memcpy(cp, &req->req_plane, req->req_count);
cp += (req->req_count - 1); /* overwrite trailing \0 */
memcpy(cp, location, strlen(location));
cp += strlen(location);
*cp = '\0';
rep->rep_path[plen + 7] = 8; /* Trailer */
*msglen = sizeof(*rep) + (plen - 512);
return 0;
}
int
mach_io_connect_map_memory(args)
struct mach_trap_args *args;
{
mach_io_connect_map_memory_request_t *req = args->smsg;
struct lwp *l = args->l;
mach_port_t mn;
struct mach_right *mr;
struct mach_iokit_devclass *mid;
mn = req->req_msgh.msgh_remote_port;
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
return mach_iokit_error(args, MACH_IOKIT_EPERM);
if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) {
mid = mr->mr_port->mp_data;
if (mid->mid_connect_map_memory == NULL)
printf("no connect_map_memory method "
"for darwin_iokit_class %s\n", mid->mid_name);
else
return (mid->mid_connect_map_memory)(args);
}
return mach_iokit_error(args, MACH_IOKIT_ENODEV);
}
int
mach_io_iterator_reset(args)
struct mach_trap_args *args;
{
mach_io_iterator_reset_request_t *req = args->smsg;
mach_io_iterator_reset_reply_t *rep = args->rmsg;
size_t *msglen = args->rsize;
struct lwp *l = args->l;
mach_port_t mn;
struct mach_right *mr;
struct mach_device_iterator *mdi;
mn = req->req_msgh.msgh_remote_port;
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
return mach_iokit_error(args, MACH_IOKIT_EPERM);
if (mr->mr_port->mp_datatype != MACH_MP_DEVICE_ITERATOR)
return mach_iokit_error(args, MACH_IOKIT_EINVAL);
mdi = mr->mr_port->mp_data;
mdi->mdi_current = 0;
rep->rep_msgh.msgh_bits =
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE);
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
rep->rep_retval = 0;
rep->rep_trailer.msgh_trailer_size = 8;
*msglen = sizeof(*rep);
return 0;
}
int
mach_io_connect_method_scalari_structo(args)
struct mach_trap_args *args;
{
mach_io_connect_method_scalari_structo_request_t *req = args->smsg;
struct lwp *l = args->l;
mach_port_t mn;
struct mach_right *mr;
struct mach_iokit_devclass *mid;
mn = req->req_msgh.msgh_remote_port;
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
return mach_iokit_error(args, MACH_IOKIT_EPERM);
if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) {
mid = mr->mr_port->mp_data;
if (mid->mid_connect_method_scalari_structo == NULL)
printf("no connect_method_scalari_structo method "
"for darwin_iokit_class %s\n", mid->mid_name);
else
return (mid->mid_connect_method_scalari_structo)(args);
}
return mach_iokit_error(args, MACH_IOKIT_ENODEV);
}
int
mach_io_connect_method_structi_structo(args)
struct mach_trap_args *args;
{
mach_io_connect_method_structi_structo_request_t *req = args->smsg;
struct lwp *l = args->l;
mach_port_t mn;
struct mach_right *mr;
struct mach_iokit_devclass *mid;
mn = req->req_msgh.msgh_remote_port;
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
return mach_iokit_error(args, MACH_IOKIT_EPERM);
if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) {
mid = mr->mr_port->mp_data;
if (mid->mid_connect_method_structi_structo == NULL)
printf("no connect_method_structi_structo method "
"for darwin_iokit_class %s\n", mid->mid_name);
else
return (mid->mid_connect_method_structi_structo)(args);
}
return mach_iokit_error(args, MACH_IOKIT_ENODEV);
}
int
mach_io_connect_set_properties(args)
struct mach_trap_args *args;
{
mach_io_connect_set_properties_request_t *req = args->smsg;
mach_io_connect_set_properties_reply_t *rep = args->rmsg;
size_t *msglen = args->rsize;
struct lwp *l = args->l;
printf("pid %d.%d: mach_io_connect_set_properties\n",
l->l_proc->p_pid, l->l_lid);
rep->rep_msgh.msgh_bits =
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE);
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
rep->rep_trailer.msgh_trailer_size = 8;
*msglen = sizeof(*rep);
return 0;
}
int
mach_io_service_close(args)
struct mach_trap_args *args;
{
mach_io_service_close_request_t *req = args->smsg;
mach_io_service_close_reply_t *rep = args->rmsg;
size_t *msglen = args->rsize;
rep->rep_msgh.msgh_bits =
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE);
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
rep->rep_retval = 0;
rep->rep_trailer.msgh_trailer_size = 8;
*msglen = sizeof(*rep);
return 0;
}
int
mach_io_connect_add_client(args)
struct mach_trap_args *args;
{
mach_io_connect_add_client_request_t *req = args->smsg;
mach_io_connect_add_client_reply_t *rep = args->rmsg;
size_t *msglen = args->rsize;
rep->rep_msgh.msgh_bits =
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE);
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
rep->rep_retval = 0;
rep->rep_trailer.msgh_trailer_size = 8;
*msglen = sizeof(*rep);
return 0;
}
int
mach_io_connect_method_scalari_structi(args)
struct mach_trap_args *args;
{
mach_io_connect_method_scalari_structi_request_t *req = args->smsg;
struct lwp *l = args->l;
mach_port_t mn;
struct mach_right *mr;
struct mach_iokit_devclass *mid;
mn = req->req_msgh.msgh_remote_port;
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
return mach_iokit_error(args, MACH_IOKIT_EPERM);
if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) {
mid = mr->mr_port->mp_data;
if (mid->mid_connect_method_scalari_structi == NULL)
printf("no connect_method_scalari_structi method "
"for darwin_iokit_class %s\n", mid->mid_name);
else
return (mid->mid_connect_method_scalari_structi)(args);
}
return mach_iokit_error(args, MACH_IOKIT_ENODEV);
}
int
mach_io_registry_entry_from_path(args)
struct mach_trap_args *args;
{
mach_io_registry_entry_from_path_request_t *req = args->smsg;
mach_io_registry_entry_from_path_reply_t *rep = args->rmsg;
size_t *msglen = args->rsize;
struct lwp *l = args->l;
struct mach_port *mp;
struct mach_right *mr;
struct mach_iokit_devclass *mid;
int i, len;
#ifdef DEBUG_MACH
printf("mach_io_registry_entry_from_path: path = %s\n", req->req_path);
#endif
mp = mach_port_get();
mp->mp_flags |= MACH_MP_INKERNEL;
mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
if (sizeof(*req) - 512 + req->req_pathcount > args->ssize) {
#ifdef DEBUG_MACH
printf("pathcount too big, truncating\n");
#endif
req->req_pathcount = args->ssize - (sizeof(*req) - 512);
}
i = 0;
while ((mid = mach_iokit_devclasses[i++]) != NULL) {
len = strlen(mid->mid_name);
/* XXX sanity check req_pathcount */
#ifdef DEBUG_MACH
printf("trying \"%s\" vs \"%s\"\n",
&req->req_path[req->req_pathcount - 1 - len],
mid->mid_name);
#endif
if (memcmp(&req->req_path[req->req_pathcount - 1 - len],
mid->mid_name, len) == 0) {
mp->mp_datatype = MACH_MP_IOKIT_DEVCLASS;
mp->mp_data = mid;
break;
}
}
rep->rep_msgh.msgh_bits =
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE) |
MACH_MSGH_BITS_COMPLEX;
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
rep->rep_body.msgh_descriptor_count = 1;
rep->rep_entry.name = (mach_port_t)mr->mr_name;
rep->rep_entry.disposition = 0x11; /* XXX */
rep->rep_trailer.msgh_trailer_size = 8;
*msglen = sizeof(*rep);
return 0;
}
int
mach_io_registry_entry_get_parent_iterator(args)
struct mach_trap_args *args;
{
mach_io_registry_entry_get_parent_iterator_request_t *req = args->smsg;
mach_io_registry_entry_get_parent_iterator_reply_t *rep = args->rmsg;
size_t *msglen = args->rsize;
struct lwp *l = args->l;
struct mach_port *mp;
struct mach_right *mr;
struct mach_iokit_devclass *mid;
struct mach_device_iterator *mdi;
mach_port_t mn;
int maxdev;
size_t size;
#ifdef DEBUG_MACH
printf("mach_io_registry_entry_get_parent_iterator: plane = %s\n",
req->req_plane);
#endif
/* Sanity check req->req_count */
if (MACH_REQMSG_OVERFLOW(args, req->req_plane[req->req_count]))
return mach_msg_error(args, EINVAL);
mn = req->req_msgh.msgh_remote_port;
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
return mach_iokit_error(args, MACH_IOKIT_EPERM);
if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS)
return mach_iokit_error(args, MACH_IOKIT_EINVAL);
mid = mr->mr_port->mp_data;
mp = mach_port_get();
mp->mp_flags |= (MACH_MP_INKERNEL | MACH_MP_DATA_ALLOCATED);
mp->mp_datatype = MACH_MP_DEVICE_ITERATOR;
maxdev = sizeof(mach_iokit_devclasses);
size = sizeof(*mdi) + (maxdev * sizeof(struct mach_iokit_devclass *));
mdi = malloc(size, M_EMULDATA, M_WAITOK);
mp->mp_data = mdi;
(void)mach_fill_parent_iterator(mdi, maxdev, 0, mid);
mdi->mdi_current = 0;
mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0);
rep->rep_msgh.msgh_bits =
MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE) |
MACH_MSGH_BITS_COMPLEX;
rep->rep_msgh.msgh_size = sizeof(*rep) - sizeof(rep->rep_trailer);
rep->rep_msgh.msgh_local_port = req->req_msgh.msgh_local_port;
rep->rep_msgh.msgh_id = req->req_msgh.msgh_id + 100;
rep->rep_body.msgh_descriptor_count = 1;
rep->rep_iterator.name = (mach_port_t)mr->mr_name;
rep->rep_iterator.disposition = 0x11; /* XXX */
rep->rep_trailer.msgh_trailer_size = 8;
*msglen = sizeof(*rep);
return 0;
}
void
mach_iokit_cleanup_notify(mr)
struct mach_right *mr;
{
int i;
struct mach_iokit_devclass *mid;
i = 0;
while ((mid = mach_iokit_devclasses[i++]) != NULL)
if (mid->mid_notify == mr)
mid->mid_notify = NULL;
return;
}
static int
mach_fill_child_iterator(mdi, size, index, mid)
struct mach_device_iterator *mdi;
int size;
int index;
struct mach_iokit_devclass *mid;
{
struct mach_iokit_devclass **midp;
struct mach_iokit_devclass **midq;
for (midp = mach_iokit_devclasses; *midp != NULL; midp++) {
for (midq = (*midp)->mid_parent; *midq != NULL; midq++) {
if (*midq == mid) {
mdi->mdi_devices[index++] = *midp;
break;
}
}
#ifdef DIAGNOSTIC
if (index >= size) {
printf("mach_device_iterator overflow\n");
break;
}
#endif
}
mdi->mdi_devices[index] = NULL;
return index;
}
static int
mach_fill_parent_iterator(mdi, size, index, mid)
struct mach_device_iterator *mdi;
int size;
int index;
struct mach_iokit_devclass *mid;
{
struct mach_iokit_devclass **midp;
for (midp = mid->mid_parent; *midp != NULL; midp++) {
mdi->mdi_devices[index++] = *midp;
#ifdef DIAGNOSTIC
if (index >= size) {
printf("mach_device_iterator overflow\n");
break;
}
#endif
}
mdi->mdi_devices[index] = NULL;
return index;
}