From 471d7380bd54c83cf6d090a144c288197b02db40 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Mon, 1 Feb 2010 15:13:08 +0100 Subject: check in libmachdev. --- libmachdev/ds_routines.c | 802 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 802 insertions(+) create mode 100644 libmachdev/ds_routines.c (limited to 'libmachdev/ds_routines.c') diff --git a/libmachdev/ds_routines.c b/libmachdev/ds_routines.c new file mode 100644 index 00000000..1cd06359 --- /dev/null +++ b/libmachdev/ds_routines.c @@ -0,0 +1,802 @@ +/* + * Mach Operating System + * Copyright (c) 1993,1991,1990,1989 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * Author: David B. Golub, Carnegie Mellon University + * Date: 3/89 + */ + +/* + * Mach device server routines (i386at version). + * + * Copyright (c) 1996 The University of Utah and + * the Computer Systems Laboratory at the University of Utah (CSL). + * All rights reserved. + * + * Permission to use, copy, modify and distribute this software is hereby + * granted provided that (1) source code retains these copyright, permission, + * and disclaimer notices, and (2) redistributions including binaries + * reproduce the notices in supporting documentation, and (3) all advertising + * materials mentioning features or use of this software display the following + * acknowledgement: ``This product includes software developed by the + * Computer Systems Laboratory at the University of Utah.'' + * + * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS + * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF + * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * CSL requests users of this software to return to csl-dist@cs.utah.edu any + * improvements that they make and grant CSL redistribution rights. + * + * Author: Shantanu Goel, University of Utah CSL + */ + +#include +#include +#include + +#include +#include +#include + +#include "vm_param.h" +#include "device_reply_U.h" +#include "io_req.h" +#include "dev_hdr.h" +#include "util.h" +#include "queue.h" + +struct port_bucket *port_bucket; +struct port_class *dev_class; + +extern struct device_emulation_ops linux_net_emulation_ops; + +#define NUM_EMULATION (sizeof (emulation_list) / sizeof (emulation_list[0])) + +/* List of emulations. */ +static struct device_emulation_ops *emulation_list[] = +{ + &linux_net_emulation_ops, +}; + +boolean_t is_master_device (mach_port_t port); + +static inline void +mach_device_deallocate (void *device) +{ + ports_port_deref (device); +} + +static inline void +mach_device_reference (mach_device_t device) +{ + ports_port_ref (device); +} + +static inline emul_device_t +mach_convert_port_to_device (device_t device) +{ + mach_device_t dev = ports_lookup_port (port_bucket, device, dev_class); + if (dev == NULL) + return NULL; + + return &dev->dev; +} + +static inline void * +device_to_pi (emul_device_t device) +{ + return ((void *) device) - (int) &((mach_device_t) 0)->dev; +} + +/* + * What follows is the interface for the native Mach devices. + */ + +static inline mach_port_t +mach_convert_device_to_port (mach_device_t device) +{ + if (device == NULL) + return MACH_PORT_NULL; + + // TODO I have to somehow dereference it when it is called at the first time. + return ports_get_right (device); +} + +/* Implementation of device interface */ +kern_return_t +ds_xxx_device_set_status (device_t device, dev_flavor_t flavor, + dev_status_t status, size_t statu_cnt) +{ + return D_INVALID_OPERATION; +} + +kern_return_t +ds_xxx_device_get_status (device_t device, dev_flavor_t flavor, + dev_status_t status, size_t *statuscnt) +{ + return D_INVALID_OPERATION; +} + +kern_return_t +ds_xxx_device_set_filter (device_t device, mach_port_t rec, + int pri, filter_array_t filt, size_t len) +{ + return D_INVALID_OPERATION; +} + +io_return_t +ds_device_intr_notify (mach_port_t master_port, int irq, + int id, mach_port_t receive_port) +{ + return D_INVALID_OPERATION; +} + +kern_return_t +ds_pci_write_config (mach_port_t master_port, char bus, char device_fn, + char where, pci_config_data_t data, + mach_msg_type_number_t dataCnt) +{ + return D_INVALID_OPERATION; +} + +kern_return_t +ds_pci_read_config (mach_port_t master_port, char bus, char device_fn, + char where, int bytes_wanted, pci_config_data_t result, + mach_msg_type_number_t *resultCnt) +{ + return D_INVALID_OPERATION; +} + +kern_return_t +ds_pci_find_device (mach_port_t master_port, short vendor, short device_id, + short index, short *bus, char *device_fn) +{ + return D_INVALID_OPERATION; +} + +kern_return_t +ds_pci_present (mach_port_t master_port) +{ + return D_INVALID_OPERATION; +} + +kern_return_t +ds_device_irq_enable (mach_port_t master_port, + int irq, char status) +{ + return D_INVALID_OPERATION; +} + +io_return_t +ds_device_open (mach_port_t open_port, mach_port_t reply_port, + mach_msg_type_name_t reply_port_type, dev_mode_t mode, + char *name, device_t *devp) +{ + int i; + io_return_t err; + + /* Open must be called on the master device port. */ + if (!is_master_device (open_port)) + return D_INVALID_OPERATION; + + /* There must be a reply port. */ + if (! MACH_PORT_VALID (reply_port)) + { + fprintf (stderr, "ds_* invalid reply port\n"); + return MIG_NO_REPLY; + } + + /* Call each emulation's open routine to find the device. */ + for (i = 0; i < NUM_EMULATION; i++) + { + err = (*emulation_list[i]->open) (reply_port, reply_port_type, + mode, name, devp); + if (err != D_NO_SUCH_DEVICE) + break; + } + + return err; +} + +io_return_t +ds_device_close (device_t dev) +{ + emul_device_t device; + io_return_t ret; + + /* Refuse if device is dead or not completely open. */ + if (dev == MACH_PORT_NULL) + return D_NO_SUCH_DEVICE; + + device = mach_convert_port_to_device (dev); + ret = (device->emul_ops->close + ? (*device->emul_ops->close) (device->emul_data) + : D_SUCCESS); + mach_device_deallocate (device_to_pi (device)); + + ports_port_deref (device_to_pi (device)); + return ret; +} + +io_return_t +ds_device_write (device_t dev, mach_port_t reply_port, + mach_msg_type_name_t reply_port_type, dev_mode_t mode, + recnum_t recnum, io_buf_ptr_t data, unsigned int count, + int *bytes_written) +{ + emul_device_t device; + io_return_t ret; + + /* Refuse if device is dead or not completely open. */ + if (dev == MACH_PORT_NULL) + return D_NO_SUCH_DEVICE; + + if (data == 0) + return D_INVALID_SIZE; + + device = mach_convert_port_to_device (dev); + + if (! device->emul_ops->write) + return D_INVALID_OPERATION; + + ret = (*device->emul_ops->write) (device->emul_data, reply_port, + reply_port_type, mode, recnum, + data, count, bytes_written); + ports_port_deref (device_to_pi (device)); + + return ret; +} + +io_return_t +ds_device_write_inband (device_t dev, mach_port_t reply_port, + mach_msg_type_name_t reply_port_type, + dev_mode_t mode, recnum_t recnum, + io_buf_ptr_inband_t data, unsigned count, + int *bytes_written) +{ + emul_device_t device; + io_return_t ret; + + /* Refuse if device is dead or not completely open. */ + if (dev == MACH_PORT_NULL) + return D_NO_SUCH_DEVICE; + + if (data == 0) + return D_INVALID_SIZE; + + device = mach_convert_port_to_device (dev); + + if (! device->emul_ops->write_inband) + return D_INVALID_OPERATION; + + ret = (*device->emul_ops->write_inband) (device->emul_data, reply_port, + reply_port_type, mode, recnum, + data, count, bytes_written); + ports_port_deref (device_to_pi (device)); + + return ret; +} + +io_return_t +ds_device_read (device_t dev, mach_port_t reply_port, + mach_msg_type_name_t reply_port_type, dev_mode_t mode, + recnum_t recnum, int count, io_buf_ptr_t *data, + unsigned *bytes_read) +{ + emul_device_t device; + io_return_t ret; + + /* Refuse if device is dead or not completely open. */ + if (dev == MACH_PORT_NULL) + return D_NO_SUCH_DEVICE; + + device = mach_convert_port_to_device (dev); + + if (! device->emul_ops->read) + return D_INVALID_OPERATION; + + ret = (*device->emul_ops->read) (device->emul_data, reply_port, + reply_port_type, mode, recnum, + count, data, bytes_read); + ports_port_deref (device_to_pi (device)); + return ret; +} + +io_return_t +ds_device_read_inband (device_t dev, mach_port_t reply_port, + mach_msg_type_name_t reply_port_type, dev_mode_t mode, + recnum_t recnum, int count, char *data, + unsigned *bytes_read) +{ + emul_device_t device; + io_return_t ret; + + /* Refuse if device is dead or not completely open. */ + if (dev == MACH_PORT_NULL) + return D_NO_SUCH_DEVICE; + + device = mach_convert_port_to_device (dev); + + if (! device->emul_ops->read_inband) + return D_INVALID_OPERATION; + + ret = (*device->emul_ops->read_inband) (device->emul_data, reply_port, + reply_port_type, mode, recnum, + count, data, bytes_read); + ports_port_deref (device_to_pi (device)); + return ret; +} + +io_return_t +ds_device_set_status (device_t dev, dev_flavor_t flavor, + dev_status_t status, mach_msg_type_number_t status_count) +{ + emul_device_t device; + io_return_t ret; + + /* Refuse if device is dead or not completely open. */ + if (dev == MACH_PORT_NULL) + return D_NO_SUCH_DEVICE; + + device = mach_convert_port_to_device (dev); + + if (! device->emul_ops->set_status) + return D_INVALID_OPERATION; + + ret = (*device->emul_ops->set_status) (device->emul_data, flavor, + status, status_count); + ports_port_deref (device_to_pi (device)); + return ret; +} + +io_return_t +ds_device_get_status (device_t dev, dev_flavor_t flavor, dev_status_t status, + mach_msg_type_number_t *status_count) +{ + emul_device_t device; + io_return_t ret; + + /* Refuse if device is dead or not completely open. */ + if (dev == MACH_PORT_NULL) + return D_NO_SUCH_DEVICE; + + device = mach_convert_port_to_device (dev); + + if (! device->emul_ops->get_status) + return D_INVALID_OPERATION; + + ret = (*device->emul_ops->get_status) (device->emul_data, flavor, + status, status_count); + ports_port_deref (device_to_pi (device)); + return ret; +} + +io_return_t +ds_device_set_filter (device_t dev, mach_port_t receive_port, int priority, + filter_t *filter, unsigned filter_count) +{ + emul_device_t device; + io_return_t ret; + + /* Refuse if device is dead or not completely open. */ + if (dev == MACH_PORT_NULL) + return D_NO_SUCH_DEVICE; + + device = mach_convert_port_to_device (dev); + + if (! device->emul_ops->set_filter) + return D_INVALID_OPERATION; + + ret = (*device->emul_ops->set_filter) (device->emul_data, receive_port, + priority, filter, filter_count); + ports_port_deref (device_to_pi (device)); + return ret; +} + +io_return_t +ds_device_map (device_t dev, vm_prot_t prot, vm_offset_t offset, + vm_size_t size, mach_port_t *pager, boolean_t unmap) +{ + /* Refuse if device is dead or not completely open. */ + if (dev == MACH_PORT_NULL) + return D_NO_SUCH_DEVICE; + + return D_INVALID_OPERATION; +} + +boolean_t +ds_open_done(ior) + register io_req_t ior; +{ + kern_return_t result; + register mach_device_t device; + + device = ior->io_device; + result = ior->io_error; + + if (result != D_SUCCESS) { + /* + * Open failed. Deallocate port and device. + */ +// dev_port_remove(device); +// ipc_port_dealloc_kernel(device->port); + + device_lock(device); + device->state = DEV_STATE_INIT; + if (device->io_wait) { + device->io_wait = FALSE; +// thread_wakeup((event_t)device); + } + device_unlock(device); + +// mach_device_deallocate(device); + device = MACH_DEVICE_NULL; + } + else { + /* + * Open succeeded. + */ + device_lock(device); + device->state = DEV_STATE_OPEN; + device->open_count = 1; + if (device->io_wait) { + device->io_wait = FALSE; +// thread_wakeup((event_t)device); + } + device_unlock(device); + + /* donate device reference to get port */ + } + /* + * Must explicitly convert device to port, since + * device_reply interface is built as 'user' side + * (thus cannot get translation). + */ + if (MACH_PORT_VALID(ior->io_reply_port)) { + (void) ds_device_open_reply(ior->io_reply_port, + ior->io_reply_port_type, + result, + mach_convert_device_to_port(device)); + } +// else +// mach_device_deallocate(device); + + mach_device_deallocate (device); + return (TRUE); +} + +boolean_t ds_read_done(ior) + io_req_t ior; +{ + vm_offset_t start_data, end_data; + vm_offset_t start_sent, end_sent; + register vm_size_t size_read; + + if (ior->io_error) + size_read = 0; + else + size_read = ior->io_count - ior->io_residual; + + start_data = (vm_offset_t)ior->io_data; + end_data = start_data + size_read; + + start_sent = (ior->io_op & IO_INBAND) ? start_data : + trunc_page(start_data); + end_sent = (ior->io_op & IO_INBAND) ? + start_data + ior->io_alloc_size : round_page(end_data); + + /* + * Zero memory that the device did not fill. + */ + if (start_sent < start_data) + memset((char *)start_sent, 0, start_data - start_sent); + if (end_sent > end_data) + memset((char *)end_data, 0, end_sent - end_data); + + + /* + * Touch the data being returned, to mark it dirty. + * If the pages were filled by DMA, the pmap module + * may think that they are clean. + */ + { + register vm_offset_t touch; + register int c; + + for (touch = start_sent; touch < end_sent; touch += PAGE_SIZE) { + c = *(volatile char *)touch; + *(volatile char *)touch = c; + } + } + + /* + * Send the data to the reply port - this + * unwires and deallocates it. + */ + if (ior->io_op & IO_INBAND) { + (void)ds_device_read_reply_inband(ior->io_reply_port, + ior->io_reply_port_type, + ior->io_error, + (char *) start_data, + size_read); + } else { +// vm_map_copy_t copy; +// kern_return_t kr; +// +// kr = vm_map_copyin_page_list(kernel_map, start_data, +// size_read, TRUE, TRUE, +// ©, FALSE); +// +// if (kr != KERN_SUCCESS) +// panic("read_done: vm_map_copyin_page_list failed"); + + (void)ds_device_read_reply(ior->io_reply_port, + ior->io_reply_port_type, + ior->io_error, + (char *) start_data, + size_read); + } + + /* + * Free any memory that was allocated but not sent. + */ + if (ior->io_count != 0) { + if (ior->io_op & IO_INBAND) { + if (ior->io_alloc_size > 0) + free (ior->io_data); +// zfree(io_inband_zone, (vm_offset_t)ior->io_data); + } else { + register vm_offset_t end_alloc; + + end_alloc = start_sent + round_page(ior->io_alloc_size); + if (end_alloc > end_sent) + vm_deallocate(mach_task_self (), + end_sent, + end_alloc - end_sent); + } + } + + mach_device_deallocate(ior->io_device); + + return (TRUE); +} + +/* + * Allocate wired-down memory for device read. + */ +kern_return_t device_read_alloc(ior, size) + register io_req_t ior; + register vm_size_t size; +{ + vm_offset_t addr; + kern_return_t kr; + + /* + * Nothing to do if no data. + */ + if (ior->io_count == 0) + return (KERN_SUCCESS); + + if (ior->io_op & IO_INBAND) { + ior->io_data = (io_buf_ptr_t) malloc(sizeof(io_buf_ptr_inband_t)); + ior->io_alloc_size = sizeof(io_buf_ptr_inband_t); + } else { + size = round_page(size); + kr = vm_allocate (mach_task_self (), &addr, size, TRUE); +// kr = kmem_alloc(kernel_map, &addr, size); + if (kr != KERN_SUCCESS) + return (kr); + + ior->io_data = (io_buf_ptr_t) addr; + ior->io_alloc_size = size; + } + + return (KERN_SUCCESS); +} + +struct thread_wait +{ + struct condition cond; + struct mutex mutex; + int v; +}; + +static struct thread_wait io_done_wait; + +void thread_wait_init (struct thread_wait *t) +{ + mutex_init (&t->mutex); + condition_init (&t->cond); + t->v = 0; +} + +void thread_block (struct thread_wait *t) +{ + mutex_lock (&t->mutex); + t->v = 1; + while (t->v) + hurd_condition_wait (&t->cond, &t->mutex); + mutex_unlock (&t->mutex); +} + +void thread_wakeup (struct thread_wait *t) +{ + mutex_lock (&t->mutex); + t->v = 0; + condition_signal (&t->cond); + mutex_unlock (&t->mutex); +} + +queue_head_t io_done_list; +struct mutex io_done_list_lock; + +#define splio splsched /* XXX must block ALL io devices */ + +void iodone(ior) + register io_req_t ior; +{ + /* + * If this ior was loaned to us, return it directly. + */ + if (ior->io_op & IO_LOANED) { + (*ior->io_done)(ior); + return; + } + /* + * If !IO_CALL, some thread is waiting for this. Must lock + * structure to interlock correctly with iowait(). Else can + * toss on queue for io_done thread to call completion. + */ + // TODO need a lock here? +// s = splio(); + if ((ior->io_op & IO_CALL) == 0) { + ior_lock(ior); + ior->io_op |= IO_DONE; + ior->io_op &= ~IO_WANTED; + ior_unlock(ior); +// thread_wakeup((event_t)ior); + } else { + ior->io_op |= IO_DONE; + mutex_lock (&io_done_list_lock); + enqueue_tail(&io_done_list, (queue_entry_t)ior); + thread_wakeup (&io_done_wait); +// thread_wakeup((event_t)&io_done_list); + mutex_unlock (&io_done_list_lock); + } +// splx(s); +} + +void wakeup_io_done_thread () +{ + thread_wakeup (&io_done_wait); +} + +void io_done_thread_continue() +{ + for (;;) { + extern void free_skbuffs (); + register io_req_t ior; + + free_skbuffs (); + mutex_lock(&io_done_list_lock); + while ((ior = (io_req_t)dequeue_head(&io_done_list)) != 0) { + mutex_unlock(&io_done_list_lock); + + if ((*ior->io_done)(ior)) { + /* + * IO done - free io_req_elt + */ + io_req_free(ior); + } + /* else routine has re-queued it somewhere */ + + mutex_lock(&io_done_list_lock); + } + +// assert_wait(&io_done_list, FALSE); + mutex_unlock(&io_done_list_lock); +// counter(c_io_done_thread_block++); +// thread_block(io_done_thread_continue); + thread_block (&io_done_wait); + } +} + + +void +wire_thread() +{ + kern_return_t kr; + mach_port_t priv_host_port; + + kr = get_privileged_ports (&priv_host_port, NULL); + if (kr != KERN_SUCCESS) + panic("get privileged port: %d", kr); + + kr = thread_wire(priv_host_port, + mach_thread_self(), + TRUE); + if (kr != KERN_SUCCESS) + panic("wire_thread: %d", kr); +} + +void +thread_set_own_priority (int priority) +{ + kern_return_t kr; + mach_port_t priv_host_port; + mach_port_t pset, psetcntl; + + kr = get_privileged_ports (&priv_host_port, NULL); + if (kr != KERN_SUCCESS) + panic("get privileged port: %d", kr); + + kr = thread_get_assignment (mach_thread_self (), &pset); + if (kr != KERN_SUCCESS) + panic("thread get assignment: %d", kr); + kr = host_processor_set_priv (priv_host_port, pset, &psetcntl); + if (kr != KERN_SUCCESS) + panic("processor set priv: %d", kr); + kr = thread_max_priority (mach_thread_self (), psetcntl, 0); + if (kr != KERN_SUCCESS) + panic("set thread max priority: %d", kr); + kr = thread_priority (mach_thread_self (), 0, FALSE); + if (kr != KERN_SUCCESS) + panic("set thread priority: %d", kr); +} + +static any_t io_done_thread(any_t unused) +{ + /* + * Set thread privileges and highest priority. + */ +// current_thread()->vm_privilege = TRUE; +// stack_privilege(current_thread()); + wire_thread (); + + thread_set_own_priority(0); + + io_done_thread_continue(); + /*NOTREACHED*/ + return 0; +} + +void mach_device_init() +{ + int i; + + queue_init(&io_done_list); + mutex_init (&io_done_list_lock); + thread_wait_init (&io_done_wait); + + port_bucket = ports_create_bucket (); + dev_class = ports_create_class (0, 0); + + for (i = 0; i < NUM_EMULATION; i++) { + emulation_list[i]->init(); + } + + cthread_detach (cthread_fork (io_done_thread, 0)); +} -- cgit v1.2.3 From 9b35bbf6dfccface4eb2878f0a45d158eadae511 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Fri, 5 Feb 2010 15:04:14 +0100 Subject: create a thread for only handling device requests. --- libmachdev/ds_routines.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) (limited to 'libmachdev/ds_routines.c') diff --git a/libmachdev/ds_routines.c b/libmachdev/ds_routines.c index 1cd06359..9152c72e 100644 --- a/libmachdev/ds_routines.c +++ b/libmachdev/ds_routines.c @@ -68,8 +68,8 @@ #include "util.h" #include "queue.h" -struct port_bucket *port_bucket; -struct port_class *dev_class; +static struct port_bucket *port_bucket; +static struct port_class *dev_class; extern struct device_emulation_ops linux_net_emulation_ops; @@ -783,6 +783,12 @@ static any_t io_done_thread(any_t unused) return 0; } +int create_device_port (int size, void *result) +{ + return ports_create_port (dev_class, port_bucket, + size, result); +} + void mach_device_init() { int i; @@ -800,3 +806,22 @@ void mach_device_init() cthread_detach (cthread_fork (io_done_thread, 0)); } + +static int +demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp) +{ + int ret; + extern int device_server (mach_msg_header_t *, mach_msg_header_t *); + extern int notify_server (mach_msg_header_t *, mach_msg_header_t *); + ret = device_server (inp, outp) || notify_server (inp, outp); + return ret; +} + +void ds_server() +{ + /* Launch. */ + do + { + ports_manage_port_operations_one_thread (port_bucket, demuxer, 0); + } while (1); +} -- cgit v1.2.3 From ceabed7508dee4df3e40d1aeccd35c90115ae95c Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Fri, 5 Feb 2010 15:05:58 +0100 Subject: dereference ports when return D_INVALID_OPERATIONS in device requests. --- libmachdev/ds_routines.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) (limited to 'libmachdev/ds_routines.c') diff --git a/libmachdev/ds_routines.c b/libmachdev/ds_routines.c index 9152c72e..c647b8e9 100644 --- a/libmachdev/ds_routines.c +++ b/libmachdev/ds_routines.c @@ -260,7 +260,10 @@ ds_device_write (device_t dev, mach_port_t reply_port, device = mach_convert_port_to_device (dev); if (! device->emul_ops->write) - return D_INVALID_OPERATION; + { + ports_port_deref (device_to_pi (device)); + return D_INVALID_OPERATION; + } ret = (*device->emul_ops->write) (device->emul_data, reply_port, reply_port_type, mode, recnum, @@ -290,7 +293,10 @@ ds_device_write_inband (device_t dev, mach_port_t reply_port, device = mach_convert_port_to_device (dev); if (! device->emul_ops->write_inband) - return D_INVALID_OPERATION; + { + ports_port_deref (device_to_pi (device)); + return D_INVALID_OPERATION; + } ret = (*device->emul_ops->write_inband) (device->emul_data, reply_port, reply_port_type, mode, recnum, @@ -316,7 +322,10 @@ ds_device_read (device_t dev, mach_port_t reply_port, device = mach_convert_port_to_device (dev); if (! device->emul_ops->read) - return D_INVALID_OPERATION; + { + ports_port_deref (device_to_pi (device)); + return D_INVALID_OPERATION; + } ret = (*device->emul_ops->read) (device->emul_data, reply_port, reply_port_type, mode, recnum, @@ -341,7 +350,10 @@ ds_device_read_inband (device_t dev, mach_port_t reply_port, device = mach_convert_port_to_device (dev); if (! device->emul_ops->read_inband) - return D_INVALID_OPERATION; + { + ports_port_deref (device_to_pi (device)); + return D_INVALID_OPERATION; + } ret = (*device->emul_ops->read_inband) (device->emul_data, reply_port, reply_port_type, mode, recnum, @@ -364,7 +376,10 @@ ds_device_set_status (device_t dev, dev_flavor_t flavor, device = mach_convert_port_to_device (dev); if (! device->emul_ops->set_status) - return D_INVALID_OPERATION; + { + ports_port_deref (device_to_pi (device)); + return D_INVALID_OPERATION; + } ret = (*device->emul_ops->set_status) (device->emul_data, flavor, status, status_count); @@ -386,7 +401,10 @@ ds_device_get_status (device_t dev, dev_flavor_t flavor, dev_status_t status, device = mach_convert_port_to_device (dev); if (! device->emul_ops->get_status) - return D_INVALID_OPERATION; + { + ports_port_deref (device_to_pi (device)); + return D_INVALID_OPERATION; + } ret = (*device->emul_ops->get_status) (device->emul_data, flavor, status, status_count); @@ -408,7 +426,10 @@ ds_device_set_filter (device_t dev, mach_port_t receive_port, int priority, device = mach_convert_port_to_device (dev); if (! device->emul_ops->set_filter) - return D_INVALID_OPERATION; + { + ports_port_deref (device_to_pi (device)); + return D_INVALID_OPERATION; + } ret = (*device->emul_ops->set_filter) (device->emul_data, receive_port, priority, filter, filter_count); -- cgit v1.2.3 From 5ea9105dff5f22606026afcd88b178110282b224 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Mon, 8 Feb 2010 08:58:53 +0100 Subject: remove io done thread. eliminate a potential race condition in thread_wait and thread_wakeup. --- libmachdev/ds_routines.c | 362 ----------------------------------------------- libmachdev/net.c | 35 +---- 2 files changed, 6 insertions(+), 391 deletions(-) (limited to 'libmachdev/ds_routines.c') diff --git a/libmachdev/ds_routines.c b/libmachdev/ds_routines.c index c647b8e9..857f64c5 100644 --- a/libmachdev/ds_routines.c +++ b/libmachdev/ds_routines.c @@ -448,362 +448,6 @@ ds_device_map (device_t dev, vm_prot_t prot, vm_offset_t offset, return D_INVALID_OPERATION; } -boolean_t -ds_open_done(ior) - register io_req_t ior; -{ - kern_return_t result; - register mach_device_t device; - - device = ior->io_device; - result = ior->io_error; - - if (result != D_SUCCESS) { - /* - * Open failed. Deallocate port and device. - */ -// dev_port_remove(device); -// ipc_port_dealloc_kernel(device->port); - - device_lock(device); - device->state = DEV_STATE_INIT; - if (device->io_wait) { - device->io_wait = FALSE; -// thread_wakeup((event_t)device); - } - device_unlock(device); - -// mach_device_deallocate(device); - device = MACH_DEVICE_NULL; - } - else { - /* - * Open succeeded. - */ - device_lock(device); - device->state = DEV_STATE_OPEN; - device->open_count = 1; - if (device->io_wait) { - device->io_wait = FALSE; -// thread_wakeup((event_t)device); - } - device_unlock(device); - - /* donate device reference to get port */ - } - /* - * Must explicitly convert device to port, since - * device_reply interface is built as 'user' side - * (thus cannot get translation). - */ - if (MACH_PORT_VALID(ior->io_reply_port)) { - (void) ds_device_open_reply(ior->io_reply_port, - ior->io_reply_port_type, - result, - mach_convert_device_to_port(device)); - } -// else -// mach_device_deallocate(device); - - mach_device_deallocate (device); - return (TRUE); -} - -boolean_t ds_read_done(ior) - io_req_t ior; -{ - vm_offset_t start_data, end_data; - vm_offset_t start_sent, end_sent; - register vm_size_t size_read; - - if (ior->io_error) - size_read = 0; - else - size_read = ior->io_count - ior->io_residual; - - start_data = (vm_offset_t)ior->io_data; - end_data = start_data + size_read; - - start_sent = (ior->io_op & IO_INBAND) ? start_data : - trunc_page(start_data); - end_sent = (ior->io_op & IO_INBAND) ? - start_data + ior->io_alloc_size : round_page(end_data); - - /* - * Zero memory that the device did not fill. - */ - if (start_sent < start_data) - memset((char *)start_sent, 0, start_data - start_sent); - if (end_sent > end_data) - memset((char *)end_data, 0, end_sent - end_data); - - - /* - * Touch the data being returned, to mark it dirty. - * If the pages were filled by DMA, the pmap module - * may think that they are clean. - */ - { - register vm_offset_t touch; - register int c; - - for (touch = start_sent; touch < end_sent; touch += PAGE_SIZE) { - c = *(volatile char *)touch; - *(volatile char *)touch = c; - } - } - - /* - * Send the data to the reply port - this - * unwires and deallocates it. - */ - if (ior->io_op & IO_INBAND) { - (void)ds_device_read_reply_inband(ior->io_reply_port, - ior->io_reply_port_type, - ior->io_error, - (char *) start_data, - size_read); - } else { -// vm_map_copy_t copy; -// kern_return_t kr; -// -// kr = vm_map_copyin_page_list(kernel_map, start_data, -// size_read, TRUE, TRUE, -// ©, FALSE); -// -// if (kr != KERN_SUCCESS) -// panic("read_done: vm_map_copyin_page_list failed"); - - (void)ds_device_read_reply(ior->io_reply_port, - ior->io_reply_port_type, - ior->io_error, - (char *) start_data, - size_read); - } - - /* - * Free any memory that was allocated but not sent. - */ - if (ior->io_count != 0) { - if (ior->io_op & IO_INBAND) { - if (ior->io_alloc_size > 0) - free (ior->io_data); -// zfree(io_inband_zone, (vm_offset_t)ior->io_data); - } else { - register vm_offset_t end_alloc; - - end_alloc = start_sent + round_page(ior->io_alloc_size); - if (end_alloc > end_sent) - vm_deallocate(mach_task_self (), - end_sent, - end_alloc - end_sent); - } - } - - mach_device_deallocate(ior->io_device); - - return (TRUE); -} - -/* - * Allocate wired-down memory for device read. - */ -kern_return_t device_read_alloc(ior, size) - register io_req_t ior; - register vm_size_t size; -{ - vm_offset_t addr; - kern_return_t kr; - - /* - * Nothing to do if no data. - */ - if (ior->io_count == 0) - return (KERN_SUCCESS); - - if (ior->io_op & IO_INBAND) { - ior->io_data = (io_buf_ptr_t) malloc(sizeof(io_buf_ptr_inband_t)); - ior->io_alloc_size = sizeof(io_buf_ptr_inband_t); - } else { - size = round_page(size); - kr = vm_allocate (mach_task_self (), &addr, size, TRUE); -// kr = kmem_alloc(kernel_map, &addr, size); - if (kr != KERN_SUCCESS) - return (kr); - - ior->io_data = (io_buf_ptr_t) addr; - ior->io_alloc_size = size; - } - - return (KERN_SUCCESS); -} - -struct thread_wait -{ - struct condition cond; - struct mutex mutex; - int v; -}; - -static struct thread_wait io_done_wait; - -void thread_wait_init (struct thread_wait *t) -{ - mutex_init (&t->mutex); - condition_init (&t->cond); - t->v = 0; -} - -void thread_block (struct thread_wait *t) -{ - mutex_lock (&t->mutex); - t->v = 1; - while (t->v) - hurd_condition_wait (&t->cond, &t->mutex); - mutex_unlock (&t->mutex); -} - -void thread_wakeup (struct thread_wait *t) -{ - mutex_lock (&t->mutex); - t->v = 0; - condition_signal (&t->cond); - mutex_unlock (&t->mutex); -} - -queue_head_t io_done_list; -struct mutex io_done_list_lock; - -#define splio splsched /* XXX must block ALL io devices */ - -void iodone(ior) - register io_req_t ior; -{ - /* - * If this ior was loaned to us, return it directly. - */ - if (ior->io_op & IO_LOANED) { - (*ior->io_done)(ior); - return; - } - /* - * If !IO_CALL, some thread is waiting for this. Must lock - * structure to interlock correctly with iowait(). Else can - * toss on queue for io_done thread to call completion. - */ - // TODO need a lock here? -// s = splio(); - if ((ior->io_op & IO_CALL) == 0) { - ior_lock(ior); - ior->io_op |= IO_DONE; - ior->io_op &= ~IO_WANTED; - ior_unlock(ior); -// thread_wakeup((event_t)ior); - } else { - ior->io_op |= IO_DONE; - mutex_lock (&io_done_list_lock); - enqueue_tail(&io_done_list, (queue_entry_t)ior); - thread_wakeup (&io_done_wait); -// thread_wakeup((event_t)&io_done_list); - mutex_unlock (&io_done_list_lock); - } -// splx(s); -} - -void wakeup_io_done_thread () -{ - thread_wakeup (&io_done_wait); -} - -void io_done_thread_continue() -{ - for (;;) { - extern void free_skbuffs (); - register io_req_t ior; - - free_skbuffs (); - mutex_lock(&io_done_list_lock); - while ((ior = (io_req_t)dequeue_head(&io_done_list)) != 0) { - mutex_unlock(&io_done_list_lock); - - if ((*ior->io_done)(ior)) { - /* - * IO done - free io_req_elt - */ - io_req_free(ior); - } - /* else routine has re-queued it somewhere */ - - mutex_lock(&io_done_list_lock); - } - -// assert_wait(&io_done_list, FALSE); - mutex_unlock(&io_done_list_lock); -// counter(c_io_done_thread_block++); -// thread_block(io_done_thread_continue); - thread_block (&io_done_wait); - } -} - - -void -wire_thread() -{ - kern_return_t kr; - mach_port_t priv_host_port; - - kr = get_privileged_ports (&priv_host_port, NULL); - if (kr != KERN_SUCCESS) - panic("get privileged port: %d", kr); - - kr = thread_wire(priv_host_port, - mach_thread_self(), - TRUE); - if (kr != KERN_SUCCESS) - panic("wire_thread: %d", kr); -} - -void -thread_set_own_priority (int priority) -{ - kern_return_t kr; - mach_port_t priv_host_port; - mach_port_t pset, psetcntl; - - kr = get_privileged_ports (&priv_host_port, NULL); - if (kr != KERN_SUCCESS) - panic("get privileged port: %d", kr); - - kr = thread_get_assignment (mach_thread_self (), &pset); - if (kr != KERN_SUCCESS) - panic("thread get assignment: %d", kr); - kr = host_processor_set_priv (priv_host_port, pset, &psetcntl); - if (kr != KERN_SUCCESS) - panic("processor set priv: %d", kr); - kr = thread_max_priority (mach_thread_self (), psetcntl, 0); - if (kr != KERN_SUCCESS) - panic("set thread max priority: %d", kr); - kr = thread_priority (mach_thread_self (), 0, FALSE); - if (kr != KERN_SUCCESS) - panic("set thread priority: %d", kr); -} - -static any_t io_done_thread(any_t unused) -{ - /* - * Set thread privileges and highest priority. - */ -// current_thread()->vm_privilege = TRUE; -// stack_privilege(current_thread()); - wire_thread (); - - thread_set_own_priority(0); - - io_done_thread_continue(); - /*NOTREACHED*/ - return 0; -} - int create_device_port (int size, void *result) { return ports_create_port (dev_class, port_bucket, @@ -814,18 +458,12 @@ void mach_device_init() { int i; - queue_init(&io_done_list); - mutex_init (&io_done_list_lock); - thread_wait_init (&io_done_wait); - port_bucket = ports_create_bucket (); dev_class = ports_create_class (0, 0); for (i = 0; i < NUM_EMULATION; i++) { emulation_list[i]->init(); } - - cthread_detach (cthread_fork (io_done_thread, 0)); } static int diff --git a/libmachdev/net.c b/libmachdev/net.c index d80e86ff..9a367a6b 100644 --- a/libmachdev/net.c +++ b/libmachdev/net.c @@ -161,32 +161,6 @@ struct net_data *search_nd (struct net_device *dev) /* Linux kernel network support routines. */ -/* Free all sk_buffs on the done list. - This routine is called by the iodone thread in ds_routines.c. */ -void -free_skbuffs () -{ - struct sk_buff *skb; - - while (1) - { - skb = skb_done_dequeue (); - if (skb) - { - struct skb_reply *reply = skb_reply(skb); - if (MACH_PORT_VALID (reply->reply)) - { - ds_device_write_reply (reply->reply, reply->reply_type, - 0, reply->pkglen); - reply->reply = MACH_PORT_NULL; - } - kfree_skb (skb); - } - else - break; - } -} - /* actions before freeing the sk_buff SKB. * If it returns 1, the packet will be deallocated later. */ int @@ -200,9 +174,12 @@ pre_kfree_skb (struct sk_buff *skb, void *data) Wakeup the iodone thread to process the list. */ if (reply && MACH_PORT_VALID (reply->reply)) { - skb_done_queue (skb); - wakeup_io_done_thread (); - return 1; + if (MACH_PORT_VALID (reply->reply)) + { + ds_device_write_reply (reply->reply, reply->reply_type, + 0, reply->pkglen); + reply->reply = MACH_PORT_NULL; + } } /* deallocate skb_reply before freeing the packet. */ free (data); -- cgit v1.2.3 From 1c3c575b2324f666b816164afe3a100896b81840 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Sat, 27 Feb 2010 14:14:02 +0100 Subject: remove RPCs for PCI conf space. --- libddekit/device.defs | 38 -------------------------------------- libmachdev/device.defs | 39 --------------------------------------- libmachdev/ds_routines.c | 29 ----------------------------- 3 files changed, 106 deletions(-) (limited to 'libmachdev/ds_routines.c') diff --git a/libddekit/device.defs b/libddekit/device.defs index 6a73853a..07ff58f6 100644 --- a/libddekit/device.defs +++ b/libddekit/device.defs @@ -157,44 +157,6 @@ routine device_intr_notify( in receive_port : mach_port_send_t ); -/* - * Test whether IPC devices exist. - */ -routine pci_present( - master_port : mach_port_t); - -/* - * Find the specified PCI device. - */ -routine pci_find_device( - master_port : mach_port_t; - vendor : short; - device_id : short; - index : short; - out bus : char; - out device_fn : char); - -/* - * Read the configuration space of a IPC device. - */ -routine pci_read_config( - master_port : mach_port_t; - bus : char; - device_fn : char; - where : char; - bytes_wanted : int; - out result : pci_config_data_t); - -/* - * Write the configuration space of a IPC device. - */ -routine pci_write_config( - master_port : mach_port_t; - bus : char; - device_fn : char; - where : char; - data : pci_config_data_t); - /* * enable/disable the specified irq. */ diff --git a/libmachdev/device.defs b/libmachdev/device.defs index 6a73853a..b514b3b9 100644 --- a/libmachdev/device.defs +++ b/libmachdev/device.defs @@ -48,7 +48,6 @@ subsystem serverprefix ds_; -type pci_config_data_t = array[*:4] of char; type reply_port_t = MACH_MSG_TYPE_MAKE_SEND_ONCE | polymorphic ctype: mach_port_t; @@ -157,44 +156,6 @@ routine device_intr_notify( in receive_port : mach_port_send_t ); -/* - * Test whether IPC devices exist. - */ -routine pci_present( - master_port : mach_port_t); - -/* - * Find the specified PCI device. - */ -routine pci_find_device( - master_port : mach_port_t; - vendor : short; - device_id : short; - index : short; - out bus : char; - out device_fn : char); - -/* - * Read the configuration space of a IPC device. - */ -routine pci_read_config( - master_port : mach_port_t; - bus : char; - device_fn : char; - where : char; - bytes_wanted : int; - out result : pci_config_data_t); - -/* - * Write the configuration space of a IPC device. - */ -routine pci_write_config( - master_port : mach_port_t; - bus : char; - device_fn : char; - where : char; - data : pci_config_data_t); - /* * enable/disable the specified irq. */ diff --git a/libmachdev/ds_routines.c b/libmachdev/ds_routines.c index 857f64c5..1961a2f3 100644 --- a/libmachdev/ds_routines.c +++ b/libmachdev/ds_routines.c @@ -154,35 +154,6 @@ ds_device_intr_notify (mach_port_t master_port, int irq, return D_INVALID_OPERATION; } -kern_return_t -ds_pci_write_config (mach_port_t master_port, char bus, char device_fn, - char where, pci_config_data_t data, - mach_msg_type_number_t dataCnt) -{ - return D_INVALID_OPERATION; -} - -kern_return_t -ds_pci_read_config (mach_port_t master_port, char bus, char device_fn, - char where, int bytes_wanted, pci_config_data_t result, - mach_msg_type_number_t *resultCnt) -{ - return D_INVALID_OPERATION; -} - -kern_return_t -ds_pci_find_device (mach_port_t master_port, short vendor, short device_id, - short index, short *bus, char *device_fn) -{ - return D_INVALID_OPERATION; -} - -kern_return_t -ds_pci_present (mach_port_t master_port) -{ - return D_INVALID_OPERATION; -} - kern_return_t ds_device_irq_enable (mach_port_t master_port, int irq, char status) -- cgit v1.2.3 From 2fe1437bd35016309e9ac4cfe57fb3daca3ba0a0 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Mon, 31 May 2010 17:21:47 +0200 Subject: make glue code of networking more independant. This change is required for block device drivers. When block device drivers are linked to the glue code, the linker should be able to perform garbage collection and exclude the code of networking from the driver programs. --- dde_e100/Makefile | 2 +- dde_e100/main.c | 6 +++--- dde_e1000/Makefile | 2 +- dde_e1000/main.c | 6 +++--- dde_ne2k_pci/Makefile | 2 +- dde_ne2k_pci/main.c | 6 +++--- dde_pcnet32/Makefile | 2 +- dde_pcnet32/main.c | 6 +++--- dde_rtl8139/Makefile | 2 +- dde_rtl8139/main.c | 6 +++--- libmachdev/Makefile | 3 ++- libmachdev/device_emul.h | 2 +- libmachdev/ds_routines.c | 14 +++++++++----- libmachdev/machdev.h | 32 ++++++++++++++++++++++++++++++++ libmachdev/net.c | 25 +++++++++++++++---------- 15 files changed, 79 insertions(+), 37 deletions(-) create mode 100644 libmachdev/machdev.h (limited to 'libmachdev/ds_routines.c') diff --git a/dde_e100/Makefile b/dde_e100/Makefile index fb1ed61e..27504068 100644 --- a/dde_e100/Makefile +++ b/dde_e100/Makefile @@ -10,7 +10,7 @@ TARGET = dde_e100 SRC_C = main.c e100.c LIBS += ../libmachdev/libmachdev.a -ldde_linux26.o -ldde_linux26_net ../libddekit/libddekit.a -lfshelp -ltrivfs -lpciaccess -lthreads -lshouldbeinlibc -lports -lhurd-slab -CFLAGS += -g +CFLAGS += -g -I/include # DDE configuration include $(L4DIR)/Makeconf diff --git a/dde_e100/main.c b/dde_e100/main.c index 8f04bfeb..98f4452a 100644 --- a/dde_e100/main.c +++ b/dde_e100/main.c @@ -6,13 +6,12 @@ #include // initcall() #include // msleep() -int using_std = 1; +#include -void netif_rx_handle (char *data, int len, struct net_device *dev); +int using_std = 1; int main(int argc, char **argv) { - extern void ds_server(void); l4dde26_init(); l4dde26_process_init(); l4dde26_softirq_init(); @@ -22,6 +21,7 @@ int main(int argc, char **argv) l4dde26_do_initcalls(); + register_net(); mach_device_init(); trivfs_init(); diff --git a/dde_e1000/Makefile b/dde_e1000/Makefile index bfe7dbaf..ffdc17ab 100644 --- a/dde_e1000/Makefile +++ b/dde_e1000/Makefile @@ -10,7 +10,7 @@ TARGET = dde_e1000 SRC_C = main.c e1000_ethtool.c e1000_hw.c e1000_main.c e1000_param.c LIBS += ../libmachdev/libmachdev.a -ldde_linux26.o -ldde_linux26_net ../libddekit/libddekit.a -lfshelp -ltrivfs -lpciaccess -lthreads -lshouldbeinlibc -lports -lhurd-slab -CFLAGS += -g +CFLAGS += -g -I/include # DDE configuration include $(L4DIR)/Makeconf diff --git a/dde_e1000/main.c b/dde_e1000/main.c index 8f04bfeb..98f4452a 100644 --- a/dde_e1000/main.c +++ b/dde_e1000/main.c @@ -6,13 +6,12 @@ #include // initcall() #include // msleep() -int using_std = 1; +#include -void netif_rx_handle (char *data, int len, struct net_device *dev); +int using_std = 1; int main(int argc, char **argv) { - extern void ds_server(void); l4dde26_init(); l4dde26_process_init(); l4dde26_softirq_init(); @@ -22,6 +21,7 @@ int main(int argc, char **argv) l4dde26_do_initcalls(); + register_net(); mach_device_init(); trivfs_init(); diff --git a/dde_ne2k_pci/Makefile b/dde_ne2k_pci/Makefile index 6cc27279..879904e1 100644 --- a/dde_ne2k_pci/Makefile +++ b/dde_ne2k_pci/Makefile @@ -10,7 +10,7 @@ TARGET = dde_ne2k_pci SRC_C = main.c ne2k-pci.c 8390.c LIBS += ../libmachdev/libmachdev.a -ldde_linux26.o -ldde_linux26_net ../libddekit/libddekit.a -lfshelp -ltrivfs -lpciaccess -lthreads -lshouldbeinlibc -lports -lhurd-slab -CFLAGS += -g +CFLAGS += -g -I/include # DDE configuration include $(L4DIR)/Makeconf diff --git a/dde_ne2k_pci/main.c b/dde_ne2k_pci/main.c index 8f04bfeb..98f4452a 100644 --- a/dde_ne2k_pci/main.c +++ b/dde_ne2k_pci/main.c @@ -6,13 +6,12 @@ #include // initcall() #include // msleep() -int using_std = 1; +#include -void netif_rx_handle (char *data, int len, struct net_device *dev); +int using_std = 1; int main(int argc, char **argv) { - extern void ds_server(void); l4dde26_init(); l4dde26_process_init(); l4dde26_softirq_init(); @@ -22,6 +21,7 @@ int main(int argc, char **argv) l4dde26_do_initcalls(); + register_net(); mach_device_init(); trivfs_init(); diff --git a/dde_pcnet32/Makefile b/dde_pcnet32/Makefile index 89e67efd..ebbb271e 100644 --- a/dde_pcnet32/Makefile +++ b/dde_pcnet32/Makefile @@ -10,7 +10,7 @@ TARGET = dde_pcnet32 SRC_C = main.c pcnet32.c LIBS += ../libmachdev/libmachdev.a -ldde_linux26.o -ldde_linux26_net ../libddekit/libddekit.a -lfshelp -ltrivfs -lpciaccess -lthreads -lshouldbeinlibc -lports -lhurd-slab -CFLAGS += -g +CFLAGS += -g -I/include # DDE configuration include $(L4DIR)/Makeconf diff --git a/dde_pcnet32/main.c b/dde_pcnet32/main.c index 8f04bfeb..98f4452a 100644 --- a/dde_pcnet32/main.c +++ b/dde_pcnet32/main.c @@ -6,13 +6,12 @@ #include // initcall() #include // msleep() -int using_std = 1; +#include -void netif_rx_handle (char *data, int len, struct net_device *dev); +int using_std = 1; int main(int argc, char **argv) { - extern void ds_server(void); l4dde26_init(); l4dde26_process_init(); l4dde26_softirq_init(); @@ -22,6 +21,7 @@ int main(int argc, char **argv) l4dde26_do_initcalls(); + register_net(); mach_device_init(); trivfs_init(); diff --git a/dde_rtl8139/Makefile b/dde_rtl8139/Makefile index dcc4a4f1..1af8e179 100644 --- a/dde_rtl8139/Makefile +++ b/dde_rtl8139/Makefile @@ -10,7 +10,7 @@ TARGET = dde_rtl8139 SRC_C = main.c 8139cp.c LIBS += ../libmachdev/libmachdev.a -ldde_linux26.o -ldde_linux26_net ../libddekit/libddekit.a -lfshelp -ltrivfs -lpciaccess -lthreads -lshouldbeinlibc -lports -lhurd-slab -CFLAGS += -g +CFLAGS += -g -I/include # DDE configuration include $(L4DIR)/Makeconf diff --git a/dde_rtl8139/main.c b/dde_rtl8139/main.c index 8f04bfeb..98f4452a 100644 --- a/dde_rtl8139/main.c +++ b/dde_rtl8139/main.c @@ -6,13 +6,12 @@ #include // initcall() #include // msleep() -int using_std = 1; +#include -void netif_rx_handle (char *data, int len, struct net_device *dev); +int using_std = 1; int main(int argc, char **argv) { - extern void ds_server(void); l4dde26_init(); l4dde26_process_init(); l4dde26_softirq_init(); @@ -22,6 +21,7 @@ int main(int argc, char **argv) l4dde26_do_initcalls(); + register_net(); mach_device_init(); trivfs_init(); diff --git a/libmachdev/Makefile b/libmachdev/Makefile index daf13a82..f64e281a 100644 --- a/libmachdev/Makefile +++ b/libmachdev/Makefile @@ -22,7 +22,8 @@ libname = libmachdev SRCS = deviceUser.c machUser.c net.c ds_routines.c queue.c trivfs_server.c \ device_replyUser.c deviceServer.c notifyServer.c LCLHDRS = dev_hdr.h device_emul.h ds_routines.h vm_param.h \ - util.h queue.h io_req.h if_ether.h + util.h queue.h io_req.h if_ether.h machdev.h +installhdrs = machdev.h device_emul.h HURDLIBS = ports threads trivfs OBJS = $(SRCS:.c=.o) $(MIGSTUBS) diff --git a/libmachdev/device_emul.h b/libmachdev/device_emul.h index edcf6d07..a5bc4f77 100644 --- a/libmachdev/device_emul.h +++ b/libmachdev/device_emul.h @@ -31,7 +31,7 @@ /* Each emulation layer provides these operations. */ struct device_emulation_ops { - void (*init) (); + void (*init) (void); void (*reference) (void *); void (*dealloc) (void *); mach_port_t (*dev_to_port) (void *); diff --git a/libmachdev/ds_routines.c b/libmachdev/ds_routines.c index 1961a2f3..f6a8e76c 100644 --- a/libmachdev/ds_routines.c +++ b/libmachdev/ds_routines.c @@ -73,13 +73,12 @@ static struct port_class *dev_class; extern struct device_emulation_ops linux_net_emulation_ops; -#define NUM_EMULATION (sizeof (emulation_list) / sizeof (emulation_list[0])) +#define NUM_EMULATION num_emul +#define MAX_NUM_EMULATION 32 /* List of emulations. */ -static struct device_emulation_ops *emulation_list[] = -{ - &linux_net_emulation_ops, -}; +static struct device_emulation_ops *emulation_list[MAX_NUM_EMULATION]; +static int num_emul; boolean_t is_master_device (mach_port_t port); @@ -447,6 +446,11 @@ demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp) return ret; } +void reg_dev_emul (struct device_emulation_ops *ops) +{ + emulation_list[num_emul++] = ops; +} + void ds_server() { /* Launch. */ diff --git a/libmachdev/machdev.h b/libmachdev/machdev.h new file mode 100644 index 00000000..27c488a5 --- /dev/null +++ b/libmachdev/machdev.h @@ -0,0 +1,32 @@ +/* + Copyright (C) 2010 Free Software Foundation, Inc. + Written by Zheng Da. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + The GNU Hurd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the GNU Hurd; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* This file declares interfaces used by driver programs. */ + +#ifndef __MACHDEV_H__ +#define __MACHDEV_H__ + +void ds_server(void); +void mach_device_init(void); +void register_net(void); +void trivfs_server(void); +int trivfs_init(void); + +#endif diff --git a/libmachdev/net.c b/libmachdev/net.c index ca6bca63..e785a5c8 100644 --- a/libmachdev/net.c +++ b/libmachdev/net.c @@ -102,7 +102,6 @@ struct skb_reply struct sk_buff; void skb_done_queue(struct sk_buff *skb); struct sk_buff *skb_done_dequeue(); -void linux_net_emulation_init (); void *skb_reply(struct sk_buff *skb); int netdev_flags(struct net_device *dev); char *netdev_addr(struct net_device *dev); @@ -116,7 +115,7 @@ int dev_open(struct net_device *dev); void *l4dde26_register_rx_callback(void *cb); void skb_done_head_init(); -struct net_data *nd_head; +static struct net_data *nd_head; /* Forward declarations. */ @@ -124,7 +123,7 @@ extern struct device_emulation_ops linux_net_emulation_ops; static int print_packet_size = 1; -mach_msg_type_t header_type = +static mach_msg_type_t header_type = { MACH_MSG_TYPE_BYTE, 8, @@ -135,7 +134,7 @@ mach_msg_type_t header_type = 0 }; -mach_msg_type_t packet_type = +static mach_msg_type_t packet_type = { MACH_MSG_TYPE_BYTE, /* name */ 8, /* size */ @@ -145,7 +144,7 @@ mach_msg_type_t packet_type = FALSE /* deallocate */ }; -struct net_data *search_nd (struct net_device *dev) +static struct net_data *search_nd (struct net_device *dev) { struct net_data *nd = nd_head; @@ -163,7 +162,7 @@ struct net_data *search_nd (struct net_device *dev) /* actions before freeing the sk_buff SKB. * If it returns 1, the packet will be deallocated later. */ -int +static int pre_kfree_skb (struct sk_buff *skb, void *data) { struct skb_reply *reply = data; @@ -190,7 +189,7 @@ pre_kfree_skb (struct sk_buff *skb, void *data) * Deliver the message to all right pfinet servers that * connects to the virtual network interface. */ -int +static int deliver_msg(mach_port_t dest, struct net_rcv_msg *msg) { mach_msg_return_t err; @@ -217,7 +216,7 @@ deliver_msg(mach_port_t dest, struct net_rcv_msg *msg) } /* Accept packet SKB received on an interface. */ -void +static void netif_rx_handle (char *data, int len, struct net_device *dev) { int pack_size; @@ -438,7 +437,7 @@ device_write (void *d, mach_port_t reply_port, /* * Other network operations */ -io_return_t +static io_return_t net_getstat(dev, flavor, status, count) struct net_device *dev; dev_flavor_t flavor; @@ -641,7 +640,7 @@ device_set_filter (void *d, mach_port_t port, int priority, } /* Do any initialization required for network devices. */ -void linux_net_emulation_init () +static void linux_net_emulation_init () { skb_done_head_init(); l4dde26_register_rx_callback(netif_rx_handle); @@ -667,3 +666,9 @@ struct device_emulation_ops linux_net_emulation_ops = NULL, NULL }; + +void register_net() +{ + extern void reg_dev_emul (struct device_emulation_ops *ops); + reg_dev_emul (&linux_net_emulation_ops); +} -- cgit v1.2.3 From a37d4548f4c696fc5a919ad3839c6472afdff86f Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Fri, 4 Jun 2010 07:37:45 +0200 Subject: remove the declaration of linux_net_emulation_ops. --- libmachdev/ds_routines.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'libmachdev/ds_routines.c') diff --git a/libmachdev/ds_routines.c b/libmachdev/ds_routines.c index f6a8e76c..65cefa3a 100644 --- a/libmachdev/ds_routines.c +++ b/libmachdev/ds_routines.c @@ -71,8 +71,6 @@ static struct port_bucket *port_bucket; static struct port_class *dev_class; -extern struct device_emulation_ops linux_net_emulation_ops; - #define NUM_EMULATION num_emul #define MAX_NUM_EMULATION 32 -- cgit v1.2.3 From 147b63b7be6671d3a7d9ee3a8b7b2f070aaf3481 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Sat, 5 Jun 2010 05:05:19 +0200 Subject: skip calling init if there is no init. --- libmachdev/ds_routines.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'libmachdev/ds_routines.c') diff --git a/libmachdev/ds_routines.c b/libmachdev/ds_routines.c index 65cefa3a..df9146a0 100644 --- a/libmachdev/ds_routines.c +++ b/libmachdev/ds_routines.c @@ -430,7 +430,8 @@ void mach_device_init() dev_class = ports_create_class (0, 0); for (i = 0; i < NUM_EMULATION; i++) { - emulation_list[i]->init(); + if (emulation_list[i]->init) + emulation_list[i]->init(); } } -- cgit v1.2.3 From 823e9dd9c55a1f34259c5398497439f5663ff2a4 Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Mon, 21 Jun 2010 09:59:01 +0200 Subject: fix port leak in block glue code of libmachdev. --- libmachdev/Makefile | 5 ++++- libmachdev/block.c | 9 +++++++-- libmachdev/device_emul.h | 3 ++- libmachdev/ds_routines.c | 4 ++-- libmachdev/net.c | 4 +++- 5 files changed, 18 insertions(+), 7 deletions(-) (limited to 'libmachdev/ds_routines.c') diff --git a/libmachdev/Makefile b/libmachdev/Makefile index e65a453a..22909949 100644 --- a/libmachdev/Makefile +++ b/libmachdev/Makefile @@ -20,7 +20,7 @@ makemode := library libname = libmachdev SRCS = deviceUser.c machUser.c net.c ds_routines.c queue.c trivfs_server.c \ - device_replyUser.c deviceServer.c notifyServer.c misc.c block.c + device_replyUser.c ourdeviceServer.c notifyServer.c misc.c block.c LCLHDRS = dev_hdr.h device_emul.h ds_routines.h vm_param.h \ util.h queue.h io_req.h if_ether.h machdev.h linux-errno.h \ errno-base.h @@ -31,3 +31,6 @@ OBJS = $(SRCS:.c=.o) $(MIGSTUBS) include ../Makeconf CFLAGS += -I$(top_srcdir)/libddekit/include + +ourdevice.defs: device.defs + $(CPP) $(CPPFLAGS) -x c $< | sed -e '/out[ ]*device[ ]*:[ ]*device_t/s/device_t/mach_port_send_t/' > $@ diff --git a/libmachdev/block.c b/libmachdev/block.c index 5400f60b..4aa07672 100644 --- a/libmachdev/block.c +++ b/libmachdev/block.c @@ -109,7 +109,8 @@ find_major: static io_return_t device_open (mach_port_t reply_port, mach_msg_type_name_t reply_port_type, - dev_mode_t mode, char *name, device_t *devp) + dev_mode_t mode, char *name, device_t *devp, + mach_msg_type_name_t *devicePoly) { io_return_t err = D_SUCCESS; struct block_data *bd = NULL; @@ -149,7 +150,11 @@ out: } } else - *devp = ports_get_send_right (bd); + { + *devp = ports_get_send_right (bd); + ports_port_deref (bd); + *devicePoly = MACH_MSG_TYPE_MOVE_SEND; + } return err; } diff --git a/libmachdev/device_emul.h b/libmachdev/device_emul.h index a5bc4f77..e27799cb 100644 --- a/libmachdev/device_emul.h +++ b/libmachdev/device_emul.h @@ -36,7 +36,8 @@ struct device_emulation_ops void (*dealloc) (void *); mach_port_t (*dev_to_port) (void *); io_return_t (*open) (mach_port_t, mach_msg_type_name_t, - dev_mode_t, char *, device_t *); + dev_mode_t, char *, device_t *, + mach_msg_type_name_t *type); io_return_t (*close) (void *); io_return_t (*write) (void *, mach_port_t, mach_msg_type_name_t, dev_mode_t, recnum_t, io_buf_ptr_t, unsigned, int *); diff --git a/libmachdev/ds_routines.c b/libmachdev/ds_routines.c index df9146a0..71457e03 100644 --- a/libmachdev/ds_routines.c +++ b/libmachdev/ds_routines.c @@ -161,7 +161,7 @@ ds_device_irq_enable (mach_port_t master_port, io_return_t ds_device_open (mach_port_t open_port, mach_port_t reply_port, mach_msg_type_name_t reply_port_type, dev_mode_t mode, - char *name, device_t *devp) + char *name, device_t *devp, mach_msg_type_name_t *devicePoly) { int i; io_return_t err; @@ -181,7 +181,7 @@ ds_device_open (mach_port_t open_port, mach_port_t reply_port, for (i = 0; i < NUM_EMULATION; i++) { err = (*emulation_list[i]->open) (reply_port, reply_port_type, - mode, name, devp); + mode, name, devp, devicePoly); if (err != D_NO_SUCH_DEVICE) break; } diff --git a/libmachdev/net.c b/libmachdev/net.c index 8c435b4b..b9d76731 100644 --- a/libmachdev/net.c +++ b/libmachdev/net.c @@ -273,7 +273,8 @@ void if_init_queues(ifp) static io_return_t device_open (mach_port_t reply_port, mach_msg_type_name_t reply_port_type, - dev_mode_t mode, char *name, device_t *devp) + dev_mode_t mode, char *name, device_t *devp, + mach_msg_type_name_t *devicePoly) { io_return_t err = D_SUCCESS; struct net_device *dev; @@ -357,6 +358,7 @@ device_open (mach_port_t reply_port, mach_msg_type_name_t reply_port_type, } *devp = ports_get_right (nd); + *devicePoly = MACH_MSG_TYPE_COPY_SEND; return D_SUCCESS; } -- cgit v1.2.3 From fee73f4e6d236a69f40e5c49e45f5f28a991d1ac Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Sun, 8 Aug 2010 07:15:04 +0200 Subject: check emul_device_t object in all DS server RPCs. --- libmachdev/ds_routines.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'libmachdev/ds_routines.c') diff --git a/libmachdev/ds_routines.c b/libmachdev/ds_routines.c index 71457e03..93ac7ecc 100644 --- a/libmachdev/ds_routines.c +++ b/libmachdev/ds_routines.c @@ -226,6 +226,8 @@ ds_device_write (device_t dev, mach_port_t reply_port, return D_INVALID_SIZE; device = mach_convert_port_to_device (dev); + if (device == NULL) + return D_INVALID_OPERATION; if (! device->emul_ops->write) { @@ -259,6 +261,8 @@ ds_device_write_inband (device_t dev, mach_port_t reply_port, return D_INVALID_SIZE; device = mach_convert_port_to_device (dev); + if (device == NULL) + return D_INVALID_OPERATION; if (! device->emul_ops->write_inband) { @@ -288,6 +292,8 @@ ds_device_read (device_t dev, mach_port_t reply_port, return D_NO_SUCH_DEVICE; device = mach_convert_port_to_device (dev); + if (device == NULL) + return D_INVALID_OPERATION; if (! device->emul_ops->read) { @@ -316,6 +322,8 @@ ds_device_read_inband (device_t dev, mach_port_t reply_port, return D_NO_SUCH_DEVICE; device = mach_convert_port_to_device (dev); + if (device == NULL) + return D_INVALID_OPERATION; if (! device->emul_ops->read_inband) { @@ -342,6 +350,8 @@ ds_device_set_status (device_t dev, dev_flavor_t flavor, return D_NO_SUCH_DEVICE; device = mach_convert_port_to_device (dev); + if (device == NULL) + return D_INVALID_OPERATION; if (! device->emul_ops->set_status) { @@ -367,6 +377,8 @@ ds_device_get_status (device_t dev, dev_flavor_t flavor, dev_status_t status, return D_NO_SUCH_DEVICE; device = mach_convert_port_to_device (dev); + if (device == NULL) + return D_INVALID_OPERATION; if (! device->emul_ops->get_status) { @@ -392,6 +404,8 @@ ds_device_set_filter (device_t dev, mach_port_t receive_port, int priority, return D_NO_SUCH_DEVICE; device = mach_convert_port_to_device (dev); + if (device == NULL) + return D_INVALID_OPERATION; if (! device->emul_ops->set_filter) { -- cgit v1.2.3 From 38b75c82d5555d1c2248fc98fb47d6fa2265059b Mon Sep 17 00:00:00 2001 From: Zheng Da Date: Sun, 8 Aug 2010 07:17:50 +0200 Subject: Make the thread of DS server known to Linux. --- libmachdev/ds_routines.c | 7 +++++++ libmachdev/mach_glue.h | 4 ++++ 2 files changed, 11 insertions(+) (limited to 'libmachdev/ds_routines.c') diff --git a/libmachdev/ds_routines.c b/libmachdev/ds_routines.c index 93ac7ecc..d31e3a9b 100644 --- a/libmachdev/ds_routines.c +++ b/libmachdev/ds_routines.c @@ -61,12 +61,15 @@ #include #include +#include + #include "vm_param.h" #include "device_reply_U.h" #include "io_req.h" #include "dev_hdr.h" #include "util.h" #include "queue.h" +#include "mach_glue.h" static struct port_bucket *port_bucket; static struct port_class *dev_class; @@ -466,6 +469,10 @@ void reg_dev_emul (struct device_emulation_ops *ops) void ds_server() { + /* This thread calls Linux functions, + * so I need to make it known to the Linux environment. */ + l4dde26_process_from_ddekit (ddekit_thread_myself ()); + /* Launch. */ do { diff --git a/libmachdev/mach_glue.h b/libmachdev/mach_glue.h index d1bd1fc7..770ea51b 100644 --- a/libmachdev/mach_glue.h +++ b/libmachdev/mach_glue.h @@ -4,6 +4,8 @@ /* network */ #include +#include + struct sk_buff; struct net_device; void skb_done_queue(struct sk_buff *skb); @@ -34,4 +36,6 @@ struct block_device *open_block_dev (char *name, int part, dev_mode_t mode); int block_dev_write (struct block_device *dev, int sectornr, char *data, int count, void (*write_done) (int err)); +int l4dde26_process_from_ddekit(ddekit_thread_t *t); + #endif -- cgit v1.2.3 From f309b0036b005dfa971def25134a5275732ddcc9 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Tue, 23 Aug 2011 02:49:15 +0200 Subject: rename device_irq_enable into device_intr_enable --- libddekit/device.defs | 4 ++-- libddekit/interrupt.c | 4 ++-- libmachdev/device.defs | 4 ++-- libmachdev/ds_routines.c | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'libmachdev/ds_routines.c') diff --git a/libddekit/device.defs b/libddekit/device.defs index ef777efe..3b39297a 100644 --- a/libddekit/device.defs +++ b/libddekit/device.defs @@ -160,7 +160,7 @@ routine device_intr_notify( /* * enable/disable the specified irq. */ -routine device_irq_enable( +routine device_intr_enable( master_port : mach_port_t; - irq : int; + line : int; status : char); diff --git a/libddekit/interrupt.c b/libddekit/interrupt.c index 9128e4d0..30515bbd 100644 --- a/libddekit/interrupt.c +++ b/libddekit/interrupt.c @@ -109,7 +109,7 @@ static void intloop(void *arg) ddekit_printf ("cannot install irq %d\n", params->irq); return; } - device_irq_enable (master_device, params->irq, TRUE); + device_intr_enable (master_device, params->irq, TRUE); #if 0 /* @@ -152,7 +152,7 @@ static void intloop(void *arg) params->handler(params->priv); /* If the irq has been disabled by the linux device, * we don't need to reenable the real one. */ - device_irq_enable (master_device, my_index, TRUE); + device_intr_enable (master_device, my_index, TRUE); if (ddekit_irq_ctrl[my_index].thread_exit) { ddekit_lock_unlock (&ddekit_irq_ctrl[my_index].irqlock); diff --git a/libmachdev/device.defs b/libmachdev/device.defs index ef777efe..3b39297a 100644 --- a/libmachdev/device.defs +++ b/libmachdev/device.defs @@ -160,7 +160,7 @@ routine device_intr_notify( /* * enable/disable the specified irq. */ -routine device_irq_enable( +routine device_intr_enable( master_port : mach_port_t; - irq : int; + line : int; status : char); diff --git a/libmachdev/ds_routines.c b/libmachdev/ds_routines.c index d31e3a9b..cc4b74f6 100644 --- a/libmachdev/ds_routines.c +++ b/libmachdev/ds_routines.c @@ -155,8 +155,8 @@ ds_device_intr_notify (mach_port_t master_port, int irq, } kern_return_t -ds_device_irq_enable (mach_port_t master_port, - int irq, char status) +ds_device_intr_enable (mach_port_t master_port, + int line, char status) { return D_INVALID_OPERATION; } -- cgit v1.2.3 From b9a3510bd830ed5c273347cf87080574a636fa8e Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Tue, 23 Aug 2011 02:57:02 +0200 Subject: rename device_intr_notify into device_intr_register --- libddekit/device.defs | 2 +- libddekit/interrupt.c | 4 ++-- libmachdev/device.defs | 2 +- libmachdev/ds_routines.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'libmachdev/ds_routines.c') diff --git a/libddekit/device.defs b/libddekit/device.defs index 3b39297a..d8968869 100644 --- a/libddekit/device.defs +++ b/libddekit/device.defs @@ -149,7 +149,7 @@ routine device_set_filter( in filter : filter_array_t ); -routine device_intr_notify( +routine device_intr_register( master_port : mach_port_t; in irq : int; in id : int; diff --git a/libddekit/interrupt.c b/libddekit/interrupt.c index 7de111d4..8085043c 100644 --- a/libddekit/interrupt.c +++ b/libddekit/interrupt.c @@ -97,10 +97,10 @@ static void intloop(void *arg) // TODO the flags for shared irq should be indicated by params->shared. // Be careful. For now, we must use shared irq. // Otherwise, the interrupt handler cannot be installed in the kernel. - ret = device_intr_notify (master_device, params->irq, + ret = device_intr_register (master_device, params->irq, 0, 0x04000000, delivery_port, MACH_MSG_TYPE_MAKE_SEND); - ddekit_printf ("device_intr_notify returns %d\n", ret); + ddekit_printf ("device_intr_register returns %d\n", ret); if (ret) { /* inform thread creator of error */ /* XXX does omega0 error code have any meaning to DDEKit users? */ diff --git a/libmachdev/device.defs b/libmachdev/device.defs index 3b39297a..d8968869 100644 --- a/libmachdev/device.defs +++ b/libmachdev/device.defs @@ -149,7 +149,7 @@ routine device_set_filter( in filter : filter_array_t ); -routine device_intr_notify( +routine device_intr_register( master_port : mach_port_t; in irq : int; in id : int; diff --git a/libmachdev/ds_routines.c b/libmachdev/ds_routines.c index cc4b74f6..6b8d1d4d 100644 --- a/libmachdev/ds_routines.c +++ b/libmachdev/ds_routines.c @@ -148,7 +148,7 @@ ds_xxx_device_set_filter (device_t device, mach_port_t rec, } io_return_t -ds_device_intr_notify (mach_port_t master_port, int irq, +ds_device_intr_register (mach_port_t master_port, int irq, int id, mach_port_t receive_port) { return D_INVALID_OPERATION; -- cgit v1.2.3