summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2020-07-09 23:43:06 +0200
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2020-07-09 23:46:13 +0200
commitaf36dbf3fd0cd065afadf0d8e7ae3aac39280bc4 (patch)
treefcff375a41bdf780f7f6c3e2c3827d2a79d3f47d
parentc0240fcf66e7dc74bcebedfa75bb685fbff705cc (diff)
parentdcf5bfa4f588a97110d52ce7de74ec4633f74461 (diff)
Merge branch 'master-user_level_drivers-debian' into master-user_level_drivers2-debian
-rw-r--r--Makefrag.am1
-rw-r--r--device/ds_routines.c94
-rw-r--r--include/device/notify.h2
-rw-r--r--include/mach/experimental.defs38
-rw-r--r--kern/ipc_kobject.c1
-rw-r--r--vm/vm_user.c14
6 files changed, 131 insertions, 19 deletions
diff --git a/Makefrag.am b/Makefrag.am
index ea612275..9307f7a5 100644
--- a/Makefrag.am
+++ b/Makefrag.am
@@ -363,7 +363,6 @@ include_device_HEADERS = \
include/device/device_types.h \
include/device/disk_status.h \
include/device/net_status.h \
- include/device/notify.defs \
include/device/notify.h \
include/device/tape_status.h \
include/device/tty_status.h
diff --git a/device/ds_routines.c b/device/ds_routines.c
index dd2978ed..c36eeecd 100644
--- a/device/ds_routines.c
+++ b/device/ds_routines.c
@@ -334,7 +334,7 @@ ds_device_intr_register (device_t dev, int id,
/* No flag is defined for now */
if (flags != 0)
- return D_NO_SUCH_DEVICE;
+ return D_INVALID_OPERATION;
/* Must be called on the irq device only */
if (! name_equal(mdev->dev_ops->d_name, 3, "irq"))
@@ -357,6 +357,82 @@ ds_device_intr_register (device_t dev, int id,
return err;
}
+static ipc_port_t intr_receive_ports[16];
+static int ackskip[16];
+io_return_t
+experimental_device_intr_register (ipc_port_t master_port, int line,
+ int id, int flags, ipc_port_t receive_port)
+{
+ io_return_t ret;
+ /* Open must be called on the master device port. */
+ if (master_port != master_device_port)
+ return D_INVALID_OPERATION;
+
+ /* XXX: move to arch-specific */
+ if (line < 0 || line >= 16)
+ return D_INVALID_OPERATION;
+
+ if (flags != 0x04000000)
+ return D_INVALID_OPERATION;
+
+ user_intr_t *user_intr = insert_intr_entry (&irqtab, line, receive_port);
+ if (!user_intr)
+ return D_NO_MEMORY;
+ // TODO The original port should be replaced
+ // when the same device driver calls it again,
+ // in order to handle the case that the device driver crashes and restarts.
+ ret = install_user_intr_handler (&irqtab, line, 0, user_intr);
+ intr_receive_ports[line] = receive_port;
+ /* For now netdde calls device_intr_enable once after registration. Assume
+ * it does so for this RPC. */
+ ackskip[line]++;
+
+ if (ret == 0)
+ {
+ /* If the port is installed successfully, increase its reference by 1.
+ * Thus, the port won't be destroyed after its task is terminated. */
+ ip_reference (receive_port);
+
+ /* For now netdde calls device_intr_enable once after registration. Assume
+ * it does so for now. When we move to IRQ acknowledgment convention we will
+ * change this. */
+ __disable_irq (line);
+ }
+
+ return ret;
+}
+
+kern_return_t
+ds_device_intr_ack (device_t dev, ipc_port_t receive_port)
+{
+ mach_device_t mdev = dev->emul_data;
+
+ /* Refuse if device is dead or not completely open. */
+ if (dev == DEVICE_NULL)
+ return D_NO_SUCH_DEVICE;
+
+ /* Must be called on the irq device only */
+ if (! name_equal(mdev->dev_ops->d_name, 3, "irq"))
+ return D_INVALID_OPERATION;
+
+ return irq_acknowledge(receive_port);
+}
+
+kern_return_t
+experimental_device_intr_enable(ipc_port_t master_port, int line, char status)
+{
+ if (master_port != master_device_port)
+ return D_INVALID_OPERATION;
+
+ if (ackskip[line])
+ {
+ ackskip[line]--;
+ return D_SUCCESS;
+ }
+
+ return irq_acknowledge(intr_receive_ports[line]);
+}
+
boolean_t
ds_notify (mach_msg_header_t *msg)
{
@@ -1837,22 +1913,6 @@ device_writev_trap (mach_device_t device, dev_mode_t mode,
return (result);
}
-kern_return_t
-ds_device_intr_ack (device_t dev, ipc_port_t receive_port)
-{
- mach_device_t mdev = dev->emul_data;
-
- /* Refuse if device is dead or not completely open. */
- if (dev == DEVICE_NULL)
- return D_NO_SUCH_DEVICE;
-
- /* Must be called on the irq device only */
- if (! name_equal(mdev->dev_ops->d_name, 3, "irq"))
- return D_INVALID_OPERATION;
-
- return irq_acknowledge(receive_port);
-}
-
struct device_emulation_ops mach_device_emulation_ops =
{
(void*) mach_device_reference,
diff --git a/include/device/notify.h b/include/device/notify.h
index addf9114..bd8d3a56 100644
--- a/include/device/notify.h
+++ b/include/device/notify.h
@@ -29,6 +29,6 @@ typedef struct
int id;
} device_intr_notification_t;
-#define DEVICE_INTR_NOTIFY 100
+#define DEVICE_INTR_NOTIFY 424242
#endif /* _MACH_DEVICE_NOTIFY_H_ */
diff --git a/include/mach/experimental.defs b/include/mach/experimental.defs
index ddcbea5f..9a2f28db 100644
--- a/include/mach/experimental.defs
+++ b/include/mach/experimental.defs
@@ -13,3 +13,41 @@ subsystem
serverprefix experimental_;
/* This is free for experimenting RPCs, with no backward compatibility guarantees. */
+
+type notify_port_t = MACH_MSG_TYPE_MOVE_SEND_ONCE
+ ctype: mach_port_t;
+
+skip; /*simpleroutine mach_intr_notify(
+ notify : notify_port_t;
+ name : int);*/
+
+routine device_intr_register(
+ master_port : mach_port_t;
+ in line : int;
+ in id : int;
+ in flags : int;
+ in receive_port : mach_port_send_t
+ );
+
+/*
+ * enable/disable the specified line.
+ */
+/* XXX: Naming a function taht can disable something "xxx_enable" is confusing. */
+/* Is the disable part actually used at all? AIUI, the kernel IRQ handler
+should always disable the line; and the userspace driver only has to
+reenable it, after acknowledging and handling the interrupt...
+*/
+routine device_intr_enable(
+ master_port : mach_port_t;
+ line : int;
+ status : char);
+
+/*
+ * This routine is for compatibility with old userland drivers.
+ */
+routine vm_allocate_contiguous(
+ host_priv : host_priv_t;
+ target_task : vm_task_t;
+ out vaddr : vm_address_t;
+ out paddr : vm_address_t;
+ size : vm_size_t);
diff --git a/kern/ipc_kobject.c b/kern/ipc_kobject.c
index 5ced4037..c65458ba 100644
--- a/kern/ipc_kobject.c
+++ b/kern/ipc_kobject.c
@@ -160,6 +160,7 @@ ipc_kobject_server(request)
* to perform the kernel function
*/
{
+ extern mig_routine_t experimental_server_routine();
check_simple_locks();
if ((routine = mach_server_routine(&request->ikm_header)) != 0
|| (routine = mach_port_server_routine(&request->ikm_header)) != 0
diff --git a/vm/vm_user.c b/vm/vm_user.c
index 4d5728c8..b13ba8dc 100644
--- a/vm/vm_user.c
+++ b/vm/vm_user.c
@@ -659,3 +659,17 @@ kern_return_t vm_allocate_contiguous(
return KERN_SUCCESS;
}
+
+kern_return_t experimental_vm_allocate_contiguous(host_priv, map, result_vaddr, result_paddr, size)
+ host_t host_priv;
+ vm_map_t map;
+ vm_address_t *result_vaddr;
+ vm_address_t *result_paddr;
+ vm_size_t size;
+{
+ rpc_phys_addr_t paddr;
+ kern_return_t ret;
+ ret = vm_allocate_contiguous(host_priv, map, result_vaddr, &paddr, size, 0, ~0ULL, 0);
+ *result_paddr = paddr;
+ return ret;
+}