>From 65acd70fcc369ab075594796330f00d4e0439a04 Mon Sep 17 00:00:00 2001 From: Damien Zammit Date: Sun, 29 Mar 2020 22:32:44 +1100 Subject: [PATCH 2/4] libmachdev: Add common machdev --- Makefile | 1 + libmachdev/Makefile | 34 ++++ libmachdev/dev_hdr.h | 133 +++++++++++++++ libmachdev/device_emul.h | 65 +++++++ libmachdev/ds_routines.c | 335 +++++++++++++++++++++++++++++++++++++ libmachdev/ds_routines.h | 57 +++++++ libmachdev/io_req.h | 135 +++++++++++++++ libmachdev/machdev.h | 34 ++++ libmachdev/mig-decls.h | 50 ++++++ libmachdev/mig-mutate.h | 36 ++++ libmachdev/trivfs_server.c | 169 +++++++++++++++++++ libmachdev/vm_param.h | 7 + 12 files changed, 1056 insertions(+) create mode 100644 libmachdev/Makefile create mode 100644 libmachdev/dev_hdr.h create mode 100644 libmachdev/device_emul.h create mode 100644 libmachdev/ds_routines.c create mode 100644 libmachdev/ds_routines.h create mode 100644 libmachdev/io_req.h create mode 100644 libmachdev/machdev.h create mode 100644 libmachdev/mig-decls.h create mode 100644 libmachdev/mig-mutate.h create mode 100644 libmachdev/trivfs_server.c create mode 100644 libmachdev/vm_param.h diff --git a/Makefile b/Makefile index 09662f87..6b1e8066 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 00000000..78f0756f --- /dev/null +++ b/libmachdev/Makefile @@ -0,0 +1,34 @@ +# 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 = dev_hdr.h device_emul.h ds_routines.h vm_param.h \ + io_req.h machdev.h +installhdrs = machdev.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/dev_hdr.h b/libmachdev/dev_hdr.h new file mode 100644 index 00000000..79edc43a --- /dev/null +++ b/libmachdev/dev_hdr.h @@ -0,0 +1,133 @@ +/* + * 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 _DEVICE_DEV_HDR_H_ +#define _DEVICE_DEV_HDR_H_ + +#include +#include +#include +#include + +#include "device_emul.h" + +/* + * Operations list for major device types. + */ +struct dev_ops { + char * d_name; /* name for major device */ + int (*d_open)(); /* open device */ + int (*d_close)(); /* close device */ + int (*d_read)(); /* read */ + int (*d_write)(); /* write */ + int (*d_getstat)(); /* get status/control */ + int (*d_setstat)(); /* set status/control */ + vm_offset_t (*d_mmap)(); /* map memory */ + int (*d_async_in)();/* asynchronous input setup */ + int (*d_reset)(); /* reset device */ + int (*d_port_death)(); + /* clean up reply ports */ + int d_subdev; /* number of sub-devices per + unit */ + int (*d_dev_info)(); /* driver info for kernel */ +}; +typedef struct dev_ops *dev_ops_t; + +/* This structure is associated with each open device port. + * The port representing the device points to this structure. */ +struct emul_device +{ + struct 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) + +/* + * To find and remove device entries + */ +mach_device_t device_lookup(char *); /* by name */ + +/* + * To find and remove port-to-device mappings + */ +void dev_port_enter(mach_device_t); +void dev_port_remove(mach_device_t); + +/* + * To call a routine on each device + */ +boolean_t dev_map(boolean_t (*)(), mach_port_t); + +/* + * To lock and unlock state and open-count + */ +#define device_lock(device) pthread_mutex_lock(&(device)->lock) +#define device_unlock(device) pthread_mutex_unlock(&(device)->lock) + +#endif /* _DEVICE_DEV_HDR_H_ */ diff --git a/libmachdev/device_emul.h b/libmachdev/device_emul.h new file mode 100644 index 00000000..e27799cb --- /dev/null +++ b/libmachdev/device_emul.h @@ -0,0 +1,65 @@ +/* + * 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 _I386AT_DEVICE_EMUL_H_ +#define _I386AT_DEVICE_EMUL_H_ + +#include + +/* Each emulation layer provides these operations. */ +struct 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 /* _I386AT_DEVICE_EMUL_H_ */ diff --git a/libmachdev/ds_routines.c b/libmachdev/ds_routines.c new file mode 100644 index 00000000..d1da8780 --- /dev/null +++ b/libmachdev/ds_routines.c @@ -0,0 +1,335 @@ +/* + * 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 + */ + +#include +#include +#include + +#include +#include + +#include "vm_param.h" +#include "device_S.h" +#include "notify_S.h" +#include "io_req.h" +#include "dev_hdr.h" +#include "machdev.h" + +struct port_bucket *device_bucket; +struct port_class *dev_class; + +#define MAX_NUM_EMULATION 32 + +/* List of emulations. */ +static struct device_emulation_ops *emulation_list[MAX_NUM_EMULATION]; +static int num_emul = 0; + +boolean_t 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 = D_NO_SUCH_DEVICE; + + /* Open must be called on the master device port. */ + if (!is_master_device (open_port)) + return D_INVALID_OPERATION; + + /* There must be a reply port. */ + if (! MACH_PORT_VALID (reply_port)) + { + mach_print ("ds_* invalid reply port\n"); + 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) +{ + io_return_t ret; + + if (device == NULL) + return D_NO_SUCH_DEVICE; + + ret = (device->dev.emul_ops->close + ? (*device->dev.emul_ops->close) (device->dev.emul_data) + : D_SUCCESS); + return ret; +} + +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) +{ + io_return_t ret; + + if (data == 0) + return D_INVALID_SIZE; + + if (device == NULL) + return D_NO_SUCH_DEVICE; + + if (! device->dev.emul_ops->write) + return D_INVALID_OPERATION; + + ret = (*device->dev.emul_ops->write) (device->dev.emul_data, reply_port, + reply_port_type, mode, recnum, + data, count, bytes_written); + return ret; +} + +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) +{ + io_return_t ret; + + if (data == 0) + return D_INVALID_SIZE; + + if (device == NULL) + return D_NO_SUCH_DEVICE; + + if (! device->dev.emul_ops->write_inband) + return D_INVALID_OPERATION; + + ret = (*device->dev.emul_ops->write_inband) (device->dev.emul_data, + reply_port, reply_port_type, + mode, recnum, + data, count, bytes_written); + return ret; +} + +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) +{ + io_return_t ret; + + if (device == NULL) + return D_NO_SUCH_DEVICE; + + if (! device->dev.emul_ops->read) + return D_INVALID_OPERATION; + + ret = (*device->dev.emul_ops->read) (device->dev.emul_data, reply_port, + reply_port_type, mode, recnum, + count, data, bytes_read); + return ret; +} + +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) +{ + io_return_t ret; + + if (device == NULL) + return D_NO_SUCH_DEVICE; + + if (! device->dev.emul_ops->read_inband) + return D_INVALID_OPERATION; + + ret = (*device->dev.emul_ops->read_inband) (device->dev.emul_data, + reply_port, + reply_port_type, mode, recnum, + count, data, bytes_read); + return ret; +} + +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) +{ + io_return_t ret; + + if (device == NULL) + return D_NO_SUCH_DEVICE; + + if (! device->dev.emul_ops->set_status) + return D_INVALID_OPERATION; + + ret = (*device->dev.emul_ops->set_status) (device->dev.emul_data, flavor, + status, status_count); + return ret; +} + +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) +{ + io_return_t ret; + + if (device == NULL) + return D_NO_SUCH_DEVICE; + + if (! device->dev.emul_ops->get_status) + return D_INVALID_OPERATION; + + ret = (*device->dev.emul_ops->get_status) (device->dev.emul_data, flavor, + status, status_count); + return ret; +} + +io_return_t +ds_device_set_filter (struct mach_device *device, mach_port_t receive_port, + int priority, filter_t *filter, unsigned filter_count) +{ + io_return_t ret; + + if (device == NULL) + return D_NO_SUCH_DEVICE; + + if (! device->dev.emul_ops->set_filter) + return D_INVALID_OPERATION; + + ret = (*device->dev.emul_ops->set_filter) (device->dev.emul_data, + receive_port, + priority, filter, filter_count); + return ret; +} + +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 == NULL) + return D_NO_SUCH_DEVICE; + + return D_INVALID_OPERATION; +} + +error_t +create_device_port (size_t size, void *result) +{ + return ports_create_port (dev_class, device_bucket, + size, result); +} + +void mach_device_init() +{ + int i; + + device_bucket = ports_create_bucket (); + dev_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 reg_dev_emul (struct device_emulation_ops *ops) +{ + emulation_list[num_emul++] = ops; +} + +void * ds_server(void *arg) +{ + /* Hook for dde to identify thread */ + ds_pre_server(); + + /* Launch. */ + do + { + ports_manage_port_operations_one_thread (device_bucket, demuxer, 0); + } while (1); + + return NULL; +} diff --git a/libmachdev/ds_routines.h b/libmachdev/ds_routines.h new file mode 100644 index 00000000..3706aa58 --- /dev/null +++ b/libmachdev/ds_routines.h @@ -0,0 +1,57 @@ +/* + * 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: 8/89 + * + * Device service utility routines. + */ + +#ifndef DS_ROUTINES_H +#define DS_ROUTINES_H + +#include + +#include "io_req.h" + +/* + * Map for device IO memory. + */ +//vm_map_t device_io_map; + +kern_return_t device_read_alloc(io_req_t, vm_size_t); +kern_return_t device_write_get(io_req_t, boolean_t *); +boolean_t device_write_dealloc(io_req_t); + +boolean_t ds_open_done(io_req_t); +boolean_t ds_read_done(io_req_t); +boolean_t ds_write_done(io_req_t); + +void iowait (io_req_t ior); + +error_t create_device_port (size_t size, void *result); + +#endif /* DS_ROUTINES_H */ diff --git a/libmachdev/io_req.h b/libmachdev/io_req.h new file mode 100644 index 00000000..9c810542 --- /dev/null +++ b/libmachdev/io_req.h @@ -0,0 +1,135 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990,1989,1988 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: 10/88 + */ + +#ifndef _IO_REQ_ +#define _IO_REQ_ + +#include +#include + +#include "dev_hdr.h" + +/* + * IO request element, queued on device for delayed replies. + */ +typedef struct io_req *io_req_t; +struct io_req { + struct io_req * io_next; /* next, ... */ + struct io_req * io_prev; /* prev pointers: link in done, + defered, or in-progress list */ + mach_device_t io_device; /* pointer to open-device structure */ + char * io_dev_ptr; /* pointer to driver structure - + filled in by driver if necessary */ + int io_unit; /* unit number ('minor') of device */ + int io_op; /* IO operation */ + dev_mode_t io_mode; /* operation mode (wait, truncate) */ + recnum_t io_recnum; /* starting record number for + random-access devices */ + + union io_un { + io_buf_ptr_t data; /* data, for IO requests */ + } io_un; +#define io_data io_un.data + + long io_count; /* amount requested */ + long io_alloc_size; /* amount allocated */ + long io_residual; /* amount NOT done */ + io_return_t io_error; /* error code */ + /* call when done - returns TRUE if IO really finished */ + boolean_t (*io_done)(io_req_t); + mach_port_t io_reply_port; /* reply port, for asynchronous + messages */ + mach_msg_type_name_t io_reply_port_type; + /* send or send-once right? */ + struct io_req * io_link; /* forward link (for driver header) */ + struct io_req * io_rlink; /* reverse link (for driver header) */ +// vm_map_copy_t io_copy; /* vm_map_copy obj. for this op. */ + long io_total; /* total op size, for write */ + pthread_mutex_t io_req_lock; +// decl_simple_lock_data(,io_req_lock) + /* Lock for this structure */ + long io_physrec; /* mapping to the physical block + number */ + long io_rectotal; /* total number of blocks to move */ +}; + +/* + * LOCKING NOTE: Operations on io_req's are in general single threaded by + * the invoking code, obviating the need for a lock. The usual IO_CALL + * path through the code is: Initiating thread hands io_req to device driver, + * driver passes it to io_done thread, io_done thread sends reply message. No + * locking is needed in this sequence. Unfortunately, a synchronous wait + * for a buffer requires a lock to avoid problems if the wait and interrupt + * happen simultaneously on different processors. + */ + +#define ior_lock(ior) pthread_mutex_lock(&(ior)->io_req_lock) +#define ior_unlock(ior) pthread_mutex_unlock(&(ior)->io_req_lock) + +/* + * Flags and operations + */ + +#define IO_WRITE 0x00000000 /* operation is write */ +#define IO_READ 0x00000001 /* operation is read */ +#define IO_OPEN 0x00000002 /* operation is open */ +#define IO_DONE 0x00000100 /* operation complete */ +#define IO_ERROR 0x00000200 /* error on operation */ +#define IO_BUSY 0x00000400 /* operation in progress */ +#define IO_WANTED 0x00000800 /* wakeup when no longer BUSY */ +#define IO_BAD 0x00001000 /* bad disk block */ +#define IO_CALL 0x00002000 /* call io_done_thread when done */ +#define IO_INBAND 0x00004000 /* mig call was inband */ +#define IO_INTERNAL 0x00008000 /* internal, device-driver specific */ +#define IO_LOANED 0x00010000 /* ior loaned by another module */ + +#define IO_SPARE_START 0x00020000 /* start of spare flags */ + +/* + * Standard completion routine for io_requests. + */ +void iodone(io_req_t); + +/* + * Macros to allocate and free IORs - will convert to zones later. + */ +#define io_req_alloc(ior,size) \ + MACRO_BEGIN \ + (ior) = (io_req_t)malloc(sizeof(struct io_req)); \ + pthread_mutex_init(&(ior)->io_req_lock, NULL); \ + MACRO_END + +#define io_req_free(ior) \ + (free(ior)) + + +//zone_t io_inband_zone; /* for inband reads */ + +#endif /* _IO_REQ_ */ diff --git a/libmachdev/machdev.h b/libmachdev/machdev.h new file mode 100644 index 00000000..4f272558 --- /dev/null +++ b/libmachdev/machdev.h @@ -0,0 +1,34 @@ +/* + 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 programs. */ + +#ifndef __MACHDEV_H__ +#define __MACHDEV_H__ + +void ds_pre_server(void); +void * ds_server(void *); +void mach_device_init(void); +void register_net(void); +void register_block(void); +void trivfs_server(void); +int trivfs_init(void); + +#endif diff --git a/libmachdev/mig-decls.h b/libmachdev/mig-decls.h new file mode 100644 index 00000000..8302029d --- /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 . */ + +#ifndef __LIBMACHDEV_MIG_DECLS_H__ +#define __LIBMACHDEV_MIG_DECLS_H__ + +#include +#include "dev_hdr.h" + +extern struct port_bucket *device_bucket; +extern struct port_class *dev_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 (device_bucket, port, dev_class); +} + +static inline struct mach_device * __attribute__ ((unused)) +begin_using_device_payload (unsigned long payload) +{ + return ports_lookup_payload (device_bucket, payload, dev_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 00000000..902ff166 --- /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 . */ + +#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 00000000..bf5210df --- /dev/null +++ b/libmachdev/trivfs_server.c @@ -0,0 +1,169 @@ +#include +#include +#include +#include +#include +#include + +#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 +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 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 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)); +} diff --git a/libmachdev/vm_param.h b/libmachdev/vm_param.h new file mode 100644 index 00000000..7b615c8a --- /dev/null +++ b/libmachdev/vm_param.h @@ -0,0 +1,7 @@ +#ifndef __VM_PARAM_H__ +#define __VM_PARAM_H__ + +#define PAGE_SIZE __vm_page_size +#define PAGE_MASK (PAGE_SIZE-1) + +#endif -- 2.25.1