aboutsummaryrefslogtreecommitdiff
path: root/patches/gnumach/79_dde-debian.patch
blob: b6a0f17dcaef8b534ea6f4c6b94bdea567f2966a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
This contains a compatibility layer for netdde and rump still using the experimental irq/alloc_contig support. It is the output of

git diff master master-user_level_drivers-debian

(master was 6054cda4de2341b9a77ec4421411725f3684006b and
master-user_level_drivers-debian was 19283fdffa782b2e485ef39e0de1574006ec4a1a at
the time)

When dropping this, break netdde (<< 0.0.20200330-5),
hurd-libs0.3 (<< hurd_1:0.9.git20200718-1+b1)

---
 Makefrag.am                     |    1 
 device/ds_routines.c            |   64 +++++++++++++++++++++++++++++++++++++++-
 device/intr.c                   |   16 ++++++----
 device/intr.h                   |    3 +
 include/mach/experimental.defs  |   38 +++++++++++++++++++++++
 linux/dev/drivers/block/genhd.c |    4 +-
 vm/vm_user.c                    |   14 ++++++++
 7 files changed, 130 insertions(+), 10 deletions(-)

--- a/Makefrag.am
+++ b/Makefrag.am
@@ -362,7 +362,6 @@ include_device_HEADERS = \
 	include/device/disk_status.h \
 	include/device/input.h \
 	include/device/net_status.h \
-	include/device/notify.defs \
 	include/device/notify.h \
 	include/device/tape_status.h \
 	include/device/tty_status.h
--- a/device/ds_routines.c
+++ b/device/ds_routines.c
@@ -354,7 +354,7 @@ ds_device_intr_register (device_t dev, i
   if (! name_equal(mdev->dev_ops->d_name, 3, "irq"))
     return D_INVALID_OPERATION;
 
-  user_intr_t *e = insert_intr_entry (&irqtab, id, receive_port);
+  user_intr_t *e = insert_intr_entry (&irqtab, id, receive_port, 0);
   if (!e)
     return D_NO_MEMORY;
 
@@ -371,6 +371,52 @@ ds_device_intr_register (device_t dev, i
 #endif /* MACH_XEN */
 }
 
+static ipc_port_t intr_receive_ports[16];
+io_return_t
+experimental_device_intr_register (ipc_port_t master_port, int line,
+		       int id, int flags, ipc_port_t receive_port)
+{
+#ifdef MACH_XEN
+  return D_INVALID_OPERATION;
+#else /* MACH_XEN */
+  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, 1);
+  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);
+
+  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);
+
+    intr_receive_ports[line] = 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;
+#endif /* MACH_XEN */
+}
+
 kern_return_t
 ds_device_intr_ack (device_t dev, ipc_port_t receive_port)
 {
@@ -399,6 +445,22 @@ ds_device_intr_ack (device_t dev, ipc_po
 #endif /* MACH_XEN */
 }
 
+kern_return_t
+experimental_device_intr_enable(ipc_port_t master_port, int line, char status)
+{
+#ifdef MACH_XEN
+  return D_INVALID_OPERATION;
+#else /* MACH_XEN */
+  if (master_port != master_device_port)
+    return D_INVALID_OPERATION;
+
+  if (status != 1)
+    return D_INVALID_OPERATION;
+
+  return irq_acknowledge(intr_receive_ports[line]);
+#endif /* MACH_XEN */
+}
+
 boolean_t
 ds_notify (mach_msg_header_t *msg)
 {
--- a/device/intr.c
+++ b/device/intr.c
@@ -25,7 +25,7 @@
 #ifndef MACH_XEN
 
 queue_head_t main_intr_queue;
-static boolean_t deliver_intr (int id, ipc_port_t dst_port);
+static boolean_t deliver_intr (int id, mach_msg_id_t msgh_id, ipc_port_t dst_port);
 
 #ifndef LINUX_DEV
 #define SA_SHIRQ 0x04000000
@@ -122,7 +122,7 @@ deliver_user_intr (struct irqdev *dev, i
  * This entry exists in the queue until
  * the corresponding interrupt port is removed.*/
 user_intr_t *
-insert_intr_entry (struct irqdev *dev, int id, ipc_port_t dst_port)
+insert_intr_entry (struct irqdev *dev, int id, ipc_port_t dst_port, int compat)
 {
   user_intr_t *e, *new, *ret;
   int free = 0;
@@ -146,7 +146,11 @@ insert_intr_entry (struct irqdev *dev, i
   new->id = id;
   new->dst_port = dst_port;
   new->interrupts = 0;
-  new->n_unacked = 0;
+  new->compat = compat;
+  if (compat)
+    new->n_unacked = 1;
+  else
+    new->n_unacked = 0;
 
   queue_enter (dev->intr_queue, new, user_intr_t *, chain);
 out:
@@ -268,7 +272,7 @@ intr_thread (void)
 		  irqtab.tot_num_intr--;
 
 		  splx (s);
-		  deliver_intr (id, dst_port);
+		  deliver_intr (id, e->compat ? 424242 : DEVICE_INTR_NOTIFY, dst_port);
 		  s = splhigh ();
 		}
 	    }
@@ -307,7 +311,7 @@ intr_thread (void)
 }
 
 static boolean_t
-deliver_intr (int id, ipc_port_t dst_port)
+deliver_intr (int id, mach_msg_id_t msgh_id, ipc_port_t dst_port)
 {
   ipc_kmsg_t kmsg;
   device_intr_notification_t *n;
@@ -331,7 +335,7 @@ deliver_intr (int id, ipc_port_t dst_por
   m->msgh_seqno = DEVICE_NOTIFY_MSGH_SEQNO;
   m->msgh_local_port = MACH_PORT_NULL;
   m->msgh_remote_port = MACH_PORT_NULL;
-  m->msgh_id = DEVICE_INTR_NOTIFY;
+  m->msgh_id = msgh_id;
 
   t->msgt_name = MACH_MSG_TYPE_INTEGER_32;
   t->msgt_size = 32;
--- a/device/intr.h
+++ b/device/intr.h
@@ -36,6 +36,7 @@ typedef struct {
   int n_unacked;  /* Number of times irqs were disabled for this */
   ipc_port_t dst_port; /* Notification port */
   int id; /* Mapping to machine dependent irq_t array elem */
+  int compat;
 } user_intr_t;
 
 struct irqdev {
@@ -52,7 +53,7 @@ struct irqdev {
 extern queue_head_t main_intr_queue;
 extern int install_user_intr_handler (struct irqdev *dev, int id, unsigned long flags, user_intr_t *e);
 extern int deliver_user_intr (struct irqdev *dev, int id, user_intr_t *e);
-extern user_intr_t *insert_intr_entry (struct irqdev *dev, int id, ipc_port_t receive_port);
+extern user_intr_t *insert_intr_entry (struct irqdev *dev, int id, ipc_port_t receive_port, int compat);
 
 void intr_thread (void);
 kern_return_t irq_acknowledge (ipc_port_t receive_port);
--- 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);
--- a/linux/dev/drivers/block/genhd.c
+++ b/linux/dev/drivers/block/genhd.c
@@ -1060,7 +1060,9 @@ void device_setup(void)
 	scsi_dev_init();
 #endif
 #ifdef CONFIG_INET
-	net_dev_init();
+	extern char *kernel_cmdline;
+	if (!strstr(kernel_cmdline, " nonetdev"))
+		net_dev_init();
 #endif
 #ifndef MACH
 	console_map_init();
--- a/vm/vm_user.c
+++ b/vm/vm_user.c
@@ -688,3 +688,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;
+}