FreeBSD/Linux Kernel Cross Reference
sys/servers/inet/sr.c
1 /* this file contains the interface of the network software with the file
2 * system.
3 *
4 * Copyright 1995 Philip Homburg
5 *
6 * The valid messages and their parameters are:
7 *
8 * Requests:
9 *
10 * m_type NDEV_MINOR NDEV_PROC NDEV_REF NDEV_MODE
11 * -------------------------------------------------------------
12 * | DEV_OPEN |minor dev | proc nr | fd | mode |
13 * |-------------+-----------+-----------+-----------+----------+
14 * | DEV_CLOSE |minor dev | proc nr | fd | |
15 * |-------------+-----------+-----------+-----------+----------+
16 *
17 * m_type NDEV_MINOR NDEV_PROC NDEV_REF NDEV_COUNT NDEV_BUFFER
18 * ---------------------------------------------------------------------------
19 * | DEV_READ |minor dev | proc nr | fd | count | buf ptr |
20 * |-------------+-----------+-----------+-----------+-----------+-----------|
21 * | DEV_WRITE |minor dev | proc nr | fd | count | buf ptr |
22 * |-------------+-----------+-----------+-----------+-----------+-----------|
23 *
24 * m_type NDEV_MINOR NDEV_PROC NDEV_REF NDEV_IOCTL NDEV_BUFFER
25 * ---------------------------------------------------------------------------
26 * | DEV_IOCTL3 |minor dev | proc nr | fd | command | buf ptr |
27 * |-------------+-----------+-----------+-----------+-----------+-----------|
28 *
29 * m_type NDEV_MINOR NDEV_PROC NDEV_REF NDEV_OPERATION
30 * -------------------------------------------------------------------|
31 * | DEV_CANCEL |minor dev | proc nr | fd | which operation|
32 * |-------------+-----------+-----------+-----------+----------------|
33 *
34 * Replies:
35 *
36 * m_type REP_PROC_NR REP_STATUS REP_REF REP_OPERATION
37 * ----------------------------------------------------------------------|
38 * | DEVICE_REPLY | proc nr | status | fd | which operation |
39 * |--------------+-------------+------------+---------+-----------------|
40 */
41
42 #include "inet.h"
43
44 #ifndef __minix_vmd /* Minix 3 */
45 #include <sys/select.h>
46 #endif
47 #include <sys/svrctl.h>
48 #include <minix/callnr.h>
49
50 #include "mq.h"
51 #include "qp.h"
52 #include "proto.h"
53 #include "generic/type.h"
54
55 #include "generic/assert.h"
56 #include "generic/buf.h"
57 #include "generic/event.h"
58 #include "generic/sr.h"
59 #include "sr_int.h"
60
61 #ifndef __minix_vmd /* Minix 3 */
62 #define DEV_CANCEL NW_CANCEL
63 #define DEVICE_REPLY REVIVE
64 #define DEV_IOCTL3 DEV_IOCTL
65 #define NDEV_BUFFER ADDRESS
66 #define NDEV_COUNT COUNT
67 #define NDEV_IOCTL REQUEST
68 #define NDEV_MINOR DEVICE
69 #define NDEV_PROC PROC_NR
70 #endif
71
72 THIS_FILE
73
74 PUBLIC sr_fd_t sr_fd_table[FD_NR];
75
76 PRIVATE mq_t *repl_queue, *repl_queue_tail;
77 #ifdef __minix_vmd
78 PRIVATE cpvec_t cpvec[CPVEC_NR];
79 #else /* Minix 3 */
80 PRIVATE struct vir_cp_req vir_cp_req[CPVEC_NR];
81 #endif
82
83 FORWARD _PROTOTYPE ( int sr_open, (message *m) );
84 FORWARD _PROTOTYPE ( void sr_close, (message *m) );
85 FORWARD _PROTOTYPE ( int sr_rwio, (mq_t *m) );
86 FORWARD _PROTOTYPE ( int sr_restart_read, (sr_fd_t *fdp) );
87 FORWARD _PROTOTYPE ( int sr_restart_write, (sr_fd_t *fdp) );
88 FORWARD _PROTOTYPE ( int sr_restart_ioctl, (sr_fd_t *fdp) );
89 FORWARD _PROTOTYPE ( int sr_cancel, (message *m) );
90 #ifndef __minix_vmd /* Minix 3 */
91 FORWARD _PROTOTYPE ( int sr_select, (message *m) );
92 FORWARD _PROTOTYPE ( void sr_status, (message *m) );
93 #endif
94 FORWARD _PROTOTYPE ( void sr_reply_, (mq_t *m, int reply, int is_revive) );
95 FORWARD _PROTOTYPE ( sr_fd_t *sr_getchannel, (int minor));
96 FORWARD _PROTOTYPE ( acc_t *sr_get_userdata, (int fd, vir_bytes offset,
97 vir_bytes count, int for_ioctl) );
98 FORWARD _PROTOTYPE ( int sr_put_userdata, (int fd, vir_bytes offset,
99 acc_t *data, int for_ioctl) );
100 #ifdef __minix_vmd
101 #define sr_select_res 0
102 #else /* Minix 3 */
103 FORWARD _PROTOTYPE (void sr_select_res, (int fd, unsigned ops) );
104 #endif
105 FORWARD _PROTOTYPE ( int sr_repl_queue, (int proc, int ref, int operation) );
106 FORWARD _PROTOTYPE ( int walk_queue, (sr_fd_t *sr_fd, mq_t **q_head_ptr,
107 mq_t **q_tail_ptr, int type, int proc_nr, int ref, int first_flag) );
108 FORWARD _PROTOTYPE ( void process_req_q, (mq_t *mq, mq_t *tail,
109 mq_t **tail_ptr) );
110 FORWARD _PROTOTYPE ( void sr_event, (event_t *evp, ev_arg_t arg) );
111 FORWARD _PROTOTYPE ( int cp_u2b, (int proc, char *src, acc_t **var_acc_ptr,
112 int size) );
113 FORWARD _PROTOTYPE ( int cp_b2u, (acc_t *acc_ptr, int proc, char *dest) );
114
115 PUBLIC void sr_init()
116 {
117 int i;
118
119 for (i=0; i<FD_NR; i++)
120 {
121 sr_fd_table[i].srf_flags= SFF_FREE;
122 ev_init(&sr_fd_table[i].srf_ioctl_ev);
123 ev_init(&sr_fd_table[i].srf_read_ev);
124 ev_init(&sr_fd_table[i].srf_write_ev);
125 }
126 repl_queue= NULL;
127 }
128
129 PUBLIC void sr_rec(m)
130 mq_t *m;
131 {
132 int result;
133 int send_reply, free_mess;
134
135 if (repl_queue)
136 {
137 if (m->mq_mess.m_type == DEV_CANCEL)
138 {
139 #ifdef __minix_vmd
140 result= sr_repl_queue(m->mq_mess.NDEV_PROC,
141 m->mq_mess.NDEV_REF,
142 m->mq_mess.NDEV_OPERATION);
143 #else /* Minix 3 */
144 result= sr_repl_queue(m->mq_mess.PROC_NR, 0, 0);
145 #endif
146 if (result)
147 {
148 mq_free(m);
149 return; /* canceled request in queue */
150 }
151 }
152 #if 0
153 else
154 sr_repl_queue(ANY, 0, 0);
155 #endif
156 }
157
158 switch (m->mq_mess.m_type)
159 {
160 case DEV_OPEN:
161 result= sr_open(&m->mq_mess);
162 send_reply= 1;
163 free_mess= 1;
164 break;
165 case DEV_CLOSE:
166 sr_close(&m->mq_mess);
167 result= OK;
168 send_reply= 1;
169 free_mess= 1;
170 break;
171 case DEV_READ:
172 case DEV_WRITE:
173 case DEV_IOCTL3:
174 result= sr_rwio(m);
175 assert(result == OK || result == SUSPEND);
176 send_reply= (result == SUSPEND);
177 free_mess= 0;
178 break;
179 case DEV_CANCEL:
180 result= sr_cancel(&m->mq_mess);
181 assert(result == OK || result == EINTR);
182 send_reply= (result == EINTR);
183 free_mess= 1;
184 #ifdef __minix_vmd
185 m->mq_mess.m_type= m->mq_mess.NDEV_OPERATION;
186 #else /* Minix 3 */
187 m->mq_mess.m_type= 0;
188 #endif
189 break;
190 #ifndef __minix_vmd /* Minix 3 */
191 case DEV_SELECT:
192 result= sr_select(&m->mq_mess);
193 send_reply= 1;
194 free_mess= 1;
195 break;
196 case DEV_STATUS:
197 sr_status(&m->mq_mess);
198 send_reply= 0;
199 free_mess= 1;
200 break;
201 #endif
202 default:
203 ip_panic(("unknown message, from %d, type %d",
204 m->mq_mess.m_source, m->mq_mess.m_type));
205 }
206 if (send_reply)
207 {
208 sr_reply_(m, result, FALSE /* !is_revive */);
209 }
210 if (free_mess)
211 mq_free(m);
212 }
213
214 PUBLIC void sr_add_minor(minor, port, openf, closef, readf, writef,
215 ioctlf, cancelf, selectf)
216 int minor;
217 int port;
218 sr_open_t openf;
219 sr_close_t closef;
220 sr_read_t readf;
221 sr_write_t writef;
222 sr_ioctl_t ioctlf;
223 sr_cancel_t cancelf;
224 sr_select_t selectf;
225 {
226 sr_fd_t *sr_fd;
227
228 assert (minor>=0 && minor<FD_NR);
229
230 sr_fd= &sr_fd_table[minor];
231
232 assert(!(sr_fd->srf_flags & SFF_INUSE));
233
234 sr_fd->srf_flags= SFF_INUSE | SFF_MINOR;
235 sr_fd->srf_port= port;
236 sr_fd->srf_open= openf;
237 sr_fd->srf_close= closef;
238 sr_fd->srf_write= writef;
239 sr_fd->srf_read= readf;
240 sr_fd->srf_ioctl= ioctlf;
241 sr_fd->srf_cancel= cancelf;
242 sr_fd->srf_select= selectf;
243 }
244
245 PRIVATE int sr_open(m)
246 message *m;
247 {
248 sr_fd_t *sr_fd;
249
250 int minor= m->NDEV_MINOR;
251 int i, fd;
252
253 if (minor<0 || minor>FD_NR)
254 {
255 DBLOCK(1, printf("replying EINVAL\n"));
256 return EINVAL;
257 }
258 if (!(sr_fd_table[minor].srf_flags & SFF_MINOR))
259 {
260 DBLOCK(1, printf("replying ENXIO\n"));
261 return ENXIO;
262 }
263 for (i=0; i<FD_NR && (sr_fd_table[i].srf_flags & SFF_INUSE); i++);
264
265 if (i>=FD_NR)
266 {
267 DBLOCK(1, printf("replying ENFILE\n"));
268 return ENFILE;
269 }
270
271 sr_fd= &sr_fd_table[i];
272 *sr_fd= sr_fd_table[minor];
273 sr_fd->srf_flags= SFF_INUSE;
274 fd= (*sr_fd->srf_open)(sr_fd->srf_port, i, sr_get_userdata,
275 sr_put_userdata, 0 /* no put_pkt */, sr_select_res);
276 if (fd<0)
277 {
278 sr_fd->srf_flags= SFF_FREE;
279 DBLOCK(1, printf("replying %d\n", fd));
280 return fd;
281 }
282 sr_fd->srf_fd= fd;
283 return i;
284 }
285
286 PRIVATE void sr_close(m)
287 message *m;
288 {
289 sr_fd_t *sr_fd;
290
291 sr_fd= sr_getchannel(m->NDEV_MINOR);
292 assert (sr_fd);
293
294 if (sr_fd->srf_flags & SFF_BUSY)
295 ip_panic(("close on busy channel"));
296
297 assert (!(sr_fd->srf_flags & SFF_MINOR));
298 (*sr_fd->srf_close)(sr_fd->srf_fd);
299 sr_fd->srf_flags= SFF_FREE;
300 }
301
302 PRIVATE int sr_rwio(m)
303 mq_t *m;
304 {
305 sr_fd_t *sr_fd;
306 mq_t **q_head_ptr, **q_tail_ptr;
307 int ip_flag, susp_flag, first_flag;
308 int r;
309 ioreq_t request;
310 size_t size;
311
312 sr_fd= sr_getchannel(m->mq_mess.NDEV_MINOR);
313 assert (sr_fd);
314
315 switch(m->mq_mess.m_type)
316 {
317 case DEV_READ:
318 q_head_ptr= &sr_fd->srf_read_q;
319 q_tail_ptr= &sr_fd->srf_read_q_tail;
320 ip_flag= SFF_READ_IP;
321 susp_flag= SFF_READ_SUSP;
322 first_flag= SFF_READ_FIRST;
323 break;
324 case DEV_WRITE:
325 q_head_ptr= &sr_fd->srf_write_q;
326 q_tail_ptr= &sr_fd->srf_write_q_tail;
327 ip_flag= SFF_WRITE_IP;
328 susp_flag= SFF_WRITE_SUSP;
329 first_flag= SFF_WRITE_FIRST;
330 break;
331 case DEV_IOCTL3:
332 q_head_ptr= &sr_fd->srf_ioctl_q;
333 q_tail_ptr= &sr_fd->srf_ioctl_q_tail;
334 ip_flag= SFF_IOCTL_IP;
335 susp_flag= SFF_IOCTL_SUSP;
336 first_flag= SFF_IOCTL_FIRST;
337 break;
338 default:
339 ip_panic(("illegal case entry"));
340 }
341
342 if (sr_fd->srf_flags & ip_flag)
343 {
344 assert(sr_fd->srf_flags & susp_flag);
345 assert(*q_head_ptr);
346
347 (*q_tail_ptr)->mq_next= m;
348 *q_tail_ptr= m;
349 return SUSPEND;
350 }
351 assert(!*q_head_ptr);
352
353 *q_tail_ptr= *q_head_ptr= m;
354 sr_fd->srf_flags |= ip_flag;
355 assert(!(sr_fd->srf_flags & first_flag));
356 sr_fd->srf_flags |= first_flag;
357
358 switch(m->mq_mess.m_type)
359 {
360 case DEV_READ:
361 r= (*sr_fd->srf_read)(sr_fd->srf_fd,
362 m->mq_mess.NDEV_COUNT);
363 break;
364 case DEV_WRITE:
365 r= (*sr_fd->srf_write)(sr_fd->srf_fd,
366 m->mq_mess.NDEV_COUNT);
367 break;
368 case DEV_IOCTL3:
369 request= m->mq_mess.NDEV_IOCTL;
370
371 /* There should be a better way to do this... */
372 if (request == NWIOQUERYPARAM)
373 {
374 r= qp_query(m->mq_mess.NDEV_PROC,
375 (vir_bytes)m->mq_mess.NDEV_BUFFER);
376 r= sr_put_userdata(sr_fd-sr_fd_table, r, NULL, 1);
377 assert(r == OK);
378 return OK;
379 }
380
381 /* And now, we continue with our regular program. */
382 size= (request >> 16) & _IOCPARM_MASK;
383 if (size>MAX_IOCTL_S)
384 {
385 DBLOCK(1, printf("replying EINVAL\n"));
386 r= sr_put_userdata(sr_fd-sr_fd_table, EINVAL,
387 NULL, 1);
388 assert(r == OK);
389 return OK;
390 }
391 r= (*sr_fd->srf_ioctl)(sr_fd->srf_fd, request);
392 break;
393 default:
394 ip_panic(("illegal case entry"));
395 }
396
397 assert(sr_fd->srf_flags & first_flag);
398 sr_fd->srf_flags &= ~first_flag;
399
400 assert(r == OK || r == SUSPEND ||
401 (printf("r= %d\n", r), 0));
402 if (r == SUSPEND)
403 sr_fd->srf_flags |= susp_flag;
404 else
405 mq_free(m);
406 return r;
407 }
408
409 PRIVATE int sr_restart_read(sr_fd)
410 sr_fd_t *sr_fd;
411 {
412 mq_t *mp;
413 int r;
414
415 mp= sr_fd->srf_read_q;
416 assert(mp);
417
418 if (sr_fd->srf_flags & SFF_READ_IP)
419 {
420 assert(sr_fd->srf_flags & SFF_READ_SUSP);
421 return SUSPEND;
422 }
423 sr_fd->srf_flags |= SFF_READ_IP;
424
425 r= (*sr_fd->srf_read)(sr_fd->srf_fd,
426 mp->mq_mess.NDEV_COUNT);
427
428 assert(r == OK || r == SUSPEND ||
429 (printf("r= %d\n", r), 0));
430 if (r == SUSPEND)
431 sr_fd->srf_flags |= SFF_READ_SUSP;
432 return r;
433 }
434
435 PRIVATE int sr_restart_write(sr_fd)
436 sr_fd_t *sr_fd;
437 {
438 mq_t *mp;
439 int r;
440
441 mp= sr_fd->srf_write_q;
442 assert(mp);
443
444 if (sr_fd->srf_flags & SFF_WRITE_IP)
445 {
446 assert(sr_fd->srf_flags & SFF_WRITE_SUSP);
447 return SUSPEND;
448 }
449 sr_fd->srf_flags |= SFF_WRITE_IP;
450
451 r= (*sr_fd->srf_write)(sr_fd->srf_fd,
452 mp->mq_mess.NDEV_COUNT);
453
454 assert(r == OK || r == SUSPEND ||
455 (printf("r= %d\n", r), 0));
456 if (r == SUSPEND)
457 sr_fd->srf_flags |= SFF_WRITE_SUSP;
458 return r;
459 }
460
461 PRIVATE int sr_restart_ioctl(sr_fd)
462 sr_fd_t *sr_fd;
463 {
464 mq_t *mp;
465 int r;
466
467 mp= sr_fd->srf_ioctl_q;
468 assert(mp);
469
470 if (sr_fd->srf_flags & SFF_IOCTL_IP)
471 {
472 assert(sr_fd->srf_flags & SFF_IOCTL_SUSP);
473 return SUSPEND;
474 }
475 sr_fd->srf_flags |= SFF_IOCTL_IP;
476
477 r= (*sr_fd->srf_ioctl)(sr_fd->srf_fd,
478 mp->mq_mess.NDEV_COUNT);
479
480 assert(r == OK || r == SUSPEND ||
481 (printf("r= %d\n", r), 0));
482 if (r == SUSPEND)
483 sr_fd->srf_flags |= SFF_IOCTL_SUSP;
484 return r;
485 }
486
487 PRIVATE int sr_cancel(m)
488 message *m;
489 {
490 sr_fd_t *sr_fd;
491 int result;
492 int proc_nr, ref, operation;
493
494 result=EINTR;
495 proc_nr= m->NDEV_PROC;
496 #ifdef __minix_vmd
497 ref= m->NDEV_REF;
498 operation= m->NDEV_OPERATION;
499 #else /* Minix 3 */
500 ref= 0;
501 operation= 0;
502 #endif
503 sr_fd= sr_getchannel(m->NDEV_MINOR);
504 assert (sr_fd);
505
506 #ifdef __minix_vmd
507 if (operation == CANCEL_ANY || operation == DEV_IOCTL3)
508 #endif
509 {
510 result= walk_queue(sr_fd, &sr_fd->srf_ioctl_q,
511 &sr_fd->srf_ioctl_q_tail, SR_CANCEL_IOCTL,
512 proc_nr, ref, SFF_IOCTL_FIRST);
513 if (result != EAGAIN)
514 return result;
515 }
516 #ifdef __minix_vmd
517 if (operation == CANCEL_ANY || operation == DEV_READ)
518 #endif
519 {
520 result= walk_queue(sr_fd, &sr_fd->srf_read_q,
521 &sr_fd->srf_read_q_tail, SR_CANCEL_READ,
522 proc_nr, ref, SFF_READ_FIRST);
523 if (result != EAGAIN)
524 return result;
525 }
526 #ifdef __minix_vmd
527 if (operation == CANCEL_ANY || operation == DEV_WRITE)
528 #endif
529 {
530 result= walk_queue(sr_fd, &sr_fd->srf_write_q,
531 &sr_fd->srf_write_q_tail, SR_CANCEL_WRITE,
532 proc_nr, ref, SFF_WRITE_FIRST);
533 if (result != EAGAIN)
534 return result;
535 }
536 #ifdef __minix_vmd
537 ip_panic((
538 "request not found: from %d, type %d, MINOR= %d, PROC= %d, REF= %d OPERATION= %ld",
539 m->m_source, m->m_type, m->NDEV_MINOR,
540 m->NDEV_PROC, m->NDEV_REF, m->NDEV_OPERATION));
541 #else /* Minix 3 */
542 ip_panic((
543 "request not found: from %d, type %d, MINOR= %d, PROC= %d",
544 m->m_source, m->m_type, m->NDEV_MINOR,
545 m->NDEV_PROC));
546 #endif
547 }
548
549 #ifndef __minix_vmd /* Minix 3 */
550 PRIVATE int sr_select(m)
551 message *m;
552 {
553 sr_fd_t *sr_fd;
554 mq_t **q_head_ptr, **q_tail_ptr;
555 int ip_flag, susp_flag;
556 int r, ops;
557 unsigned m_ops, i_ops;
558 ioreq_t request;
559 size_t size;
560
561 sr_fd= sr_getchannel(m->NDEV_MINOR);
562 assert (sr_fd);
563
564 sr_fd->srf_select_proc= m->m_source;
565
566 m_ops= m->PROC_NR;
567 i_ops= 0;
568 if (m_ops & SEL_RD) i_ops |= SR_SELECT_READ;
569 if (m_ops & SEL_WR) i_ops |= SR_SELECT_WRITE;
570 if (m_ops & SEL_ERR) i_ops |= SR_SELECT_EXCEPTION;
571 if (!(m_ops & SEL_NOTIFY)) i_ops |= SR_SELECT_POLL;
572
573 r= (*sr_fd->srf_select)(sr_fd->srf_fd, i_ops);
574 if (r < 0)
575 return r;
576 m_ops= 0;
577 if (r & SR_SELECT_READ) m_ops |= SEL_RD;
578 if (r & SR_SELECT_WRITE) m_ops |= SEL_WR;
579 if (r & SR_SELECT_EXCEPTION) m_ops |= SEL_ERR;
580
581 return m_ops;
582 }
583
584 PRIVATE void sr_status(m)
585 message *m;
586 {
587 int fd, result;
588 unsigned m_ops;
589 sr_fd_t *sr_fd;
590 mq_t *mq;
591
592 mq= repl_queue;
593 if (mq != NULL)
594 {
595 repl_queue= mq->mq_next;
596
597 mq->mq_mess.m_type= DEV_REVIVE;
598 result= send(mq->mq_mess.m_source, &mq->mq_mess);
599 if (result != OK)
600 ip_panic(("unable to send"));
601 mq_free(mq);
602
603 return;
604 }
605
606 for (fd=0, sr_fd= sr_fd_table; fd<FD_NR; fd++, sr_fd++)
607 {
608 if ((sr_fd->srf_flags &
609 (SFF_SELECT_R|SFF_SELECT_W|SFF_SELECT_X)) == 0)
610 {
611 /* Nothing to report */
612 continue;
613 }
614 if (sr_fd->srf_select_proc != m->m_source)
615 {
616 /* Wrong process */
617 continue;
618 }
619
620 m_ops= 0;
621 if (sr_fd->srf_flags & SFF_SELECT_R) m_ops |= SEL_RD;
622 if (sr_fd->srf_flags & SFF_SELECT_W) m_ops |= SEL_WR;
623 if (sr_fd->srf_flags & SFF_SELECT_X) m_ops |= SEL_ERR;
624
625 sr_fd->srf_flags &= ~(SFF_SELECT_R|SFF_SELECT_W|SFF_SELECT_X);
626
627 m->m_type= DEV_IO_READY;
628 m->DEV_MINOR= fd;
629 m->DEV_SEL_OPS= m_ops;
630
631 result= send(m->m_source, m);
632 if (result != OK)
633 ip_panic(("unable to send"));
634 return;
635 }
636
637 m->m_type= DEV_NO_STATUS;
638 result= send(m->m_source, m);
639 if (result != OK)
640 ip_panic(("unable to send"));
641 }
642 #endif
643
644 PRIVATE int walk_queue(sr_fd, q_head_ptr, q_tail_ptr, type, proc_nr, ref,
645 first_flag)
646 sr_fd_t *sr_fd;
647 mq_t **q_head_ptr;
648 mq_t **q_tail_ptr;
649 int type;
650 int proc_nr;
651 int ref;
652 int first_flag;
653 {
654 mq_t *q_ptr_prv, *q_ptr;
655 int result;
656
657 for(q_ptr_prv= NULL, q_ptr= *q_head_ptr; q_ptr;
658 q_ptr_prv= q_ptr, q_ptr= q_ptr->mq_next)
659 {
660 if (q_ptr->mq_mess.NDEV_PROC != proc_nr)
661 continue;
662 #ifdef __minix_vmd
663 if (q_ptr->mq_mess.NDEV_REF != ref)
664 continue;
665 #endif
666 if (!q_ptr_prv)
667 {
668 assert(!(sr_fd->srf_flags & first_flag));
669 sr_fd->srf_flags |= first_flag;
670
671 result= (*sr_fd->srf_cancel)(sr_fd->srf_fd, type);
672 assert(result == OK);
673
674 *q_head_ptr= q_ptr->mq_next;
675 mq_free(q_ptr);
676
677 assert(sr_fd->srf_flags & first_flag);
678 sr_fd->srf_flags &= ~first_flag;
679
680 return OK;
681 }
682 q_ptr_prv->mq_next= q_ptr->mq_next;
683 mq_free(q_ptr);
684 if (!q_ptr_prv->mq_next)
685 *q_tail_ptr= q_ptr_prv;
686 return EINTR;
687 }
688 return EAGAIN;
689 }
690
691 PRIVATE sr_fd_t *sr_getchannel(minor)
692 int minor;
693 {
694 sr_fd_t *loc_fd;
695
696 compare(minor, >=, 0);
697 compare(minor, <, FD_NR);
698
699 loc_fd= &sr_fd_table[minor];
700
701 assert (!(loc_fd->srf_flags & SFF_MINOR) &&
702 (loc_fd->srf_flags & SFF_INUSE));
703
704 return loc_fd;
705 }
706
707 PRIVATE void sr_reply_(mq, status, is_revive)
708 mq_t *mq;
709 int status;
710 int is_revive;
711 {
712 int result, proc, ref,operation;
713 message reply, *mp;
714
715 proc= mq->mq_mess.NDEV_PROC;
716 #ifdef __minix_vmd
717 ref= mq->mq_mess.NDEV_REF;
718 #else /* Minix 3 */
719 ref= 0;
720 #endif
721 operation= mq->mq_mess.m_type;
722 #ifdef __minix_vmd
723 assert(operation != DEV_CANCEL);
724 #endif
725
726 if (is_revive)
727 mp= &mq->mq_mess;
728 else
729 mp= &reply;
730
731 mp->m_type= DEVICE_REPLY;
732 mp->REP_PROC_NR= proc;
733 mp->REP_STATUS= status;
734 #ifdef __minix_vmd
735 mp->REP_REF= ref;
736 mp->REP_OPERATION= operation;
737 #endif
738 if (is_revive)
739 {
740 notify(mq->mq_mess.m_source);
741 result= ELOCKED;
742 }
743 else
744 result= send(mq->mq_mess.m_source, mp);
745
746 if (result == ELOCKED && is_revive)
747 {
748 mq->mq_next= NULL;
749 if (repl_queue)
750 repl_queue_tail->mq_next= mq;
751 else
752 repl_queue= mq;
753 repl_queue_tail= mq;
754 return;
755 }
756 if (result != OK)
757 ip_panic(("unable to send"));
758 if (is_revive)
759 mq_free(mq);
760 }
761
762 PRIVATE acc_t *sr_get_userdata (fd, offset, count, for_ioctl)
763 int fd;
764 vir_bytes offset;
765 vir_bytes count;
766 int for_ioctl;
767 {
768 sr_fd_t *loc_fd;
769 mq_t **head_ptr, *m, *mq;
770 int ip_flag, susp_flag, first_flag;
771 int result, suspended, is_revive;
772 char *src;
773 acc_t *acc;
774 event_t *evp;
775 ev_arg_t arg;
776
777 loc_fd= &sr_fd_table[fd];
778
779 if (for_ioctl)
780 {
781 head_ptr= &loc_fd->srf_ioctl_q;
782 evp= &loc_fd->srf_ioctl_ev;
783 ip_flag= SFF_IOCTL_IP;
784 susp_flag= SFF_IOCTL_SUSP;
785 first_flag= SFF_IOCTL_FIRST;
786 }
787 else
788 {
789 head_ptr= &loc_fd->srf_write_q;
790 evp= &loc_fd->srf_write_ev;
791 ip_flag= SFF_WRITE_IP;
792 susp_flag= SFF_WRITE_SUSP;
793 first_flag= SFF_WRITE_FIRST;
794 }
795
796 assert (loc_fd->srf_flags & ip_flag);
797
798 if (!count)
799 {
800 m= *head_ptr;
801 mq= m->mq_next;
802 *head_ptr= mq;
803 result= (int)offset;
804 is_revive= !(loc_fd->srf_flags & first_flag);
805 sr_reply_(m, result, is_revive);
806 suspended= (loc_fd->srf_flags & susp_flag);
807 loc_fd->srf_flags &= ~(ip_flag|susp_flag);
808 if (suspended)
809 {
810 if (mq)
811 {
812 arg.ev_ptr= loc_fd;
813 ev_enqueue(evp, sr_event, arg);
814 }
815 }
816 return NULL;
817 }
818
819 src= (*head_ptr)->mq_mess.NDEV_BUFFER + offset;
820 result= cp_u2b ((*head_ptr)->mq_mess.NDEV_PROC, src, &acc, count);
821
822 return result<0 ? NULL : acc;
823 }
824
825 PRIVATE int sr_put_userdata (fd, offset, data, for_ioctl)
826 int fd;
827 vir_bytes offset;
828 acc_t *data;
829 int for_ioctl;
830 {
831 sr_fd_t *loc_fd;
832 mq_t **head_ptr, *m, *mq;
833 int ip_flag, susp_flag, first_flag;
834 int result, suspended, is_revive;
835 char *dst;
836 event_t *evp;
837 ev_arg_t arg;
838
839 loc_fd= &sr_fd_table[fd];
840
841 if (for_ioctl)
842 {
843 head_ptr= &loc_fd->srf_ioctl_q;
844 evp= &loc_fd->srf_ioctl_ev;
845 ip_flag= SFF_IOCTL_IP;
846 susp_flag= SFF_IOCTL_SUSP;
847 first_flag= SFF_IOCTL_FIRST;
848 }
849 else
850 {
851 head_ptr= &loc_fd->srf_read_q;
852 evp= &loc_fd->srf_read_ev;
853 ip_flag= SFF_READ_IP;
854 susp_flag= SFF_READ_SUSP;
855 first_flag= SFF_READ_FIRST;
856 }
857
858 assert (loc_fd->srf_flags & ip_flag);
859
860 if (!data)
861 {
862 m= *head_ptr;
863 mq= m->mq_next;
864 *head_ptr= mq;
865 result= (int)offset;
866 is_revive= !(loc_fd->srf_flags & first_flag);
867 sr_reply_(m, result, is_revive);
868 suspended= (loc_fd->srf_flags & susp_flag);
869 loc_fd->srf_flags &= ~(ip_flag|susp_flag);
870 if (suspended)
871 {
872 if (mq)
873 {
874 arg.ev_ptr= loc_fd;
875 ev_enqueue(evp, sr_event, arg);
876 }
877 }
878 return OK;
879 }
880
881 dst= (*head_ptr)->mq_mess.NDEV_BUFFER + offset;
882 return cp_b2u (data, (*head_ptr)->mq_mess.NDEV_PROC, dst);
883 }
884
885 #ifndef __minix_vmd /* Minix 3 */
886 PRIVATE void sr_select_res(fd, ops)
887 int fd;
888 unsigned ops;
889 {
890 sr_fd_t *sr_fd;
891
892 sr_fd= &sr_fd_table[fd];
893
894 if (ops & SR_SELECT_READ) sr_fd->srf_flags |= SFF_SELECT_R;
895 if (ops & SR_SELECT_WRITE) sr_fd->srf_flags |= SFF_SELECT_W;
896 if (ops & SR_SELECT_EXCEPTION) sr_fd->srf_flags |= SFF_SELECT_X;
897
898 notify(sr_fd->srf_select_proc);
899 }
900 #endif
901
902 PRIVATE void process_req_q(mq, tail, tail_ptr)
903 mq_t *mq, *tail, **tail_ptr;
904 {
905 mq_t *m;
906 int result;
907
908 for(;mq;)
909 {
910 m= mq;
911 mq= mq->mq_next;
912
913 result= sr_rwio(m);
914 if (result == SUSPEND)
915 {
916 if (mq)
917 {
918 (*tail_ptr)->mq_next= mq;
919 *tail_ptr= tail;
920 }
921 return;
922 }
923 }
924 return;
925 }
926
927 PRIVATE void sr_event(evp, arg)
928 event_t *evp;
929 ev_arg_t arg;
930 {
931 sr_fd_t *sr_fd;
932 int r;
933
934 sr_fd= arg.ev_ptr;
935 if (evp == &sr_fd->srf_write_ev)
936 {
937 while(sr_fd->srf_write_q)
938 {
939 r= sr_restart_write(sr_fd);
940 if (r == SUSPEND)
941 return;
942 }
943 return;
944 }
945 if (evp == &sr_fd->srf_read_ev)
946 {
947 while(sr_fd->srf_read_q)
948 {
949 r= sr_restart_read(sr_fd);
950 if (r == SUSPEND)
951 return;
952 }
953 return;
954 }
955 if (evp == &sr_fd->srf_ioctl_ev)
956 {
957 while(sr_fd->srf_ioctl_q)
958 {
959 r= sr_restart_ioctl(sr_fd);
960 if (r == SUSPEND)
961 return;
962 }
963 return;
964 }
965 ip_panic(("sr_event: unkown event\n"));
966 }
967
968 PRIVATE int cp_u2b (proc, src, var_acc_ptr, size)
969 int proc;
970 char *src;
971 acc_t **var_acc_ptr;
972 int size;
973 {
974 static message mess;
975 acc_t *acc;
976 int i;
977
978 acc= bf_memreq(size);
979
980 *var_acc_ptr= acc;
981 i=0;
982
983 while (acc)
984 {
985 size= (vir_bytes)acc->acc_length;
986
987 #ifdef __minix_vmd
988 cpvec[i].cpv_src= (vir_bytes)src;
989 cpvec[i].cpv_dst= (vir_bytes)ptr2acc_data(acc);
990 cpvec[i].cpv_size= size;
991 #else /* Minix 3 */
992 vir_cp_req[i].count= size;
993 vir_cp_req[i].src.proc_nr = proc;
994 vir_cp_req[i].src.segment = D;
995 vir_cp_req[i].src.offset = (vir_bytes) src;
996 vir_cp_req[i].dst.proc_nr = this_proc;
997 vir_cp_req[i].dst.segment = D;
998 vir_cp_req[i].dst.offset = (vir_bytes) ptr2acc_data(acc);
999 #endif
1000
1001 src += size;
1002 acc= acc->acc_next;
1003 i++;
1004
1005 if (i == CPVEC_NR || acc == NULL)
1006 {
1007 #ifdef __minix_vmd
1008 mess.m_type= SYS_VCOPY;
1009 mess.m1_i1= proc;
1010 mess.m1_i2= this_proc;
1011 mess.m1_i3= i;
1012 mess.m1_p1= (char *)cpvec;
1013 #else /* Minix 3 */
1014 mess.m_type= SYS_VIRVCOPY;
1015 mess.VCP_VEC_SIZE= i;
1016 mess.VCP_VEC_ADDR= (char *)vir_cp_req;
1017 #endif
1018 if (sendrec(SYSTASK, &mess) <0)
1019 ip_panic(("unable to sendrec"));
1020 if (mess.m_type <0)
1021 {
1022 bf_afree(*var_acc_ptr);
1023 *var_acc_ptr= 0;
1024 return mess.m_type;
1025 }
1026 i= 0;
1027 }
1028 }
1029 return OK;
1030 }
1031
1032 PRIVATE int cp_b2u (acc_ptr, proc, dest)
1033 acc_t *acc_ptr;
1034 int proc;
1035 char *dest;
1036 {
1037 static message mess;
1038 acc_t *acc;
1039 int i, size;
1040
1041 acc= acc_ptr;
1042 i=0;
1043
1044 while (acc)
1045 {
1046 size= (vir_bytes)acc->acc_length;
1047
1048 if (size)
1049 {
1050 #ifdef __minix_vmd
1051 cpvec[i].cpv_src= (vir_bytes)ptr2acc_data(acc);
1052 cpvec[i].cpv_dst= (vir_bytes)dest;
1053 cpvec[i].cpv_size= size;
1054 #else /* Minix 3 */
1055 vir_cp_req[i].src.proc_nr = this_proc;
1056 vir_cp_req[i].src.segment = D;
1057 vir_cp_req[i].src.offset= (vir_bytes)ptr2acc_data(acc);
1058 vir_cp_req[i].dst.proc_nr = proc;
1059 vir_cp_req[i].dst.segment = D;
1060 vir_cp_req[i].dst.offset= (vir_bytes)dest;
1061 vir_cp_req[i].count= size;
1062 #endif
1063 i++;
1064 }
1065
1066 dest += size;
1067 acc= acc->acc_next;
1068
1069 if (i == CPVEC_NR || acc == NULL)
1070 {
1071 #ifdef __minix_vmd
1072 mess.m_type= SYS_VCOPY;
1073 mess.m1_i1= this_proc;
1074 mess.m1_i2= proc;
1075 mess.m1_i3= i;
1076 mess.m1_p1= (char *)cpvec;
1077 #else /* Minix 3 */
1078 mess.m_type= SYS_VIRVCOPY;
1079 mess.VCP_VEC_SIZE= i;
1080 mess.VCP_VEC_ADDR= (char *) vir_cp_req;
1081 #endif
1082 if (sendrec(SYSTASK, &mess) <0)
1083 ip_panic(("unable to sendrec"));
1084 if (mess.m_type <0)
1085 {
1086 bf_afree(acc_ptr);
1087 return mess.m_type;
1088 }
1089 i= 0;
1090 }
1091 }
1092 bf_afree(acc_ptr);
1093 return OK;
1094 }
1095
1096 PRIVATE int sr_repl_queue(proc, ref, operation)
1097 int proc;
1098 int ref;
1099 int operation;
1100 {
1101 mq_t *m, *m_cancel, *m_tmp;
1102 int result;
1103
1104 m_cancel= NULL;
1105
1106 for (m= repl_queue; m;)
1107 {
1108 #ifdef __minix_vmd
1109 if (m->mq_mess.REP_PROC_NR == proc &&
1110 m->mq_mess.REP_REF ==ref &&
1111 (m->mq_mess.REP_OPERATION == operation ||
1112 operation == CANCEL_ANY))
1113 #else /* Minix 3 */
1114 if (m->mq_mess.REP_PROC_NR == proc)
1115 #endif
1116 {
1117 assert(!m_cancel);
1118 m_cancel= m;
1119 m= m->mq_next;
1120 continue;
1121 }
1122 result= send(m->mq_mess.m_source, &m->mq_mess);
1123 if (result != OK)
1124 ip_panic(("unable to send: %d", result));
1125 m_tmp= m;
1126 m= m->mq_next;
1127 mq_free(m_tmp);
1128 }
1129 repl_queue= NULL;
1130 if (m_cancel)
1131 {
1132 result= send(m_cancel->mq_mess.m_source, &m_cancel->mq_mess);
1133 if (result != OK)
1134 ip_panic(("unable to send: %d", result));
1135 mq_free(m_cancel);
1136 return 1;
1137 }
1138 return 0;
1139 }
1140
1141 /*
1142 * $PchId: sr.c,v 1.17 2005/06/28 14:26:16 philip Exp $
1143 */
Cache object: 407eaaf8aa4f75c9d0876a449669b685
|