diff options
author | Marcus Brinkmann <marcus@gnu.org> | 2002-11-20 19:31:08 +0000 |
---|---|---|
committer | Thomas Schwinge <tschwinge@gnu.org> | 2009-06-17 23:50:21 +0200 |
commit | 0f6d506d705226d2f87830e0fa9ea83d733a444e (patch) | |
tree | 30e39f10bde9782890adc4caaa6d8b945e323c76 | |
parent | 4aaa0c775232b8a111baa004e51f9f0da2a33e35 (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-- | ChangeLog | 7 | ||||
-rw-r--r-- | i386/i386/io_perm.c | 10 | ||||
-rw-r--r-- | i386/i386/iopb.c | 614 | ||||
-rw-r--r-- | i386/i386/iopb.h | 61 |
4 files changed, 14 insertions, 678 deletions
@@ -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_ */ |