summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZheng Da <zhengda1936@gmail.com>2020-03-29 22:32:44 +1100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2020-03-29 22:10:19 +0000
commit47682aaf93b85b3d00fad5426cf9c5a1c7f610ea (patch)
tree007b1b7991c146580c00d8212a4278cbccab3e23
parentdb69a5281b23003af71068e494a20dc4f3a047aa (diff)
libmachdev: Add common machdev
* libmachdev: New directory.
-rw-r--r--Makefile1
-rw-r--r--libmachdev/Makefile33
-rw-r--r--libmachdev/ds_routines.c326
-rw-r--r--libmachdev/machdev-dev_hdr.h88
-rw-r--r--libmachdev/machdev-device_emul.h65
-rw-r--r--libmachdev/machdev.h39
-rw-r--r--libmachdev/mig-decls.h50
-rw-r--r--libmachdev/mig-mutate.h36
-rw-r--r--libmachdev/trivfs_server.c192
9 files changed, 830 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index 09662f874..6b1e80665 100644
--- a/Makefile
+++ b/Makefile
@@ -31,6 +31,7 @@ lib-subdirs = libshouldbeinlibc libihash libiohelp libports libthreads \
libnetfs libpipe libstore libhurdbugaddr libftpconn libcons \
libhurd-slab \
libbpf \
+ libmachdev \
# Hurd programs
prog-subdirs = auth proc exec term \
diff --git a/libmachdev/Makefile b/libmachdev/Makefile
new file mode 100644
index 000000000..08479a3eb
--- /dev/null
+++ b/libmachdev/Makefile
@@ -0,0 +1,33 @@
+# Copyright (C) 2009 Free Software Foundation, Inc.
+# This file is part of the GNU Hurd.
+#
+# The GNU Hurd is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# The GNU Hurd is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with the GNU Hurd; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+dir := libmachdev
+makemode := library
+libname = libmachdev
+
+SRCS = deviceUser.c machUser.c ds_routines.c trivfs_server.c \
+ device_replyUser.c deviceServer.c notifyServer.c
+
+LCLHDRS = machdev.h machdev-device_emul.h machdev-dev_hdr.h
+installhdrs = machdev.h machdev-device_emul.h
+HURDLIBS = ports trivfs
+LDLIBS += -lpthread
+OBJS = $(SRCS:.c=.o) $(MIGSTUBS)
+MIGSFLAGS = -imacros $(srcdir)/mig-mutate.h
+device-MIGSFLAGS="-DMACH_PAYLOAD_TO_PORT=ports_payload_get_name"
+
+include ../Makeconf
diff --git a/libmachdev/ds_routines.c b/libmachdev/ds_routines.c
new file mode 100644
index 000000000..5a61805c9
--- /dev/null
+++ b/libmachdev/ds_routines.c
@@ -0,0 +1,326 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1993,1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * Author: David B. Golub, Carnegie Mellon University
+ * Date: 3/89
+ */
+
+/*
+ * Mach device server routines (i386at version).
+ *
+ * Copyright (c) 1996 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ * Author: Shantanu Goel, University of Utah CSL
+ */
+
+/*
+ * This is is providing the same multiplexing layer as in the GNU Mach kernel,
+ * which also handles the MIG details.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <error.h>
+#include <assert.h>
+
+#include <hurd.h>
+#include <mach.h>
+
+#include "device_S.h"
+#include "notify_S.h"
+#include "machdev-dev_hdr.h"
+#include "machdev.h"
+
+struct port_bucket *machdev_device_bucket;
+struct port_class *machdev_device_class;
+
+#define MAX_NUM_EMULATION 32
+
+/* List of emulations. */
+static struct machdev_device_emulation_ops *emulation_list[MAX_NUM_EMULATION];
+static int num_emul = 0;
+
+boolean_t machdev_is_master_device (mach_port_t port);
+
+/*
+ * What follows is the interface for the native Mach devices.
+ */
+
+/* Implementation of device interface */
+io_return_t
+ds_device_open (mach_port_t open_port, mach_port_t reply_port,
+ mach_msg_type_name_t reply_port_type, dev_mode_t mode,
+ char *name, device_t *devp, mach_msg_type_name_t *devicePoly)
+{
+ int i;
+ io_return_t err;
+
+ /* Open must be called on the master device port. */
+ if (!machdev_is_master_device (open_port))
+ return D_INVALID_OPERATION;
+
+ /* There must be a reply port. */
+ if (! MACH_PORT_VALID (reply_port))
+ return MIG_NO_REPLY;
+
+ /* Call each emulation's open routine to find the device. */
+ for (i = 0; i < num_emul; i++)
+ {
+ err = (*emulation_list[i]->open) (reply_port, reply_port_type,
+ mode, name, devp, devicePoly);
+ if (err != D_NO_SUCH_DEVICE)
+ break;
+ }
+
+ return err;
+}
+
+io_return_t
+ds_device_close (struct mach_device *device)
+{
+ /* Refuse if device is dead or not completely open. */
+ if (device == MACH_DEVICE_NULL)
+ return D_NO_SUCH_DEVICE;
+
+ return (device->dev.emul_ops->close
+ ? (*device->dev.emul_ops->close) (device->dev.emul_data)
+ : D_SUCCESS);
+}
+
+io_return_t
+ds_device_write (struct mach_device *device, mach_port_t reply_port,
+ mach_msg_type_name_t reply_port_type, dev_mode_t mode,
+ recnum_t recnum, io_buf_ptr_t data, unsigned int count,
+ int *bytes_written)
+{
+ /* Refuse if device is dead or not completely open. */
+ if (device == MACH_DEVICE_NULL)
+ return D_NO_SUCH_DEVICE;
+
+ if (data == 0)
+ return D_INVALID_SIZE;
+
+ if (! device->dev.emul_ops->write)
+ return D_INVALID_OPERATION;
+
+ return (*device->dev.emul_ops->write) (device->dev.emul_data, reply_port,
+ reply_port_type, mode, recnum,
+ data, count, bytes_written);
+}
+
+io_return_t
+ds_device_write_inband (struct mach_device *device, mach_port_t reply_port,
+ mach_msg_type_name_t reply_port_type,
+ dev_mode_t mode, recnum_t recnum,
+ io_buf_ptr_inband_t data, unsigned count,
+ int *bytes_written)
+{
+ /* Refuse if device is dead or not completely open. */
+ if (device == MACH_DEVICE_NULL)
+ return D_NO_SUCH_DEVICE;
+
+ if (data == 0)
+ return D_INVALID_SIZE;
+
+ if (! device->dev.emul_ops->write_inband)
+ return D_INVALID_OPERATION;
+
+ return (*device->dev.emul_ops->write_inband) (device->dev.emul_data,
+ reply_port, reply_port_type,
+ mode, recnum,
+ data, count, bytes_written);
+}
+
+io_return_t
+ds_device_read (struct mach_device *device, mach_port_t reply_port,
+ mach_msg_type_name_t reply_port_type, dev_mode_t mode,
+ recnum_t recnum, int count, io_buf_ptr_t *data,
+ unsigned *bytes_read)
+{
+ /* Refuse if device is dead or not completely open. */
+
+ if (device == MACH_DEVICE_NULL)
+ return D_NO_SUCH_DEVICE;
+
+ if (! device->dev.emul_ops->read)
+ return D_INVALID_OPERATION;
+
+ return (*device->dev.emul_ops->read) (device->dev.emul_data, reply_port,
+ reply_port_type, mode, recnum,
+ count, data, bytes_read);
+}
+
+io_return_t
+ds_device_read_inband (struct mach_device *device, mach_port_t reply_port,
+ mach_msg_type_name_t reply_port_type, dev_mode_t mode,
+ recnum_t recnum, int count, char *data,
+ unsigned *bytes_read)
+{
+ /* Refuse if device is dead or not completely open. */
+
+ if (device == MACH_DEVICE_NULL)
+ return D_NO_SUCH_DEVICE;
+
+ if (! device->dev.emul_ops->read_inband)
+ return D_INVALID_OPERATION;
+
+ return (*device->dev.emul_ops->read_inband) (device->dev.emul_data,
+ reply_port,
+ reply_port_type, mode, recnum,
+ count, data, bytes_read);
+}
+
+io_return_t
+ds_device_set_status (struct mach_device *device, dev_flavor_t flavor,
+ dev_status_t status, mach_msg_type_number_t status_count)
+{
+ /* Refuse if device is dead or not completely open. */
+ if (device == MACH_DEVICE_NULL)
+ return D_NO_SUCH_DEVICE;
+
+ if (! device->dev.emul_ops->set_status)
+ return D_INVALID_OPERATION;
+
+ return (*device->dev.emul_ops->set_status) (device->dev.emul_data, flavor,
+ status, status_count);
+}
+
+io_return_t
+ds_device_get_status (struct mach_device *device, dev_flavor_t flavor,
+ dev_status_t status,
+ mach_msg_type_number_t *status_count)
+{
+ /* Refuse if device is dead or not completely open. */
+ if (device == MACH_DEVICE_NULL)
+ return D_NO_SUCH_DEVICE;
+
+ if (! device->dev.emul_ops->get_status)
+ return D_INVALID_OPERATION;
+
+ return (*device->dev.emul_ops->get_status) (device->dev.emul_data, flavor,
+ status, status_count);
+}
+
+io_return_t
+ds_device_set_filter (struct mach_device *device, mach_port_t receive_port,
+ int priority, filter_t *filter, unsigned filter_count)
+{
+ /* Refuse if device is dead or not completely open. */
+ if (device == MACH_DEVICE_NULL)
+ return D_NO_SUCH_DEVICE;
+
+ if (! device->dev.emul_ops->set_filter)
+ return D_INVALID_OPERATION;
+
+ return (*device->dev.emul_ops->set_filter) (device->dev.emul_data,
+ receive_port,
+ priority, filter, filter_count);
+}
+
+io_return_t
+ds_device_map (struct mach_device *device, vm_prot_t prot, vm_offset_t offset,
+ vm_size_t size, mach_port_t *pager, boolean_t unmap)
+{
+ /* Refuse if device is dead or not completely open. */
+ if (device == MACH_DEVICE_NULL)
+ return D_NO_SUCH_DEVICE;
+
+ if (! device->dev.emul_ops->map)
+ return D_INVALID_OPERATION;
+
+ return (*device->dev.emul_ops->map) (device->dev.emul_data, prot,
+ offset, size, pager, unmap);
+
+}
+
+error_t
+machdev_create_device_port (size_t size, void *result)
+{
+ return ports_create_port (machdev_device_class, machdev_device_bucket,
+ size, result);
+}
+
+void machdev_device_init()
+{
+ int i;
+
+ machdev_device_bucket = ports_create_bucket ();
+ machdev_device_class = ports_create_class (0, 0);
+
+ for (i = 0; i < num_emul; i++)
+ {
+ if (emulation_list[i]->init)
+ emulation_list[i]->init();
+ }
+}
+
+static int
+demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp)
+{
+ mig_routine_t routine;
+ if ((routine = device_server_routine (inp)) ||
+ (routine = notify_server_routine (inp)))
+ {
+ (*routine) (inp, outp);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+void machdev_register (struct machdev_device_emulation_ops *ops)
+{
+ assert(num_emul < MAX_NUM_EMULATION-1);
+ emulation_list[num_emul++] = ops;
+}
+
+void * machdev_server(void *arg)
+{
+ /* Launch. */
+ do
+ {
+ ports_manage_port_operations_one_thread (machdev_device_bucket, demuxer, 0);
+ } while (1);
+
+ return NULL;
+}
diff --git a/libmachdev/machdev-dev_hdr.h b/libmachdev/machdev-dev_hdr.h
new file mode 100644
index 000000000..5b5e3e615
--- /dev/null
+++ b/libmachdev/machdev-dev_hdr.h
@@ -0,0 +1,88 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * Author: David B. Golub, Carnegie Mellon University
+ * Date: 3/89
+ */
+
+/*
+ * Mach device emulation definitions (i386at version).
+ *
+ * Copyright (c) 1996 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ * Author: Shantanu Goel, University of Utah CSL
+ */
+
+#ifndef _MACHDEV_DEVICE_DEV_HDR_H_
+#define _MACHDEV_DEVICE_DEV_HDR_H_
+
+#include <mach.h>
+#include <hurd.h>
+#include <hurd/ports.h>
+
+#include "machdev-device_emul.h"
+
+/* This structure is associated with each open device port.
+ * The port representing the device points to this structure. */
+struct emul_device
+{
+ struct machdev_device_emulation_ops *emul_ops;
+ void *emul_data;
+};
+
+typedef struct emul_device *emul_device_t;
+
+#define DEVICE_NULL ((device_t) 0)
+
+/*
+ * Generic device header. May be allocated with the device,
+ * or built when the device is opened.
+ */
+struct mach_device {
+ struct port_info port;
+ struct emul_device dev; /* the real device structure */
+};
+typedef struct mach_device *mach_device_t;
+#define MACH_DEVICE_NULL ((mach_device_t)0)
+
+#endif /* _MACHDEV_DEVICE_DEV_HDR_H_ */
diff --git a/libmachdev/machdev-device_emul.h b/libmachdev/machdev-device_emul.h
new file mode 100644
index 000000000..db0b106f0
--- /dev/null
+++ b/libmachdev/machdev-device_emul.h
@@ -0,0 +1,65 @@
+/*
+ * Mach device emulation definitions.
+ *
+ * Copyright (c) 1996 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ * Author: Shantanu Goel, University of Utah CSL
+ */
+
+#ifndef _MACHDEV_DEVICE_EMUL_H_
+#define _MACHDEV_DEVICE_EMUL_H_
+
+#include <mach.h>
+
+/* Each emulation layer provides these operations. */
+struct machdev_device_emulation_ops
+{
+ void (*init) (void);
+ void (*reference) (void *);
+ void (*dealloc) (void *);
+ mach_port_t (*dev_to_port) (void *);
+ io_return_t (*open) (mach_port_t, mach_msg_type_name_t,
+ dev_mode_t, char *, device_t *,
+ mach_msg_type_name_t *type);
+ io_return_t (*close) (void *);
+ io_return_t (*write) (void *, mach_port_t, mach_msg_type_name_t,
+ dev_mode_t, recnum_t, io_buf_ptr_t, unsigned, int *);
+ io_return_t (*write_inband) (void *, mach_port_t, mach_msg_type_name_t,
+ dev_mode_t, recnum_t, io_buf_ptr_inband_t,
+ unsigned, int *);
+ io_return_t (*read) (void *, mach_port_t, mach_msg_type_name_t,
+ dev_mode_t, recnum_t, int, io_buf_ptr_t *, unsigned *);
+ io_return_t (*read_inband) (void *, mach_port_t, mach_msg_type_name_t,
+ dev_mode_t, recnum_t, int, char *, unsigned *);
+ io_return_t (*set_status) (void *, dev_flavor_t, dev_status_t,
+ mach_msg_type_number_t);
+ io_return_t (*get_status) (void *, dev_flavor_t, dev_status_t,
+ mach_msg_type_number_t *);
+ io_return_t (*set_filter) (void *, mach_port_t, int, filter_t [], unsigned);
+ io_return_t (*map) (void *, vm_prot_t, vm_offset_t,
+ vm_size_t, mach_port_t *, boolean_t);
+ void (*no_senders) (mach_no_senders_notification_t *);
+ io_return_t (*write_trap) (void *, dev_mode_t,
+ recnum_t, vm_offset_t, vm_size_t);
+ io_return_t (*writev_trap) (void *, dev_mode_t,
+ recnum_t, io_buf_vec_t *, vm_size_t);
+};
+
+#endif /* _MACHDEV_DEVICE_EMUL_H_ */
diff --git a/libmachdev/machdev.h b/libmachdev/machdev.h
new file mode 100644
index 000000000..78b100c6c
--- /dev/null
+++ b/libmachdev/machdev.h
@@ -0,0 +1,39 @@
+/*
+ Copyright (C) 2010 Free Software Foundation, Inc.
+ Written by Zheng Da.
+
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ The GNU Hurd is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the GNU Hurd; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This file declares interfaces used by driver translators. */
+
+#ifndef __MACHDEV_H__
+#define __MACHDEV_H__
+
+#include <mach.h>
+#include "machdev-device_emul.h"
+
+void machdev_register (struct machdev_device_emulation_ops *ops);
+
+void machdev_device_init(void);
+void * machdev_server(void *);
+error_t machdev_create_device_port (size_t size, void *result);
+
+int machdev_trivfs_init(void);
+void machdev_trivfs_server(void);
+boolean_t machdev_is_master_device (mach_port_t port);
+
+#endif
diff --git a/libmachdev/mig-decls.h b/libmachdev/mig-decls.h
new file mode 100644
index 000000000..d0077f8d1
--- /dev/null
+++ b/libmachdev/mig-decls.h
@@ -0,0 +1,50 @@
+/*
+ Copyright (C) 2014 Free Software Foundation, Inc.
+ Written by Justus Winter.
+
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ The GNU Hurd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef __LIBMACHDEV_MIG_DECLS_H__
+#define __LIBMACHDEV_MIG_DECLS_H__
+
+#include <hurd/ports.h>
+#include "machdev-dev_hdr.h"
+
+extern struct port_bucket *machdev_device_bucket;
+extern struct port_class *machdev_device_class;
+
+/* Called by server stub functions. */
+
+static inline struct mach_device * __attribute__ ((unused))
+begin_using_device_port (mach_port_t port)
+{
+ return ports_lookup_port (machdev_device_bucket, port, machdev_device_class);
+}
+
+static inline struct mach_device * __attribute__ ((unused))
+begin_using_device_payload (unsigned long payload)
+{
+ return ports_lookup_payload (machdev_device_bucket, payload, machdev_device_class);
+}
+
+static inline void __attribute__ ((unused))
+end_using_device (struct mach_device *p)
+{
+ if (p)
+ ports_port_deref (p);
+}
+
+#endif /* __LIBMACHDEV_MIG_DECLS_H__ */
diff --git a/libmachdev/mig-mutate.h b/libmachdev/mig-mutate.h
new file mode 100644
index 000000000..902ff166f
--- /dev/null
+++ b/libmachdev/mig-mutate.h
@@ -0,0 +1,36 @@
+/*
+ Copyright (C) 2014 Free Software Foundation, Inc.
+ Written by Justus Winter.
+
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ The GNU Hurd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */
+
+#define NOTIFY_INTRAN \
+ port_info_t begin_using_port_info_port (mach_port_t)
+#define NOTIFY_INTRAN_PAYLOAD \
+ port_info_t begin_using_port_info_payload
+#define NOTIFY_DESTRUCTOR \
+ end_using_port_info (port_info_t)
+#define NOTIFY_IMPORTS \
+ import "libports/mig-decls.h";
+
+#define DEVICE_INTRAN \
+ mach_device_t begin_using_device_port (mach_port_t)
+#define DEVICE_INTRAN_PAYLOAD \
+ mach_device_t begin_using_device_payload
+#define DEVICE_DESTRUCTOR \
+ end_using_device (mach_device_t)
+#define DEVICE_IMPORTS \
+ import "libmachdev/mig-decls.h";
diff --git a/libmachdev/trivfs_server.c b/libmachdev/trivfs_server.c
new file mode 100644
index 000000000..d6bafccbb
--- /dev/null
+++ b/libmachdev/trivfs_server.c
@@ -0,0 +1,192 @@
+/*
+ Copyright (C) 2009 Free Software Foundation, Inc.
+ Written by Zheng Da.
+
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ The GNU Hurd is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the GNU Hurd; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This manages the master ports obtained when opening the libmachdev-based
+ translator node. */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <error.h>
+#include <hurd/ports.h>
+#include <hurd/trivfs.h>
+#include <hurd.h>
+
+#include "device_S.h"
+#include "notify_S.h"
+
+static struct port_bucket *port_bucket;
+
+/* Trivfs hooks. */
+int trivfs_fstype = FSTYPE_MISC;
+int trivfs_fsid = 0;
+int trivfs_support_read = 0;
+int trivfs_support_write = 0;
+int trivfs_support_exec = 0;
+int trivfs_allow_open = O_READ | O_WRITE;
+
+/* Our port classes. */
+struct port_class *trivfs_protid_class;
+struct port_class *trivfs_cntl_class;
+
+/* Implementation of notify interface */
+kern_return_t
+do_mach_notify_port_deleted (struct port_info *pi,
+ mach_port_t name)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+do_mach_notify_msg_accepted (struct port_info *pi,
+ mach_port_t name)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+do_mach_notify_port_destroyed (struct port_info *pi,
+ mach_port_t port)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+do_mach_notify_no_senders (struct port_info *pi,
+ mach_port_mscount_t mscount)
+{
+ return ports_do_mach_notify_no_senders (pi, mscount);
+}
+
+kern_return_t
+do_mach_notify_send_once (struct port_info *pi)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+do_mach_notify_dead_name (struct port_info *pi,
+ mach_port_t name)
+{
+ return EOPNOTSUPP;
+}
+
+boolean_t
+machdev_is_master_device (mach_port_t port)
+{
+ struct port_info *pi = ports_lookup_port (port_bucket, port,
+ trivfs_protid_class);
+ if (pi == NULL)
+ return FALSE;
+
+ ports_port_deref (pi);
+ return TRUE;
+}
+
+error_t
+trivfs_append_args (struct trivfs_control *fsys, char **argz, size_t *argz_len)
+{
+ error_t err = 0;
+
+#define ADD_OPT(fmt, args...) \
+ do { char buf[100]; \
+ if (! err) { \
+ snprintf (buf, sizeof buf, fmt , ##args); \
+ err = argz_add (argz, argz_len, buf); } } while (0)
+
+#undef ADD_OPT
+ return err;
+}
+
+int machdev_trivfs_init()
+{
+ port_bucket = ports_create_bucket ();
+ trivfs_cntl_class = ports_create_class (trivfs_clean_cntl, 0);
+ trivfs_protid_class = ports_create_class (trivfs_clean_protid, 0);
+ return 0;
+}
+
+error_t
+trivfs_goaway (struct trivfs_control *fsys, int flags)
+{
+ int count;
+
+ /* Stop new requests. */
+ ports_inhibit_class_rpcs (trivfs_cntl_class);
+ ports_inhibit_class_rpcs (trivfs_protid_class);
+
+ count = ports_count_class (trivfs_protid_class);
+
+ if (count && !(flags & FSYS_GOAWAY_FORCE))
+ {
+ /* We won't go away, so start things going again... */
+ ports_enable_class (trivfs_protid_class);
+ ports_resume_class_rpcs (trivfs_cntl_class);
+ ports_resume_class_rpcs (trivfs_protid_class);
+ return EBUSY;
+ }
+
+ exit (0);
+}
+
+static int
+demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp)
+{
+ mig_routine_t routine;
+ if ((routine = device_server_routine (inp)) ||
+ (routine = notify_server_routine (inp)) ||
+ (routine = NULL, trivfs_demuxer (inp, outp)))
+ {
+ if (routine)
+ (*routine) (inp, outp);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+void
+trivfs_modify_stat (struct trivfs_protid *cred, io_statbuf_t *stat)
+{
+}
+
+void machdev_trivfs_server()
+{
+ mach_port_t bootstrap;
+ struct trivfs_control *fsys;
+ int err;
+
+ task_get_bootstrap_port (mach_task_self (), &bootstrap);
+ if (bootstrap == MACH_PORT_NULL)
+ error (1, 0, "must be started as a translator");
+
+ /* Reply to our parent. */
+ err = trivfs_startup (bootstrap, 0,
+ trivfs_cntl_class, port_bucket,
+ trivfs_protid_class, port_bucket, &fsys);
+ mach_port_deallocate (mach_task_self (), bootstrap);
+ if (err)
+ error (1, err, "Contacting parent");
+
+ /* Launch. */
+ do
+ {
+ ports_manage_port_operations_one_thread (port_bucket, demuxer, 0);
+ } while (trivfs_goaway (fsys, 0));
+}