diff options
-rw-r--r-- | devio/ChangeLog | 270 | ||||
-rw-r--r-- | devio/MAKEDEV | 80 | ||||
-rw-r--r-- | devio/Makefile | 30 | ||||
-rw-r--r-- | devio/dev.c | 227 | ||||
-rw-r--r-- | devio/dev.h | 147 | ||||
-rw-r--r-- | devio/devio.c | 359 | ||||
-rw-r--r-- | devio/devpager.c | 257 | ||||
-rw-r--r-- | devio/io.c | 396 | ||||
-rw-r--r-- | devio/iostate.c | 79 | ||||
-rw-r--r-- | devio/iostate.h | 67 | ||||
-rw-r--r-- | devio/mem.c | 57 | ||||
-rw-r--r-- | devio/mem.h | 33 | ||||
-rw-r--r-- | devio/open.c | 90 | ||||
-rw-r--r-- | devio/open.h | 73 | ||||
-rw-r--r-- | devio/ptypes.h | 23 | ||||
-rw-r--r-- | devio/rdwr.c | 471 | ||||
-rw-r--r-- | devio/window.c | 171 | ||||
-rw-r--r-- | devio/window.h | 84 |
18 files changed, 0 insertions, 2914 deletions
diff --git a/devio/ChangeLog b/devio/ChangeLog deleted file mode 100644 index 07f59609..00000000 --- a/devio/ChangeLog +++ /dev/null @@ -1,270 +0,0 @@ -Sun Sep 8 18:10:57 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * Makefile (DIST_FILES): Variable removed. - (install, $(prefix)/dev/MAKEDEV): Targets removed. - -Fri Jul 19 15:55:27 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * io.c (trivfs_S_file_get_storage_info): Return correct values for - NUM_RUNS and NUM_OFFSETS. - -Thu Jul 18 18:33:49 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * io.c (trivfs_S_file_get_storage_info): Fill in the array-length - return values. - - * MAKEDEV: Add "com[0-9]". - -Wed Jul 17 10:00:04 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * MAKEDEV (st): New function. - Use new st function (get rid of chmods). - Accept disk device names without partitions, & with slice + partition. - -Sat Jun 15 14:13:24 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> - - * MAKEDEV ([hrs]d*): Allow user to specify slice as well. Patch - from Gord Matzigkeit, gord@enci.ucalgary.ca. - -Thu May 9 12:15:47 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * io.c (trivfs_S_io_select): Remove TAG arg. - (trivfs_S_file_get_storage_info): Fix param type. - -Tue May 7 16:41:48 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * io.c (trivfs_S_file_get_storage_info): Swap PORTS_TYPE & NUM_PORTS. - -Mon May 6 20:14:43 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * io.c (trivfs_S_file_get_storage_info): Enable new version. - -Fri May 3 15:09:00 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * io.c [0] (trivfs_S_file_get_storage_info): Rewrite for new interface. - -Tue Apr 30 10:03:50 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> - - * Makefile (include ../Makeconf): BEFORE dependencies. - ($(prefix)/dev/MAKEDEV): Find MAKEDEV in $(srcdir). - -Fri Feb 16 19:28:32 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * MAKEDEV: Add rule for `time', and add `time' to std. - -Tue Jan 30 12:34:28 1996 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * MAKEDEV: Grok `tty'. - -Thu Jan 25 18:10:24 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * devio.c (trivfs_goaway): Handle errors from ports_inhibit_class_rpcs. - Allow rpcs to resume if we're going to return EBUSY. - -Tue Jan 16 16:19:51 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * devio.c (trivfs_modify_stat): The peropen hook holds a struct - open, not a struct dev. - -Fri Dec 29 23:41:39 1995 Miles Bader <miles@gnu.ai.mit.edu> - - * MAKEDEV (std): Make `fd' one of the standard devices. - -Fri Dec 15 13:30:33 1995 Miles Bader <miles@gnu.ai.mit.edu> - - * MAKEDEV (ST): Variable holding the proper settrans command, - which use. - (_CWD): Use this variable to pass down the current directory to - sub MAKEDEVS. - (console): Use the new term syntax. - (tty[0-9]?|tty[0-9a-f]): New rule for normal ttys. - ([pt]ty[pqPQ]?): New rule for ptys (both master and slave). - ([pt]ty[pqPQ]): New rule for making sets of ptys. - -Mon Dec 4 15:17:14 1995 Miles Bader <miles@gnu.ai.mit.edu> - - * io.c (trivfs_S_file_set_size, trivfs_S_file_sync, - trivfs_S_file_syncfs, trivfs_S_file_get_storage_info): Add totally - gratuitous, annoying, and trouble-making reply-port args. - - * io.c (trivfs_S_file_get_storage_info): Use inline return if possible. - -Wed Nov 8 16:44:05 1995 Miles Bader <miles@gnu.ai.mit.edu> - - * io.c (trivfs_S_file_set_size): Renamed from trivfs_S_file_truncate. - -Sun Nov 5 10:00:56 1995 Miles Bader <miles@gnu.ai.mit.edu> - - * devio.c (main): Add FLAGS arg to trivfs_startup call. - -Sat Nov 4 20:03:05 1995 Miles Bader <miles@gnu.ai.mit.edu> - - * io.c (trivfs_S_file_get_storage_info): Add FLAGS argument. - -Fri Oct 6 17:25:37 1995 Miles Bader <miles@gnu.ai.mit.edu> - - * io.c (trivfs_S_file_get_storage_info): Change type of ADDRESSES - to off_t **, and add BLOCK_SIZE parameter. - -Sun Oct 1 16:20:45 1995 Miles Bader <miles@gnu.ai.mit.edu> - - * devio.c (main, trivfs_S_fsys_syncfs): Get rid of debugging noise. - * rdwr.c (open_write, open_read): Ditto. - * dev.c (dev_open, dev_sync, dev_write, dev_read): Ditto. - * io.c (trivfs_S_file_syncfs, trivfs_S_file_sync): Ditto. - * devpager.c (pager_write_page, pager_read_page): Ditto. - * window.c (position): Ditto. - -Tue Sep 26 15:33:14 1995 Miles Bader <miles@gnu.ai.mit.edu> - - * io.c (trivfs_S_file_get_storage_info): New function. - * dev.c (dev_open): Record NAME in the returned dev structure. - * dev.h (struct dev): Add the NAME field. - -Thu Aug 24 10:28:00 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * Makefile (devio): Put all dependencies here. - (HURDLIBS): Removed. - -Tue Aug 22 10:45:31 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * Makefile (HURDLIBS): Add libshouldbeinlibc. - (OBJS): Get rid of error.o. - Get rid of rules dealing with error.o. - ($(prefix)/dev/MAKEDEV): Use $(INSTALL_PROGRAM) instead of - $(INSTALL_DATA) + `chmod +x'. - - * devio.c (trivfs_modify_stat): Get the device from CRED now that - we have it. - -Mon Aug 21 16:34:29 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * devio.c (trivfs_goaway, trivfs_modify_stat): Update arguments. - -Tue Aug 15 19:47:57 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * MAKEDEV ([hrs]d*): Fixed partition parsing: use glob pattern, - not regexp. - -Sun Aug 13 10:57:03 1995 Miles Bader <miles@duality.gnu.ai.mit.edu> - - * devio.c (trivfs_peropen_create_hook): This now returns an error_t. - (open_hook): And thus this does as well. - -Sat Jul 22 18:32:03 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * rdwr.c (open_read, open_write): Clean up STATE before returning - with an error. - * devpager.c (dev_get_memory_object): A new pager now comes with 1 - ref, so we allocate a ref ourselves when we're using an old one, - and once we've created the send right, remove a reference. - -Mon Jul 10 15:15:45 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * rdwr.c (open_seek): New function. - (raw_read, raw_write): Return EINVAL if *OFFS isn't a block boundary. - * open.h: Add declaration for open_seek. - * io.c (trivfs_S_io_seek): Call open_seek instead of doing ourselves. - -Sat Jul 8 18:35:17 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * MAKEDEV (fd): Put the fd server on `fd', not `stdin'. - * MAKEDEV (console): Give /hurd/term a ttyname argument. - -Thu Jul 6 15:33:33 1995 Miles Bader <miles@geech.gnu.ai.mit.edu> - - * Makefile: Remove include dependencies. - -Wed Jun 28 19:22:47 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * Makefile (HURDLIBS): Add libihash. - - * iostate.c (io_state_sync): Remember that we've synced the buffer. - * devpager.c (dev_stop_paging): New function. - (pager_dropweak): New function. - * dev.h (struct dev): Add the pager_port_bucket field. - Declare dev_stop_paging (). - * devio.c (trivfs_goaway): Make trivfs_goaway do the right thing. - (clean_exit, close_device): Deleted functions. - (thread_cancel): New function. - - * devpager.c (pager_port_type): Deleted var. - (pager_port_bucket, pager_port_class): New vars. - (dev_get_memory_object): Moved here from dev.c. Also, call - init_dev_pager if necessary. - (service_paging_requests): New function. - (init_dev_pager): New function. - * dev.c (dev_get_memory_object): Moved function to devpager.c. - - * devio.c (fsys_port_class, root_port_class, port_bucket): New vars. - (trivfs_protid_portclasses, trivfs_cntl_portclasses, - trivfs_protid_nportclasses, trivfs_cntl_nportclasses): New vars. - (main): Initialize *portclasses vars, and convert to new trivfs lib. - (trivfs_protid_porttypes, trivfs_cntl_porttypes, - trivfs_protid_nporttypes, trivfs_cntl_nporttypes): Deleted vars. - (trivfs_goaway): Convert args for new trivfs lib. - (ports_cleanroutines): Delete var. - (ports_demuxer, ports_notice_idle, ports_no_live_ports, - ports_no_hard_ports): Delete functions. - * ptypes.h: Deleted file. - -Wed Jun 28 15:51:51 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu> - - * Makefile: Repair mangled include-file dependencies. - -Fri Apr 21 14:17:19 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * MAKEDEV: Split out `std' into individual device-makers it calls. - Rewrote /dev/fd stuff (still commented out). Use case built-in - instead of expr program. - -Tue Apr 11 15:46:35 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu> - - * Makefile (DIST_FILES): New var, for MAKEDEV. - (install): Depend on $(prefix)/dev/MAKEDEV. - ($(prefix)/dev/MAKEDEV): New target. - * MAKEDEV: New file. - -Mon Apr 10 10:22:26 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * rdwr.c (open_write, open_read): Bounds check I/O. - - * io.c (trivfs_S_file_truncate): Always return 0, so O_TRUNC works. - - * devio.c (main, check_open_hook, close_device, trivfs_goaway): - Add a new lock, device_lock, and use it to control access to the - DEVICE variable. - (open_hook, trivfs_modify_stat, trivfs_S_fys_syncfs): Copy DEVICE - before using it, so it doesn't change underneath us. - - * devio.c (clean_exit): Add a new argument that says whether to - aquire a lock before doing our work. - (ports_notice_idle, ports_no_live_ports): Use it. - - * devio.c (close_device): New function, closes DEVICE cleanly. - (clean_exit, ports_no_hard_ports): Use close_device. - - * devio.c (main): Use trivfs_startup instead of doing it manually. - - * devio.c (trivfs_goaway): Try and do it better, paying attention - to flags, etc.; this still isn't right though, we may want to wait - for the ports library to be fixed first. - - * devio.c (DEBUG): New macro, executes its arg with debug_lock locked. - (most everything): use DEBUG instead of doing things manually. - - * open.c (open_create): Supply our dev's size when creating a window. - -Sun Apr 9 14:49:33 1995 Miles Bader <miles@duality.gnu.ai.mit.edu> - - * window.h: Add a new window field, max_pos. Rename the location - field `pos'. - * window.c (position): Use a shorter than normal window if - necessary to avoid going past the end of the device. - (window_create): Initialize the new MAX_POS field. - (window_create, position, window_write, window_read): Rename the - location field `pos'. - - * devpager.c (pager_read_page, pager_write_page): Read or write - partial pages at the end of the device. - diff --git a/devio/MAKEDEV b/devio/MAKEDEV deleted file mode 100644 index 7d13fe3b..00000000 --- a/devio/MAKEDEV +++ /dev/null @@ -1,80 +0,0 @@ -#!/bin/sh -# -# Make standard devices -# - -PATH=/bin - -function st { - NODE="$1" - OWNER="$2" - PERM="$3" - shift 3 - settrans -cg "$NODE" - chown "$OWNER" "$NODE" - chmod "$PERM" "$NODE" - settrans "$NODE" "$@" -} - -_CWD=${_CWD:-`pwd`} -export _CWD - -for I; do - case "$I" in - std) - $0 console tty null zero fd time - ;; - console|tty[0-9][0-9a-f]|tty[0-9a-f]|com[0-9]) - st $I root 600 /hurd/term $_CWD/$I device $I;; - null) - st $I root 666 /hurd/null;; - zero) - st $I root 666 /hurd/null -z;; - tty) - st $I root 666 /hurd/magic tty;; - fd) - st $I root 666 /hurd/magic fd - ln -f -s fd/0 stdin - ln -f -s fd/1 stdout - ln -f -s fd/2 stderr - ;; - time) - st $I root 666 /hurd/devport time ;; - - # ptys - [pt]ty[pqPQ]?) - # Make one pty, both the master and slave halves - ID="`expr substr $I 4 99`" - st pty$ID root 640 /hurd/term $_CWD/pty$ID pty-master $_CWD/tty$ID - st tty$ID root 640 /hurd/term $_CWD/tty$ID pty-slave $_CWD/pty$ID - ;; - [pt]ty[pqPQ]) - # Make a bunch of ptys - $0 ${I}0 ${I}1 ${I}2 ${I}3 ${I}4 ${I}5 ${I}6 ${I}7 - $0 ${I}8 ${I}9 ${I}a ${I}b ${I}c ${I}d ${I}e ${I}f - ;; - - fd*|mt*) - st r$I root 640 /hurd/devio $I - st $I root 640 /hurd/devio -b $I - ;; - - [hrs]d*) - case "$I" in - [a-z][a-z][0-9][a-z] | [a-z][a-z][0-9]s[1-9] | [a-z][a-z][0-9]s[1-9][a-z] | [a-z][a-z][0-9]) - st r$I root 640 /hurd/devio $I - st $I root 640 /hurd/devio -b $I - ;; - *) - echo 1>&2 $0: $I: Illegal device name: must supply a device number - exit 1 - ;; - esac - ;; - - *) - echo >&2 $0: $I: Unknown device - exit 1 - ;; - esac -done diff --git a/devio/Makefile b/devio/Makefile deleted file mode 100644 index 1dda469d..00000000 --- a/devio/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# Makefile for devio -# -# Copyright (C) 1995, 1996 Free Software Foundation, Inc. -# -# This program 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. -# -# This program 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 this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -dir := devio -makemode := server - -target = devio -SRCS = dev.c iostate.c window.c devio.c open.c devpager.c io.c rdwr.c mem.c -LCLHDRS = dev.h iostate.h window.h open.h ptypes.h mem.h - -OBJS = $(SRCS:.c=.o) - -include ../Makeconf - -devio: $(OBJS) ../libtrivfs/libtrivfs.a ../libpager/libpager.a ../libports/libports.a ../libfshelp/libfshelp.a ../libthreads/libthreads.a ../libihash/libihash.a ../libshouldbeinlibc/libshouldbeinlibc.a diff --git a/devio/dev.c b/devio/dev.c deleted file mode 100644 index 4d3b89cb..00000000 --- a/devio/dev.c +++ /dev/null @@ -1,227 +0,0 @@ -/* Mach devices. - - Copyright (C) 1995 Free Software Foundation, Inc. - - Written by Miles Bader <miles@gnu.ai.mit.edu> - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include <hurd.h> -#include <device/device.h> -#include <assert.h> -#include <hurd/pager.h> - -#include "dev.h" -#include "iostate.h" - -/* ---------------------------------------------------------------- */ - -/* Returns a pointer to a new device structure in DEV for the kernel device - NAME, with the given FLAGS. If BLOCK_SIZE is non-zero, it should be the - desired block size, and must be a multiple of the device block size. - If an error occurs, the error code is returned, otherwise 0. */ -error_t -dev_open(char *name, int flags, int block_size, struct dev **dev) -{ - error_t err = 0; - static mach_port_t device_master = MACH_PORT_NULL; - - *dev = malloc(sizeof (struct dev)); - - if (!(flags & DEV_SERIAL)) - flags |= DEV_SEEKABLE; - - if (*dev == NULL) - return ENOMEM; - - (*dev)->name = malloc (strlen (name) + 1); - if ((*dev)->name) - strcpy ((*dev)->name, name); - else - err = ENOMEM; - - (*dev)->port = MACH_PORT_NULL; - - if (!err && device_master == MACH_PORT_NULL) - err = get_privileged_ports(NULL, &device_master); - - if (!err) - err = device_open(device_master, - D_READ | (flags & DEV_READONLY ? D_WRITE : 0), - name, &(*dev)->port); - - if (!err) - { - int count = DEV_GET_SIZE_COUNT; - int sizes[DEV_GET_SIZE_COUNT]; - - /* Get info about the device: total size (in bytes) and block size (in - bytes). Block size is unit in which device addressing is done. */ - err = device_get_status((*dev)->port, DEV_GET_SIZE, sizes, &count); - if (!err) - { - (*dev)->size = sizes[DEV_GET_SIZE_DEVICE_SIZE]; - (*dev)->dev_block_size = sizes[DEV_GET_SIZE_RECORD_SIZE]; - } - } - - if (!err) - { - if (block_size > 0) - if (block_size > (*dev)->dev_block_size - && block_size % (*dev)->dev_block_size == 0) - (*dev)->block_size = block_size; - else - err = EINVAL; - else - (*dev)->block_size = (*dev)->dev_block_size; - - if ((*dev)->dev_block_size == 1) - flags |= DEV_SERIAL; - - (*dev)->flags = flags; - (*dev)->owner = 0; - } - - if (!err) - err = io_state_init(&(*dev)->io_state, *dev); - - if (err) - { - if ((*dev)->port != MACH_PORT_NULL) - mach_port_deallocate(mach_task_self(), (*dev)->port); - free(*dev); - } - - return err; -} - -/* Free DEV and any resources it consumes. */ -void -dev_close(struct dev *dev) -{ - if (!dev_is(dev, DEV_READONLY)) - { - if (dev->pager != NULL) - pager_shutdown(dev->pager); - io_state_sync(&dev->io_state, dev); - } - - device_close(dev->port); - io_state_finalize(&dev->io_state); - - free(dev); -} - -/* ---------------------------------------------------------------- */ - -/* Try and write out any pending writes to DEV. If WAIT is true, will wait - for any paging activity to cease. */ -error_t -dev_sync(struct dev *dev, int wait) -{ - error_t err = 0; - - if (!dev_is(dev, DEV_READONLY)) - { - struct io_state *ios = &dev->io_state; - - io_state_lock(ios); - - /* Sync any paged backing store. */ - if (dev->pager != NULL) - pager_sync(dev->pager, wait); - - /* Write out any stuff buffered in our io_state. */ - err = io_state_sync(ios, dev); - - io_state_unlock(ios); - } - - return err; -} - -/* ---------------------------------------------------------------- */ - -/* Writes AMOUNT bytes from the buffer pointed to by BUF to the device DEV. - *OFFS is incremented to reflect the amount read/written. Both AMOUNT and - *OFFS must be multiples of DEV's block size, and either BUF must be - page-aligned, or dev_write_valid() must return true for these arguments. - If an error occurs, the error code is returned, otherwise 0. */ -error_t -dev_write(struct dev *dev, - vm_address_t buf, vm_size_t amount, vm_offset_t *offs) -{ - int bsize = dev->dev_block_size; - vm_offset_t written = 0; - vm_offset_t block = (bsize == 1 ? *offs : *offs / bsize); - error_t err; - - assert(dev_write_valid(dev, buf, amount, *offs)); - assert(*offs % bsize == 0); - assert(amount % bsize == 0); - - if (amount < IO_INBAND_MAX) - err = - device_write_inband (dev->port, 0, block, - (io_buf_ptr_t)buf, amount, &written); - else - err = - device_write (dev->port, 0, block, (io_buf_ptr_t)buf, amount, &written); - - if (!err) - *offs += written; - - return err; -} - -/* Reads AMOUNT bytes from DEV and returns it in BUF and BUF_LEN (using the - standard mach out-array convention). *OFFS is incremented to reflect the - amount read/written. Both LEN and *OFFS must be multiples of DEV's block - size. If an error occurs, the error code is returned, otherwise 0. */ -error_t -dev_read(struct dev *dev, - vm_address_t *buf, vm_size_t *buf_len, vm_size_t amount, - vm_offset_t *offs) -{ - error_t err = 0; - int bsize = dev->dev_block_size; - vm_offset_t read = 0; - vm_offset_t block = (bsize == 1 ? *offs : *offs / bsize); - - assert(*offs % bsize == 0); - assert(amount % bsize == 0); - - if (amount < IO_INBAND_MAX) - { - if (*buf_len < amount) - err = vm_allocate(mach_task_self(), buf, amount, 1); - if (!err) - err = - device_read_inband(dev->port, 0, block, - amount, (io_buf_ptr_t)*buf, &read); - } - else - err = - device_read(dev->port, 0, block, amount, (io_buf_ptr_t *)buf, &read); - - if (!err) - { - *offs += read; - *buf_len = read; - } - - return err; -} diff --git a/devio/dev.h b/devio/dev.h deleted file mode 100644 index de51d788..00000000 --- a/devio/dev.h +++ /dev/null @@ -1,147 +0,0 @@ -/* A handle on a mach device. - - Copyright (C) 1995 Free Software Foundation, Inc. - - Written by Miles Bader <miles@gnu.ai.mit.edu> - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#ifndef __DEV_H__ -#define __DEV_H__ - -#include <mach.h> -#include <device/device.h> - -#include "iostate.h" - -/* #define FAKE */ -#define MSG - -#ifdef MSG -#include <stdio.h> -#include <string.h> -#include <unistd.h> -extern FILE *debug; -extern struct mutex debug_lock; -#endif - -/* ---------------------------------------------------------------- */ - -/* Information about a kernel device. */ -struct dev -{ - /* The device port for the kernel device we're doing paging on. */ - device_t port; - /* The mach device name which we opened. */ - char *name; - - /* The total size of DEV. */ - vm_size_t size; - - /* The block size of DEV. I/O to DEV must occur in multiples of - block_size. */ - int dev_block_size; - /* The block size in which we will do I/O; this must be a multiple of - DEV_BLOCK_SIZE. */ - int block_size; - - /* Various attributes of this device (see below for the DEV_ flag bits). - This field is constant. */ - int flags; - - /* Current state of our output stream -- location and the buffer used to do - buffered i/o. */ - struct io_state io_state; - - /* The pager we're using to do disk i/o for us. If NULL, a pager hasn't - been allocated yet. Lock the lock in IO_STATE if you want to update - this field. */ - struct pager *pager; - /* The port_bucket for paging ports. */ - struct port_bucket *pager_port_bucket; - - /* The current owner of the open device. For terminals, this affects - controlling terminal behavior (see term_become_ctty). For all objects - this affects old-style async IO. Negative values represent pgrps. This - has nothing to do with the owner of a file (as returned by io_stat, and - as used for various permission checks by filesystems). An owner of 0 - indicates that there is no owner. */ - pid_t owner; -}; - -/* Various bits to be set in the flags field. */ - -/* True if this device should be used in `block' mode, with buffering of - sub-block-size i/o. */ -#define DEV_BUFFERED 0x1 -/* True if this device only supports serial i/o (that is, there's only one - read/write location, which must explicitly be moved to do i/o elsewhere.*/ -#define DEV_SERIAL 0x2 -/* True if we can change the current i/o location of a serial device. */ -#define DEV_SEEKABLE 0x4 -/* True if a device cannot be written on. */ -#define DEV_READONLY 0x8 - -/* Returns TRUE if any of the flags in BITS are set for DEV. */ -#define dev_is(dev, bits) ((dev)->flags & (bits)) - -/* Returns true if it's ok to call dev_write on these arguments, without - first copying BUF to a page-aligned buffer. */ -#define dev_write_valid(dev, buf, len, offs) \ - ((len) <= IO_INBAND_MAX || (buf) % vm_page_size == 0) - -/* Returns a pointer to a new device structure in DEV for the kernel device - NAME, with the given FLAGS. If BLOCK_SIZE is non-zero, it should be the - desired block size, and must be a multiple of the device block size. - If an error occurs, the error code is returned, otherwise 0. */ -error_t dev_open(char *name, int flags, int block_size, struct dev **dev); - -/* Free DEV and any resources it consumes. */ -void dev_close(struct dev *dev); - -/* Reads AMOUNT bytes from DEV and returns it in BUF and BUF_LEN (using the - standard mach out-array convention). *OFFS is incremented to reflect the - amount read/written. Both LEN and *OFFS must be multiples of DEV's block - size. If an error occurs, the error code is returned, otherwise 0. */ -error_t dev_read(struct dev *dev, - vm_address_t *buf, vm_size_t *buf_len, vm_size_t amount, - vm_offset_t *offs); - -/* Writes AMOUNT bytes from the buffer pointed to by BUF to the device DEV. - *OFFS is incremented to reflect the amount read/written. Both AMOUNT and - *OFFS must be multiples of DEV's block size, and either BUF must be - page-aligned, or dev_write_valid() must return true for these arguments. - If an error occurs, the error code is returned, otherwise 0. */ -error_t dev_write(struct dev *dev, - vm_address_t buf, vm_size_t amount, vm_offset_t *offs); - -/* Returns in MEMOBJ the port for a memory object backed by the storage on - DEV. Returns 0 or the error code if an error occurred. */ -error_t dev_get_memory_object(struct dev *dev, memory_object_t *memobj); - -/* Try to stop all paging activity on DEV, returning true if we were - successful. If NOSYNC is true, then we won't write back any (kernel) - cached pages to the device. */ -int dev_stop_paging (struct dev *dev, int nosync); - -/* Try and write out any pending writes to DEV. If WAIT is true, will wait - for any paging activity to cease. */ -error_t dev_sync(struct dev *dev, int wait); - -#ifdef MSG -char *brep(vm_address_t buf, vm_size_t len); -#endif - -#endif /* !__DEV_H__ */ diff --git a/devio/devio.c b/devio/devio.c deleted file mode 100644 index f1eb428a..00000000 --- a/devio/devio.c +++ /dev/null @@ -1,359 +0,0 @@ -/* A translator for doing I/O to mach kernel devices. - - Copyright (C) 1995 Free Software Foundation, Inc. - - Written by Miles Bader <miles@gnu.ai.mit.edu> - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include <hurd.h> -#include <hurd/ports.h> -#include <hurd/pager.h> -#include <hurd/trivfs.h> -#include <hurd/fsys.h> - -#include <stdio.h> -#include <error.h> -#include <getopt.h> -#include <assert.h> -#include <fcntl.h> - -#include "open.h" -#include "dev.h" - -/* ---------------------------------------------------------------- */ - -/* The port class of our file system control pointer. */ -struct port_class *fsys_port_class; -/* The port class of the (only) root file port for the opened device. */ -struct port_class *root_port_class; - -/* A bucket to put all our ports in. */ -struct port_bucket *port_bucket; - -/* Trivfs noise. */ -struct port_class *trivfs_protid_portclasses[1]; -struct port_class *trivfs_cntl_portclasses[1]; -int trivfs_protid_nportclasses = 1; -int trivfs_cntl_nportclasses = 1; - -/* ---------------------------------------------------------------- */ - -#define USAGE "Usage: %s [OPTION...] DEVICE\n" - -static void -usage(int status) -{ - if (status != 0) - fprintf(stderr, "Try `%s --help' for more information.\n", - program_invocation_name); - else - { - printf(USAGE, program_invocation_name); - printf("\ -\n\ - -d, --devnum=NUM Give DEVICE a device number NUM\n\ - -r, --readonly Disable writing to DEVICE\n\ - -p, --seekable Enable seeking if DEVICE is serial\n\ - -s, --serial Indicate that DEVICE has a single R/W point\n\ - -b, --buffered, --block Open DEVICE in `block' mode, which allows reads\n\ - or writes less than a single block and buffers\n\ - I/O to the actual device. By default, all reads\n\ - and writes are made directly to the device,\n\ - with no buffering, and any sub-block-size I/O\n\ - is padded to the nearest full block.\n\ - -B NUM, --block-size=NUM Use a block size of NUM, which must be an integer\n\ - multiple of DEVICE's real block size\n\ -"); - } - - exit(status); -} - -#define SHORT_OPTIONS "bB:d:D:?rpsu" - -static struct option options[] = -{ - {"block-size", required_argument, 0, 'B'}, - {"help", no_argument, 0, '?'}, - {"devnum", required_argument, 0, 'm'}, - {"block", no_argument, 0, 'b'}, - {"buffered", no_argument, 0, 'b'}, - {"readonly", no_argument, 0, 'r'}, - {"seekable", no_argument, 0, 'p'}, - {"serial", no_argument, 0, 's'}, - {0, 0, 0, 0} -}; - -/* ---------------------------------------------------------------- */ - -/* A struct dev for the open kernel device. */ -static struct dev *device = NULL; -/* And a lock to arbitrate changes to it. */ -static struct mutex device_lock; - -/* Desired device parameters specified by the user. */ -static char *device_name = NULL; -static int device_flags = 0; -static int device_block_size = 0; - -/* A unixy device number to return when the device is stat'd. */ -static int device_number = 0; - -void main(int argc, char *argv[]) -{ - int opt; - error_t err; - mach_port_t bootstrap; - - while ((opt = getopt_long(argc, argv, SHORT_OPTIONS, options, 0)) != EOF) - switch (opt) - { - case 'r': device_flags |= DEV_READONLY; break; - case 's': device_flags |= DEV_SERIAL; break; - case 'b': device_flags |= DEV_BUFFERED; break; - case 'p': device_flags |= DEV_SEEKABLE; break; - case 'B': device_block_size = atoi(optarg); break; - case 'd': device_number = atoi(optarg); break; - case '?': usage(0); - default: usage(1); - } - - if (device_flags & DEV_READONLY) - /* Catch illegal writes at the point of open. */ - trivfs_allow_open &= ~O_WRITE; - - if (argv[optind] == NULL || argv[optind + 1] != NULL) - { - fprintf(stderr, USAGE, program_invocation_name); - usage(1); - } - - device_name = argv[optind]; - - task_get_bootstrap_port (mach_task_self (), &bootstrap); - if (bootstrap == MACH_PORT_NULL) - error(2, 0, "Must be started as a translator"); - - fsys_port_class = ports_create_class (trivfs_clean_cntl, 0); - root_port_class = ports_create_class (trivfs_clean_protid, 0); - port_bucket = ports_create_bucket (); - trivfs_protid_portclasses[0] = root_port_class; - trivfs_cntl_portclasses[0] = fsys_port_class; - - /* Reply to our parent */ - err = - trivfs_startup(bootstrap, 0, - fsys_port_class, port_bucket, - root_port_class, port_bucket, - NULL); - if (err) - error(3, err, "Contacting parent"); - - /* Open the device only when necessary. */ - device = NULL; - mutex_init(&device_lock); - - /* Launch. */ - ports_manage_port_operations_multithread (port_bucket, trivfs_demuxer, - 30*1000, 5*60*1000, 0, 0); - - exit(0); -} - -/* Called whenever someone tries to open our node (even for a stat). We - delay opening the kernel device until this point, as we can usefully - return errors from here. */ -static error_t -check_open_hook (struct trivfs_control *trivfs_control, - uid_t *uids, u_int nuids, - gid_t *gids, u_int ngids, - int flags) -{ - error_t err = 0; - - mutex_lock(&device_lock); - if (device == NULL) - /* Try and open the device. */ - { - err = dev_open(device_name, device_flags, device_block_size, &device); - if (err) - device = NULL; - if (err && (flags & (O_READ|O_WRITE)) == 0) - /* If we're not opening for read or write, then just ignore the - error, as this allows stat to word correctly. XXX */ - err = 0; - } - mutex_unlock(&device_lock); - - return err; -} - -static error_t -open_hook(struct trivfs_peropen *peropen) -{ - struct dev *dev = device; - if (dev) - return open_create(dev, (struct open **)&peropen->hook); - else - return 0; -} - -static void -close_hook(struct trivfs_peropen *peropen) -{ - if (peropen->hook) - open_free(peropen->hook); -} - -/* ---------------------------------------------------------------- */ -/* Trivfs hooks */ - -int trivfs_fstype = FSTYPE_DEV; -int trivfs_fsid = 0; - -int trivfs_support_read = 1; -int trivfs_support_write = 1; -int trivfs_support_exec = 0; - -int trivfs_allow_open = O_READ | O_WRITE; - -void -trivfs_modify_stat (struct trivfs_protid *cred, struct stat *st) -{ - struct open *open = cred->po->hook; - - if (open) - /* An open device. */ - { - struct dev *dev = open->dev; - vm_size_t size = dev->size; - - if (dev->block_size > 1) - st->st_blksize = dev->block_size; - - st->st_size = size; - st->st_blocks = size / 512; - - if (dev_is(dev, DEV_READONLY)) - st->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); - - st->st_mode &= ~S_IFMT; - st->st_mode |= dev_is(dev, DEV_BUFFERED) ? S_IFBLK : S_IFCHR; - } - else - /* Try and do things without an open device... */ - { - st->st_blksize = device_block_size; - st->st_size = 0; - st->st_blocks = 0; - st->st_mode &= ~S_IFMT; - st->st_mode |= (device_flags & DEV_BUFFERED) ? S_IFBLK : S_IFCHR; - if (device_flags & DEV_READONLY) - st->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); - } - - st->st_rdev = device_number; -} - -error_t -trivfs_goaway (struct trivfs_control *fsys, int flags) -{ - error_t err; - int force = (flags & FSYS_GOAWAY_FORCE); - int nosync = (flags & FSYS_GOAWAY_NOSYNC); - - mutex_lock(&device_lock); - - if (device == NULL) - exit (0); - - /* Wait until all pending rpcs are done. */ - err = ports_inhibit_class_rpcs (root_port_class); - if (err == EINTR || (err && !force)) - { - mutex_unlock (&device_lock); - return err; - } - - if (force && nosync) - /* Exit with extreme prejudice. */ - exit (0); - - if (!force && ports_count_class (root_port_class) > 0) - /* Still users, so don't exit. */ - goto busy; - - if (!nosync) - /* Sync the device here, if necessary, so that closing it won't result in - any I/O (which could get hung up trying to use one of our pagers). */ - dev_sync (device, 1); - - /* devpager_shutdown may sync the pagers as side-effect (if NOSYNC is 0), - so we put that first in this test. */ - if (dev_stop_paging (device, nosync) || force) - /* Bye-bye. */ - { - if (!nosync) - /* If NOSYNC is true, we don't close DEV, as that could cause data to - be written back. */ - dev_close (device); - exit (0); - } - - busy: - /* Allow normal operations to proceed. */ - ports_enable_class (root_port_class); - ports_resume_class_rpcs (root_port_class); - mutex_unlock(&device_lock); - - /* Complain that there are still users. */ - return EBUSY; -} - -/* If this variable is set, it is called every time an open happens. - UIDS, GIDS, and FLAGS are from the open; CNTL identifies the - node being opened. This call need not check permissions on the underlying - node. If the open call should block, then return EWOULDBLOCK. Other - errors are immediately reflected to the user. If O_NONBLOCK - is not set in FLAGS and EWOULDBLOCK is returned, then call - trivfs_complete_open when all pending open requests for this - file can complete. */ -error_t (*trivfs_check_open_hook)(struct trivfs_control *trivfs_control, - uid_t *uids, u_int nuids, - gid_t *gids, u_int ngids, - int flags) - = check_open_hook; - -/* If this variable is set, it is called every time a new peropen - structure is created and initialized. */ -error_t (*trivfs_peropen_create_hook)(struct trivfs_peropen *) = open_hook; - -/* If this variable is set, it is called every time a peropen structure - is about to be destroyed. */ -void (*trivfs_peropen_destroy_hook) (struct trivfs_peropen *) = close_hook; - -/* Sync this filesystem. */ -kern_return_t -trivfs_S_fsys_syncfs (struct trivfs_control *cntl, - mach_port_t reply, mach_msg_type_name_t replytype, - int wait, int dochildren) -{ - struct dev *dev = device; - if (dev) - return dev_sync(dev, wait); - else - return 0; -} diff --git a/devio/devpager.c b/devio/devpager.c deleted file mode 100644 index 1f3b3ee1..00000000 --- a/devio/devpager.c +++ /dev/null @@ -1,257 +0,0 @@ -/* A pager interface for raw mach devices. - - Copyright (C) 1995 Free Software Foundation, Inc. - - Written by Miles Bader <miles@gnu.ai.mit.edu> - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include <hurd.h> -#include <hurd/pager.h> -#include <device/device.h> -#include <assert.h> - -#include "dev.h" - -/* ---------------------------------------------------------------- */ -/* Pager library callbacks; see <hurd/pager.h> for more info. */ - -/* For pager PAGER, read one page from offset PAGE. Set *BUF to be the - address of the page, and set *WRITE_LOCK if the page must be provided - read-only. The only permissable error returns are EIO, EDQUOT, and - ENOSPC. */ -error_t -pager_read_page(struct user_pager_info *upi, - vm_offset_t page, vm_address_t *buf, int *writelock) -{ - error_t err; - int read; /* bytes actually read */ - int want = vm_page_size; /* bytes we want to read */ - struct dev *dev = (struct dev *)upi; - - if (page + want > dev->size) - /* Read a partial page if necessary to avoid reading off the end. */ - want = dev->size - page; - - err = device_read(dev->port, 0, page / dev->dev_block_size, want, - (io_buf_ptr_t *)buf, &read); - - if (!err && want < vm_page_size) - /* Zero anything we didn't read. Allocation only happens in page-size - multiples, so we know we can write there. */ - bzero((char *)*buf + want, vm_page_size - want); - - *writelock = (dev->flags & DEV_READONLY); - - if (err || read < want) - return EIO; - else - return 0; -} - -/* For pager PAGER, synchronously write one page from BUF to offset PAGE. In - addition, vm_deallocate (or equivalent) BUF. The only permissable error - returns are EIO, EDQUOT, and ENOSPC. */ -error_t -pager_write_page(struct user_pager_info *upi, - vm_offset_t page, vm_address_t buf) -{ - struct dev *dev = (struct dev *)upi; - - if (dev->flags & DEV_READONLY) - return EROFS; - else - { - error_t err; - int written; - int want = vm_page_size; - - if (page + want > dev->size) - /* Write a partial page if necessary to avoid reading off the end. */ - want = dev->size - page; - - err = device_write(dev->port, 0, page / dev->dev_block_size, - (io_buf_ptr_t)buf, want, &written); - - vm_deallocate(mach_task_self(), buf, vm_page_size); - - if (err || written < want) - return EIO; - else - return 0; - } -} - -/* A page should be made writable. */ -error_t -pager_unlock_page(struct user_pager_info *upi, vm_offset_t address) -{ - struct dev *dev = (struct dev *)upi; - - if (dev->flags & DEV_READONLY) - return EROFS; - else - return 0; -} - -/* The user must define this function. It should report back (in - *OFFSET and *SIZE the minimum valid address the pager will accept - and the size of the object. */ -error_t -pager_report_extent(struct user_pager_info *upi, - vm_address_t *offset, vm_size_t *size) -{ - *offset = 0; - *size = ((struct dev *)upi)->size; - return 0; -} - -/* This is called when a pager is being deallocated after all extant send - rights have been destroyed. */ -void -pager_clear_user_data(struct user_pager_info *upi) -{ -} - -/* ---------------------------------------------------------------- */ - -/* A top-level function for the paging thread that just services paging - requests. */ -static void -service_paging_requests (any_t arg) -{ - struct dev *dev = (struct dev *)arg; - for (;;) - ports_manage_port_operations_multithread (dev->pager_port_bucket, - pager_demuxer, - 1000 * 30, 1000 * 60 * 5, - 1, MACH_PORT_NULL); -} - -/* Initialize paging for this device. */ -static void -init_dev_paging (struct dev *dev) -{ - dev->pager_port_bucket = ports_create_bucket (); - - /* Make a thread to service paging requests. */ - cthread_detach (cthread_fork ((cthread_fn_t)service_paging_requests, - (any_t)dev)); -} - -void -pager_dropweak (struct user_pager_info *upi __attribute__ ((unused))) -{ -} - -/* ---------------------------------------------------------------- */ - -/* Try to stop all paging activity on DEV, returning true if we were - successful. If NOSYNC is true, then we won't write back any (kernel) - cached pages to the device. */ -int -dev_stop_paging (struct dev *dev, int nosync) -{ - int success = 1; /* Initially assume success. */ - - io_state_lock(&dev->io_state); - - if (dev->pager != NULL) - { - int num_pagers = ports_count_bucket (dev->pager_port_bucket); - if (num_pagers > 0 && !nosync) - { - error_t block_cache (void *arg) - { - struct pager *p = arg; - pager_change_attributes (p, 0, MEMORY_OBJECT_COPY_DELAY, 1); - return 0; - } - error_t enable_cache (void *arg) - { - struct pager *p = arg; - pager_change_attributes (p, 1, MEMORY_OBJECT_COPY_DELAY, 0); - return 0; - } - - /* Loop through the pagers and turn off caching one by one, - synchronously. That should cause termination of each pager. */ - ports_bucket_iterate (dev->pager_port_bucket, block_cache); - - /* Give it a second; the kernel doesn't actually shutdown - immediately. XXX */ - sleep (1); - - num_pagers = ports_count_bucket (dev->pager_port_bucket); - if (num_pagers > 0) - /* Darn, there are actual honest users. Turn caching back on, - and return failure. */ - { - ports_bucket_iterate (dev->pager_port_bucket, enable_cache); - success = 0; - } - } - - if (success && !nosync) - /* shutdown the pager on DEV. If NOSYNC is set, we don't bother, for - fear that this may result in I/O. In this case we've disabled - rpcs on the pager's ports, so this will result in hanging... What - do we do??? XXXX */ - pager_shutdown (dev->pager); - } - - if (success) - dev->pager = NULL; - - io_state_lock(&dev->io_state); - - return success; -} - -/* ---------------------------------------------------------------- */ - -/* Returns in MEMOBJ the port for a memory object backed by the storage on - DEV. Returns 0 or the error code if an error occurred. */ -error_t -dev_get_memory_object(struct dev *dev, memory_object_t *memobj) -{ - if (dev_is(dev, DEV_SERIAL)) - return ENODEV; - - io_state_lock(&dev->io_state); - if (dev->pager_port_bucket == NULL) - init_dev_paging (dev); - if (dev->pager == NULL) - dev->pager = - pager_create((struct user_pager_info *)dev, dev->pager_port_bucket, - 1, MEMORY_OBJECT_COPY_DELAY); - else - ports_port_ref (dev->pager); - io_state_unlock(&dev->io_state); - - if (dev->pager == NULL) - return ENODEV; /* XXX ??? */ - - *memobj = pager_get_port(dev->pager); - ports_port_deref (dev->pager); /* Drop our original ref on PAGER. */ - - if (*memobj != MACH_PORT_NULL) - return - mach_port_insert_right(mach_task_self(), - *memobj, *memobj, - MACH_MSG_TYPE_MAKE_SEND); - - return 0; -} diff --git a/devio/io.c b/devio/io.c deleted file mode 100644 index 61f655d2..00000000 --- a/devio/io.c +++ /dev/null @@ -1,396 +0,0 @@ -/* Implements the hurd io interface to devio. - - Copyright (C) 1995, 1996 Free Software Foundation, Inc. - - Written by Miles Bader <miles@gnu.ai.mit.edu> - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include <hurd.h> -#include <hurd/ports.h> -#include <hurd/trivfs.h> -#include <stdio.h> -#include <fcntl.h> - -#include "open.h" -#include "dev.h" -#include "iostate.h" - -/* ---------------------------------------------------------------- */ - -/* Return objects mapping the data underlying this memory object. If - the object can be read then memobjrd will be provided; if the - object can be written then memobjwr will be provided. For objects - where read data and write data are the same, these objects will be - equal, otherwise they will be disjoint. Servers are permitted to - implement io_map but not io_map_cntl. Some objects do not provide - mapping; they will set none of the ports and return an error. Such - objects can still be accessed by io_read and io_write. */ -kern_return_t -trivfs_S_io_map(struct trivfs_protid *cred, - memory_object_t *rdobj, - mach_msg_type_name_t *rdtype, - memory_object_t *wrobj, - mach_msg_type_name_t *wrtype) -{ - if (!cred) - return EOPNOTSUPP; - else - { - mach_port_t memobj; - struct open *open = (struct open *)cred->po->hook; - error_t err = dev_get_memory_object(open->dev, &memobj); - - if (!err) - { - if (cred->po->openmodes & O_READ) - { - *rdobj = memobj; - *rdtype = MACH_MSG_TYPE_MOVE_SEND; - } - else - *rdobj = MACH_PORT_NULL; - - if (cred->po->openmodes & O_WRITE) - { - *wrobj = memobj; - *wrtype = MACH_MSG_TYPE_MOVE_SEND; - } - else - *wrobj = MACH_PORT_NULL; - } - - return err; - } -} - -/* ---------------------------------------------------------------- */ - -/* Read data from an IO object. If offset if -1, read from the object - maintained file pointer. If the object is not seekable, offset is - ignored. The amount desired to be read is in AMT. */ -kern_return_t -trivfs_S_io_read(struct trivfs_protid *cred, - mach_port_t reply, mach_msg_type_name_t replytype, - vm_address_t *data, - mach_msg_type_number_t *datalen, - off_t offs, - mach_msg_type_number_t amt) -{ - if (!cred) - return EOPNOTSUPP; - else if (!(cred->po->openmodes & O_READ)) - return EBADF; - else - return open_read((struct open *)cred->po->hook, data, datalen, amt, offs); -} - -/* ---------------------------------------------------------------- */ - -/* Tell how much data can be read from the object without blocking for - a "long time" (this should be the same meaning of "long time" used - by the nonblocking flag. */ -kern_return_t -trivfs_S_io_readable (struct trivfs_protid *cred, - mach_port_t reply, mach_msg_type_name_t replytype, - mach_msg_type_number_t *amount) -{ - if (!cred) - return EOPNOTSUPP; - else if (!(cred->po->openmodes & O_READ)) - return EINVAL; - else - { - struct open *open = (struct open *)cred->po->hook; - struct dev *dev = open->dev; - vm_offset_t location = open_get_io_state(open)->location; - *amount = dev->size - location; - return 0; - } -} - -/* ---------------------------------------------------------------- */ - -/* Change current read/write offset */ -kern_return_t -trivfs_S_io_seek (struct trivfs_protid *cred, - mach_port_t reply, mach_msg_type_name_t replytype, - off_t offs, int whence, off_t *new_offs) -{ - if (!cred) - return EOPNOTSUPP; - else - return open_seek ((struct open *)cred->po->hook, offs, whence, new_offs); -} - -/* ---------------------------------------------------------------- */ - -/* SELECT_TYPE is the bitwise OR of SELECT_READ, SELECT_WRITE, and SELECT_URG. - Block until one of the indicated types of i/o can be done "quickly", and - return the types that are then available. */ -kern_return_t -trivfs_S_io_select (struct trivfs_protid *cred, - mach_port_t reply, mach_msg_type_name_t replytype, - int *type) -{ - if (!cred) - return EOPNOTSUPP; - else if (((*type & SELECT_READ) && !(cred->po->openmodes & O_READ)) - || ((*type & SELECT_WRITE) && !(cred->po->openmodes & O_WRITE))) - return EBADF; - else - *type &= ~SELECT_URG; - return 0; -} - -/* ---------------------------------------------------------------- */ - -/* Write data to an IO object. If offset is -1, write at the object - maintained file pointer. If the object is not seekable, offset is - ignored. The amount successfully written is returned in amount. A - given user should not have more than one outstanding io_write on an - object at a time; servers implement congestion control by delaying - responses to io_write. Servers may drop data (returning ENOBUFS) - if they recevie more than one write when not prepared for it. */ -kern_return_t -trivfs_S_io_write (struct trivfs_protid *cred, - mach_port_t reply, mach_msg_type_name_t replytype, - vm_address_t data, mach_msg_type_number_t datalen, - off_t offs, mach_msg_type_number_t *amt) -{ - if (!cred) - return EOPNOTSUPP; - else if (!(cred->po->openmodes & O_WRITE)) - return EBADF; - else - return open_write((struct open *)cred->po->hook, data, datalen, amt, offs); -} - -/* ---------------------------------------------------------------- */ - -/* Truncate file. */ -kern_return_t -trivfs_S_file_set_size (struct trivfs_protid *cred, - mach_port_t reply, mach_msg_type_name_t reply_type, - off_t size) -{ - if (!cred) - return EOPNOTSUPP; - else - return 0; -} - -/* ---------------------------------------------------------------- */ -/* These four routines modify the O_APPEND, O_ASYNC, O_FSYNC, and - O_NONBLOCK bits for the IO object. In addition, io_get_openmodes - will tell you which of O_READ, O_WRITE, and O_EXEC the object can - be used for. The O_ASYNC bit affects icky async I/O; good async - I/O is done through io_async which is orthogonal to these calls. */ - -kern_return_t -trivfs_S_io_get_openmodes (struct trivfs_protid *cred, - mach_port_t reply, mach_msg_type_name_t replytype, - int *bits) -{ - if (!cred) - return EOPNOTSUPP; - else - { - *bits = cred->po->openmodes; - return 0; - } -} - -error_t -trivfs_S_io_set_all_openmodes(struct trivfs_protid *cred, - mach_port_t reply, - mach_msg_type_name_t replytype, - int mode) -{ - if (!cred) - return EOPNOTSUPP; - else - return 0; -} - -kern_return_t -trivfs_S_io_set_some_openmodes (struct trivfs_protid *cred, - mach_port_t reply, - mach_msg_type_name_t replytype, - int bits) -{ - if (!cred) - return EOPNOTSUPP; - else - return 0; -} - -kern_return_t -trivfs_S_io_clear_some_openmodes (struct trivfs_protid *cred, - mach_port_t reply, - mach_msg_type_name_t replytype, - int bits) -{ - if (!cred) - return EOPNOTSUPP; - else - return 0; -} - -/* ---------------------------------------------------------------- */ -/* Get/set the owner of the IO object. For terminals, this affects - controlling terminal behavior (see term_become_ctty). For all - objects this affects old-style async IO. Negative values represent - pgrps. This has nothing to do with the owner of a file (as - returned by io_stat, and as used for various permission checks by - filesystems). An owner of 0 indicates that there is no owner. */ - -kern_return_t -trivfs_S_io_get_owner (struct trivfs_protid *cred, - mach_port_t reply, - mach_msg_type_name_t replytype, - pid_t *owner) -{ - if (!cred) - return EOPNOTSUPP; - else - { - struct open *open = (struct open *)cred->po->hook; - *owner = open->dev->owner; - return 0; - } -} - -kern_return_t -trivfs_S_io_mod_owner (struct trivfs_protid *cred, - mach_port_t reply, mach_msg_type_name_t replytype, - pid_t owner) -{ - if (!cred) - return EOPNOTSUPP; - else - { - struct open *open = (struct open *)cred->po->hook; - open->dev->owner = owner; - return 0; - } -} - - -/* ---------------------------------------------------------------- */ -/* File syncing operations; these all do the same thing, sync the underlying - device. */ - -kern_return_t -trivfs_S_file_sync (struct trivfs_protid *cred, - mach_port_t reply, mach_msg_type_name_t reply_type, - int wait) -{ - if (cred) - return dev_sync (((struct open *)cred->po->hook)->dev, wait); - else - return EOPNOTSUPP; -} - -kern_return_t -trivfs_S_file_syncfs (struct trivfs_protid *cred, - mach_port_t reply, mach_msg_type_name_t reply_type, - int wait, int dochildren) -{ - if (!cred) - return dev_sync (((struct open *)cred->po->hook)->dev, wait); - else - return EOPNOTSUPP; -} - -error_t -trivfs_S_file_get_storage_info (struct trivfs_protid *cred, - mach_port_t reply, - mach_msg_type_name_t reply_type, - mach_port_t **ports, - mach_msg_type_name_t *ports_type, - mach_msg_type_number_t *num_ports, - int **ints, mach_msg_type_number_t *num_ints, - off_t **offsets, - mach_msg_type_number_t *num_offsets, - char **data, mach_msg_type_number_t *data_len) -{ - error_t err = 0; - - if (!cred) - err = EOPNOTSUPP; - else - { - /* True when we've allocated memory for the corresponding vector. */ - int al_ports = 0, al_ints = 0, al_offsets = 0, al_data = 0; - -#define ENSURE_MEM(v, vl, alp, num) \ - if (!err && *vl < num) \ - { \ - err = vm_allocate (mach_task_self (), \ - (vm_address_t *)v, num * sizeof (**v), 1); \ - if (! err) \ - { \ - *vl = num; \ - alp = 1; \ - } \ - } - - ENSURE_MEM (ports, num_ports, al_ports, 1); - ENSURE_MEM (ints, num_ints, al_ints, 6); - ENSURE_MEM (offsets, num_offsets, al_offsets, 2); - ENSURE_MEM (data, data_len, al_data, 1); - - if (! err) - { - struct dev *dev = ((struct open *)cred->po->hook)->dev; - (*ints)[0] = STORAGE_DEVICE; /* type */ - (*ints)[1] = 0; /* flags */ - (*ints)[2] = dev->dev_block_size; /* block_size */ - (*ints)[3] = 1; /* num_runs */ - (*ints)[4] = strlen (dev->name) + 1; /* name_len */ - (*ints)[5] = 0; /* misc_len */ - *num_ints = 6; - - (*offsets)[0] = 0; - (*offsets)[1] = dev->size / dev->dev_block_size; - *num_offsets = 2; - - strcpy (*data, dev->name); - *data_len = strlen (dev->name) + 1; - - if (cred->isroot) - (*ports)[0] = dev->port; - else - (*ports)[0] = MACH_PORT_NULL; - *num_ports = 1; - *ports_type = MACH_MSG_TYPE_COPY_SEND; - } - else - /* Some memory allocation failed (not bloody likely). */ - { -#define DISCARD_MEM(v, vl, alp) \ - if (alp) \ - vm_deallocate (mach_task_self (), (vm_address_t)*v, *vl * sizeof (**v)); - - DISCARD_MEM (ports, num_ports, al_ports); - DISCARD_MEM (ints, num_ints, al_ints); - DISCARD_MEM (offsets, num_offsets, al_offsets); - DISCARD_MEM (data, data_len, al_data); - } - } - - return err; -} diff --git a/devio/iostate.c b/devio/iostate.c deleted file mode 100644 index fe40fcd2..00000000 --- a/devio/iostate.c +++ /dev/null @@ -1,79 +0,0 @@ -/* State for an I/O stream. - - Copyright (C) 1995 Free Software Foundation, Inc. - - Written by Miles Bader <miles@gnu.ai.mit.edu> - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include <hurd.h> - -#include "iostate.h" -#include "dev.h" - -/* ---------------------------------------------------------------- */ - -/* Initialize the io_state structure IOS to be used with the device DEV. If - a memory allocation error occurs, ENOMEM is returned, otherwise 0. */ -error_t -io_state_init(struct io_state *ios, struct dev *dev) -{ - error_t err = - vm_allocate(mach_task_self(), - (vm_address_t *)&ios->buffer, dev->block_size, 1); - - ios->location = 0; - ios->buffer_size = dev->block_size; - ios->buffer_use = 0; - mutex_init(&ios->lock); - - return err; -} - -/* Frees all resources used by IOS. */ -void -io_state_finalize(struct io_state *ios) -{ - vm_deallocate(mach_task_self(), (vm_address_t)ios->buffer, ios->buffer_size); -} - -/* If IOS's location isn't block aligned because writes have been buffered - there, then sync the whole buffer out to the device. Any error that - occurs while writing is returned, otherwise 0. */ -error_t -io_state_sync(struct io_state *ios, struct dev *dev) -{ - error_t err = 0; - - if (ios->buffer_use == IO_STATE_BUFFERED_WRITE) - { - vm_offset_t pos = ios->location; - int block_offs = pos % dev->block_size; - - if (block_offs > 0) - { - bzero((char *)ios->buffer + block_offs, - dev->block_size - block_offs); - ios->location -= block_offs; - err = - dev_write(dev, ios->buffer, dev->block_size, &ios->location); - } - - /* Remember that there's nothing left in the buffer. */ - ios->buffer_use = 0; - } - - return err; -} diff --git a/devio/iostate.h b/devio/iostate.h deleted file mode 100644 index 1795e153..00000000 --- a/devio/iostate.h +++ /dev/null @@ -1,67 +0,0 @@ -/* State for an I/O stream. - - Copyright (C) 1995 Free Software Foundation, Inc. - - Written by Miles Bader <miles@gnu.ai.mit.edu> - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#ifndef __IOSTATE_H__ -#define __IOSTATE_H__ - -/* ---------------------------------------------------------------- */ - -enum io_state_buffer_use -{ - /* 0 means nothing */ - IO_STATE_BUFFERED_WRITE = 1, IO_STATE_BUFFERED_READ = 2 -}; - -struct io_state { - /* What we think the current position is. */ - vm_offset_t location; - - /* The buffer in which we accumulate buffered i/o. */ - vm_address_t buffer; - /* The size of BUFFER. */ - vm_size_t buffer_size; - - /* If LOCATION is not a multiple of the block size (and so points somewhere - in the middle of BUFFER), this indicates why. */ - enum io_state_buffer_use buffer_use; - - /* Lock this if you want to read/modify LOCATION or BUFFER. */ - struct mutex lock; -}; - -#define io_state_lock(ios) mutex_lock(&(ios)->lock) -#define io_state_unlock(ios) mutex_unlock(&(ios)->lock) - -/* Declare this to keep the parameter scope below sane. */ -struct dev; - -/* Initialize the io_state structure IOS to be used with the device DEV. If - a memory allocation error occurs, ENOMEM is returned, otherwise 0. */ -error_t io_state_init(struct io_state *ios, struct dev *dev); - -/* Frees all resources used by IOS. */ -void io_state_finalize(struct io_state *ios); - -/* If IOS's location isn't block aligned because writes have been buffered - there, then sync the whole buffer out to the device. Any error that - occurs while writing is returned, otherwise 0. */ -error_t io_state_sync(struct io_state *ios, struct dev *dev); - -#endif /* !__IOSTATE_H__ */ diff --git a/devio/mem.c b/devio/mem.c deleted file mode 100644 index 65caa19f..00000000 --- a/devio/mem.c +++ /dev/null @@ -1,57 +0,0 @@ -/* Some random handy ops for dealing with rpcs that return memory. - - Copyright (C) 1995 Free Software Foundation, Inc. - - Written by Miles Bader <miles@gnu.ai.mit.edu> - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include <hurd.h> -#include <string.h> - -/* ---------------------------------------------------------------- */ - -/* Makes sure that BUF, points to a buffer with AMOUNT bytes available. - *BUF_LEN should be the current length of *BUF, and if this isn't enough to - hold AMOUNT bytes, then more is allocated and the new buffer is returned - in *BUF and *BUF_LEN. If a memory allocation error occurs, the error code - is returned, otherwise 0. */ -error_t -allocate(vm_address_t *buf, vm_size_t *buf_len, vm_size_t amount) -{ - if (*buf_len < amount) - { - error_t err = vm_allocate(mach_task_self(), buf, amount, 1); - if (err) - return err; - } - - *buf_len = amount; - return 0; -} - -/* Deallocates any pages entirely within the last EXCESS bytes of the BUF_LEN - long buffer, BUF. */ -error_t -deallocate_excess(vm_address_t buf, vm_size_t buf_len, vm_size_t excess) -{ - vm_size_t excess_pages = buf_len - round_page(buf_len - excess); - if (excess_pages > 0) - return - vm_deallocate(mach_task_self(), - round_page(buf + buf_len - excess), excess_pages); - else - return 0; -} diff --git a/devio/mem.h b/devio/mem.h deleted file mode 100644 index e19b590c..00000000 --- a/devio/mem.h +++ /dev/null @@ -1,33 +0,0 @@ -/* Some random handy memory ops that know about VM. - - Copyright (C) 1995 Free Software Foundation, Inc. - - Written by Miles Bader <miles@gnu.ai.mit.edu> - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/* For bcopy &c. */ -#include <string.h> - -/* Makes sure that BUF, points to a buffer with AMOUNT bytes available. - *BUF_LEN should be the current length of *BUF, and if this isn't enough to - hold AMOUNT bytes, then more is allocated and the new buffer is returned - in *BUF and *BUF_LEN. If a memory allocation error occurs, the error code - is returned, otherwise 0. */ -error_t allocate(vm_address_t *buf, vm_size_t *buf_len, vm_size_t amount); - -/* Deallocates any pages entirely within the last EXCESS bytes of the BUF_LEN - long buffer, BUF. */ -error_t deallocate_excess(vm_address_t buf, vm_size_t buf_len, vm_size_t excess); diff --git a/devio/open.c b/devio/open.c deleted file mode 100644 index bab4fe99..00000000 --- a/devio/open.c +++ /dev/null @@ -1,90 +0,0 @@ -/* Per-open information for devio. - - Copyright (C) 1995 Free Software Foundation, Inc. - - Written by Miles Bader <miles@gnu.ai.mit.edu> - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include <hurd.h> - -#include "open.h" -#include "window.h" -#include "dev.h" - -/* ---------------------------------------------------------------- */ - -/* Returns a new per-open structure for the device DEV in OPEN. If an error - occurs, the error-code is returned, otherwise 0. */ -error_t -open_create(struct dev *dev, struct open **open) -{ - error_t err; - - *open = malloc(sizeof(struct open)); - - if (*open == NULL) - return ENOMEM; - - (*open)->dev = dev; - - err = io_state_init(&(*open)->io_state, dev); - - if (!err && dev_is(dev, DEV_BUFFERED) && !dev_is(dev, DEV_SERIAL)) - /* A random-access buffered device -- use a pager to do i/o to it. */ - { - mach_port_t memobj; - err = dev_get_memory_object(dev, &memobj); - if (!err) - err = - window_create(memobj, dev->size, 0, 0, dev_is(dev, DEV_READONLY), - &(*open)->window); /* XXX sizes */ - if (err) - { - mach_port_destroy(mach_task_self(), memobj); - io_state_finalize(&(*open)->io_state); - } - } - else - (*open)->window = NULL; - - if (err) - free(*open); - - return err; -} - -/* ---------------------------------------------------------------- */ - -/* Free OPEN and any resources it holds. */ -void -open_free(struct open *open) -{ - io_state_finalize(&open->io_state); - window_free(open->window); - free(open); -} - - -/* ---------------------------------------------------------------- */ - -/* Returns the appropiate io_state object for OPEN (which may be either - per-open or a per-device depending on the device). */ -struct io_state * -open_get_io_state(struct open *open) -{ - return - dev_is(open->dev, DEV_SERIAL) ? &open->dev->io_state : &open->io_state; -} diff --git a/devio/open.h b/devio/open.h deleted file mode 100644 index 80763585..00000000 --- a/devio/open.h +++ /dev/null @@ -1,73 +0,0 @@ -/* Per-open information for devio. - - Copyright (C) 1995 Free Software Foundation, Inc. - - Written by Miles Bader <miles@gnu.ai.mit.edu> - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#ifndef __OPEN_H__ -#define __OPEN_H__ - -#include "iostate.h" - -/* ---------------------------------------------------------------- */ - -/* A structure describing a particular i/o stream on this device. */ -struct open -{ - /* Current state of our output stream -- location and the buffer used to do - buffered i/o. */ - struct io_state io_state; - - /* The memory window we're using to do i/o. This may be NULL, indicating - we're not doing buffered random access i/o. */ - struct window *window; - - /* The device that this an open on. */ - struct dev *dev; -}; - -/* Returns a new per-open structure for the device DEV in OPEN. If an error - occurs, the error-code is returned, otherwise 0. */ -error_t open_create(struct dev *dev, struct open **open); - -/* Free OPEN and any resources it holds. */ -void open_free(struct open *open); - -/* Returns the appropiate io_state object for OPEN (which may be either - per-open or a per-device depending on the device). */ -struct io_state *open_get_io_state(struct open *open); - -/* Writes up to LEN bytes from BUF to OPEN's device at device offset OFFS - (which may be ignored if the device doesn't support random access), - and returns the number of bytes written in AMOUNT. If no error occurs, - zero is returned, otherwise the error code is returned. */ -error_t open_write(struct open *open, vm_address_t buf, vm_size_t len, - vm_size_t *amount, off_t offs); - -/* Reads up to AMOUNT bytes from the device into BUF and BUF_LEN using the - standard mach out-array convention. If no error occurs, zero is returned, - otherwise the error code is returned. */ -error_t open_read(struct open *open, vm_address_t *buf, vm_size_t *buf_len, - vm_size_t amount, off_t offs); - -/* Set OPEN's location to OFFS, interpreted according to WHENCE as by seek. - The new absolute location is returned in NEW_OFFS (and may not be the same - as OFFS). If no error occurs, zero is returned, otherwise the error code - is returned. */ -error_t open_seek (struct open *open, off_t offs, int whence, off_t *new_offs); - -#endif /* !__OPEN_H__ */ diff --git a/devio/ptypes.h b/devio/ptypes.h deleted file mode 100644 index 64aa3b0d..00000000 --- a/devio/ptypes.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Libports port types for devio. - - Copyright (C) 1995 Free Software Foundation, Inc. - - Written by Miles Bader <miles@gnu.ai.mit.edu> - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#define PT_FSYS 0 -#define PT_NODE 1 -#define PT_MEMOBJ 2 diff --git a/devio/rdwr.c b/devio/rdwr.c deleted file mode 100644 index 67f087a0..00000000 --- a/devio/rdwr.c +++ /dev/null @@ -1,471 +0,0 @@ -/* Implements various types of I/O on top of raw devices. - - Copyright (C) 1995 Free Software Foundation, Inc. - - Written by Miles Bader <miles@gnu.ai.mit.edu> - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include <hurd.h> -#include <assert.h> -#include <string.h> - -#include "open.h" -#include "dev.h" -#include "mem.h" -#include "window.h" - -/* ---------------------------------------------------------------- */ - -/* Writes BUF to DEV, copying through an intermediate buffer to page-align - it. If STAGING_BUF isn't 0, it is used as the copy buffer for - small-enough transfers (staging_buf is assumed to be one block in length). - AMOUNT is the actual amount written, and LEN is the amount of source - material actually in BUF; if LEN is smaller than AMOUNT, the remainder is - zero. */ -static error_t -copying_block_write(struct dev *dev, vm_address_t staging_buf, - vm_address_t buf, vm_size_t len, vm_size_t amount, - vm_offset_t *offs) -{ - error_t err = 0; - vm_address_t copy_buf = staging_buf; - vm_size_t copy_buf_len = dev->block_size; - - if (amount > dev->block_size || staging_buf == 0) - { - copy_buf_len = amount; - err = vm_allocate(mach_task_self(), ©_buf, copy_buf_len, 1); - if (err) - return err; - } - - bcopy((char *)buf, (char *)copy_buf, len); - if (len < amount && copy_buf == staging_buf) - /* We need to zero the rest of the bloc, but only if we didn't - vm_allocate it (in which case it will be zero-filled). */ - bzero((char *)buf + len, amount - len); - - err = dev_write(dev, copy_buf, amount, offs); - - if (copy_buf != staging_buf) - vm_deallocate(mach_task_self(), copy_buf, copy_buf_len); - - return err; -} - -/* ---------------------------------------------------------------- */ - -/* Copies LEN bytes from BUF to DEV, using STAGING_BUF to do buffering of - partial blocks, and returning the amount actually written in AMOUNT. - *OFFS is incremented to reflect the amount read/written. If an error - occurs, the error code is returned, otherwise 0. */ -error_t -buffered_write(struct dev *dev, vm_address_t staging_buf, - vm_address_t buf, vm_size_t len, vm_size_t *amount, - vm_offset_t *offs) -{ - error_t err = 0; - int bsize = dev->block_size; - int staging_buf_loc = *offs % bsize; - int left_in_staging_buf = bsize - staging_buf_loc; - vm_offset_t start_offs = *offs; - - if (left_in_staging_buf > 0) - /* Write what's buffered from the last I/O. */ - { - /* Amount of the current i/o we can put in the staging buffer. */ - int stage = (left_in_staging_buf > len ? len : left_in_staging_buf); - - bcopy((char *)buf, (char *)staging_buf + staging_buf_loc, stage); - - buf += stage; - len -= stage; - *offs += stage; - - if (stage == left_in_staging_buf) - /* We've filled up STAGING_BUF so we can write it out now. */ - { - /* Backup OFFS to reflect the beginning-of-block position. */ - *offs -= bsize; - err = dev_write(dev, staging_buf, bsize, offs); - } - } - - if (!err && len > bsize) - /* Enough i/o pending to do whole block transfers. */ - { - /* The number of bytes at the end of the transfer that aren't a - multiple of the block-size. We have to deal with these separately - because device i/o must be in block multiples. */ - int excess = len % bsize; - vm_size_t block_len = len - excess; - - if (dev_write_valid(dev, buf, block_len, offs)) - /* BUF is page-aligned, so we can do i/o directly to the device, or - it is small enough that it doesn't matter. */ - err = dev_write(dev, buf, block_len, offs); - else - /* Argh! BUF isn't page aligned! We must filter the i/o though an - intermediate buffer... */ - err = copying_block_write(dev, staging_buf, - buf, block_len, block_len, offs); - - if (*offs - start_offs < left_in_staging_buf + block_len) - /* Didn't write out all the blocks, so suppress buffering the rest. */ - len = 0; - else - len = excess; - } - - /* At this point, LEN should be < BLOCK_SIZE, so we use buffering again. */ - if (!err && len > 0) - { - bcopy((char *)staging_buf, (char *)buf, len); - *offs += len; - } - - *amount = *offs - start_offs; - if (*amount > 0) - /* If an error occurred, but we successfully wrote *something*, then - pretend nothing bad happened; the error will probably get caught next - time. */ - err = 0; - - return err; -} - -/* ---------------------------------------------------------------- */ - -/* Reads AMOUNT bytes from DEV and returns them in BUF and BUF_LEN (using the - standard mach out-array conventions), using STAGING_BUF to do buffering of - partial blocks. *OFFS is incremented to reflect the amount read/written. - If an error occurs, the error code is returned, otherwise 0. */ -error_t -buffered_read (struct dev *dev, vm_address_t staging_buf, - vm_address_t *buf, vm_size_t *buf_len, vm_size_t amount, - vm_offset_t *offs) -{ - error_t err = 0; - int bsize = dev->block_size; - vm_offset_t start_offs = *offs; - int staging_buf_loc = *offs % bsize; - int from_staging_buf = bsize - staging_buf_loc; - vm_address_t block_buf = *buf; - vm_size_t block_buf_size = *buf_len; - vm_size_t block_amount = amount; - - if (staging_buf_loc > 0) - { - /* Read into a temporary buffer. */ - block_buf = 0; - block_buf_size = 0; - - if (from_staging_buf > amount) - from_staging_buf = amount; - - block_amount -= from_staging_buf; - } - else - from_staging_buf = 0; - - /* Read any new block required. */ - if (block_amount > 0) - { - /* We read enough to get every full block of BLOCK_AMOUNT, plus an - additional whole block if there's any more; we just copy any excess - from that last block into STAGING_BUF for next time. */ - block_amount = ((block_amount + bsize - 1) / bsize) * bsize; - - err = dev_read(dev, &block_buf, &block_buf_size, block_amount, offs); - if (err && staging_buf_loc > 0) - /* We got an error, but don't abort, since we did get the bit from - the buffer. */ - { - err = 0; - amount = from_staging_buf; - block_amount = 0; - } - - if (amount > *offs - start_offs) - /* If we read less than we hoped, reflect this down below. */ - amount = *offs - start_offs; - } - - if (staging_buf_loc > 0) - /* Coalesce what we have in STAGING_BUF with what we read. */ - { - err = allocate(buf, buf_len, amount); - assert_perror(err); - bcopy((char *)staging_buf + staging_buf_loc, (char *)*buf, - from_staging_buf); - - if (block_amount > 0) - bcopy((char *)block_buf, (char *)*buf + from_staging_buf, - amount - from_staging_buf); - } - else - /* Otherwise, BLOCK_BUF should already contain the correct data. */ - { - *buf = block_buf; - *buf_len = block_buf_size; - } - - if (*offs - start_offs > amount) - /* We've read too far, so put some amount from the end back into - STAGING_BUF. */ - { - int excess = (*offs - start_offs) - amount; - - bcopy((char *)block_buf + amount, - (char *)staging_buf + bsize - excess, - excess); - *offs -= excess; - - if (excess >= vm_page_size) - deallocate_excess(*buf, *buf_len, excess); - *buf_len -= excess; - } - - /* Deallocate any extra copy buffer if necessary. */ - if (*buf != block_buf) - vm_deallocate(mach_task_self(), block_buf, block_buf_size); - - return err; -} - -/* ---------------------------------------------------------------- */ - -/* Write BUF_LEN bytes from BUF to DEV, padding with zeros as necessary to - write whole blocks, and returning the amount actually written in AMOUNT. - If successful, 0 is returned, otherwise an error code is returned. *OFFS - is incremented by the change in device location. */ -error_t -raw_write(struct dev *dev, - vm_address_t buf, vm_size_t buf_len, - vm_size_t *amount, vm_offset_t *offs) -{ - error_t err; - int bsize = dev->block_size; - int block_amount = ((buf_len + bsize - 1) / bsize) * bsize; - vm_offset_t start_offs = *offs; - - if (start_offs % bsize != 0) - return EINVAL; - - if (block_amount == buf_len && dev_write_valid(dev, buf, block_amount, offs)) - /* BUF is page-aligned, so we can do i/o directly to the device, or - it is small enough that it doesn't matter. */ - err = dev_write(dev, buf, block_amount, offs); - else - /* Argh! BUF isn't page aligned! We must filter the i/o though an - intermediate buffer... [We use DEV's io_state buffer, as we know - that the io_state is locked in open_rdwr, and it isn't otherwise - used...] */ - err = copying_block_write(dev, dev->io_state.buffer, - buf, buf_len, block_amount, offs); - - if (!err && *offs - start_offs < buf_len) - *amount = *offs - start_offs; - else - *amount = buf_len; - - return err; -} - -/* Read AMOUNT bytes from DEV into BUF and BUF_LEN; only whole blocks are - read, but anything greater than *AMOUNT bytes is discarded. The standard - mach out-array convention is used to return the data in BUF and BUF_LEN. - If successful, 0 is returned, otherwise an error code is returned. *OFFS - is incremented by the change in device location. */ -error_t -raw_read(struct dev *dev, - vm_address_t *buf, vm_size_t *buf_len, - vm_size_t amount, vm_offset_t *offs) -{ - error_t err; - int bsize = dev->block_size; - int block_amount = ((amount + bsize - 1) / bsize) * bsize; - - if (*offs % bsize != 0) - return EINVAL; - - err = dev_read(dev, buf, buf_len, block_amount, offs); - if (!err) - { - int excess = *buf_len - amount; - if (excess > vm_page_size) - deallocate_excess(*buf, *buf_len, excess); - if (excess > 0) - *buf_len = amount; - } - - return err; -} - -/* ---------------------------------------------------------------- */ - -struct rdwr_state -{ - struct dev *dev; - off_t user_offs; - vm_offset_t *offs_p; - struct io_state *io_state; -}; - -/* Setup state needed for I/O to/from OPEN, putting it into STATE. OFFS - should be the original user-supplied offset. */ -static void -rdwr_state_init(struct rdwr_state *state, struct open *open, off_t offs) -{ - state->dev = open->dev; - state->io_state = open_get_io_state(open); - state->user_offs = offs; - - if (dev_is(state->dev, DEV_SERIAL)) - /* For serial i/o, we always ignore the proffered offs, and use the - actual device offset. */ - state->user_offs = -1; - - if (state->user_offs == -1 || !dev_is(state->dev, DEV_BUFFERED)) - /* If we're going to use some bit of IO_STATE, lock it first. This - should only not happen if we're going to used windowed i/o with an - explicit offset. */ - io_state_lock(state->io_state); - - if (state->user_offs == -1) - state->offs_p = &state->io_state->location; - else - state->offs_p = (vm_offset_t *)&state->user_offs; -} - -/* Destroy any state created by rdwr_state_init. */ -static void -rdwr_state_finalize(struct rdwr_state *state) -{ - if (state->user_offs == -1 || !dev_is(state->dev, DEV_BUFFERED)) - io_state_unlock(state->io_state); -} - -/* ---------------------------------------------------------------- */ - -/* Writes up to LEN bytes from BUF to OPEN's device at device offset OFFS - (which may be ignored if the device doesn't support random access), - and returns the number of bytes written in AMOUNT. If no error occurs, - zero is returned, otherwise the error code is returned. */ -error_t -open_write(struct open *open, vm_address_t buf, vm_size_t len, - vm_size_t *amount, off_t offs) -{ - error_t err; - struct rdwr_state state; - struct dev *dev = open->dev; - - rdwr_state_init(&state, open, offs); - - offs = *state.offs_p; - if (offs < 0) - err = EINVAL; - if (offs + len > dev->size) - err = EIO; - else if (!dev_is(dev, DEV_BUFFERED)) - err = raw_write(dev, buf, len, amount, state.offs_p); - else if (dev_is(dev, DEV_SERIAL)) - { - state.io_state->buffer_use = IO_STATE_BUFFERED_WRITE; - err = buffered_write(dev, state.io_state->buffer, buf, len, - amount, state.offs_p); - } - else - err = window_write(open->window, buf, len, amount, state.offs_p); - - rdwr_state_finalize(&state); - - return err; -} - -/* Reads up to AMOUNT bytes from the device into BUF and BUF_LEN using the - standard mach out-array convention. If no error occurs, zero is returned, - otherwise the error code is returned. */ -error_t -open_read(struct open *open, vm_address_t *buf, vm_size_t *buf_len, - vm_size_t amount, off_t offs) -{ - error_t err; - struct rdwr_state state; - struct dev *dev = open->dev; - - rdwr_state_init(&state, open, offs); - - offs = *state.offs_p; - if (offs < 0) - err = EINVAL; - if (offs + amount > dev->size) - err = EIO; - else if (!dev_is(dev, DEV_BUFFERED)) - err = raw_read(dev, buf, buf_len, amount, state.offs_p); - else if (dev_is(dev, DEV_SERIAL)) - { - state.io_state->buffer_use = IO_STATE_BUFFERED_READ; - err = buffered_read(dev, state.io_state->buffer, buf, buf_len, - amount, state.offs_p); - } - else - err = window_read(open->window, buf, buf_len, amount, state.offs_p); - - rdwr_state_finalize(&state); - - return err; -} - -/* Set OPEN's location to OFFS, interpreted according to WHENCE as by seek. - The new absolute location is returned in NEW_OFFS (and may not be the same - as OFFS). If no error occurs, zero is returned, otherwise the error code - is returned. */ -error_t -open_seek (struct open *open, off_t offs, int whence, off_t *new_offs) -{ - error_t err = 0; - struct io_state *io_state = open_get_io_state (open); - - if (!dev_is (open->dev, DEV_SEEKABLE)) - return ESPIPE; - - io_state_lock (io_state); - - switch (whence) - { - case SEEK_SET: - *new_offs = offs; break; - case SEEK_CUR: - *new_offs = io_state->location + offs; break; - case SEEK_END: - *new_offs = open->dev->size - offs; break; - default: - err = EINVAL; - } - - if (!err) - { - if (!dev_is (open->dev, DEV_BUFFERED)) - /* On unbuffered devices force seeks to the nearest block boundary. */ - *new_offs -= *new_offs % open->dev->block_size; - io_state->location = *new_offs; - } - - io_state_unlock (io_state); - - return err; -} diff --git a/devio/window.c b/devio/window.c deleted file mode 100644 index f7df045d..00000000 --- a/devio/window.c +++ /dev/null @@ -1,171 +0,0 @@ -/* Window management routines for buffered I/O using VM. - - Copyright (C) 1995 Free Software Foundation, Inc. - - Written by Miles Bader <miles@gnu.ai.mit.edu> - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include <hurd.h> - -#include "window.h" -#include "mem.h" - -/* ---------------------------------------------------------------- */ - -/* Create a VM window onto the memory object MEMOBJ, and return it in WIN. - MIN_SIZE and MAX_SIZE are the minimum and maximum sizes that the window - will shrink/grow to (a value of 0 will use some default). */ -error_t -window_create(mach_port_t memobj, vm_offset_t max_pos, - vm_size_t min_size, vm_size_t max_size, int read_only, - struct window **win) -{ - *win = malloc(sizeof(struct window)); - if (*win == NULL) - return ENOMEM; - - if (min_size < max_size) - min_size = max_size; - - (*win)->pos = 0; - (*win)->max_pos = max_pos; - (*win)->size = 0; - (*win)->memobj = memobj; - (*win)->min_size = (min_size < vm_page_size ? vm_page_size : min_size); - (*win)->max_size = (max_size < vm_page_size ? vm_page_size : max_size); - (*win)->read_only = read_only; - - return 0; -} - -/* Free WIN and any resources it holds. */ -void -window_free(struct window *win) -{ - if (win->size > 0) - vm_deallocate(mach_task_self(), win->buffer, win->size); - mach_port_destroy(mach_task_self(), win->memobj); - free(win); -} - -/* ---------------------------------------------------------------- */ - -/* Makes sure that WIN's memory window contains at least positions POS - through POS + LEN on the device WIN's mapping. If an error occurs in the - process, the error code is returned (and WIN may not map the desired - locations), otherwise 0. WIN is assumed to already be locked when this is - called. */ -static error_t -position(struct window *win, vm_offset_t pos, vm_size_t len) -{ - vm_offset_t end = pos + len; - vm_offset_t win_beg = win->pos; - vm_offset_t win_end = win_beg + win->size; - - if (pos >= win_beg && end <= win_end) - /* The request is totally satisfied by our current position. */ - return 0; - else -#if 0 /* XXXXXXX */ - if (end < win_beg || pos >= win_end) - /* The desired locations are entirely outside our current window, so just - trash it, and map a new buffer anywhere. */ -#endif - { - int prot = VM_PROT_READ | (win->read_only ? 0 : VM_PROT_WRITE); - - if (win->size > 0) - vm_deallocate(mach_task_self(), win->buffer, win->size); - - win->pos = trunc_page(pos); - win->size = round_page(len + (pos - win->pos)); - win->buffer = 0; - - if (win->size < win->min_size) - win->size = win->min_size; - - if (win->pos + win->size > win->max_pos) - win->size = win->max_pos - win->pos; - - return - vm_map(mach_task_self(), &win->buffer, win->size, 0, 1, - win->memobj, win->pos, 0, prot, prot, VM_INHERIT_NONE); - } - - return 0; -} - -/* ---------------------------------------------------------------- */ - -/* Write up to BUF_LEN bytes from BUF to the device that WIN is a window on, - at offset *OFFS, using memory-mapped buffered I/O. If successful, 0 is - returned, otherwise an error code is returned. *OFFS is incremented by - the amount sucessfully written. */ -error_t -window_write(struct window *win, - vm_address_t buf, vm_size_t buf_len, vm_size_t *amount, - vm_offset_t *offs) -{ - error_t err; - - mutex_lock(&win->lock); - - err = position(win, *offs, buf_len); - if (!err) - { - bcopy((char *)buf, - (char *)win->buffer + (*offs - win->pos), - buf_len); - *amount = buf_len; - *offs += buf_len; - } - - mutex_unlock(&win->lock); - - return err; -} - -/* Read up to AMOUNT bytes from the device that WIN is a window on, at offset - *OFFS, into BUF and BUF_LEN (using the standard mach out-array - conventions), using memory-mapped buffered I/O. If successful, 0 is - returned, otherwise an error code is returned. *OFFS is incremented by - the amount sucessfully written. */ -error_t -window_read(struct window *win, - vm_address_t *buf, vm_size_t *buf_len, - vm_size_t amount, vm_offset_t *offs) -{ - error_t err; - - mutex_lock(&win->lock); - - err = position(win, *offs, amount); - if (!err) - { - err = allocate(buf, buf_len, amount); - if (!err) - { - bcopy((char *)win->buffer + (*offs - win->pos), - (char *)*buf, - amount); - *offs += amount; - } - } - - mutex_unlock(&win->lock); - - return err; -} diff --git a/devio/window.h b/devio/window.h deleted file mode 100644 index c15ebd9e..00000000 --- a/devio/window.h +++ /dev/null @@ -1,84 +0,0 @@ -/* Window management routines for buffered I/O using VM. - - Copyright (C) 1995 Free Software Foundation, Inc. - - Written by Miles Bader <miles@gnu.ai.mit.edu> - - This program 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#ifndef __WINDOW_H__ -#define __WINDOW_H__ - -#include <mach.h> - -/* ---------------------------------------------------------------- */ - -/* A structure describing a memory window used to do buffered random access - device i/o through the device pager. */ -struct window -{ - /* The currently allocated vm window backed by the device pager. */ - vm_address_t buffer; - - /* The device offset of the window. */ - vm_offset_t pos; - /* The end of the device. */ - vm_offset_t max_pos; - - /* The length of the window (should be a multiple of __vm_page_size). If - this is 0, this window isn't allocated. */ - vm_size_t size; - /* If SIZE < MIN_SIZE we won't shrink the window. */ - vm_size_t min_size; - /* If SIZE > MAX_SIZE, we'll try and shrink the window to fit. */ - vm_size_t max_size; - - /* The device pager providing backing store for this window. */ - mach_port_t memobj; - /* True if the mapping should be read_only. */ - int read_only; - - /* Lock this if you want to read/write some field(s) here. */ - struct mutex lock; -}; - -/* Create a VM window onto the memory object MEMOBJ, and return it in WIN. - MIN_SIZE and MAX_SIZE are the minimum and maximum sizes that the window - will shrink/grow to. */ -error_t window_create(mach_port_t memobj, vm_offset_t max_pos, - vm_size_t min_size, vm_size_t max_size, int read_only, - struct window **win); - -/* Free WIN and any resources it holds. */ -void window_free(struct window *win); - -/* Write up to BUF_LEN bytes from BUF to the device that WIN is a window on, - at offset *OFFS, using memory-mapped buffered I/O. If successful, 0 is - returned, otherwise an error code is returned. *OFFS is incremented by - the amount sucessfully written. */ -error_t window_write(struct window *win, - vm_address_t buf, vm_size_t buf_len, vm_size_t *amount, - vm_offset_t *offs); - -/* Read up to AMOUNT bytes from the device that WIN is a window on, at offset - *OFFS, into BUF and BUF_LEN (using the standard mach out-array - conventions), using memory-mapped buffered I/O. If successful, 0 is - returned, otherwise an error code is returned. *OFFS is incremented by - the amount sucessfully written. */ -error_t window_read(struct window *win, - vm_address_t *buf, vm_size_t *buf_len, - vm_size_t amount, vm_offset_t *offs); - -#endif /* !__WINDOW_H__ */ |