summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Brinkmann <marcus@gnu.org>2002-11-20 19:31:08 +0000
committerThomas Schwinge <tschwinge@gnu.org>2009-06-17 23:50:21 +0200
commit0f6d506d705226d2f87830e0fa9ea83d733a444e (patch)
tree30e39f10bde9782890adc4caaa6d8b945e323c76
parent4aaa0c775232b8a111baa004e51f9f0da2a33e35 (diff)
2002-11-20 Marcus Brinkmann <marcus@gnu.org>
* i386/i386/io_perm.c (io_perm_device_ops): New static variable. (i386_io_perm_create): Use the io_perm_device_ops for the device. (i386_io_perm_modify): Check that this is really an io_perm device. * iopb.h, iopb.c: Obsolete files removed.
-rw-r--r--ChangeLog7
-rw-r--r--i386/i386/io_perm.c10
-rw-r--r--i386/i386/iopb.c614
-rw-r--r--i386/i386/iopb.h61
4 files changed, 14 insertions, 678 deletions
diff --git a/ChangeLog b/ChangeLog
index cf663c96..90d1fafb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2002-11-20 Marcus Brinkmann <marcus@gnu.org>
+
+ * i386/i386/io_perm.c (io_perm_device_ops): New static variable.
+ (i386_io_perm_create): Use the io_perm_device_ops for the device.
+ (i386_io_perm_modify): Check that this is really an io_perm device.
+ * iopb.h, iopb.c: Obsolete files removed.
+
2002-11-12 Roland McGrath <roland@frob.com>
* oskit/ds_routines.c (dev_open_com): Revert last change.
diff --git a/i386/i386/io_perm.c b/i386/i386/io_perm.c
index ba5df707..5ad565d9 100644
--- a/i386/i386/io_perm.c
+++ b/i386/i386/io_perm.c
@@ -62,12 +62,15 @@
#include "io_perm.h"
#include "gdt.h"
-
/* XXX From oskit/ds_routines.c */
device_t dev_open_alloc (void);
void setup_no_senders (device_t dev);
+/* We use our own device ops to identify an io_perm pseudo device. */
+static struct device_ops io_perm_device_ops;
+
+
/* The outtran which allows MiG to convert an io_perm_t object to a port
representing it. */
ipc_port_t
@@ -144,7 +147,7 @@ i386_io_perm_create (ipc_port_t master_port, io_port_t from, io_port_t to,
/* Set up the dummy device. */
(*new)->com_device = 0;
(*new)->mode = 0;
- (*new)->ops = &no_device_ops;
+ (*new)->ops = &io_perm_device_ops;
setup_no_senders ((device_t) *new);
(*new)->com.io_perm.from = from;
@@ -173,7 +176,8 @@ i386_io_perm_modify (task_t target_task, io_perm_t io_perm, boolean_t enable)
unsigned char *iopb;
io_port_t iopb_size;
- if (target_task == TASK_NULL || (device_t) io_perm == DEVICE_NULL)
+ if (target_task == TASK_NULL || (device_t) io_perm == DEVICE_NULL
+ || ((device_t) io_perm)->ops != &io_perm_device_ops)
return KERN_INVALID_ARGUMENT;
from = io_perm->com.io_perm.from;
diff --git a/i386/i386/iopb.c b/i386/i386/iopb.c
deleted file mode 100644
index a955b28a..00000000
--- a/i386/i386/iopb.c
+++ /dev/null
@@ -1,614 +0,0 @@
-/*
- * Mach Operating System
- * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-/*
- * Code to manipulate IO permission bitmaps.
- */
-
-#include <mach/boolean.h>
-#include <mach/kern_return.h>
-
-#include <ipc/ipc_port.h>
-
-#include <kern/kalloc.h>
-#include <kern/lock.h>
-#include <kern/queue.h>
-#include <kern/thread.h>
-
-#include <device/dev_hdr.h>
-
-#include "io_port.h"
-#include "iopb.h"
-#include "gdt.h"
-
-/*
- * A set of ports for an IO device.
- */
-struct io_port {
- device_t device; /* Mach device */
- queue_chain_t dev_list; /* link in device list */
- queue_chain_t io_use_list; /* List of threads that use it */
- io_reg_t *io_port_list; /* list of IO ports that use it */
- /* list ends with IO_REG_NULL */
-};
-typedef struct io_port *io_port_t;
-
-/*
- * Lookup table for device -> io_port mapping
- * (a linked list - I don't expect too many)
- */
-queue_head_t device_to_io_port_list;
-
-/*
- * Cross-reference:
- * all threads that have IO ports mapped
- * all IO ports that have threads mapped
- */
-struct io_use {
- queue_chain_t psq; /* Links from port set */
- queue_chain_t tsq; /* links from tss */
- io_port_t ps; /* Port set */
- iopb_tss_t ts; /* Task segment */
-};
-typedef struct io_use *io_use_t;
-
-/*
- * Big lock for the whole mess.
- */
-decl_simple_lock_data(, iopb_lock)
-
-/*
- * Initialize the package.
- */
-void
-iopb_init(void)
-{
- queue_init(&device_to_io_port_list);
- simple_lock_init(&iopb_lock);
-}
-
-/*
- * Initialize bitmap (set all bits to OFF == 1)
- */
-void
-io_bitmap_init(
- isa_iopb bp,
- boolean_t on_off)
-{
- register unsigned char *b = bp;
- register int s;
- unsigned char c;
-
- /*
- * Disallow access to ports 0x00 .. 0xff
- */
- for (s = 0; s < (0xff+1)/8; s++) {
- *b++ = ~0; /* no access */
- }
-
- if (on_off)
- c = 0;
- else
- c = ~0;
-
- for (; s < sizeof(isa_iopb); s++) {
- *b++ = c;
- }
-}
-
-/*
- * Set selected bits in bitmap to ON == 0
- */
-void
-io_bitmap_set(
- isa_iopb bp,
- io_reg_t *bit_list)
-{
- io_reg_t io_bit;
-
- while ((io_bit = *bit_list++) != IO_REG_NULL) {
- bp[io_bit>>3] &= ~(1 << (io_bit & 0x7));
- }
-}
-
-/*
- * Set selected bits in bitmap to OFF == 1
- */
-void
-io_bitmap_clear(
- isa_iopb bp,
- io_reg_t *bit_list)
-{
- io_reg_t io_bit;
-
- while ((io_bit = *bit_list++) != IO_REG_NULL) {
- bp[io_bit>>3] |= (1 << (io_bit & 0x7));
- }
-}
-
-/*
- * Lookup an io-port set by device
- */
-io_port_t
-device_to_io_port_lookup(
- device_t device)
-{
- register io_port_t io_port;
-
- queue_iterate(&device_to_io_port_list, io_port, io_port_t, dev_list) {
- if (io_port->device == device) {
- return io_port;
- }
- }
- return 0;
-}
-
-/*
- * [exported]
- * Create an io_port set
- */
-void
-io_port_create(
- device_t device,
- io_reg_t *io_port_list)
-{
- register io_port_t io_port;
-
- io_port = (io_port_t) kalloc(sizeof(struct io_port));
-
- simple_lock(&iopb_lock);
- if (device_to_io_port_lookup(device) != 0) {
- simple_unlock(&iopb_lock);
- kfree((vm_offset_t) io_port, sizeof(struct io_port));
- return;
- }
-
- io_port->device = device;
- queue_init(&io_port->io_use_list);
- io_port->io_port_list = io_port_list;
-
- /*
- * Enter in lookup list.
- */
- queue_enter(&device_to_io_port_list, io_port, io_port_t, dev_list);
-
- simple_unlock(&iopb_lock);
-}
-
-/*
- * [exported]
- * Destroy an io port set, removing any IO mappings.
- */
-void
-io_port_destroy(
- device_t device)
-{
- io_port_t io_port;
- io_use_t iu;
-
- simple_lock(&iopb_lock);
- io_port = device_to_io_port_lookup(device);
- if (io_port == 0) {
- simple_unlock(&iopb_lock);
- return;
- }
-
- queue_iterate(&io_port->io_use_list, iu, io_use_t, psq) {
- iopb_tss_t io_tss;
- io_tss = iu->ts;
- io_bitmap_clear(io_tss->bitmap, io_port->io_port_list);
- queue_remove(&io_tss->io_port_list, iu, io_use_t, tsq);
- }
- queue_remove(&device_to_io_port_list, io_port, io_port_t, dev_list);
- simple_unlock(&iopb_lock);
-
- while (!queue_empty(&io_port->io_use_list)) {
- iu = (io_use_t) queue_first(&io_port->io_use_list);
- queue_remove(&io_port->io_use_list, iu, io_use_t, psq);
- kfree((vm_offset_t)iu, sizeof(struct io_use));
- }
-
- kfree((vm_offset_t)io_port, sizeof(struct io_port));
-}
-
-/*
- * Initialize an IO TSS.
- */
-void
-io_tss_init(
- iopb_tss_t io_tss,
- boolean_t access_all) /* allow access or not */
-{
- vm_offset_t addr = (vm_offset_t) io_tss;
- vm_size_t size = (char *)&io_tss->barrier - (char *)io_tss;
-
- bzero(&io_tss->tss, sizeof(struct x86_tss));
- io_tss->tss.io_bit_map_offset
- = (char *)&io_tss->bitmap - (char *)io_tss;
- io_tss->tss.ss0 = KERNEL_DS;
- io_bitmap_init(io_tss->bitmap, access_all);
- io_tss->barrier = ~0;
- queue_init(&io_tss->io_port_list);
- io_tss->iopb_desc[0] = ((size-1) & 0xffff)
- | ((addr & 0xffff) << 16);
- io_tss->iopb_desc[1] = ((addr & 0x00ff0000) >> 16)
- | ((ACC_TSS|ACC_PL_K|ACC_P) << 8)
- | ((size-1) & 0x000f0000)
- | (addr & 0xff000000);
-}
-
-/*
- * [exported]
- * Create an IOPB_TSS
- */
-iopb_tss_t
-iopb_create(void)
-{
- register iopb_tss_t ts;
-
- ts = (iopb_tss_t) kalloc(sizeof (struct iopb_tss));
- io_tss_init(ts, TRUE); /* XXX */
- return ts;
-}
-
-/*
- * [exported]
- * Destroy an IOPB_TSS
- */
-void
-iopb_destroy(
- iopb_tss_t io_tss)
-{
- io_use_t iu;
- io_port_t io_port;
-
- simple_lock(&iopb_lock);
-
- queue_iterate(&io_tss->io_port_list, iu, io_use_t, tsq) {
- io_port = iu->ps;
- /* skip bitmap clear - entire bitmap will vanish */
- queue_remove(&io_port->io_use_list, iu, io_use_t, psq);
- }
-
- simple_unlock(&iopb_lock);
-
- while (!queue_empty(&io_tss->io_port_list)) {
- iu = (io_use_t) queue_first(&io_tss->io_port_list);
- queue_remove(&io_tss->io_port_list, iu, io_use_t, tsq);
- kfree((vm_offset_t)iu, sizeof(struct io_use));
- }
-
- kfree((vm_offset_t)io_tss, sizeof(struct iopb_tss));
-}
-
-/*
- * Add an IO mapping to a thread.
- */
-kern_return_t
-i386_io_port_add(
- thread_t thread,
- device_t device)
-{
- pcb_t pcb;
- iopb_tss_t io_tss, new_io_tss;
- io_port_t io_port;
- io_use_t iu, old_iu;
-
- if (thread == THREAD_NULL
- || device == DEVICE_NULL)
- return KERN_INVALID_ARGUMENT;
-
- pcb = thread->pcb;
-
- new_io_tss = 0;
- iu = (io_use_t) kalloc(sizeof(struct io_use));
-
- Retry:
- simple_lock(&iopb_lock);
-
- /* find the io_port_t for the device */
- io_port = device_to_io_port_lookup(device);
- if (io_port == 0) {
- /*
- * Device does not have IO ports available.
- */
- simple_unlock(&iopb_lock);
- if (new_io_tss)
- kfree((vm_offset_t)new_io_tss, sizeof(struct iopb_tss));
- kfree((vm_offset_t) iu, sizeof(struct io_use));
- return KERN_INVALID_ARGUMENT;
- }
-
- /* Have the IO port. */
-
- /* Make sure the thread has a TSS. */
-
- simple_lock(&pcb->lock);
- io_tss = pcb->ims.io_tss;
- if (io_tss == 0) {
- if (new_io_tss == 0) {
- /*
- * Allocate an IO-tss.
- */
- simple_unlock(&pcb->lock);
- simple_unlock(&iopb_lock);
-
- new_io_tss = (iopb_tss_t) kalloc(sizeof(struct iopb_tss));
- io_tss_init(new_io_tss, TRUE); /* XXX */
-
- goto Retry;
- }
- io_tss = new_io_tss;
- pcb->ims.io_tss = io_tss;
- new_io_tss = 0;
- }
-
- /*
- * Have io_port and io_tss.
- * See whether device is already mapped.
- */
- queue_iterate(&io_tss->io_port_list, old_iu, io_use_t, tsq) {
- if (old_iu->ps == io_port) {
- /*
- * Already mapped.
- */
- simple_unlock(&pcb->lock);
- simple_unlock(&iopb_lock);
-
- kfree((vm_offset_t)iu, sizeof(struct io_use));
- if (new_io_tss)
- kfree((vm_offset_t)new_io_tss, sizeof(struct iopb_tss));
- return KERN_SUCCESS;
- }
- }
-
- /*
- * Add mapping.
- */
- iu->ps = io_port;
- iu->ts = io_tss;
- queue_enter(&io_port->io_use_list, iu, io_use_t, psq);
- queue_enter(&io_tss->io_port_list, iu, io_use_t, tsq);
- io_bitmap_set(io_tss->bitmap, io_port->io_port_list);
-
- simple_unlock(&pcb->lock);
- simple_unlock(&iopb_lock);
-
- if (new_io_tss)
- kfree((vm_offset_t)new_io_tss, sizeof(struct iopb_tss));
- return KERN_SUCCESS;
-
-}
-
-/*
- * Remove an IO mapping from a thread.
- */
-kern_return_t
-i386_io_port_remove(thread, device)
- thread_t thread;
- device_t device;
-{
- pcb_t pcb;
- iopb_tss_t io_tss;
- io_port_t io_port;
- io_use_t iu;
-
- if (thread == THREAD_NULL
- || device == DEVICE_NULL)
- return KERN_INVALID_ARGUMENT;
-
- pcb = thread->pcb;
-
- simple_lock(&iopb_lock);
-
- /* find the io_port_t for the device */
-
- io_port = device_to_io_port_lookup(device);
- if (io_port == 0) {
- /*
- * Device does not have IO ports available.
- */
- simple_unlock(&iopb_lock);
- return KERN_INVALID_ARGUMENT;
- }
-
- simple_lock(&pcb->lock);
- io_tss = pcb->ims.io_tss;
- if (io_tss == 0) {
- simple_unlock(&pcb->lock);
- simple_unlock(&iopb_lock);
- return KERN_INVALID_ARGUMENT; /* not mapped */
- }
-
- /*
- * Find the mapping.
- */
- queue_iterate(&io_tss->io_port_list, iu, io_use_t, tsq) {
- if (iu->ps == io_port) {
- /*
- * Found mapping. Remove it.
- */
- io_bitmap_clear(io_tss->bitmap, io_port->io_port_list);
-
- queue_remove(&io_port->io_use_list, iu, io_use_t, psq);
- queue_remove(&io_tss->io_port_list, iu, io_use_t, tsq);
-
- simple_unlock(&pcb->lock);
- simple_unlock(&iopb_lock);
-
- kfree((vm_offset_t)iu, sizeof(struct io_use));
-
- return KERN_SUCCESS;
- }
- }
-
- /*
- * No mapping.
- */
- return KERN_INVALID_ARGUMENT;
-}
-
-/*
- * Return the IO ports mapped into a thread.
- */
-extern ipc_port_t mach_convert_device_to_port(/* device_t */);
-
-kern_return_t
-i386_io_port_list(thread, list, list_count)
- thread_t thread;
- device_t **list;
- unsigned int *list_count;
-{
- register pcb_t pcb;
- register iopb_tss_t io_tss;
- unsigned int count, alloc_count;
- device_t *devices;
- vm_size_t size_needed, size;
- vm_offset_t addr;
- int i;
-
- if (thread == THREAD_NULL)
- return KERN_INVALID_ARGUMENT;
-
- pcb = thread->pcb;
-
- alloc_count = 16; /* a guess */
-
- do {
- size_needed = alloc_count * sizeof(ipc_port_t);
- if (size_needed <= size)
- break;
-
- if (size != 0)
- kfree(addr,size);
-
- assert(size_needed > 0);
- size = size_needed;
-
- addr = kalloc(size);
- if (addr == 0)
- return KERN_RESOURCE_SHORTAGE;
-
- devices = (device_t *)addr;
- count = 0;
-
- simple_lock(&iopb_lock);
- simple_lock(&pcb->lock);
- io_tss = pcb->ims.io_tss;
- if (io_tss != 0) {
- register io_use_t iu;
-
- queue_iterate(&io_tss->io_port_list, iu, io_use_t, tsq) {
- if (++count < alloc_count) {
- *devices = iu->ps->device;
- device_reference(*devices);
- devices++;
- }
- }
- }
- simple_unlock(&pcb->lock);
- simple_unlock(&iopb_lock);
- } while (count > alloc_count);
-
- if (count == 0) {
- /*
- * No IO ports
- */
- *list = 0;
- *list_count = 0;
-
- if (size != 0)
- kfree(addr, size);
- }
- else {
- /*
- * If we allocated too much, must copy.
- */
- size_needed = count * sizeof(ipc_port_t);
- if (size_needed < size) {
- vm_offset_t new_addr;
-
- new_addr = kalloc(size_needed);
- if (new_addr == 0) {
- for (i = 0; i < count; i++)
- device_deallocate(devices[i]);
- kfree(addr, size);
- return KERN_RESOURCE_SHORTAGE;
- }
-
- bcopy((void *)addr, (void *)new_addr, size_needed);
- kfree(addr, size);
- devices = (device_t *)new_addr;
- }
-
- for (i = 0; i < count; i++)
- ((ipc_port_t *)devices)[i] =
- mach_convert_device_to_port(devices[i]);
- }
- *list = devices;
- *list_count = count;
-
- return KERN_SUCCESS;
-}
-
-/*
- * Check whether an IO device is mapped to a particular thread.
- * Used to support the 'iopl' device automatic mapping.
- */
-boolean_t
-iopb_check_mapping(thread, device)
- thread_t thread;
- device_t device;
-{
- pcb_t pcb;
- io_port_t io_port;
- io_use_t iu;
-
- pcb = thread->pcb;
-
- simple_lock(&iopb_lock);
-
- /* Find the io port for the device */
-
- io_port = device_to_io_port_lookup(device);
- if (io_port == 0) {
- simple_unlock(&iopb_lock);
- return FALSE;
- }
-
- /* Look up the mapping in the device`s mapping list. */
-
- queue_iterate(&io_port->io_use_list, iu, io_use_t, psq) {
- if (iu->ts == pcb->ims.io_tss) {
- /*
- * Device is mapped.
- */
- simple_unlock(&iopb_lock);
- return TRUE;
- }
- }
- simple_unlock(&iopb_lock);
- return FALSE;
-}
diff --git a/i386/i386/iopb.h b/i386/i386/iopb.h
deleted file mode 100644
index 483ab318..00000000
--- a/i386/i386/iopb.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Mach Operating System
- * Copyright (c) 1991,1990 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-#ifndef _I386_IOPB_H_
-#define _I386_IOPB_H_
-
-#include <oskit/x86/tss.h>
-#include <kern/queue.h>
-
-/*
- * IO permission bitmap.
- *
- * Allows only IO ports 0 .. 0x3ff: for ISA machines.
- */
-
-#define iopb_howmany(a,b) (((a)+(b)-1)/(b))
-
-#define IOPB_MAX 0xffff /* ISA bus allows ports 0..3ff */
- /* but accelerator cards are funky */
-#define IOPB_BYTES (iopb_howmany(IOPB_MAX+1,8))
-
-typedef unsigned char isa_iopb[IOPB_BYTES];
-
-/*
- * An IO permission map is a task segment with an IO permission bitmap.
- */
-
-struct iopb_tss {
- struct x86_tss tss; /* task state segment */
- isa_iopb bitmap; /* bitmap of mapped IO ports */
- unsigned int barrier; /* bitmap barrier for CPU slop */
- queue_head_t io_port_list; /* list of mapped IO ports */
- int iopb_desc[2]; /* descriptor for this TSS */
-};
-
-typedef struct iopb_tss *iopb_tss_t;
-
-#endif /* _I386_IOPB_H_ */